home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 301_01 / lif.c < prev    next >
C/C++ Source or Header  |  1989-12-30  |  17KB  |  1,061 lines

  1. /*
  2.     HEADER:      CUG301;
  3.     TITLE:       Conway's game of life;
  4.     DATE:        09/30/89;
  5.     DESCRIPTION: "This program is an example of the usage of the pull-down
  6.                       graphics menu system (menu.c/menu.h) on the same disk.";
  7.     KEYWORDS:       mathematical games, finite automata;
  8.     FILENAME:       LIF.C;
  9.     WARNINGS:       "The author claims copyrights and authorizes
  10.                       non-commercial use only.";
  11.     AUTHORS:       John Muczynski;
  12.     COMPILERS:   Turbo C version 2.0;
  13. */
  14.  
  15. /*
  16.     lif.c
  17.  
  18.     Conway's game of life.
  19.  
  20.     (uses menu)
  21.  
  22.     (c) Copyright 1989 by John Muczynski. All Rights Reserved.
  23. */
  24.  
  25.  
  26. /*      BULLETINS
  27.  
  28. jsm    09/04/89    known problems:
  29.     1. the box is not being turned off properly.
  30.     2. add a menu so that 1. is a feature after the bug is fixed.
  31.     3. make global commands work inside of box (run/seed/...)
  32.     4. the main computation loop can be made to run faster by using
  33.        a state table.
  34.     5. if you stamp when no file is active, then it blows up.
  35.     6. if you stamp when part of the box isn't on the plane, then
  36.         it blows up.  (should wrap-around)
  37.  
  38. FUTURE EXPANSION:
  39. jsm      09/29/89 -Need to check details before executing each function
  40.                    from the user's keys.  For example, the [?][b][r] function
  41.                    will run into never-never land if you execute it before
  42.                    specifing a block.
  43.                   -Need to assign default hot-keys.
  44.                   -Need functions to mirror image the box over either the 
  45.                    x or the y axis.  A second cursor (and box) would also
  46.                    be useful.
  47.                   -Need to take the input for the file name from the MENU
  48.                    buffer so that macros can name files to be loaded and
  49.                    saved.
  50.                   -Need to optimize the run-time loop with a state machine
  51.                    so that it runs faster.
  52.  
  53. */
  54.  
  55.  
  56. #include <stdlib.h>
  57. #include <stdio.h>
  58. #include <time.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61.  
  62. #include <bios.h>
  63. #include <graphics.h>
  64.  
  65.  
  66.  
  67. #include "menu.h"
  68.  
  69.  
  70. #define SIZE   5
  71. #define COLS  17    /* MAX OF 17 MIN OF  ??1?? */
  72. #define ROWS  60    /* MAX OF 60 MIN OF        */
  73.  
  74. /* HOW MUCH SPACE TO LEAVE AT LEFT OF SCREEN */
  75. #define COLOFF 11
  76.  
  77. /* HOW MUCH SPACE TO LEAVE AT TOP OF SCREEN (FOR MENUS) */
  78. #define ROWOFF 30    /* MIN OF 30 OR SO */
  79.  
  80.  
  81. void initgr();
  82. void onblk();
  83.  
  84. typedef int plane[COLS][ROWS];
  85.  
  86.   plane data1 = {0};
  87.   plane data2 = {0};
  88.  
  89.   plane *old_ptr = &data1;
  90.   plane *new_ptr = &data2;
  91.   plane *temp_ptr = 0;
  92.  
  93. #define OLD_DATA (*old_ptr)
  94. #define NEW_DATA (*new_ptr)
  95.  
  96. void cleardat();
  97.  
  98. static int oldX=0, oldY=0;
  99. static int curX=0, curY=0;
  100. static int blockX=0, blockY=0, blockon=0;
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108. FILE *infil;
  109. FILE *outfil;
  110.  
  111.  
  112. int writeit(int val)
  113. {
  114.   fprintf(outfil,"%c",val*( '*' - '.' ) +'.');
  115.   return(val);
  116. };
  117. void writelf()
  118. {
  119.   fprintf(outfil,"\n");
  120. };
  121.  
  122.  
  123.  
  124. static failflag=0;
  125.  
  126. /* doesn't use param that is passed */
  127. int readit()
  128. {
  129.   unsigned char ch;
  130.   int val;
  131.  
  132.   fscanf(infil,"%c",&ch);
  133.   val = (ch!='.');        /* IF ERROR, THEN MAKE IT 'ON' */
  134.   return(val||failflag);
  135. };
  136.  
  137. void readlf()
  138. {
  139.   char ch;
  140.  
  141.   fscanf(infil,"%c",&ch);
  142.   if (ch!='\n') failflag=1;
  143. };
  144.  
  145.  
  146.   static int temp;
  147. #define swapint(a,b) {temp=a; a=b; b=temp;}
  148.  
  149.  
  150.  
  151.  
  152. /* do something to the marked block */
  153. void eachblk(funct,functlf)
  154.   int funct(int val);
  155.   void functlf();
  156. {
  157.   int x,y;
  158.   int ex, ey;
  159.   int i,j, mask, oldval,newval;
  160.   int fx,fy;
  161.   int bX,bY;
  162.   failflag=0;
  163.  
  164.   if (blockon==1) {
  165.     bX=blockX;
  166.     bY=blockY;
  167.   };
  168.   if (blockon==2) {
  169.     bX=oldX-blockX;
  170.     bY=oldY-blockY;
  171.   };
  172.  
  173.  
  174.     fx=bX;
  175.     fy=bY;
  176.  
  177.     ex=oldX;
  178.     ey=oldY;
  179.  
  180.     if (ex<fx) swapint(ex,fx);
  181.     if (ey<fy) swapint(ey,fy);
  182.  
  183.     for(j=fy;j<=ey;j++){
  184.       for(i=fx;i<=ex;i++){
  185.     x=i/8;
  186.     mask = (1 << (i%8));
  187.     y=j;
  188.  
  189.     oldval = ( (NEW_DATA[x][y] & mask) != 0);
  190.     newval = (funct(oldval) != 0);
  191.     if (newval!=oldval) {
  192.       NEW_DATA[x][y] = NEW_DATA[x][y] ^ mask;
  193.       if( (OLD_DATA[x][y] & mask) == (NEW_DATA[x][y] & mask) ) {
  194.         OLD_DATA[x][y] = OLD_DATA[x][y] ^ mask;
  195.       };
  196.     };
  197.  
  198.       }; /* end for i */
  199.       functlf();
  200.     }; /* end for j */
  201. };
  202.  
  203.  
  204.  
  205.  
  206.  static char filnam[80];
  207.  static char *root = "";  /* WAS   "IMAGES\\"   */
  208.  
  209. /* turn off graphics and get a file name */
  210. void getname(char *filnam)
  211. {
  212.   int len;
  213.   char base[40];
  214.  
  215.   savescr();
  216.  
  217.   system("dir /w images");
  218.   printf("\n\n\nEnter the base file name: ");
  219.   fgets(base,40,stdin);
  220.  
  221.   len = strlen(base);
  222.   if (isspace(base[len-1]) ) len--;
  223.   base[len]='\0';
  224.  
  225.   strcpy(filnam,root);
  226.   strcat(filnam,base);
  227.   printf("\n using '%s'\n\n",filnam);
  228. };
  229.  
  230.  
  231. void readblk()
  232. {
  233.   int i,j;
  234.   char ch;
  235.  
  236.  
  237.   getname(filnam);
  238.   infil = fopen(filnam,"r");
  239.   fscanf(infil,"%d %d%c",&i,&j,&ch);
  240.  
  241.  
  242.   fclose(infil);
  243.   restorescr();
  244.  
  245.     blockon=2;
  246.     blockX=1-i;
  247.     blockY=1-j;
  248.   onblk();
  249. };
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257. /* doesn't use param that is passed */
  258. int fillit()
  259. {
  260.   return(1);
  261. };
  262. void filllf()
  263. {
  264. };
  265.  
  266. void fillblk()
  267. {
  268.   eachblk(fillit,filllf);
  269. };
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276. /* doesn't use param that is passed */
  277. int emptyit()
  278. {
  279.   return(0);
  280. };
  281. void emptylf()
  282. {
  283. };
  284.  
  285. void emptyblk()
  286. {
  287.   eachblk(emptyit,emptylf);
  288. };
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295. int revit(int it)
  296. {
  297.   return(!it);
  298. };
  299. void revlf()
  300. {
  301. };
  302.  
  303. void reverseblk()
  304. {
  305.   eachblk(revit,revlf);
  306. };
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314. void enterblk()
  315. {
  316.   int i,j;
  317.   char ch;
  318.  
  319.   infil = fopen(filnam,"r");
  320.   fscanf(infil,"%d %d%c",&i,&j,&ch);
  321.  
  322.     blockon=2;
  323.     blockX=1-i;
  324.     blockY=1-j;
  325.  
  326.  
  327.   eachblk(readit,readlf);
  328.   fclose(infil);
  329.  
  330. };
  331.  
  332.  
  333.  
  334. void writeblk()
  335. {
  336.   char filnam[80];
  337.   int x,y;
  338.   int ex, ey;
  339.   int i,j;
  340.   int bX,bY;
  341.  
  342.   if (blockon==1) {
  343.     bX=blockX;
  344.     bY=blockY;
  345.   };
  346.   if (blockon==2) {
  347.     bX=oldX-blockX;
  348.     bY=oldY-blockY;
  349.   };
  350.  
  351.  
  352.  
  353.     x=bX;
  354.     y=bY;
  355.  
  356.     ex=oldX;
  357.     ey=oldY;
  358.  
  359.     if (ex<x) swapint(ex,x);
  360.     if (ey<y) swapint(ey,y);
  361.  
  362.     i=ex-x+1;
  363.     j=ey-y+1;
  364.  
  365.  
  366.  
  367.   getname(filnam);
  368.   outfil = fopen(filnam,"w");
  369.   fprintf(outfil,"%d %d\n",i,j);
  370.  
  371.   eachblk(writeit,writelf);
  372.   fclose(outfil);
  373.  
  374.   restorescr();
  375. };
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386. /* turn the block on or off */
  387. void putblk(col)
  388.  int col;
  389. {
  390.   int x,y;
  391.   int ex, ey;
  392.   int bX,bY;
  393.  
  394.  
  395.   if (blockon==1) {
  396.     bX=blockX;
  397.     bY=blockY;
  398.   };
  399.   if (blockon==2) {
  400.     bX=oldX-blockX;
  401.     bY=oldY-blockY;
  402.   };
  403.  
  404.   if (blockon) {
  405.     x=bX*SIZE+SIZE+1+COLOFF-2;
  406.     y=bY*SIZE+SIZE+1+ROWOFF    -2;
  407.  
  408.     ex=oldX*SIZE+SIZE+1+COLOFF -2;
  409.     ey=oldY*SIZE+SIZE+1+ROWOFF        -2;
  410.  
  411.     if (ex<x) swapint(ex,x);
  412.     if (ey<y) swapint(ey,y);
  413.  
  414.     setcolor(col);
  415.     rectangle(x,y,ex+SIZE,ey+SIZE);
  416.   };
  417. };
  418.  
  419. void onblk()
  420. {
  421.   putblk(15);
  422. };
  423.  
  424. void offblk()
  425. {
  426.   putblk(00);
  427. };
  428.  
  429.  
  430.  
  431. void rim()
  432. {
  433.   int x1,y1;
  434.   int x2,y2;
  435.  
  436.   x1=8*COLS *SIZE+SIZE+1+COLOFF-2;
  437.   y1=ROWS   *SIZE+SIZE+1+ROWOFF     -2;
  438.  
  439.   x2=          SIZE+1+COLOFF-2;
  440.   y2=          SIZE+1+ROWOFF     -2;
  441.  
  442.   setcolor(15);
  443.   rectangle(x1+1,y1+1,x2-1,y2-1);
  444. };
  445.  
  446.  
  447.  
  448. void cleardat()
  449. {
  450.   int i,j;
  451.  
  452.  
  453.   offblk();
  454.   blockon=0;
  455.  
  456.   clearviewport();
  457.   rim();
  458.  
  459.   for(i=0;i<COLS;i=i+2){
  460.     for(j=0;j<ROWS;j=j+3){
  461.       OLD_DATA[i][j] = 0;
  462.       NEW_DATA[i][j] = 0;
  463.     };
  464.   };
  465. };
  466.  
  467.  
  468.  
  469. void randdata()
  470. {
  471.   int i,j;
  472.   for(i=0;i<COLS;i=i+1){        
  473.     for(j=0;j<ROWS;j=j+1){
  474.       OLD_DATA[i][j] = (rand() % 256)& 0xFF;
  475.       NEW_DATA[i][j] = OLD_DATA[i][j] ^ 0xFF;
  476.     };
  477.   };
  478. };
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486. void neighbor(funct)
  487.   int funct(int);
  488. {
  489.   int row_before, row_here, row_after;
  490.   int col_here, shiftsize;
  491.   int bits_before, bits_here, bits_after;
  492.   int col_mod, bitpos;
  493.   int mask;
  494.   int newmod;    /* value of current row,col */
  495.  
  496.   row_before = ROWS-1;
  497.   row_here = 0;
  498.   row_after = 1;
  499.  
  500. nextrow:
  501.   /* load up first 9 bits to be the last 1 and the leftmost 8 */
  502.   bits_before = ( (OLD_DATA[0][row_before]) <<1) | ( 1&( (OLD_DATA[COLS-1][row_before])>>7 ) );
  503.   bits_here   = ( (OLD_DATA[0][row_here]) <<1)   | ( 1&( (OLD_DATA[COLS-1][row_here])>>7     ) );
  504.   bits_after  = ( (OLD_DATA[0][row_after]) <<1)  | ( 1&( (OLD_DATA[COLS-1][row_after])>>7  ) );
  505.  
  506.  
  507.   col_here = 0; /* where we just read a byte */
  508.   shiftsize = 9;
  509.  
  510.   col_mod  = 0; /* where we are changing bits */
  511.   bitpos = 1;
  512.   newmod = OLD_DATA[col_here][row_here];
  513.  
  514.  
  515. innerloop:
  516.   mask = ((7&bits_before)<<6) | ((7&bits_here)<<3) | (7&bits_after);
  517.   if (funct(mask)) {
  518.     newmod = newmod ^ bitpos; /* xor */
  519.   };
  520.  
  521.  
  522.   bits_before = bits_before/2;
  523.   bits_here   = bits_here/2;
  524.   bits_after  = bits_after/2;
  525.   shiftsize = shiftsize-1;
  526.   bitpos = bitpos<<1;
  527.  
  528.  
  529.   if (bitpos==256) {
  530.     bitpos=1;
  531.     NEW_DATA[col_mod][row_here] = newmod;
  532.     col_mod++;
  533.     if (col_mod==COLS) {
  534.       goto quitinner;
  535.     };
  536.     newmod = OLD_DATA[col_mod][row_here];
  537.   };
  538.  
  539.   if (shiftsize == 3) {
  540.     shiftsize = 11; /* shiftsize+8 = 3+8 = 11 */
  541.  
  542.     col_here++;
  543.     if (col_here==COLS) col_here=0;
  544.  
  545.     bits_before = bits_before | (OLD_DATA[col_here][row_before]<<3);
  546.     bits_here    = bits_here   | (OLD_DATA[col_here][row_here]<<3);
  547.     bits_after    = bits_after  | (OLD_DATA[col_here][row_after]<<3);
  548.   };
  549.  
  550.   goto innerloop;
  551.  
  552.  
  553. quitinner:
  554.   row_before++;
  555.   row_here++;
  556.   row_after++;
  557.   if (row_before==ROWS) row_before=0;
  558.   if (row_after==ROWS)    row_after=0;
  559.   if (row_here!=ROWS)  goto nextrow;
  560.  
  561. };
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571. /* turn cursor pointer on and off */
  572. void putptr(col)
  573.   int col;
  574. {
  575.   int x,y;
  576.   x=oldX*SIZE+SIZE+1+COLOFF;
  577.   y=oldY*SIZE+SIZE+1+ROWOFF;
  578.  
  579.   putpixel(x,y,col);
  580.   putpixel(x+1,y+1,col);
  581.   putpixel(x+1,y,col);
  582.   putpixel(x,y+1,col);
  583. };
  584.  
  585. void onptr()
  586. {
  587.   putptr(15);
  588. };
  589.  
  590. void offptr()
  591. {
  592.   putptr(00);
  593. };
  594.  
  595.  
  596.  
  597.  
  598. /* update editing pointer */
  599. void updpointer()
  600. {
  601.   static period=0;
  602.  
  603.   if( (oldX==curX) && (oldY==curY) ){
  604.     period = (period+1) % 64;
  605.     if (period & 32) {
  606.       offptr();
  607.     }else{
  608.       onptr();
  609.     };
  610.   }else{
  611.  
  612.     offptr();
  613.     offblk();
  614.  
  615.     curX=(curX+COLS*8) % (COLS*8);
  616.     curY=(curY+ROWS) % ROWS;
  617.     oldX=curX;
  618.     oldY=curY;
  619.     onptr();
  620.     onblk();
  621.   };
  622.  
  623. };
  624.  
  625.  
  626.  
  627.  
  628.  
  629. void eachunit(funct)
  630.   void funct(int old, int new);
  631. {
  632.   int row_here;
  633.   int bits_old;
  634.   int bits_new;
  635.   int col_mod, bitpos;
  636.  
  637.   row_here = 0;
  638.  
  639. nextrow:
  640.   col_mod  = 0; /* where we are checking bits */
  641.  
  642.  
  643.   bits_old = OLD_DATA[col_mod][row_here];
  644.   bits_new = NEW_DATA[col_mod][row_here];
  645.   bitpos = 1;
  646.  
  647.  
  648. innerloop:
  649.   funct(bitpos & bits_old, bitpos & bits_new);
  650.   bitpos = bitpos<<1;
  651.  
  652.   if (bitpos==256) {
  653.     /* remember that the screen has been updated for this byte */
  654.     OLD_DATA[col_mod][row_here] = NEW_DATA[col_mod][row_here];
  655.  
  656.     bitpos=1;
  657.     col_mod++;
  658.     if (col_mod==COLS) {
  659.       goto quitinner;
  660.     };
  661.     bits_old = OLD_DATA[col_mod][row_here];
  662.     bits_new = NEW_DATA[col_mod][row_here];
  663.   };
  664.  
  665.   goto innerloop;
  666.  
  667.  
  668. quitinner:
  669.   updpointer();
  670.   row_here++;
  671.   if (row_here!=ROWS)  goto nextrow;
  672.  
  673. };
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680. void turnon(x,y)
  681.   int x,y;
  682. {
  683.   /* if (! getpixel(x,y) ){ */
  684.     setcolor(15);
  685.     rectangle(x,y,x+SIZE-2,y+SIZE-2);
  686.   /* }; */
  687. };
  688.  
  689. void turnoff(x,y)
  690.   int x,y;
  691. {
  692.   /* if (getpixel(x,y) ){ */
  693.     setcolor(00);
  694.     rectangle(x,y,x+SIZE-2,y+SIZE-2);
  695.   /* }; */
  696. };
  697.  
  698.  
  699.  
  700.   static dump_col;
  701.   static dump_row;
  702. int dump(int old, int new)
  703. {
  704.   dump_col+=SIZE;
  705.   if (dump_col==COLS*8*SIZE+SIZE+COLOFF) {
  706.     dump_col=SIZE+COLOFF;
  707.     dump_row+=SIZE;
  708.   };
  709.  
  710.   if (old != new) {
  711.     if (new) {
  712.       turnon(dump_col,dump_row);
  713.     }else{
  714.       turnoff(dump_col,dump_row);
  715.     };
  716.   };
  717.  
  718.   return(0);
  719. };
  720.  
  721.  
  722. void display()
  723. {
  724.   dump_col=COLOFF;
  725.   dump_row=SIZE+ROWOFF;
  726.   eachunit(dump);
  727. };
  728.  
  729.  
  730.  
  731.  
  732.  
  733. int change(int dat)
  734. {
  735.   int ct=0; /* count */
  736.  
  737.   if ((dat&0x100)!=0) ct++;
  738.   if ((dat&0x80)!=0) ct++;
  739.   if ((dat&0x40)!=0) ct++;
  740.  
  741.   if ((dat&0x20)!=0) ct++;
  742.   if ((dat&0x08)!=0) ct++;
  743.  
  744.   if ((dat&0x04)!=0) ct++;
  745.   if ((dat&0x02)!=0) ct++;
  746.   if ((dat&0x01)!=0) ct++;
  747.  
  748.   if ( (dat&0x10)!=0 ) {      /* if currently a 1 */
  749.     if (ct<2) return(1);
  750.     if (ct>3) return(1);
  751.   }else{            /* if currently a 0 */
  752.     if (ct==3) return(1);
  753.   };
  754.   return(0);
  755. };
  756.  
  757.  
  758. void generation()
  759. {
  760.   neighbor(change);
  761. };
  762.  
  763.  
  764.  
  765. /* routine to setup flags to set or clear the cursor's bit */
  766. void m_celltoggle()
  767. {
  768.   int x,y;
  769.   int mask;
  770.  
  771.   x=oldX /8;
  772.   mask = 1 << (oldX%8);
  773.   y=oldY;
  774.  
  775.     NEW_DATA[x][y] = NEW_DATA[x][y] ^ mask;
  776.     if( (OLD_DATA[x][y] & mask) == (NEW_DATA[x][y] & mask) ) {
  777.       OLD_DATA[x][y] = OLD_DATA[x][y] ^ mask;
  778.     };
  779. };
  780.  
  781.  
  782.  
  783.  
  784. static int steps=-1;
  785. static int mod;    /* flag for screen update */
  786.  
  787.  
  788.  
  789.  
  790. void m_beginblk()
  791. {
  792.    if (blockon){
  793.      offblk();
  794.      blockon=1; /* change from 2 to 1 */
  795.    };
  796.    blockX=curX;
  797.    blockY=curY;
  798.    blockon=1-blockon; /* invert 1 or 2 <--> 0 */
  799. };
  800.  
  801.  
  802.  
  803.  
  804. void m_unblock()
  805. {
  806.  
  807.    if (blockon) offblk();
  808.    blockon=0;
  809.    /*
  810.    curX=blockX;     this doesn't work for blockon==2
  811.    curY=blockY;
  812.    */
  813. };
  814.  
  815. void m_pause()
  816. {
  817.    steps=0;
  818. };
  819.  
  820. void m_run()
  821. {
  822.   steps=-1;
  823. };
  824.  
  825.  
  826. void m_step()
  827. {
  828.   steps=1;
  829. };
  830.  
  831.  
  832. void m_fill()
  833. {
  834.    mod=1;
  835.    fillblk();
  836. };
  837.  
  838.  
  839. void m_empty()
  840. {
  841.    mod=1;
  842.    emptyblk();
  843. };
  844.  
  845. void m_reverse()
  846. {
  847.    mod=1;
  848.    reverseblk();
  849. };
  850.  
  851.  
  852. /* enter the 'read' file name's data into the cell plane */
  853. void m_usefile()
  854. {
  855.   mod=1;
  856.   enterblk();
  857. };
  858.  
  859. void m_readdisk()
  860. {
  861.   if (blockon) offblk();
  862.   mod=1;
  863.   readblk();
  864. };
  865.  
  866.  
  867. void m_writedisk()
  868. {
  869.   if (blockon) offblk();
  870.    mod=1;
  871.    writeblk();
  872. };
  873.  
  874. void m_clear()
  875. {
  876.    cleardat();
  877. };
  878.  
  879.  
  880. void m_seed()
  881. {
  882.    mod=1;
  883.    cleardat();
  884.    randomize();
  885.    randdata();
  886. };
  887.  
  888. void m_quit()
  889. {
  890.    closegraph();
  891.    exit(256);
  892. };
  893.  
  894. void m_go_up()
  895. {
  896.   curY=curY-1;
  897. };
  898.  
  899. void m_go_down()
  900. {
  901.   curY=curY+1;
  902. };
  903.  
  904. void m_go_left()
  905. {
  906.   curX=curX-1;
  907. };
  908.  
  909. void m_go_right()
  910. {
  911.   curX=curX+1;
  912. };
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920. void m_exit()
  921. {    
  922.   closegraph();
  923.   exit(0);
  924. };
  925.  
  926. void mystep()
  927. {
  928.   if (steps) {
  929.     temp_ptr = old_ptr;
  930.     old_ptr = new_ptr;
  931.     new_ptr = temp_ptr;
  932.     temp_ptr = 0;
  933.     generation();
  934.     if (steps != -1) steps--;
  935.   };
  936.   display();
  937.   updpointer();
  938.  
  939. };
  940.  
  941.  
  942.  
  943. void user_menus()
  944. {
  945.  
  946.  
  947. #define RIGHT 1
  948. #define LEFT 2
  949. #define UP 3
  950. #define DOWN 4
  951. #define QUITTER 5
  952.  
  953.  
  954.   hot_key(RIGHT,m_go_right);
  955.   hot_key(LEFT,m_go_left);
  956.   hot_key(UP,m_go_up);
  957.   hot_key(DOWN,m_go_down);
  958.   hot_key(QUITTER,m_exit);
  959.  
  960.   def_fkey(RIGHT,     "[SHIFT-ARROW-RIGHT]",   "<RIGHT>");
  961.   def_fkey(LEFT,      "[SHIFT-ARROW-LEFT]",    "<LEFT>");
  962.   def_fkey(UP,        "[SHIFT-ARROW-UP]",      "<UP>");
  963.   def_fkey(DOWN,      "[SHIFT-ARROW-DOWN]",    "<DOWN>");
  964.   def_fkey(QUITTER,   "[ALT-Q]",               "<QUIT>");
  965.  
  966.   wait_key(updpointer); /* FLASH GRAPHICS CURSOR WHEN WAITING FOR KEYS */
  967.  
  968.  
  969.   /* the 'root' menu defaults to horizontal */
  970.   def_submenu('Q',"Quit","  ARE YOU SURE YOU WANT TO QUIT?  ");
  971.     def_entry('Y',"Yes",m_exit);
  972.     def_entry('N',"No",nofn);
  973.   endef_submenu("Quit");
  974.  
  975.   def_submenu('B',"Block","--cell block menu--"); /* vertical */
  976.  
  977.     def_entry('B',   "Begin block",     m_beginblk);
  978.     def_entry('U',   "Unbegin block",   m_unblock);
  979.  
  980.     def_submenu('D',"Disk","-------Blocks-------");
  981.       def_entry('W',   "Write box to disk",        m_writedisk);
  982.       def_entry('R',   "Read stamp from disk",     m_readdisk);
  983.       def_entry('S',   "Stamp onto cell plane",    m_usefile);
  984.     endef_submenu("Disk");         menu_horizontal();
  985.    /* build this 'disk' menu horizontal -- the others default to vertical */
  986.  
  987.  
  988.     def_entry('F',   "Fill block",            m_fill);
  989.     def_entry('E',   "Empty block",           m_empty);
  990.     def_entry('R',   "Reverse cells",         m_reverse);
  991.  
  992.   endef_submenu("Block");  
  993.  
  994.   def_entry('P',   "Pause",             m_pause);
  995.   def_entry('S',   "Step",              m_step);
  996.   def_entry('R',   "Run",               m_run);
  997.   def_entry('S',   "Seed the cell plane",   m_seed);
  998.  
  999.   def_submenu('C',"Cell menu","---Cell manipulations---");
  1000.     def_entry('C',   "Cell value toggle", m_celltoggle);
  1001.     def_entry('R',   "Move cursor right", m_go_right);
  1002.     def_entry('L',   "Move cursor left",  m_go_left);
  1003.     def_entry('U',   "Move cursor up",    m_go_up);
  1004.     def_entry('D',   "Move cursor down",  m_go_down);
  1005.   endef_submenu("Cell menu");
  1006.  
  1007.  
  1008.  
  1009. };
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016. void main()
  1017. {
  1018.   long int menukey,helpkey;
  1019.  
  1020.  
  1021.   initgr();    /* init graphics */
  1022.   menu_init();
  1023.  
  1024.   cleardat();
  1025.   randomize();
  1026. /*  randdata(); */
  1027.  
  1028.   boxtext(0,0,"Press '?' for help.");
  1029.  
  1030.   menukey = lkeyof('/');
  1031.   helpkey = lkeyof('?');
  1032.  
  1033.  
  1034.   while (1) {
  1035.     menu_run();
  1036.     while (bioskey(1)) {
  1037.       menu_run();
  1038.     };
  1039.  
  1040. /* want this any more ? */
  1041.     if (mod && (steps!=0)) {
  1042.       display();
  1043.       mod=0;
  1044.     };
  1045.  
  1046.     do {
  1047.       while( !keyready() ){
  1048.         mystep();
  1049.  
  1050.       };  
  1051.       call_for_key(rootmenu);
  1052.     } while (  (menukey != the_key)  & (helpkey != the_key)  );
  1053.  
  1054.   };
  1055.  
  1056.  
  1057.   m_exit();
  1058. };
  1059.  
  1060.  
  1061.