phillips@cs.ubc.ca (George Phillips) (02/12/90)
Here is my wireworld simulator for UNIX. It uses curses for the display so it should work on any reasonable terminal. I've run it on Sun 3's and Sun 4's under SunOS 4.0. WARNING: This program is almost everything a good program shouldn't be: inefficient, fragile and inflexible. It does, however, simulate wireworld. It is in the public domain and if you want to claim you wrote it, please do. -- George Phillips phillips@cs.ubc.ca {alberta,uw-beaver,uunet}!ubc-cs!phillips /* * wire - simulate the wirewold cellular automaton as described in the * Jan. 1990 issue of Scientific American (Computer Recreations, p. 146). * * The algorithm used is about as stupid as they get. Big files will * almost certainly cause core dumps. The input file format is rigid. * * '=' is a wire * '#' is an electron head * '-' is an electron tail * ' ' space * '.' space, too * * (watch out for tabs!) * * Just interrupt the program to quit (^C probably) * * To compile, use: * cc -o wire wire.c -lcurses -ltermcap * * (And without the -ltermcap for System V Unix, I think) */ #include <stdio.h> #include <curses.h> #include <string.h> char* w1; char* w2; char* aworld(); #define SPACE (0) #define WIRE (1) #define HEAD (2) #define TAIL (3) main(argc, argv) int argc; char* argv[]; { char buf[256]; char* p; char* q; int line; initscr(); w1 = aworld(); w2 = aworld(); line = 1; while (fgets(buf, 256, stdin) != NULL) { p = w1 + line * COLS + 1; for (q = buf; *q; q++) { switch (*q) { case '=': *p++ = WIRE; break; case '-': *p++ = TAIL; break; case '#': *p++ = HEAD; break; case ' ': case '.': *p++ = SPACE; break; case '\n': break; default: fprintf(stderr, "bad char (%c) in file\n", *q); bye(1); } } line++; } for (;;) { do_gen(); display(); } bye(0); } do_gen() { int x; int y; char* z; int count; #define loc(x, y) (*(w1 + (x) + (y) * COLS)) #define add(x, y) if (loc(x, y) == HEAD) count++ for (x = 1; x < COLS - 1; x++) { for (y = 1; y < LINES - 1; y++) { z = w2 + x + y * COLS; switch (*(w1 + x + y * COLS)) { case SPACE: *z = SPACE; break; case TAIL: *z = WIRE; break; case HEAD: *z = TAIL; break; case WIRE: count = 0; add(x - 1, y); add(x + 1, y); add(x - 1, y - 1); add(x, y - 1); add(x + 1, y - 1); add(x - 1, y + 1); add(x, y + 1); add(x + 1, y + 1); if (count == 1 || count == 2) *z = HEAD; else *z = WIRE; break; default: fprintf(stderr, "oops, bad internal character (%d) %c at %d,%d\n", *(w1 + x + y * COLS), *(w1 + x + y * COLS), x, y); sleep(2); bye(1); } } } } char ch[] = " =#-"; display() { int x; int y; char c; for (x = 0; x < COLS; x++) for (y = 0; y < LINES; y++) { c = *(w2 + x + y * COLS); mvaddch(y, x, ch[c]); *(w1 + x + y * COLS) = c; } refresh(); } char* aworld() { char* w; int i; w = (char*)malloc(LINES * COLS); if (w == NULL) { fprintf(stderr, "out of memory!\n"); bye(1); } for (i = 0; i < LINES * COLS; i++) w[i] = SPACE; return(w); } bye(ecode) int ecode; { mvaddch(LINES - 1, COLS - 1, '\r'); refresh(); endwin(); exit(ecode); }