home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 155_01 / oned.c < prev    next >
Text File  |  1979-12-31  |  9KB  |  297 lines

  1. /* HEADER: xxx.yy;
  2.    TITLE: ONED;
  3.    DATE: 4/30/85;
  4.    DESCRIPTION: "One dimensional cellular automata simulation";
  5.    VERSION: 1.0;
  6.    KEYWORDS: Life, cellular automata, games;
  7.    FILENAME: ONED.C;
  8.    CRC: xxxx;
  9.    SYSTEM: CP/M, Osborne 1;
  10.    COMPILERS: C/80;
  11.    AUTHORS: David L. Fox;
  12.    REFERENCES: AUTHORS: A. K. Dewdney;
  13.          TITLE: "Computer Recreations";
  14.          CITATION: "Scientific American, 252, 18-30(May 1985).";
  15.          AUTHORS: S. Wolfram;
  16.          TITLE: "Computer Software in Science and Mathematics";
  17.          CITATION: "Scientific American, 251, 188-203(September 1984).";
  18.          AUTHORS: S. Wolfram;
  19.          TITLE: "";
  20.          CITATION: "Physical Review Letters, 54, #8, 735-739(1985)."
  21.       ENDREF
  22. */
  23. /* oned.c -- One dimensional cellular automata simulator.
  24.  
  25.     Copyright 1985 by David L. Fox.
  26.     All rights reserved.
  27.     Permission granted for unlimited
  28.     personal and non-commercial use
  29.     provided that this notice is included.
  30. */
  31.  
  32. #include    <stdio.h>
  33. #include    <printf.h>
  34.  
  35. #define    MAXST    10    /* Maximum number of different states. */
  36. #define    MAXNB    10    /* Maximum number of neighboors (to one side). */
  37. #define    UNIVSIZ    250
  38. #define    SCRNSIZ    80    /* Number of characters in one line of display. */
  39.  
  40. /* Osborne 1 graphic characters to represent states. */
  41. char stsym[] = {' ', '\0', '\026', '\015', '\014', '5', '6', '7', '8', '9'};
  42. /* Osborne 1 screen controls (emulate Televideo 912 and 920. */
  43. #define    UPLINE    "\013"        /* Move cursor up one line. */
  44. #define    ERALINE    "\033T"        /* Erase from cursor to end of line. */
  45. #define    GPHST    "\033g"        /* Start display of graphics characters. */
  46. #define    GPHEND    "\033G"        /* End display of graphics characters. */
  47.  
  48. char pgmname[] = "ONED";
  49. char copyright[] = "(c) Copyright 1985 David L. Fox";
  50. char version[] = "1.0";
  51. char univ[2][UNIVSIZ]    /* Arrays for current and next generations. */
  52.     = {0,0,0,0,1,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,0,0,1};
  53. int gen = 0;        /* Generation index in univ. */
  54. int origin = 0;        /* Origin of displayed region. */
  55.  
  56. extern int (*CtlB)();    /* C/80 vectors here when ^B is pressed. */
  57. int restart();        /* Called on ^B interrupt. */
  58. char env[6];        /* Use    #include <setjmp.h>
  59.                 jmp_buf env;
  60.                with a fully UNIX compatable library. */
  61.  
  62. main(argc, argv)
  63. int argc;
  64. char **argv;
  65. {    int ngen;    /* Number of generations. */
  66.     int i, j;
  67.     char line[MAXSTR], *s;
  68.     static struct automaton {
  69.         int nstate;    /* Number of possible states for each cell. */
  70.         int neighb;    /* Number of neighbors on one side. */
  71.         int nexts[(MAXST - 1)*(2*MAXNB + 1) + 1];    /* Next state function. */
  72.     } ca = {2, 2, {0,0,1,0,1,0},};        /* r=2, s=2, code 20 automation. */
  73.     char *fgets();
  74.  
  75.     printf("%s  Version %s\n%s\n", pgmname, version, copyright);
  76.     CtlB = restart;
  77.     setjmp(env);        /* Return here after interrupt. */
  78.     while ((printf(": "), s = fgets(line, MAXSTR, stdin)) != NULL) {
  79.         switch(*s) {
  80.         case 'a':    /* Modify automaton. */
  81.             adisp(&ca);
  82.             break;
  83.         case 'd':    /* Show current state of universe. */
  84.             printf(UPLINE);
  85.             dispst(univ[gen]);
  86.             break;
  87.         case 'e':    /* Edit current state of universe. */
  88.             ued();
  89.             break;
  90.         case 'n': ++s;    /* Do n generations. */
  91.             printf(UPLINE);
  92.             ngen = getval(&s);
  93.             evolve(ngen, &ca);
  94.             break;
  95.         case 'o':    /* Shift origin. */
  96.             switch(*++s) {
  97.             case '=': origin = (getval(&s) + UNIVSIZ) % UNIVSIZ; break;
  98.             case '+': ++s; origin += getval(&s) % UNIVSIZ; break;
  99.             case '-': ++s; origin -= (getval(&s) - UNIVSIZ) % UNIVSIZ; break;
  100.             }
  101.             break;
  102.         case '\n':
  103.             printf(UPLINE);
  104.             evolve(1, &ca); 
  105.             break;
  106.         case 'r':
  107.             ++s;
  108.             if ((ca.neighb = getval(&s)) > MAXNB)
  109.                 ca.neighb = MAXNB;
  110.             break;
  111.         case 's':
  112.             ++s;
  113.             if ((ca.nstate = getval(&s)) > MAXST)
  114.                 ca.nstate = MAXST;
  115.             break;
  116.         case 't':
  117.             if (*++s == '=') {    /* Define transition table by t=code */
  118.                 i = getval(&s);
  119.                 for (j = 0; j <= (ca.nstate - 1)*(2*ca.neighb + 1) + 1; ++j) {
  120.                     ca.nexts[j] = i % ca.nstate;
  121.                     i /= ca.nstate;
  122.                 }
  123.             }
  124.             else {    /* Set members of transition table individually: txx=yy */
  125.                 do {
  126.                     if ((i = getval(&s)) > (ca.nstate-1)*(2*ca.neighb+1)) {
  127.                         printf("total too large\n");
  128.                         i = getval(&s);
  129.                         continue;
  130.                         }
  131.                     if ((j = getval(&s)) < ca.nstate)
  132.                         ca.nexts[i] = j;
  133.                     else
  134.                         printf("illegal state\n");
  135.                 } while (*s);
  136.             }
  137.             break;
  138.         case 'x': exit();
  139.         default: printf("Unknown command: %s\n", s);
  140.         case '?': printf("Command summary\n\n  ?\t\tDisplay this message.\n");
  141.             printf("  a\t\tDisplay automaton\n");
  142.             printf("  d\t\tDisplay state of universe.\n");
  143.             printf("  e\t\tEdit current state.\n");
  144.             printf("  n=xx\t\tCompute xx generations.\n");
  145.             printf("  o=xx\t\tSet display origin to xx.\n");
  146.             printf("  o+xx\t\tIncrease display origin to curent value + xx.\n");
  147.             printf("  o-xx\t\tDecrease display origin to curent value - xx.\n");
  148.             printf("  r=xx\t\tSet size of neighborhood.\n");
  149.             printf("  s=xx\t\tSet number of states.\n");
  150.             printf("  t=code\tTransition table given by code.\n");
  151.             printf("  txx=yy\tSet next state = yy for total xx.\n");
  152.             printf("  x\t\tExit to CP/M.\n");
  153.         }
  154.     }
  155. }
  156.  
  157. /* getval -- Convert command string to a integer,
  158.          on exit strp contains pointer to next character to be processed. */
  159. getval(strp)
  160. char **strp;
  161. {    char *s;
  162.     int n;
  163.  
  164.     for (s = *strp; *s == '=' || *s == ',' || isspace(*s); ++s)
  165.         ;    /* Skip separators. */
  166.     n = atoi(s);
  167.     while (isdigit(*s))
  168.         ++s;
  169.     *strp = s;
  170.     return(n);
  171. }
  172.  
  173. /* evolve -- Compute next n generations of cellular automaton. */
  174. evolve(n, ca)
  175. int n;
  176. struct automation *ca;
  177. {    int i;
  178.  
  179.     for (i=0; i < n; ++i) {
  180.         dogener(univ, ca);
  181.         gen = 1-gen;
  182.         dispst(univ[gen]);
  183.     }
  184. }
  185.  
  186. /* dogener -- Compute next generation. */
  187. dogener(univ, ca)
  188. char univ[2][UNIVSIZ];
  189. struct automaton *ca;
  190. {    static int i, j, total;        /* Static for speed. */
  191.     static char *uvp;
  192.  
  193.     CtlCk();    /* C/80 routine to check for control characters. */
  194.     uvp = univ[gen];
  195.     for (i=0; i < UNIVSIZ; ++i) {
  196.         total = uvp[i];
  197.         for (j=1; j <= ca->neighb; ++j) {
  198.             total += ((i - j < 0) ? uvp[i-j+UNIVSIZ] : uvp[i-j]) +
  199.                    ((i + j >= UNIVSIZ) ? uvp[i+j-UNIVSIZ] : uvp[i+j]);
  200.         }
  201.         univ[1-gen][i] = ca->nexts[total];
  202.     }
  203. }
  204.  
  205. /* dispst -- Display state of the universe. */
  206. dispst(univ)
  207. char univ[UNIVSIZ];
  208. {    int i;
  209.     char c;
  210.  
  211.     printf("%s", GPHST);    /* Enter graphic mode. */
  212.     for (i=origin; i < origin+SCRNSIZ; ++i) {
  213.         putchar(stsym[univ[i % UNIVSIZ]]);
  214.         if (c = bdos(6, 0xff)) {    /* Check for a character from keyboard. */
  215.             switch(c) {
  216.             case '\014': case '\04':    /* Move display to right. */
  217.                 origin = (origin + 1)%UNIVSIZ;
  218.                 break;
  219.             case '\b': case '\023':    /* Move display to left. */
  220.                 origin = (origin - 1 + UNIVSIZ)%UNIVSIZ;
  221.                 break;
  222.             }
  223.         }
  224.     }
  225.     printf("%s\n", GPHEND);    /* Exit graphic mode, new line. */
  226. }
  227.  
  228. /* ued -- Edit the current state of the universe. */
  229. ued()
  230. {    int curpos, i, c;
  231.     extern char Cmode;
  232.  
  233.     Cmode = 0;    /* Set char at a time input for C/80. */
  234.     curpos = 0;
  235.     printf("%s%s",UPLINE, UPLINE);    /* Move up two lines. */
  236.     dispst(univ[gen]);
  237.     while (1) {
  238.         putchar('\r');        /* Return to left margin. */
  239.         for (i=0; i < curpos; ++i)
  240.             putchar(' ');
  241.         printf("^%s\b",ERALINE);    /* Display cursor, erase to end of line. */
  242.         switch(c = getchar()) {
  243.         case '\b':
  244.         case '\023':
  245.             curpos = (curpos - 1 + UNIVSIZ)%UNIVSIZ;
  246.             break;
  247.         case '\014':
  248.         case '\04':
  249.             curpos = (curpos + 1)%UNIVSIZ;
  250.             break;
  251.         case ' ':    /* Special case: blank = state 0. */
  252.             c = '0';
  253.         case '0': case '1': case '2': case '3': case '4':
  254.         case '5': case '6': case '7': case '8': case '9':
  255.             univ[gen][(curpos+origin)%UNIVSIZ] = c - '0';
  256.             printf("\r%s",UPLINE);
  257.             dispst(univ[gen]);
  258.             break;
  259.         case 'z':    /* Zap universe. */
  260.             printf("\nZero entire universe (y/n)? ");
  261.             if ((c = toupper(getchar())) == 'Y')
  262.                 for (i=0; i < UNIVSIZ; ++i)
  263.                     univ[gen][i] = 0;
  264.             printf("\r%s%s",UPLINE, UPLINE);
  265.             dispst(univ[gen]);
  266.             printf("\n%s%s",ERALINE, UPLINE);    /* Erase message. */
  267.             break;
  268.         case '\n':
  269.             printf(UPLINE);
  270.         default:
  271.             printf("\r%s", ERALINE);    /* Erase cursor line. */
  272.             Cmode = 1;    /* Restore line at a time input for C/80. */
  273.             return;
  274.         }
  275.     }
  276. }
  277.  
  278. /* adisp -- Display properties of automaton. */
  279. adisp(ca)
  280. struct automaton *ca;
  281. {    int i;
  282.  
  283.     printf("origin=%d\n", origin);
  284.     printf("states=%d\nneighboors=%d\ntotal\tnext state\n", ca->nstate, ca->neighb);
  285.     for (i = 0; i < (ca->nstate - 1)*(2*ca->neighb + 1) + 1; ++i) {
  286.         printf("%d\t%d\n",i, ca->nexts[i]);
  287.     }
  288. }
  289.  
  290. /* restart -- Control B vectors through CtlB to here. */
  291. restart()
  292. {    longjmp(env, 1);    /* Restart program. */
  293. }
  294.  
  295. #include    "b:onedlib.c"
  296. #include    <stdlib.c>
  297.