home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume15 / xmines2 / part01 / xmines.c < prev    next >
C/C++ Source or Header  |  1993-01-27  |  13KB  |  545 lines

  1. #include <math.h>
  2. #include <sys/types.h>
  3. #include <sys/timeb.h>
  4. #include <sys/time.h>
  5. #include <signal.h>
  6. #include <stdio.h>
  7. #include <X11/Xlib.h>
  8. #include <X11/Xutil.h>
  9. #include <xview/xview.h>
  10. #include <xview/panel.h>
  11. #include <xview/frame.h>
  12. #include <xview/canvas.h>
  13. #include <xview/notice.h>
  14. #include "xmines.h"
  15.  
  16. #include "xmines.icons"
  17.  
  18. #define CREATE_ICON(bits,width,height) XCreateBitmapFromData(display,RootWindow(display,screen),\
  19.                     bits,width,height) 
  20. #define PLACE_ICON(icon,wherey,wherex) XCopyPlane(display,icon,pmap,def_gc,0,0, \
  21.                                           IC_WIDTH,IC_HEIGHT,wherex,wherey,1L)
  22. /*#define DEBUG */
  23.  
  24. #define POW(x,y)        pow((double)(x),(double)(y))
  25. #define INITRAND        srandom(time((time_t *)0))
  26. #define MAXRANDOM       2147483648 /* 2^31 */
  27. #define RAND01          (((double)(random()))/MAXRANDOM)
  28. #define FRAND(min,max)  (RAND01*((max)-(min))+(min))
  29. #define RAND(min,max)   (int)FRAND(min,max)
  30.  
  31. #ifndef lint
  32. static char     sccsid[] = "@(#)xmines,v0.1 by Manolis Lourakis.";
  33. static char     Copyright[] = "(c) 1992 Lourakis Manolis.\n";
  34. static char     Mail[] = "lourakis@csd.uch.gr";
  35. #endif
  36.  
  37.  
  38. extern char     *optarg ;
  39. extern int      optind ;
  40.  
  41. void canvas_event_proc(Xv_Window, Event*); 
  42. void canvas_repaint_proc(void);
  43. void settime(void);
  44. void finish(char *);
  45.  
  46.  
  47. Display *display;
  48. Visual *visual;
  49. int screen;
  50. GC def_gc;
  51.  
  52. Frame frame;
  53. Panel panel1,panel2;
  54. Panel_item pmsg,smsg,tmsg;
  55. Canvas canvas;
  56.  
  57. Window dr_win;
  58. Pixmap pmap,icons[NUM_ICONS];
  59. cell *Cells;
  60. char buff[256];
  61.  
  62. int quit_proc(),init();
  63. int place_tiles(int,int);
  64. int mark_tile(int,int);
  65. int open_tile(int,int);
  66. int auto_open(int,int);
  67.  
  68. int mines_2_go,closed_tiles,playing,checks,secs;
  69. int width=HORIZ_CELLS,
  70.     height=VERT_CELLS,
  71.     mines=NUM_MINES,
  72.     quantum=QUANTUM;
  73.  
  74. struct itimerval timer;
  75. int first_tile;
  76.  
  77. void main(int argc, char *argv[]){
  78.   int ret,tmp;
  79.   register int i,j;
  80.   int   errflag = 0,gc;
  81.   XWMHints        wm_hints;
  82.   XClassHint      class_hints;
  83.   XTextProperty   windowName, iconName;
  84.   char           *window_name = "Xmines";
  85.   char           *icon_name = "Xmines";
  86.   
  87.   xv_init (XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
  88.   while ((gc = getopt(argc, argv, "w:h:m:q:")) != EOF)
  89.   switch (gc) {
  90.       case 'w' :
  91.               tmp=atoi(optarg);
  92.           if(tmp>0) width=tmp;
  93.               break ;
  94.       case 'h' :
  95.           tmp=atoi(optarg);
  96.           if(tmp>0) height=tmp;
  97.               break ;
  98.       case 'm' :
  99.           tmp=atoi(optarg);
  100.           if(tmp>0) mines=tmp;
  101.               break;
  102.       case 'q' :
  103.           tmp=atoi(optarg);
  104.           if(tmp>0) quantum=tmp;
  105.           break;
  106.       case '?' :
  107.               errflag++;
  108.               break ;
  109.   }
  110.   if(errflag){
  111.     fprintf(stderr,
  112.     "Usage: xmines [-w width] [-h height] [-m mines] [-q quantum]\n");
  113.     exit(1);
  114.   }
  115.   if(mines>=width*height){
  116.      fprintf(stderr,"xmines: Too many mines, using defaults\n");
  117.      width=HORIZ_CELLS;
  118.      height=VERT_CELLS;
  119.      mines=NUM_MINES;
  120.   }
  121.   
  122.   Cells=(cell *)malloc(width*height*sizeof(cell));
  123.   if(Cells==NULL){
  124.      fprintf(stderr,"xmines: malloc failed\n");
  125.      exit(1);
  126.   }
  127.  
  128.   frame = (Frame) xv_create (NULL, FRAME,
  129.                  FRAME_LABEL,PROG_NAME,
  130.                  XV_WIDTH,width*IC_WIDTH,
  131.                              NULL);
  132.   display = (Display *)xv_get (frame, XV_DISPLAY);
  133.   screen = DefaultScreen(display);
  134.   visual = DefaultVisual(display, screen);
  135.   def_gc = DefaultGC(display, screen);
  136.  
  137.   panel1 = xv_create (frame, PANEL,
  138.               PANEL_LAYOUT,PANEL_HORIZONTAL,
  139.                       NULL);
  140.  
  141.        xv_create (panel1, PANEL_BUTTON,
  142.                    PANEL_LABEL_STRING, "Quit",
  143.                    PANEL_NOTIFY_PROC, quit_proc,
  144.                    NULL);
  145.     xv_create (panel1, PANEL_BUTTON,
  146.                     PANEL_LABEL_STRING, "New",
  147.                     PANEL_NOTIFY_PROC, init,
  148.                     NULL);
  149.     tmsg=xv_create (panel1, PANEL_MESSAGE,
  150.             PANEL_LABEL_STRING,"Time:  0:0",
  151.             PANEL_LABEL_BOLD,TRUE,
  152.                 NULL);
  153.     window_fit_height(panel1);
  154.   panel2 = xv_create (frame, PANEL,
  155.                       PANEL_LAYOUT,PANEL_HORIZONTAL,
  156.                       NULL);
  157.  
  158.     sprintf(buff,"Mines: %d\n",mines);
  159.      xv_create(panel2,PANEL_MESSAGE,
  160.                    PANEL_LABEL_STRING,buff,
  161.            PANEL_LABEL_BOLD,TRUE,
  162.                    NULL);
  163.     sprintf(buff,"Checks: 0");
  164.     pmsg=xv_create(panel2,PANEL_MESSAGE,
  165.            PANEL_LABEL_STRING,buff,
  166.            PANEL_LABEL_BOLD,TRUE,
  167.            NULL);
  168.     smsg=xv_create(panel2,PANEL_MESSAGE,
  169.                    XV_SHOW, FALSE,
  170.                    NULL);
  171.     window_fit_height(panel2);
  172.             
  173.   canvas = xv_create (frame, CANVAS,
  174.             CANVAS_X_PAINT_WINDOW, TRUE,
  175.             XV_WIDTH,IC_WIDTH*width,
  176.             XV_HEIGHT,IC_HEIGHT*height,
  177.             WIN_EVENT_PROC, canvas_event_proc,
  178.             CANVAS_REPAINT_PROC, canvas_repaint_proc,
  179.             NULL);
  180.   xv_set (canvas_paint_window (canvas), WIN_CONSUME_EVENTS,
  181.       WIN_MOUSE_BUTTONS,
  182.          NULL,
  183.       WIN_EVENT_PROC, canvas_event_proc,
  184.       NULL);
  185.  
  186.   dr_win = xv_get(canvas_paint_window (canvas), XV_XID);
  187.  
  188.   pmap=XCreatePixmap(display,dr_win,IC_WIDTH*width,
  189.                      IC_HEIGHT*height,DefaultDepth(display,screen)); 
  190.  
  191.   icons[EMPTY]=CREATE_ICON(empty_bits,empty_width,empty_height);
  192.   icons[ONE]=CREATE_ICON(one_bits,one_width,one_height);
  193.   icons[TWO]=CREATE_ICON(two_bits,two_width,two_height);
  194.   icons[THREE]=CREATE_ICON(three_bits,three_width,three_height);
  195.   icons[FOUR]=CREATE_ICON(four_bits,four_width,four_height);
  196.   icons[FIVE]=CREATE_ICON(five_bits,five_width,five_height);
  197.   icons[SIX]=CREATE_ICON(six_bits,six_width,six_height);
  198.   icons[SEVEN]=CREATE_ICON(seven_bits,seven_width,seven_height); 
  199.   icons[EIGHT]=CREATE_ICON(eight_bits,eight_width,eight_height);
  200.   icons[CLOSED]=CREATE_ICON(closed_bits,closed_width,closed_height);
  201.   icons[MARKED]=CREATE_ICON(marked_bits,marked_width,marked_height);
  202.   icons[MINE]=CREATE_ICON(mine_bits,mine_width,mine_height);
  203.   icons[QUEST]=CREATE_ICON(quest_bits,quest_width,quest_height);
  204.   
  205.   if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) {
  206.     fprintf(stderr, "structure allocation for windowName failed\n");
  207.     exit(1);
  208.   }
  209.   if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0) {
  210.     fprintf(stderr, "structure allocation for windowName failed\n");
  211.     exit(1);
  212.   }
  213.   wm_hints.initial_state = NormalState;
  214.   wm_hints.input = True;
  215.   wm_hints.icon_pixmap = icons[MINE];
  216.   wm_hints.flags = StateHint | IconPixmapHint | InputHint;
  217.  
  218.   class_hints.res_name = "Xmines";
  219.   class_hints.res_class = "Games";
  220.  
  221.   XSetWMProperties(display, xv_get(frame,XV_XID), &windowName, &iconName, argv,
  222.                    argc, NULL, &wm_hints, &class_hints);
  223.  
  224.  
  225.   
  226.   timer.it_interval.tv_sec=quantum;
  227.   timer.it_interval.tv_usec=0;
  228.  
  229.   timer.it_value.tv_sec=quantum;
  230.   timer.it_value.tv_usec=0;
  231.  
  232.   init();
  233.   window_fit(frame);
  234.   xv_main_loop(frame);
  235. }
  236.  
  237.  
  238. void
  239. canvas_repaint_proc ()
  240.   XCopyArea(display,pmap,dr_win,def_gc,0,0,
  241.              width*IC_WIDTH,height*IC_HEIGHT,0,0);
  242. }
  243.  
  244. void
  245. canvas_event_proc (Xv_Window window, Event *event)
  246. {
  247. int x,y;
  248. cell *aux;
  249.  
  250.   if(!playing) return;
  251.   switch (event_xevent (event)->type)
  252.     {
  253.     case ButtonRelease:
  254.       get_cell(event_xevent (event)->xbutton.x,event_xevent (event)->xbutton.y,
  255.                         &x,&y);
  256.       switch (event_xevent (event)->xbutton.button){
  257.     case Button1: 
  258.           if(open_tile(x,y)){
  259.             XCopyArea(display,pmap,dr_win,def_gc,0,0,
  260.                width*IC_WIDTH,height*IC_HEIGHT,0,0);
  261.            }
  262.           if(mines_2_go==0 && closed_tiles==mines)
  263.            finish("  Successful");
  264.       break;
  265.     case Button2:
  266.       aux=Cells+x*width+y;
  267.       if(aux->out_state!=CLOSED) break;
  268.       PLACE_ICON(icons[QUEST],x*IC_WIDTH,
  269.                               y*IC_HEIGHT);
  270.           aux->out_state=QUEST;
  271.       XCopyArea(display,pmap,dr_win,def_gc,0,0,
  272.                width*IC_WIDTH,height*IC_HEIGHT,0,0);
  273.       break;
  274.     case Button3:
  275.           if(mark_tile(x,y)){
  276.              XCopyArea(display,pmap,dr_win,def_gc,0,0,
  277.                 width*IC_WIDTH,height*IC_HEIGHT,0,0);
  278.           }
  279.       if(mines_2_go==0 && closed_tiles==mines)
  280.         finish("  Successful");
  281.  
  282.       break;
  283.     }
  284.       break;
  285.     default:
  286.       break;
  287.     }
  288. }
  289.  
  290. error(char *msg)
  291. {
  292.  fprintf(stderr,"xmines: %s\n",msg);
  293.  exit(1);
  294. }
  295.  
  296. get_cell(int where_x,int where_y,int *i,int *j)
  297. {
  298.  register int k;
  299.  
  300.  for(k=0;k*IC_WIDTH<where_x;k++)
  301.       ;
  302.  *j=k-1;
  303.  for(k=0;k*IC_HEIGHT<where_y;k++)
  304.           ;
  305.  *i=k-1;
  306. }
  307.  
  308. quit_proc()
  309. {
  310.   int          result;
  311.  
  312.   result = notice_prompt(panel1, NULL,
  313.         NOTICE_MESSAGE_STRINGS,
  314.                 "Realy Quit?",
  315.                 "Press YES to confirm",
  316.                 "Press NO to cancel",
  317.                 NULL,
  318.         NOTICE_BUTTON_YES,      "YES",
  319.         NOTICE_BUTTON_NO,       "NO",
  320.         NULL);
  321.  
  322.   switch(result) {
  323.         case NOTICE_YES:
  324.             exit(0);
  325.             break;
  326.         case NOTICE_NO:
  327.             break;
  328.         case NOTICE_FAILED:
  329.         default: break;
  330.     }
  331. }
  332.  
  333.  
  334. place_tiles(int len,int num_mines)
  335. {
  336.  register int i,j;
  337.  int where,aux,cnt;
  338.  
  339.  for(i=0;i<len;i++){
  340.   (Cells+i)->in_state=EMPTY;
  341.   (Cells+i)->out_state=CLOSED;
  342.  }
  343.  
  344.  INITRAND;
  345.  
  346.  for(i=0;i<num_mines; ){
  347.    aux=RAND(0,len);
  348.    if((Cells+aux)->in_state==MINE) continue;
  349.    (Cells+aux)->in_state=MINE;
  350.    i++;
  351.  }
  352.  
  353.  for(j=0;j<width;j++)
  354.   for(i=0;i<height;i++){
  355.  
  356.      where=i*width+j;
  357.      if((Cells+where)->in_state==MINE) continue;
  358.  
  359.     cnt=0;
  360.     if(i-1>=0){
  361.        if((Cells+where-width)->in_state==MINE) cnt++;
  362.     if(j-1>=0)
  363.       if((Cells+where-width-1)->in_state==MINE) cnt++;
  364.     if(j+1<width)
  365.       if((Cells+where-width+1)->in_state==MINE) cnt++;
  366.     }
  367.     if(i+1<height){
  368.        if((Cells+where+width)->in_state==MINE) cnt++;
  369.     if(j-1>=0)
  370.       if((Cells+where+width-1)->in_state==MINE) cnt++;
  371.     if(j+1<width)
  372.       if((Cells+where+width+1)->in_state==MINE) cnt++;
  373.     }
  374.     if(j-1>=0)
  375.        if((Cells+where-1)->in_state==MINE) cnt++;
  376.       
  377.     if(j+1<width)
  378.        if((Cells+where+1)->in_state==MINE) cnt++;
  379.     (Cells+where)->in_state=cnt;
  380.  }
  381.  
  382. #ifdef DEBUG
  383.  for(i=0;i<height;i++){
  384.   for(j=0;j<width;j++)
  385.    if((Cells+i*width+j)->in_state==MINE) printf("* "); else
  386.    printf("%d ",(Cells+i*width+j)->in_state);
  387.   printf("\n");
  388.  }
  389. #endif
  390.  
  391. }   
  392.    
  393.  
  394. open_tile(int i,int j)
  395. {
  396.  cell *aux;
  397.  
  398.  if (first_tile) {
  399.       signal(SIGALRM,settime);
  400.       setitimer(ITIMER_REAL,&timer,NULL);
  401.       first_tile=0;
  402.  }
  403.  aux=Cells+i*width+j;
  404.  if(aux->out_state!=CLOSED && aux->out_state!=MARKED && aux->out_state!=QUEST) 
  405.     return FALSE;
  406.  
  407.  if(aux->in_state==MINE){
  408.          finish("  Game Over");
  409.   }
  410.   else if(aux->in_state==EMPTY)
  411.            return auto_open(i,j); 
  412.        else {
  413.       if(aux->out_state==MARKED){
  414.         checks--;
  415.         sprintf(buff,"Checks: %d\n",checks);
  416.         xv_set(pmsg,PANEL_LABEL_STRING,buff,NULL);
  417.        }
  418.  
  419.           PLACE_ICON(icons[aux->in_state],i*IC_WIDTH,
  420.                               j*IC_HEIGHT);
  421.           aux->out_state=aux->in_state;
  422.           closed_tiles--;
  423.           return TRUE;
  424.        }
  425. }
  426.  
  427. mark_tile(int i,int j)
  428. {
  429.  cell *aux;
  430.  
  431.  aux=Cells+i*width+j;
  432.  
  433.  if(aux->out_state==MARKED || aux->out_state!=CLOSED && aux->out_state!=QUEST)
  434.          return FALSE;
  435.  
  436.  PLACE_ICON(icons[MARKED],i*IC_WIDTH,j*IC_HEIGHT);
  437.  aux->out_state=MARKED;
  438.  checks++;
  439.  
  440.  if(aux->in_state==MINE)
  441.     mines_2_go--;
  442.  
  443.  sprintf(buff,"Checks: %d\n",checks);
  444.  xv_set(pmsg,PANEL_LABEL_STRING,buff,NULL);
  445.  return TRUE;
  446. }
  447.  
  448. auto_open(int i,int j)
  449. {
  450.  int where;
  451.  cell *ptr;
  452.  
  453.   ptr=Cells+i*width+j;
  454.   if(ptr->out_state!=CLOSED && ptr->out_state!=MARKED && ptr->out_state!=QUEST
  455.          || ptr->in_state>EIGHT) return FALSE;
  456.  
  457.   if(ptr->out_state==MARKED){
  458.         checks--;
  459.         sprintf(buff,"Checks: %d\n",checks);
  460.         xv_set(pmsg,PANEL_LABEL_STRING,buff,NULL);
  461.   }
  462.  
  463.   PLACE_ICON(icons[ptr->in_state],i*IC_WIDTH,j*IC_HEIGHT);
  464.   ptr->out_state=ptr->in_state;
  465.   closed_tiles--;
  466.  
  467.    if(ptr->in_state==EMPTY){
  468.      if(i-1>=0){ 
  469.     auto_open(i-1,j);
  470.     if(j-1>=0) auto_open(i-1,j-1);
  471.     if(j+1<width) auto_open(i-1,j+1);
  472.      }
  473.      if(i+1<height){
  474.      auto_open(i+1,j);
  475.      if(j-1>=0) auto_open(i+1,j-1);
  476.         if(j+1<width) auto_open(i+1,j+1);
  477.      }
  478.  
  479.      if(j-1>=0) auto_open(i,j-1);
  480.      if(j+1<width) auto_open(i,j+1);
  481.  
  482.      return TRUE;
  483.   }
  484. }
  485.    
  486. int init(){
  487. register int i;
  488. int j;
  489.  
  490.   place_tiles(width*height,mines);
  491.   mines_2_go=mines;
  492.   playing=TRUE;
  493.   j=closed_tiles=width*height;
  494.   checks=0;
  495.   for(i=0;i<j;i++)
  496. #ifndef DEBUG
  497.      PLACE_ICON(icons[CLOSED],(i/width)*IC_WIDTH,(i%width)*IC_HEIGHT);
  498. #else
  499.      PLACE_ICON(icons[(Cells+i)->in_state],(i/width)*IC_WIDTH,(i%width)*IC_HEIGHT);
  500. #endif
  501.  
  502.   XCopyArea(display,pmap,dr_win,def_gc,0,0,
  503.              width*IC_WIDTH,height*IC_HEIGHT,0,0);
  504.   xv_set(smsg,XV_SHOW,FALSE,NULL);
  505.   xv_set(tmsg,PANEL_LABEL_STRING,"Time:  0:0",NULL);
  506.   xv_set(pmsg,PANEL_LABEL_STRING,"Checks: 0",NULL);
  507.   secs=0;
  508.   first_tile=1;
  509.   signal(SIGALRM,SIG_IGN);
  510. }
  511.    
  512.  
  513. show_placements(int len){
  514.  register int i;
  515.  
  516.  for(i=0;i<len;i++)
  517.     if((Cells+i)->in_state==MINE) PLACE_ICON(icons[MINE],(i/width)*IC_WIDTH,
  518.                         (i%width)*IC_HEIGHT);
  519.  XCopyArea(display,pmap,dr_win,def_gc,0,0,
  520.              width*IC_WIDTH,height*IC_HEIGHT,0,0);
  521. }
  522.  
  523. void settime(void)
  524. {
  525.   secs+=quantum;
  526.   sprintf(buff,"Time:  %2d:%2d",secs/60,secs%60);
  527.   xv_set(tmsg,PANEL_LABEL_STRING,buff,NULL);
  528. }
  529.  
  530. void finish(char *result)
  531. {
  532.     playing=FALSE;
  533.     show_placements(width*height);
  534.         xv_set(smsg,PANEL_LABEL_STRING,result,
  535.                     XV_SHOW,TRUE,
  536.                     NULL);
  537.      getitimer(ITIMER_REAL,&timer);
  538.      secs+=quantum-timer.it_value.tv_sec;
  539.      sprintf(buff,"Time:  %2d:%2d",secs/60,secs%60);
  540.          xv_set(tmsg,PANEL_LABEL_STRING,buff,NULL);
  541.          signal(SIGALRM,SIG_IGN);
  542. }
  543.  
  544.