home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 102_01 / nlife.c < prev    next >
Text File  |  1984-02-12  |  7KB  |  273 lines

  1. /* Yet another LIFE simulator                9/14/80 Steve Ward
  2.  * Uses H19 graphics, 25th line to give a 50x80 field.
  3.  * Usage:
  4.  *    nlife <filename>        default is "nlife.dat"
  5.  *
  6.  * Commands:
  7.  *    CURSOR MOTION:    ^F, ^N, ^P, ^H, TAB, RETURN, keypad arrows, 0.
  8.  *    SET POINTS:    period, keypad 5 (XORs)
  9.  *    DELETE:        DELETE key.
  10.  *    SAVE:        A-Z save relative to cursor in one of 26 slots.
  11.  *    GET:        a-z fetch (XOR) relative to cursor.
  12.  *    MISC:        ^X write out A-Z slots in file and exit.
  13.  *            ^C quit, no file output.
  14.  *            ENTER (keypad): step one simulation step.
  15.  *            LINEFEED: run until character typed.
  16.  *            ^L redisplay screen.
  17.  *            ^Z clear LIFE space.
  18.  *            KEY 9:  Rotate about cursor
  19.  *            KEY 7:  Flip about cursor
  20.  *            KEY 1:  Random 5x5 configuration around cursor
  21.  *            KEY 3:  Random 10x10 configuration around cursor
  22.  *
  23.  * N.B: Left/right, top/bottom edges of 50x80 field are adjacent.
  24.  */
  25.  
  26. #define    XSIZE    80    /* Horizontal size            */
  27. #define    YSIZE    50    /* Vertical size            */
  28. #define    LIVE    0x10    /* Live cell flag.            */
  29.  
  30. int  LStep();        /* Assy-lang update routine.        */
  31. int  Fixup();
  32. int  Forall();
  33.  
  34. int    CurX, CurY;    /* Current cell coordinates.        */
  35. char    DpyX, DpyY;    /* Current (raw) display coordinates    */
  36.  
  37. char *row[YSIZE];        /* ptrs to each row.        */
  38.  
  39. int    Rand1, Rand2, Rand3;    /* Random number seeds        */
  40. char    RanFlag;        /* Flag: initialize randoms    */
  41.  
  42. struct {
  43.  char bits[(XSIZE*YSIZE)/8]; } Memory[27];
  44.  
  45. char space[XSIZE*YSIZE];    /* the universe matrix        */
  46.  
  47. MoveTo(x,y)
  48.  {    puts("\033Y"); putchar(y+32); putchar(x+32); }
  49.  
  50. Split()
  51.  {    puts("\033z"); exit(); }
  52.  
  53. /* Update a point on the screen:  assumes graphics mode.
  54.  */
  55.  
  56. Updpy(x, y)
  57.  {    char key, dpyy;
  58.     dpyy = y & 0xFE;
  59.     MoveTo(x, dpyy>>1);
  60.     key = (((LIVE & (row[dpyy | 1])[x]))? 2:0) |
  61.             (((LIVE & (row[dpyy])[x]))? 1 : 0);
  62.     switch(key) {
  63.         case 0:    ReVid(0); key = ' '; break;
  64.         case 3: ReVid(1); key = ' '; break;
  65.         case 1:    ReVid(0); key = 'p'; break;
  66.         case 2:    ReVid(1); key = 'p'; break; }
  67.     putchar(key); }
  68.  
  69. /* Change a cell contents:
  70.  */
  71.  
  72. CCell(x, y)
  73.  {    Updpy(x, y); }
  74.  
  75. /* Set/clear reverse video mode:
  76.  */
  77.  
  78. ReVid(flag)
  79.  {    puts((flag != 0)? "\033p" : "\033q"); }
  80.  
  81.  
  82. /*
  83.     Blink the cursor, waiting for input, and return whatever
  84.     was typed:
  85. */
  86.  
  87. int Blink()
  88.  {    char *it, save, i;    int delay;
  89.     it = (row[CurY])+CurX;
  90.     save = *it;
  91.     for (;;i++)
  92.      { switch (i &= 3)
  93.         { case 0:    *it = 0; break;
  94.           case 2:    *it = LIVE; break;
  95.           case 1:
  96.           case 3:    *it = save; break; }
  97.        Updpy(CurX, CurY);
  98.        for (delay=200; delay--; Rand1++)
  99.         if (kbhit()) {  i = getchar();
  100.                 *it = save; Updpy(CurX, CurY); RanFlag=1;
  101.                 return i; }}}
  102.  
  103. Move(dx, dy)
  104.  {    if ((CurX += dx) >= XSIZE) CurX = 0;
  105.     if (CurX < 0) CurX = XSIZE-1;
  106.     if ((CurY += dy) >= YSIZE) CurY = 0;
  107.     if (CurY < 0) CurY = YSIZE-1; }
  108.  
  109. /* Put a random n by n configuration at cursor:
  110.  */
  111.  
  112. RandConf(n)
  113.  {    char x,y,i,j;
  114.     x = CurX-(n>>1);
  115.     y = CurY-(n>>1);
  116.     if (RanFlag) nrand(-1, Rand1, Rand2, Rand3); Rand3=Rand2; Rand2=Rand1;
  117.     RanFlag=0;
  118.     for (j=0; j<=n; j++)
  119.      for (i=0; i<=n; i++) if (!(nrand(1) & 0x30))
  120.                 { (row[j+y])[i+x] ^= LIVE; UpDpy(i+x,j+y); }}
  121.  
  122. Edit()
  123.  {    char ch, *cc;
  124.     CurX = XSIZE>>1;
  125.     CurY = YSIZE>>1;
  126.     puts("\033F");
  127.     for (;;)
  128.      {  switch(ch = Blink())
  129.          {    case '.':
  130.         case '.':    (row[CurY])[CurX] = LIVE;
  131.                 Updpy(CurX++, CurY);
  132.         case ' ':
  133.         case '6':
  134.         case 'F'-64:    Move(1,0); continue;
  135.         case '4':
  136.         case 'H'-64:    Move(-1,0); continue;
  137.         case '7':    Flip(); continue;
  138.         case '9':    Rotate(); continue;
  139.         case 'X'-64:    return;
  140.         case '5':    (row[CurY])[CurX] ^= LIVE; continue;
  141.         case 0177:    Move(-1,0);
  142.                 (row[CurY])[CurX] = 0;
  143.                 Updpy(CurX, CurY); continue;
  144.         case '\r':    CurX = 0; Move(0,1); continue;
  145.         case '8':
  146.         case 'P'-64:    Move(0,-1); continue;
  147.         case '2':
  148.         case 'N'-64:    Move(0,1); continue;
  149.         case '\n':    while (!kbhit()) LStep(space); continue;
  150.         case '\\':    while (1) {    ch = 100; RandConf(5);
  151.                         while (ch--)
  152.                          { if (kbhit()) goto endit;
  153.                            LStep(space); }}
  154.                 endit: continue;
  155.         case 'Z'-64:    clear(); continue;
  156.         case 'L'-64:    display(); continue;
  157.         case 'C'-64:    Split();
  158.         case '\t':    CurX = (CurX + 8) & 0xF8;
  159.                 Move(0,0); continue;
  160.         case '/':    LStep(space); continue;
  161.         case '0':    if (CurX|CurY) CurX = CurY = 0;
  162.                 else { CurX=(XSIZE>>1); CurY=(YSIZE>>1); }
  163.                 continue;
  164.         case '1':    RandConf(5); continue;
  165.         case '3':    RandConf(10); continue;
  166.         default:    if ((ch >= 'a') && (ch <= 'z'))
  167.                  { Unsave(&(Memory[ch-'a'])); continue; }
  168.                 if ((ch >= 'A') && (ch <= 'Z'))
  169.                  { Save(&(Memory[ch-'A'])); continue; }
  170.                 putchar(7); continue;
  171.         }}
  172.  }
  173.  
  174. main(argc,argv)
  175.  char **argv;
  176.  {    char *cc, x, y, *name;
  177.     int FileSize, fileid;
  178.     FileSize = (26*(XSIZE/8)*YSIZE + 127) >> 7; /* File size, in blocks */
  179.     setmem(Memory, 26*(XSIZE/8)*YSIZE, 0);
  180.  
  181.     fileid = -1;
  182.     name = "nlife.dat";
  183.     if (argc > 1) name = argv[1];
  184.     if ((fileid = open(name, 2)) == -1)
  185.         { puts("Creating file "); puts(name); puts("\r\n");
  186.           fileid = creat(name); }
  187.     else { seek(fileid,0,0); read(fileid, Memory, FileSize); }
  188.  
  189.     cc = space;
  190.     for (y=0; y<YSIZE; y++)
  191.      { row[y] = cc; cc += XSIZE; }
  192.  
  193.     puts("\033x1\033x5");
  194.     clear();
  195.     Edit();
  196.     if (fileid != -1)
  197.      { seek(fileid,0,0); write(fileid, Memory, FileSize); close(fileid); }
  198.     Split(); }
  199.  
  200. clear()
  201. {    puts("\033H\033J\033Y8 \033K");
  202.     setmem(space,(XSIZE*YSIZE),0);
  203.     CurX = (XSIZE>>1); CurY = (YSIZE>>1); }
  204.  
  205.  
  206. /* Display the current generation */
  207.  
  208. display()
  209. {    char x, y, *cc;
  210.     cc = space;
  211.     puts("\033F\033Y8 \033K\033H\033J");
  212.     for (y=0; y<YSIZE; y += 2)
  213.      { for (x=0; x<XSIZE; x++, cc++)
  214.         if ((*cc | (cc[XSIZE])) & LIVE) Updpy(x,y);
  215.        cc += XSIZE; }}
  216.  
  217. Unsave(where)
  218.  char *where;
  219.  {    char *p, bit, x, y;
  220.     bit = 0; where--; y = CurY;
  221.     do {    p = row[y] + (x = CurX);
  222.         do {    if (!(bit <<= 1)) { bit = 1; where++; }
  223.             if (bit & *where) { *p ^= LIVE; Updpy(x,y); }
  224.             p++;
  225.             if (++x == XSIZE) { x = 0; p = row[y]; }
  226.            } while (x != CurX);
  227.         if (++y == YSIZE) y = 0;
  228.        } while (y != CurY); }
  229.  
  230. Save(where)
  231.  char *where;
  232.  {    char *p, bit, x, y;
  233.     bit = 0; where--; y = CurY;
  234.     do {    p = row[y] + (x = CurX);
  235.         do {    if (!(bit <<= 1)) { bit = 1; *++where = 0; }
  236.             if (*p) *where |= bit;
  237.             p++;
  238.             if (++x == XSIZE) { x = 0; p = row[y]; }
  239.            } while (x != CurX);
  240.         if (++y == YSIZE) y = 0;
  241.        } while (y != CurY); }
  242.  
  243. char *Cell();
  244.  
  245. Rot1(x,y)
  246.  {    *Cell(space, CurX+CurY-y, CurY+x-CurX) |= (LIVE>>1); }
  247.  
  248. Rotate()
  249.  {    Forall(space, &Rot1); Fixup(space); }
  250.  
  251. Flip1(x,y)
  252.  {    *Cell(space, CurX+y-CurY, CurY+x-CurX) |= (LIVE>>1); }
  253.  
  254. Flip()
  255.  {    Forall(space, &Flip1); Fixup(space); }
  256.  
  257. getchar()
  258. {
  259.     char c;    
  260.     return bios(3);
  261. }
  262.  
  263. putchar(c)
  264. char c;
  265. {
  266.     return bios(4,c);
  267. }
  268.  
  269. kbhit()
  270. {
  271.     return bios(2);
  272. }
  273.