home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume17 / clife / part01 next >
Internet Message Format  |  1991-03-21  |  9KB

  1. From: jek5036@ultb.isc.rit.edu (J.E. King)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i061:  clife - Curses based Life simulator, Part01/01
  4. Message-ID: <1991Mar21.210335.11867@sparky.IMD.Sterling.COM>
  5. Date: 21 Mar 91 21:03:35 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 33523710 56f0f4dc 69397a9c d9920629
  8.  
  9. Submitted-by: J.E. King <jek5036@ultb.isc.rit.edu>
  10. Posting-number: Volume 17, Issue 61
  11. Archive-name: clife/part01
  12.  
  13. This is called clife, or a curses implementation life simulator. It
  14. simulates the life 'function' which is described in the manual page.
  15. Basically it could be thought of as a game, but it isn't.  That's 
  16. why the manual page is under clife.6.
  17.  
  18. Jim King, (jek5036@ultb.isc.rit.edu)
  19.  
  20. -- cut here -- cut here -- cut here -- cut here -- cut here -- cut here --
  21. #!/bin/sh
  22. # to extract, remove the header and type "sh filename"
  23. if `test ! -s ./Makefile`
  24. then
  25. echo "writing ./Makefile"
  26. cat > ./Makefile << '\End\Of\Shar\'
  27. CFLAGS        = -O
  28. DEST          = .
  29. MANDEST       = /usr/man/man6
  30. EXTHDRS          = /usr/include/curses.h \
  31.         /usr/include/sgtty.h \
  32.         /usr/include/signal.h \
  33.         /usr/include/stdio.h \
  34.         /usr/include/sys/ioctl.h \
  35.         /usr/include/sys/ttychars.h \
  36.         /usr/include/sys/ttydev.h \
  37.         /usr/include/sys/ttyio.h \
  38.         /usr/include/time.h
  39. HDRS          =
  40. LDFLAGS          = -O
  41. LIBS          = -lcurses -ltermlib
  42. LINKER          = cc
  43. MAKEFILE      = Makefile
  44. OBJS          = clife.o
  45. PRINT          = lpr
  46. PROGRAM          = clife
  47. SRCS          = clife.c
  48.  
  49. all:        $(PROGRAM)
  50.  
  51. $(PROGRAM):     $(OBJS)
  52.         @echo -n "Loading $(PROGRAM) ... "
  53.         @$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
  54.         @echo "done"
  55.  
  56. clean:;        @rm -f $(OBJS)
  57.  
  58. depend:;    @mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
  59.  
  60. index:;        @ctags -wx $(HDRS) $(SRCS)
  61.  
  62. install:    $(PROGRAM)
  63.         @echo Installing $(PROGRAM) in $(DEST)
  64.         @install -s $(PROGRAM) $(DEST)
  65.         @echo Copying manual pages...
  66.         @cp clife.6 $(MANDEST)
  67.         @chmod 644 $(MANDEST)/clife.6
  68.  
  69. print:;        @$(PRINT) $(HDRS) $(SRCS)
  70.  
  71. program:        $(PROGRAM)
  72.  
  73. tags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
  74.  
  75. update:        $(DEST)/$(PROGRAM)
  76.  
  77. $(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
  78.         @make -f $(MAKEFILE) DEST=$(DEST) 
  79. ###
  80. clife.o: /usr/include/signal.h /usr/include/time.h /usr/include/stdio.h \
  81.     /usr/include/curses.h /usr/include/sgtty.h /usr/include/sys/ioctl.h \
  82.     /usr/sys/h/ttychars.h /usr/sys/h/ttydev.h /usr/sys/h/ttyio.h \
  83.     /usr/sys/h/sgtty.h /usr/include/sys/ttychars.h \
  84.     /usr/include/sys/ttydev.h /usr/include/sys/ttyio.h
  85. \End\Of\Shar\
  86. else
  87.   echo "will not over write ./Makefile"
  88. fi
  89. if `test ! -s ./clife.6`
  90. then
  91. echo "writing ./clife.6"
  92. cat > ./clife.6 << '\End\Of\Shar\'
  93. .TH clife 6
  94. .SH Name
  95. clife \- Life simulation using curses
  96. .SH Syntax
  97. .B clife
  98. \fI[-d] [-p]\fR
  99. .SH Description
  100. The
  101. .PN clife
  102. program is a simulator which has been around for quite some time.
  103. The screen is set up, with random 'people' on the screen.  Each
  104. person is represented by a '*'.  The rules are simple:  If there are
  105. three people around any given square, a person is born there.  If
  106. there are only two people around any given square, then it does not
  107. change.  Any other number around a square kills the person there.
  108. .PP
  109. The clife (which stands for curses life) simulator will produce certain
  110. distinguishable patterns attributable to the life equation.
  111. .SH Options
  112. The
  113. .PN \-d
  114. option allows you to draw your own pattern on the screen
  115. and run it through the simulator.  This is done by moving around the
  116. screen with the arrow keys and using space to put a person in the
  117. square you are currently over, or if there is a person there already,
  118. kill it.
  119.  
  120. The
  121. .PN \-p
  122. option will print out information about the life cycles on the bottom
  123. of the screen.
  124. .SH Author
  125. Jim King, (jek5036@ritvax.isc.rit.edu)
  126. \End\Of\Shar\
  127. else
  128.   echo "will not over write ./clife.6"
  129. fi
  130. if `test ! -s ./clife.c`
  131. then
  132. echo "writing ./clife.c"
  133. cat > ./clife.c << '\End\Of\Shar\'
  134. /*
  135.  * clife.c - curses life simulator.  Translated from Pascal to C implementing
  136.  *           curses Oct 1988 by pulsar@lsrhs, not jek5036@ritvax.isc.rit.edu
  137.  *
  138.  *      V2 - Draw your own pattern then 'life' it.
  139.  */
  140.  
  141. #include <signal.h>
  142. #include <time.h>
  143. #include <stdio.h>
  144. #include <curses.h>
  145.  
  146.                 /* a value of -1 will make it go forever */
  147.                 /* a value of 0 will make it exit immed. */
  148. #define    REPSTOP        -1    /* number of repetitions before stop */
  149.  
  150. int    present[23][80],    /* screen 1 cycle ago */
  151.     past[23][80],        /* screen this cycle */
  152.     total,            /* total # of changes */
  153.     icnt,            /* counter to check for repetition */
  154.     maxrow = 22,        /* some defines to represent the screen */
  155.     maxcol = 79,
  156.     minrow = 0,
  157.     mincol = 0,
  158.     pri = 0,        /* flag for printing stats on bottom line */
  159.     draw = 0,        /* flag for drawing your own screen */
  160.     i, j, k,        /* loop counters */
  161.     cycle,            /* current cycle # */
  162.     changes,        /* # of changes this cycle (live + die) */
  163.     die,            /* number of deaths this cycle */
  164.     live;            /* number of births this cycle */
  165.  
  166. WINDOW    *mns,                /* Main Screen */
  167.     *info;                /* Bottom line */
  168.  
  169. /*
  170.  * cleanup - cleanup then exit
  171.  */
  172.  
  173. cleanup()
  174. {
  175.     move(23, 0);        /* go to bottom of screen */
  176.     refresh();        /* update cursor */
  177.     exit(1);        /* exit */
  178. }
  179.  
  180. /*
  181.  * initialize - init windows, variables, and signals
  182.  */
  183.  
  184. initialize()
  185. {
  186.     srandom(getpid());    /* init random seed */
  187.     initscr();        /* init curses */
  188.     signal(SIGINT, cleanup);    /* catch ^C */
  189.     mns = newwin(maxrow, maxcol, 0, 0);    /* new window */
  190.     scrollok(mns, FALSE);
  191.     info = newwin(1, 80, 23, 0);
  192.     scrollok(info, FALSE);
  193.     wclear(mns);
  194.     wclear(info);
  195.     wmove(info, 0, 0);
  196.     wprintw(info, "Life V2 by Jim King (pulsar@lsrhs)");
  197.     wrefresh(info);
  198.     sleep(3);
  199.     if (!draw) {        /* if no draw, make random pattern */
  200.         for (j = 0; j < maxrow; j++) {
  201.             for (k = 0; k < maxcol; k++) {
  202.                 present[j][k] = random()%2;
  203.                 if (present[j][k] == 1) changes++, live++;
  204.             }
  205.         }
  206.     }
  207. }
  208.  
  209. /*
  210.  * makscr - make your own screen using arrow keys and space bar
  211.  */
  212.  
  213. makscr()
  214. {
  215.     int    curx, cury;        /* current point on screen */
  216.     char    c;            /* input char */
  217.     
  218.     wclear(info);
  219.     wmove(info, 0, 0);
  220.     wprintw(info, "Use arrow keys to move, space to place / erase, ^D to start");
  221.     wrefresh(info);
  222.     curx = cury = 1;
  223.     wmove(mns, cury-1, curx-1); wrefresh(mns);
  224.     noecho(); crmode();
  225.     for (;;) {
  226.         c = wgetch(mns);
  227.         if (c == '\004')
  228.             break;
  229.         else if (c == ' ') {
  230.             if (present[cury][curx]) {
  231.                 --present[cury][curx];
  232.                 changes++;
  233.                 die++;
  234.                 mvwaddch(mns, cury, curx, ' ');
  235.             } else {
  236.                 ++present[cury][curx];
  237.                 changes++;
  238.                 live++;
  239.                 mvwaddch(mns, cury, curx, '*');
  240.             }
  241.         } else if (c == '\033') {
  242.             wgetch(mns);
  243.             switch(wgetch(mns)) {
  244.                 case 'A':
  245.                     --cury; break;
  246.                 case 'B':
  247.                     ++cury; break;
  248.                 case 'C':
  249.                     ++curx; break;
  250.                 case 'D':
  251.                     --curx; break;
  252.                 default:
  253.                     break;
  254.             }
  255.         }
  256.         if (cury > maxrow) cury = minrow;
  257.         if (cury < minrow) cury = maxrow;
  258.         if (curx > maxcol) curx = mincol;
  259.         if (curx < mincol) curx = maxcol;
  260.         wmove(mns, cury, curx);
  261.         wrefresh(mns);
  262.     }
  263.     wclear(info);
  264. }
  265.  
  266. /* Update rules:  2 or 3 adjacent alive --- stay alive
  267.  *                3 adjacent alive -- dead to live
  268.  *                all else die or stay dead
  269.  */
  270.  
  271. update()    /* Does all mathmatical calculations */
  272. {
  273.     int    howmany, w, x, y, z;
  274.     changes = die = live = 0;
  275.     for (j = 0; j < maxrow; j++) {
  276.         for (k = 0; k < maxcol; k++) {
  277.             w = j-1; x = j+1;
  278.             y = k-1; z = k+1;
  279.  
  280.             howmany = (past[w][y] + past[w][k] + past[w][z] +
  281.                   past[j][y] + past[j][z] + past[x][y] +
  282.                   past[x][k] + past[x][z]);
  283.  
  284.             switch(howmany) {
  285.                 case 0:
  286.                 case 1:
  287.                 case 4:
  288.                 case 5:
  289.                 case 6:
  290.                 case 7:
  291.                 case 8:
  292.                     present[j][k] = 0;
  293.                     if (past[j][k]) changes++, die++;
  294.                     break;
  295.                 case 3:
  296.                     present[j][k] = 1;
  297.                     if (!past[j][k]) changes++, live++;
  298.                     break;
  299.                 default:
  300.                     break;
  301.             }
  302.         }
  303.     }
  304.     if (live == die)
  305.         ++icnt;
  306.     else
  307.         icnt = 0;
  308.  
  309.     if (icnt == REPSTOP)
  310.         cleanup();
  311. }
  312.  
  313. /*
  314.  * print - updates the screen according to changes from past to present
  315.  */
  316.  
  317. print()        /* Updates the screen, greatly improved using curses */
  318. {
  319.     if (pri) {
  320.         wmove(info, 0, 0);
  321.         total += changes;
  322.         wprintw(info, "Cycle %d | %d changes: %d died and %d born & %d total changes", ++cycle, changes, die, live, total);
  323.         wclrtoeol(info);
  324.     }
  325.     for (j = 1; j < maxrow; j++) {
  326.         for (k = 1; k < maxcol; k++) {
  327.             if (present[j][k] != past[j][k] && present[j][k] == 1) {
  328.                 wmove(mns, j, k);
  329.                 wprintw(mns, "*");
  330.             } else if (present[j][k] != past[j][k] && present[j][k] == 0) {
  331.                 wmove(mns, j, k);
  332.                 wprintw(mns, " ");
  333.             }
  334.         }
  335.     }
  336.     if (pri) wrefresh(info);
  337.     wrefresh(mns);
  338. }
  339.  
  340. /*
  341.  * main - main procedure
  342.  */
  343.  
  344. main(ac, av)
  345. int    ac;
  346. char    *av[];
  347. {
  348.     if (ac > 1) {
  349.         for (j = 1; j < ac; j++) {
  350.             switch(av[j][1]) {
  351.                 case 'd':
  352.                     ++draw;
  353.                     break;
  354.                 case 'p':
  355.                     ++pri;
  356.                     break;
  357.                 default:
  358.                     fprintf(stderr, "%s: usage: %s [-d] [-p]\n", av[0]);
  359.                     exit(1);
  360.             }
  361.         }
  362.     }
  363.  
  364.     if (draw)
  365.         printf("User-built screen\n");
  366.     if (pri)
  367.         printf("Print statistics\n");
  368.  
  369.     sleep(2);
  370.  
  371.     initialize();
  372.     if (draw)
  373.         makscr();
  374.  
  375.     for (;;) {
  376.         print();
  377.         for (j = 0; j < maxrow; j++) {
  378.             for (k = 0; k < maxcol; k++)
  379.                 past[j][k] = present[j][k];
  380.         }
  381.         update();
  382.     }
  383. }
  384. \End\Of\Shar\
  385. else
  386.   echo "will not over write ./clife.c"
  387. fi
  388. echo "Finished archive 1 of 1"
  389. exit
  390.  
  391. exit 0 # Just in case...
  392. -- 
  393. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  394. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  395. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  396. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  397.