biglife1.1/0040755000175200017560000000000007306140327013145 5ustar stephensstephengbiglife1.1/src/0040755000175200017560000000000007306140324013731 5ustar stephensstephengbiglife1.1/src/biglife/0040755000175200017560000000000007306140324015332 5ustar stephensstephengbiglife1.1/src/biglife/CVS/0040755000175200017560000000000007236675451016005 5ustar stephensstephengbiglife1.1/src/biglife/CVS/Root0100644000175200017560000000003407236675451016645 0ustar stephensstepheng:local://cvs/ioncvs/cvsroot biglife1.1/src/biglife/CVS/Repository0100644000175200017560000000002507236675451020101 0ustar stephensstephenghome/ion/src/biglife biglife1.1/src/biglife/CVS/Entries0100644000175200017560000000110407236675451017332 0ustar stephensstepheng/Makefile/1.7/Sun Nov 14 04:02:19 1999// /PKG/1.6/Sun Nov 14 04:02:19 1999// /README/1.3/Sun Nov 14 04:02:19 1999// /biglife.c/1.15/Sun Dec 26 19:53:22 1999// /biglife.gdb/1.4/Wed Oct 13 15:49:58 1999// /biglife.h/1.4/Sun Nov 14 04:02:19 1999// /biglife.in/1.2/Fri Feb 19 09:25:25 1999// /blgtk.c/1.2/Sun Nov 14 04:02:19 1999// /blterm.c/1.3/Sun Nov 14 04:02:19 1999// /gtklife.c/1.2/Sun Nov 14 04:02:20 1999// /gtklife.h/1.3/Sun Dec 26 19:52:45 1999// /life.c/1.2/Fri Nov 5 09:02:16 1999// /term.c/1.2/Sun Dec 26 19:52:25 1999// /term.h/1.1/Sun Nov 14 04:02:20 1999// D/lib//// biglife1.1/src/biglife/Makefile0100644000175200017560000000201407013432113016757 0ustar stephensstepheng# $Id: Makefile,v 1.7 1999/11/14 04:02:19 stephensk Exp $ CFLAGS+=-O3 -g -Wall ######################################################################## # Terminal support OFILES = \ biglife.o \ term.o all : biglife gbiglife biglife : blterm.o $(OFILES) Makefile $(CC) $(CFLAGS) -o $@ blterm.o $(OFILES) ######################################################################## # GTK support GTK_CFLAGS=`gtk-config --cflags` GTK_LIBS=`gtk-config --libs` GTK_OFILES = \ blgtk.o \ gtklife.o gtklife.o : gtklife.c $(COMPILE.c) $(GTK_CFLAGS) -c gtklife.c blgtk.o : blgtk.c $(COMPILE.c) $(GTK_CFLAGS) -c blgtk.c gbiglife : $(GTK_OFILES) $(OFILES) Makefile $(CC) $(CFLAGS) -o $@ $(GTK_OFILES) $(OFILES) $(GTK_LIBS) ######################################################################## # dependencies *.o : *.h ######################################################################## # misc clean : rm -f biglife gbiglife *.exe *core *.o ######################################################################## # EOF biglife1.1/src/biglife/PKG0100644000175200017560000000044607013432113015672 0ustar stephensstephengNAME=biglife VERSION=1.1 RCS_ID="$Id: PKG,v 1.6 1999/11/14 04:02:19 stephensk Exp $" DESC="A Game-of-Life program that uses sparse, hashed block, bit matrices to allow Life boards up to any size." CATEGORY="Games" REQUIRES_PKGS="" REQUIRES_OTHERS="ansi_terminal" OPTIONAL_OTHERS="gtk gdk glib" biglife1.1/src/biglife/README0100644000175200017560000000541507013432113016207 0ustar stephensstepheng$Id: README,v 1.3 1999/11/14 04:02:19 stephensk Exp $ Biglife Copyright 1998, 1999, Kurt A. Stephens http://www.acm.org/~stephensk The biglife library implements Conway's "Game-of-Life" using sparse bitmap arrays. It achieves its speed by unrolling the four nested loops of a naive implementation into 9 different types of bitwise operations and by not processing empty areas. A naive implementations can be used for validation of the fast routines. Currently supported displays are: ANSI terminals (vt100) and GTK+ libraries. Each life_array object is a hash table containing 8x8 bitmaps (life_chunk) indexed by chunk position. Each life_chunk has a chunk coordinate (x,y). Each coordinate element is a short and the hash of the position is a unsigned long concatenation of the coordinate. This allows an effective board size of 524288/524288 (memory permitting). Empty life_chunks, chunks with no live cells are not stored in the life_array, except when determining chunks adjacent to live chunks. Live chunks have at least one live cell. The storage overhead is 8 bytes for the 4 bytes of position and 4 bytes of linked list. This is %50 overhead over a full bit array representation. If we moved up to 16x16 bit chunks (64 bytes) the overhead would be %17.5 but there might be some very sparse chunks due to "gliders" going off to infinity. Iteration algorithm: 1. For each live chunk (C) 2. Find chunks neighboring C (CS[3][3]) 3. Create a new empty chunk (NC) 4. For each cell in chunk C (S) 5. Compute the number of neighbor cells of cell S. 6. Compute the corresponding cell in NC based on the number of neighbor cells for S. 7. For all neighbororing chunks created by step 2, 8. Do steps 3-6. 9. Filter out all dead chunks. A state table (life_trans_table[]) is used to map the 9 cell states into a new center cell state. The index into life_trans_table is the following bits: +---+---+---+ | | | | | 0 | 1 | 2 | | | | | +---+-V-+---+ | | | | | 3 > 4 < 5 | | | | | +---+-^-+---+ | | | | | 6 | 7 | 8 | | | | | +---+---+---+ Bit 4 is the center cell, all other cells are represented by other bits. The state of a cell and all neighbors is represented in 9 bits. For each cell in the life chunk, create a index into the state table from the neighboring cells. This is done using bitwise operations for speed. The display algorithm: 1. Choose a viewport in the chunks. 2. Clear the window. 3. Iterate through the chunks in the window without allocating dead chunks and blit each. Incremental display: TO BE IMPLEMENTED: Toggle the update bit in the chunk if its different from a last chunk. Only draw chunks that have changed as long as the viewport is the same. Commands: Please type '?-RETURN' at the command prompt for a description of each command. biglife1.1/src/biglife/biglife.c0100644000175200017560000011760507031471062017107 0ustar stephensstepheng#ifndef __rcs_id__ #ifndef __rcs_id_biglife_biglife_c__ #define __rcs_id_biglife_biglife_c__ static const char __rcs_id_biglife_biglife_c[] = "$Id: biglife.c,v 1.15 1999/12/26 19:53:22 stephensk Exp $"; #endif #endif /* __rcs_id__ */ /* Copyright 1998, 1999, Kurt A. Stephens http://www.acm.org/~stephensk */ #include "biglife.h" #include "term.h" #include #include #include #include #include #include #include #include /**********************************************************/ /* global tables. */ /**********************************************************/ /* Returns the number of 1 bits for any number [0,0x200) */ static unsigned char bit_count[0x200]; #define BIT_COUNT(X) bit_count[X] /**********************************************************/ /* Postional bit masks */ static life_chunk_word bit_mask[8][4]; /* bitmask[0] = { 00000001 11000000 00000000 01000000 }, bitmask[1] = { 00000000 11100000 00000000 10100000 }, bitmask[2] = { 00000000 01110000 00000000 01010000 }, ... bitmask[7] = { 00000000 00000011 10000000 00000010 }, */ /**********************************************************/ /* Translate a bit sequence into a string for printing */ char life_bit_string[0x100][life_chunk_SIZE + 1]; char life_bit_string9[0x200][10]; /**********************************************************/ /* The transition table. */ life_chunk_word life_trans_table[1 << 9]; /**********************************************************/ /* system init */ static int gen_bit_string(unsigned long k, size_t length, const char *c, char *buf) { int j = 0; char *s = buf; const char *cp = c + 1; while ( length -- ) { if ( k & 1 ) { *(s ++) = *cp; j ++; } else { *(s ++) = c[0]; } if ( cp[1] ) { cp ++; } k >>= 1; } *s = '\0'; return j; } void life_init() { int i; for ( i = 0; i < (1 << life_chunk_SIZE); i ++ ) { gen_bit_string(i, life_chunk_SIZE, " #", life_bit_string[i]); } for ( i = 0; i < 0x200; i ++ ) { bit_count[i] = gen_bit_string(i, 9, ".0123456789", life_bit_string9[i]); } /* Generate the top and bottom row masks */ bit_mask[0][0] = 1 << (life_chunk_SIZE - 1); bit_mask[0][1] = 0x03; bit_mask[0][2] = 0x00; for ( i = 1; i < life_chunk_SIZE; i ++ ) { bit_mask[i][0] = 0x00; bit_mask[i][1] = 0x07 << (i - 1); bit_mask[i][2] = 0x00; } bit_mask[7][2] = 0x01; /* Generate the center row mask, without the center pixel */ for ( i = 0; i < life_chunk_SIZE; i ++ ) { bit_mask[i][3] = bit_mask[i][1] & ~(1 << i); } /* Compute the transition table */ for ( i = 0; i < (1 << 9); i ++ ) { int k = i & ~ (1 << 4); /* bit 4 is the center bit */ int n_neighbors = BIT_COUNT(k); if ( n_neighbors == 2 ) { /* 2 neighbors -> leave bit alone */ life_trans_table[i] = i & (1 << 4) ? ~ 0 : 0; } else if ( n_neighbors == 3 ) { /* 3 neighbors -> on */ life_trans_table[i] = ~ 0; } else { /* off */ life_trans_table[i] = 0; } } } /**********************************************************/ /* A place holder for empty chunks. */ const life_chunk life_chunk_zero = { 0, { { 32767, 32767 } } }; /* A dead chunk */ /**********************************************************/ /* A free list of unused chunks. */ static life_chunk *life_chunk_free_list; #define life_chunk_free(X) ((X)->next = life_chunk_free_list, life_chunk_free_list = (X)) /**********************************************************/ /* Compute the number of cells on in a chunk. */ int life_chunk_n_bits(life_chunk *c) { if ( c->n_bits < 0 ) { int i; c->n_bits = 0; for ( i = life_chunk_SIZE; i --; ) { c->n_bits += BIT_COUNT(c->b[i]); } } return c->n_bits; } /**********************************************************/ /* Reset the computed vars of a life_array before iteration. */ static void life_array_reset(life_array *a) { X(a->min) = Y(a->min) = 32767; X(a->max) = Y(a->max) = -32767; a->n_chunks = 0; a->n_cells = 0; a->needs_cleanup = 0; } /**********************************************************/ /* Initialize a new life_array. */ void life_array_init(life_array *a) { memset(a, 0, sizeof(*a)); life_array_reset(a); a->generation = 1; } /**********************************************************/ /* Clear a life_array. */ void life_array_clear(life_array *a) { /* Empty chunks */ life_chunk_LOOP(a, chunks, c, (void) 0); { life_chunk_free(c); } life_chunk_LOOP_END; life_chunk_LOOP(a, new_chunks, c, (void) 0); { life_chunk_free(c); } life_chunk_LOOP_END; life_array_init(a); } /**********************************************************/ /* Update computed varables after adding a life_chunk. */ static void life_array_added(life_array *a, life_chunk *c) { a->n_chunks ++; a->n_cells += life_chunk_n_bits(c); /* a->changed |= c->changed; */ /* Update range. */ if ( X(a->min) > X(c->p) ) X(a->min) = X(c->p); if ( Y(a->min) > Y(c->p) ) Y(a->min) = Y(c->p); if ( X(a->max) < X(c->p) ) X(a->max) = X(c->p); if ( Y(a->max) < Y(c->p) ) Y(a->max) = Y(c->p); } /**********************************************************/ /* Add a new life_chunk to a life_array. */ static life_chunk *life_array_add(life_array *a, life_chunk *c) { life_chunk **e; unsigned int hash_i; hash_i = HASH(c->p) % life_array_SIZE(a); e = &(a->chunks[hash_i]); c->next = *e; *e = c; life_array_added(a, c); return c; } /**********************************************************/ /* Lookup stats. */ static int life_array_get_total = 0; static int life_array_get_cache_hits = 0; /**********************************************************/ /* Get a life_chunk by position. */ life_chunk *life_array_get(life_array *a, int x, int y, int add) { life_pos p; life_chunk *e; unsigned int hash_i; X(p) = x; Y(p) = y; hash_i = HASH(p) % life_array_SIZE(a); life_array_get_total ++; /* Check cache */ if ( a->cache && HASH(a->cache->p) == HASH(p) ) { life_array_get_cache_hits ++; return a->cache; } /* Check if it's a new chunk */ e = a->new_chunks[hash_i]; while ( e ) { if ( HASH(e->p) == HASH(p) ) { return a->cache = e; } e = e->next; } /* A real chunk? */ e = a->chunks[hash_i]; while ( e ) { if ( HASH(e->p) == HASH(p) ) { return a->cache = e; } e = e->next; } /* Make a new empty chunk and put it in the table */ if ( add ) { life_chunk **ep; /* Check the free list */ if ( life_chunk_free_list ) { e = life_chunk_free_list; life_chunk_free_list = life_chunk_free_list->next; } else { /* Allocate one */ e = malloc(sizeof(*e)); } life_chunk_CLEAR(e); e->p = p; if ( a->add_to_new_chunks ) { ep = &(a->new_chunks[hash_i]); } else { ep = &(a->chunks[hash_i]); } e->next = *ep; *ep = e; e->changed = 1; /* force display */ a->n_chunks ++; a->needs_cleanup = 1; return a->cache = e; } else { assert(life_chunk_zero.next == 0); assert(X(life_chunk_zero.p) == Y(life_chunk_zero.p) && Y(life_chunk_zero.p) == 32767); assert(!life_chunk_LIVE(&life_chunk_zero)); return (void*) &life_chunk_zero; } } /**********************************************************/ /* Get a cell by position. */ int life_array_get_cell(life_array *a, long cx, long cy) { life_chunk *c = life_array_get(a, cx >> life_chunk_SIZE_LOG2, cy >> life_chunk_SIZE_LOG2, 0); return c->b[cy & life_chunk_SIZE_MASK] & (1 << (cx & life_chunk_SIZE_MASK)) ? 1 : 0; } /**********************************************************/ /* Toggle a cell by position. */ void life_array_toggle_cell(life_array *a, long cx, long cy) { life_chunk *c = life_array_get(a, cx >> life_chunk_SIZE_LOG2, cy >> life_chunk_SIZE_LOG2, 1); c->b[cy & life_chunk_SIZE_MASK] ^= (1 << (cx & life_chunk_SIZE_MASK)); c->changed = 1; a->needs_cleanup = 1; } /**********************************************************/ /* Set a cell by position. */ void life_array_set_cell(life_array *a, long cx, long cy, int value) { life_chunk *c = life_array_get(a, cx >> life_chunk_SIZE_LOG2, cy >> life_chunk_SIZE_LOG2, 1); if ( value ) { c->b[cy & life_chunk_SIZE_MASK] |= (1 << (cx & life_chunk_SIZE_MASK)); } else { c->b[cy & life_chunk_SIZE_MASK] &= ~ (1 << (cx & life_chunk_SIZE_MASK)); } c->changed = 1; a->needs_cleanup = 1; } /****************************************************************/ /* Chunk output. */ static char chunk_row_sep[] = "--------+--------+--------\n"; void life_chunk_print(life_array *src, int x, int y, FILE *fp) { int i, j; for ( i = -1; i <= 1; i ++ ) { life_chunk *c[3]; int y_i = y + i; c[0] = life_array_get(src, x - 1, y_i, 0); c[1] = life_array_get(src, x , y_i, 0); c[2] = life_array_get(src, x + 1, y_i, 0); for ( j = ((i == -1)? life_chunk_SIZE - 1 : 0); j <= ((i == 1) ? 0 : life_chunk_SIZE - 1); j ++ ) { fprintf(fp, "%s%s|%s|%s\n%s", i == 1 ? chunk_row_sep : "", life_BIT_STRING(c[0]->b[j]), life_BIT_STRING(c[1]->b[j]), life_BIT_STRING(c[2]->b[j]), i == -1 ? chunk_row_sep : ""); } fprintf(fp, "\n"); } } void _life_chunk_print(life_chunk *c, FILE *fp) { int j; fprintf(fp, "\n%p @ %d,%d\n", (void*) c, X(c->p), Y(c->p)); for ( j = 0; j < life_chunk_SIZE; j ++ ) { fprintf(fp, "%s\n", life_BIT_STRING(c->b[j])); } fprintf(fp, "\n"); } /****************************************************************/ /* iteration. */ life_chunk life_chunk_errors; /* Check computation errors */ #ifndef DEBUG #define DEBUG 0 #endif #if DEBUG static life_chunk *do_chunk_debug = 0; #endif static void life_array_iterate_chunk(life_array *src, life_array *dst, life_chunk *c) { life_chunk *cs[3][3]; life_chunk result; life_chunk *dst_c; /* ** Get all adjacent src chunks, ** creating empty chunks in dst if we are doing the live chunks. */ { int add = src->add_to_new_chunks; cs[0][0] = life_array_get(src, X(c->p) - 1, Y(c->p) - 1, add); cs[0][1] = life_array_get(src, X(c->p) , Y(c->p) - 1, add); cs[0][2] = life_array_get(src, X(c->p) + 1, Y(c->p) - 1, add); cs[1][0] = life_array_get(src, X(c->p) - 1, Y(c->p) , add); cs[1][1] = c; cs[1][2] = life_array_get(src, X(c->p) + 1, Y(c->p) , add); cs[2][0] = life_array_get(src, X(c->p) - 1, Y(c->p) + 1, add); cs[2][1] = life_array_get(src, X(c->p) , Y(c->p) + 1, add); cs[2][2] = life_array_get(src, X(c->p) + 1, Y(c->p) + 1, add); } #if DEBUG if ( c == do_chunk_debug ) { fprintf(stderr, "\n%s|%s|%s\n%s", life_BIT_STRING(cs[0][0]->b[7]), life_BIT_STRING(cs[0][1]->b[7]), life_BIT_STRING(cs[0][2]->b[7]), chunk_row_sep); } #endif /*********************************************************************/ /* Configuration */ #ifndef CHECK /* Enable validation of FAST routines against the SIMPLE_NEIGHBORS routines. */ #define CHECK 0 #endif #ifndef CHECK2 #define CHECK2 0 #endif #if CHECK #define SIMPLE_NEIGHBORS 1 #define FAST 1 #endif #ifndef FAST /* Default to FAST */ #define FAST 1 #endif #if ! FAST /* Default to SIMPLE_NEIGHBORS */ #define SIMPLE_NEIGHBORS 1 #endif #ifndef SIMPLE_NEIGHBORS #define SIMPLE_NEIGHBORS 0 #endif { /*************************************************************/ #if CHECK life_chunk _dst_c; short _ti[life_chunk_SIZE][life_chunk_SIZE]; life_chunk_CLEAR(&_dst_c); memset(_ti, 0, sizeof(_ti)); #if 0 /* Dump each translation index generation. */ #define TI_DUMP(X,Y)fprintf(stderr, "Bit(%d,%d) = '%s' 0x%x\n", (X), (Y), life_BIT_STRING9(_ti[(Y)][(X)]), _ti[(Y)][(X)]); life_chunk_print(src, c->p.p.x, c->p.p.y, stderr); _life_chunk_print(&result, stderr); #endif #define TI(X,Y,E)(_ti[(Y)][(X)]=(E)) #define dst_c (&_dst_c) #define FAST 1 #endif #if FAST /* Enable fast translation index generation. */ #ifndef TI #define TI(X,Y,E)(E) #endif #ifndef TI_DUMP #define TI_DUMP(X,Y) #endif #if 1 #define DO(X,Y,E)result.b[(Y)] |= (1 << (X)) & life_trans_table[TI((X),(Y),(E))]; TI_DUMP(X,Y) #else #define DO(X,Y,E) assert(TI((X),(Y),(E)) < (1 << 9)); TI_DUMP(X,Y) #endif /* Clear the result chunk */ life_chunk_CLEAR(&result); /**************************************************************/ /* corner cells */ /* Case 1: x = 0, y = 0 7 0 1 +-+ +-+-+ |0| |1|2| b[7] +-+ +-+-+ +-+ +-+-+ |3| |4|5| b[0] +-+ +-+-+ |6| |7|8| b[1] +-+ +-+-+ */ #define R_BIT (1U << (life_chunk_SIZE - 1)) #define R_BITS (3U << (life_chunk_SIZE - 2)) #define L_BITS (3U) #define L_BIT (1U) DO(0, 0, ((cs[0][0]->b[7] & R_BIT ) >> 7) | /* 0 */ ((cs[0][1]->b[7] & L_BITS) << 1) | /* 1,2 */ ((cs[1][0]->b[0] & R_BIT ) >> 4) | /* 3 */ ((cs[1][1]->b[0] & L_BITS) << 4) | /* 4,5 */ ((cs[1][0]->b[1] & R_BIT ) >> 1) | /* 6 */ ((cs[1][1]->b[1] & L_BITS) << 7)); /* 7, 8 */ /* Case 2: x = 7, y = 0 6 7 0 +-+-+ +-+ |0|1| |2| b[7] +-+-+ +-+ +-+-+ +-+ |3|4| |5| b[0] +-+-+ +-+ |6|7| |8| b[1] +-+-+ +-+ */ DO(7, 0, ((cs[0][1]->b[7] >> 6)) | /* 0,1 */ ((cs[0][2]->b[7] & L_BIT ) << 2) | /* 2 */ ((cs[1][1]->b[0] & R_BITS) >> 3) | /* 3,4 */ ((cs[1][2]->b[0] & L_BIT ) << 5) | /* 5 */ ((cs[1][1]->b[1] & R_BITS)) | /* 6,7 */ ((cs[1][2]->b[1] & L_BIT ) << 8)); /* 8 */ /* Case 3: x = 0, y = 7 7 0 1 +-+ +-+-+ |0| |1|2| b[6] +-+ +-+-+ |3| |4|5| b[7] +-+ +-+-+ +-+ +-+-+ |6| |7|8| b[0] +-+ +-+-+ */ DO(0, 7, ((cs[1][0]->b[6] ) >> 7) | /* 0 */ ((cs[1][1]->b[6] & L_BITS) << 1) | /* 1,2 */ ((cs[1][0]->b[7] & R_BIT ) >> 4) | /* 3 */ ((cs[1][1]->b[7] & L_BITS) << 4) | /* 4,5 */ ((cs[2][0]->b[0] & R_BIT ) >> 1) | /* 6 */ ((cs[2][1]->b[0] & L_BITS) << 7)); /* 7, 8 */ /* Case 4: x = 7, y = 7 6 7 0 +-+-+ +-+ |0|1| |2| b[6] +-+-+ +-+ |3|4| |5| b[7] +-+-+ +-+ +-+-+ +-+ |6|7| |8| b[0] +-+-+ +-+ */ DO(7, 7, ((cs[1][1]->b[6]) >> 6) | /* 0,1 */ ((cs[1][2]->b[6] & L_BIT ) << 2) | /* 2 */ ((cs[1][1]->b[7] & R_BITS) >> 3) | /* 3,4 */ ((cs[1][2]->b[7] & L_BIT ) << 5) | /* 5 */ ((cs[2][1]->b[0] & R_BITS) ) | /* 6,7 */ ((cs[2][2]->b[0] & L_BIT ) << 8)); /* 8 */ /**************************************************************/ /* Left and right edges. */ { int i; for ( i = 0; i <= 5; i ++ ) { /**************************************************************/ /* left edge cells */ /* Case 5: x = 0, 0 < y < 7 7 0 1 +-+ +-+-+ |0| |1|2| b[i] +-+ +-+-+ |3| |4|5| b[i + 1] +-+ +-+-+ |6| |7|8| b[i + 2] +-+ +-+-+ */ DO(0, i + 1, ((cs[1][0]->b[i ] ) >> 7) | /* 0 */ ((cs[1][1]->b[i ] & L_BITS) << 1) | /* 1,2 */ ((cs[1][0]->b[i + 1] & R_BIT ) >> 4) | /* 3 */ ((cs[1][1]->b[i + 1] & L_BITS) << 4) | /* 4,5 */ ((cs[1][0]->b[i + 2] & R_BIT ) >> 1) | /* 6 */ ((cs[1][1]->b[i + 2] & L_BITS) << 7)); /* 7, 8 */ /**************************************************************/ /* right edge cells */ /* Case 6: x = 7, 0 < y < 7 6 7 0 +-+-+ +-+ |0|1| |2| b[i] +-+-+ +-+ |3|4| |5| b[i + 1] +-+-+ +-+ |6|7| |8| b[i + 2] +-+-+ +-+ */ DO(7, i + 1, ((cs[1][1]->b[i ] ) >> 6) | /* 0,1 */ ((cs[1][2]->b[i ] & L_BIT ) << 2) | /* 2 */ ((cs[1][1]->b[i + 1] & R_BITS) >> 3) | /* 3,4 */ ((cs[1][2]->b[i + 1] & L_BIT ) << 5) | /* 5 */ ((cs[1][1]->b[i + 2] & R_BITS) ) | /* 6,7 */ ((cs[1][2]->b[i + 2] & L_BIT ) << 8)); /* 8 */ /**************************************************************/ /* top edge cells */ /* Case 7: 0 < x < 7, y = 0 i 1 2 +-+-+-+ |0|1|2| b[7] +-+-+-+ +-+-+-+ |3|4|5| b[0] +-+-+-+ |6|7|8| b[1] +-+-+-+ */ DO(i + 1, 0, (((cs[0][1]->b[7] >> i) ) & (7) ) | /* 0,1,2 */ (((cs[1][1]->b[0] >> i) << 3) & (7 << 3)) | /* 3,4,5 */ (((cs[1][1]->b[1] >> i) << 6) & (7 << 6))); /* 6,7,8 */ /**************************************************************/ /* bottom edge cells */ /* Case 8: 0 < x < 7, y = 7 i 1 2 +-+-+-+ |0|1|2| b[6] +-+-+-+ |3|4|5| b[7] +-+-+-+ +-+-+-+ |6|7|8| b[0] +-+-+-+ */ DO(i + 1, 7, (((cs[1][1]->b[6] >> i) ) & (7) ) | /* 0,1,2 */ (((cs[1][1]->b[7] >> i) << 3) & (7 << 3)) | /* 3,4,5 */ (((cs[2][1]->b[0] >> i) << 6) & (7 << 6))); /* 6,7,8 */ /**************************************************************/ /* Interior cells */ /* Case 9: 0 < x < 7, 0 < y < 7 i 1 2 +-+-+-+ |0|1|2| b[j] +-+-+-+ |3|4|5| b[j + 1] +-+-+-+ |6|7|8| b[j + 1] +-+-+-+ */ { int j; for ( j = 0; j < life_chunk_SIZE - 2; j ++ ) { DO(i + 1, j + 1, (((cs[1][1]->b[j ] >> i) ) & (7) ) | /* 0,1,2 */ (((cs[1][1]->b[j + 1] >> i) << 3) & (7 << 3)) | /* 3,4,5 */ (((cs[1][1]->b[j + 2] >> i) << 6) & (7 << 6))); /* 6,7,8 */ } } } } #undef DO #endif #ifdef dst_c #undef dst_c #endif #if SIMPLE_NEIGHBORS /* Do each position in the chunk */ { int i1; #if CHECK2 int errors = 0; #endif for ( i1 = 0; i1 < life_chunk_SIZE; i1 ++ ) { int i0, i0_, i2, i2_; int j; i0_ = (i1 + 7) >> life_chunk_SIZE_LOG2; /* index into cs[] */ i0 = (i1 + 7) & life_chunk_SIZE_MASK; i2_ = ((i1 + 1) >> life_chunk_SIZE_LOG2) + 1; /* index into cs[] */ i2 = (i1 + 1) & life_chunk_SIZE_MASK; /* index into cs[i2_]->b[] */ //fprintf(stderr, "i0 = %d, i0_ = %d, i1 = %d, i2 = %d, i2_ = %d\n", i0, i0_, i1, i2, i2_); #if DEBUG if ( c == do_chunk_debug ) { fprintf(stderr, "%s|", life_BIT_STRING(cs[1][0]->b[i1])); } #endif for ( j = 0; j < life_chunk_SIZE; j ++ ) { int n_neighbors = /* row i - 1 */ BIT_COUNT(bit_mask[j][0] & cs[i0_][0]->b[i0]) + /* col j - 1 */ BIT_COUNT(bit_mask[j][1] & cs[i0_][1]->b[i0]) + /* col j */ BIT_COUNT(bit_mask[j][2] & cs[i0_][2]->b[i0]) + /* col j + 1 */ /* row i */ BIT_COUNT(bit_mask[j][0] & cs[ 1 ][0]->b[i1]) + BIT_COUNT(bit_mask[j][3] & cs[ 1 ][1]->b[i1]) + /* ignore self */ BIT_COUNT(bit_mask[j][2] & cs[ 1 ][2]->b[i1]) + /* row i + 1 */ BIT_COUNT(bit_mask[j][0] & cs[i2_][0]->b[i2]) + BIT_COUNT(bit_mask[j][1] & cs[i2_][1]->b[i2]) + BIT_COUNT(bit_mask[j][2] & cs[i2_][2]->b[i2]) ; int b_result; #if CHECK2 int tx = X(c->p) * life_chunk_SIZE + j, ty = Y(c->p) * life_chunk_SIZE + i1, ti, ti_neighbors, ti_result; assert(life_array_get_cell(src, tx , ty ) == (((1 << j) & cs[1][1]->b[i1]) ? 1 : 0)); ti = (life_array_get_cell(src, tx - 1, ty - 1) << 0) | (life_array_get_cell(src, tx , ty - 1) << 1) | (life_array_get_cell(src, tx + 1, ty - 1) << 2) | (life_array_get_cell(src, tx - 1, ty ) << 3) | (life_array_get_cell(src, tx , ty ) << 4) | (life_array_get_cell(src, tx + 1, ty ) << 5) | (life_array_get_cell(src, tx - 1, ty + 1) << 6) | (life_array_get_cell(src, tx , ty + 1) << 7) | (life_array_get_cell(src, tx + 1, ty + 1) << 8) ; #endif #if DEBUG if ( c == do_chunk_debug ) { fprintf(stderr, "%d", n_neighbors); } #endif if ( n_neighbors == 2 ) { b_result = ((1 << j) & c->b[i1]) ? 1 : 0; result.b[i1] |= (1 << j) & c->b[i1]; } else if ( n_neighbors == 3 ) { b_result = 1; result.b[i1] |= (1 << j); } else { b_result = 0; } #if CHECK2 assert(ti < (1 << 9)); ti_neighbors = BIT_COUNT(ti & ~(1<<4)); ti_result = life_trans_table[ti] ? 1 : 0; if ( b_result != ti_result || n_neighbors != ti_neighbors /* || ti != _ti[i1][j] */ ) { life_chunk_print(src, X(c->p), Y(c->p), stderr); fprintf(stderr, "ERROR:\nsrc(%d,%d) bit(%d,%d)\n", X(c->p), Y(c->p), j, i1); fprintf(stderr, "i0 = %d, i0_ = %d, i1 = %d, i2 = %d, i2_ = %d\n", i0, i0_, i1, i2, i2_); fprintf(stderr, "n_neighbors = %d, b_result = %d, ti = 0x%0X %s (%d bits), ti_result = %d, ti[] = 0x%0X %s\n", n_neighbors, b_result, ti, life_BIT_STRING9(ti), ti_neighbors, ti_result, _ti[i1][j], life_BIT_STRING9(_ti[i1][j])); errors ++; } #endif } #if CHECK2 if ( errors ) { exit(errors); } #endif #if DEBUG if ( c == do_chunk_debug ) { fprintf(stderr, "|%s\n", life_BIT_STRING(cs[1][2]->b[i1])); } #endif } } #endif /* Get the dst chunk */ dst_c = life_array_get(dst, X(c->p), Y(c->p), 1); /* Copy result to dst_c and compute dst_c->changed. */ dst_c->changed = 0; { int i; for ( i = 0; i < life_chunk_SIZE; i ++ ) { dst_c->changed |= dst_c->b[i] ^ c->b[i]; dst_c->b[i] = result.b[i]; } } #if 0 if ( ! life_chunk_LIVE(dst_c) ) { fprintf(stderr, "!%d,%d ", X(dst_c->p), Y(dst_c->p)); } #endif /* We don't know n_bits anymore if changed. */ //if ( dst_c->changed ) dst_c->n_bits = -1; #if CHECK { int i; for ( i = 0; i < life_chunk_SIZE; i ++ ) { if ( dst_c->b[i] ^ _dst_c.b[i] ) { for ( i = 0; i < life_chunk_SIZE; i ++ ) { life_chunk_errors.b[i] |= dst_c->b[i] ^ _dst_c.b[i]; // fprintf(stderr, "chunk %d, %d: %s\n", X(dst_c->p), Y(dst_c->p), life_BIT_STRING(dst_c->b[i] ^ _dst_c.b[i])); } break; } } } #endif } #if DEBUG if ( c == do_chunk_debug ) { fprintf(stderr, "%s%s|%s|%s\n\n", chunk_row_sep, life_BIT_STRING(cs[2][0]->b[0]), life_BIT_STRING(cs[2][1]->b[0]), life_BIT_STRING(cs[2][2]->b[0])); fprintf(stderr, "\n=============>>>>\n"); life_chunk_print(dst, X(c->p), Y(c->p), stderr); } #endif } /**********************************************************/ /* Clean up chunk modifications. */ void life_array_cleanup(life_array *dst) { int live = 0, dead = 0; if ( ! dst->needs_cleanup ) return; dst->needs_cleanup = 0; life_array_reset(dst); /* ** Move new live chunks into real chunk list, ** and free dead chunks. */ life_chunk_LOOP(dst, chunks, c, (void)0); { if ( life_chunk_LIVE(c) ) { cp = &(c->next); life_array_added(dst, c); live ++; } else { *cp = c->next; life_chunk_free(c); dead ++; } } life_chunk_LOOP_END; life_chunk_LOOP(dst, new_chunks, c, *cp = 0); { if ( life_chunk_LIVE(c) ) { life_array_add(dst, c); live ++; } else { life_chunk_free(c); dead ++; } } life_chunk_LOOP_END; dst->cache = 0; assert(dst->n_chunks == live); // fprintf(stderr, "%p, live %d, dead %d\n", dst, live, dead); } /**********************************************************/ /* Iteration on entire life_array. */ void life_array_iterate(life_array *src, life_array *dst) { /* Clean up src */ life_array_cleanup(src); /* Do each live src chunk */ src->add_to_new_chunks = 1; life_chunk_LOOP(src, chunks, c, (void)0); { life_array_iterate_chunk(src, dst, c); } life_chunk_LOOP_END; src->add_to_new_chunks = 0; /* Do each new src chunk, because they are adjacent to the live chunks in src */ life_chunk_LOOP(src, new_chunks, c, (void)0); { life_array_iterate_chunk(src, dst, c); } life_chunk_LOOP_END; /* clean up dst */ life_array_cleanup(dst); /* new generation. */ dst->generation = src->generation + 1; } void life_cntx_iterate(life_cntx *cntx) { life_array_clear(cntx->dst); life_array_iterate(cntx->src, cntx->dst); { life_array *tmp; tmp = cntx->src; cntx->src = cntx->dst; cntx->dst = tmp; } } /**********************************************************/ /* Apply fp to entire life_array. */ int life_array_chunk_loop(life_array *src, int (*fp)(life_array *src, life_chunk *c, void *data), void *data) { int result = 0; life_chunk_LOOP(src, chunks, c, (void)0); { if ( (result = fp(src, c, data)) ) return result; } life_chunk_LOOP_END; life_chunk_LOOP(src, new_chunks, c, (void)0); { if ( (result = fp(src, c, data)) ) return result; } life_chunk_LOOP_END; return result; } /*****************************************************************/ /* I/O */ static int life_chunk_save(life_array *src, life_chunk *c, void *data) { int i; fprintf((FILE*) data, "%d %d ", c->p.p.x, c->p.p.y); for ( i = 0; i < life_chunk_SIZE; i ++ ) { fprintf((FILE*) data, "%02x ", (unsigned int) c->b[i]); } fprintf((FILE*) data, "\n"); return 0; /* continue chunk loop */ } int life_array_save_file(life_array *src, int x, int y, int xs, int ys, const char *file) { FILE *fp; int errors = 0; if ( (fp = fopen(file, "w")) ) { if ( xs <= 1 || ys <= 1 ) { fprintf(fp, "biglife 1.0 %d ascii\n", life_chunk_SIZE); fprintf(fp, "generation %lu\n", src->generation); life_array_chunk_loop(src, life_chunk_save, fp); } else { int i, j; for ( j = 0; j < ys; j ++ ) { for ( i = 0; i < xs; i ++ ) { fprintf(fp, "%c", " #"[life_array_get_cell(src, x + i, y + j)]); } fprintf(fp, "\n"); } } fprintf(fp, "EOF\n"); fclose(fp); } else { fprintf(stderr, "Cannot write file '%s'\n", file); } return errors; } int life_array_load_file(life_array *dst, int x, int y, const char *file) { FILE *fp; int errors = 0; int cxo = (x >> life_chunk_SIZE_LOG2), cyo = (x >> life_chunk_SIZE_LOG2); if ( (fp = fopen(file, "r")) ) { char buf[2048]; int i, j = 0; while ( fgets(buf, 2048, fp) ) { char *s = buf; if ( strncmp(s, "EOF", 3) == 0 ) break; if ( strncmp(s, "biglife ", 8) == 0 ) { /* Load a chunked document */ fgets(buf, sizeof(buf), fp); if ( dst->generation <= 1 ) { sscanf(buf, "generation %lu", &dst->generation); } while ( fgets(buf, sizeof(buf), fp) ) { if ( strncmp(s, "EOF", 3) == 0 ) break; { int cx, cy, offset, i, word; life_chunk *c; char *s = buf; sscanf(s, "%d%d%n", &cx, &cy, &offset); s += offset; c = life_array_get(dst, cxo + cx, cyo + cy, 1); for ( i = 0; i < life_chunk_SIZE; i ++ ) { sscanf(s, "%02x%n", &word, &offset); s += offset; c->b[i] = word; } life_chunk_modified(c); } } break; } /* Default: unchunked load. */ i = 0; while ( *s && *s != '\n' ) { if ( *s != ' ' ) { life_array_set_cell(dst, x + i, y + j, *s == '#'); } i ++; s ++; } j ++; } fclose(fp); dst->needs_cleanup = 1; life_array_cleanup(dst); } else { fprintf(stderr, "Cannot read file '%s'\n", file); errors ++; } return errors; } /*****************************************************************/ /* Command support */ static void clear_term(life_cntx *cntx) { if ( cntx->out && isatty(fileno(cntx->out)) && cntx->term_clear ) { cntx->term_clear(cntx); } } static char * prompt_for_string(life_cntx *cntx, const char *prompt, char *buf, size_t size) { char *r; /* Force redisplay of prompt. */ life_term_show_prompt(cntx, prompt); buf[0] = '\0'; if ( fgets(buf, size, cntx->in) ) { buf[size - 1] = '\0'; /* Remove trailing newline/carrage return */ if ( (r = strchr(buf, '\n')) ) *r = '\0'; if ( (r = strchr(buf, '\r')) ) *r = '\0'; return buf; } else { return 0; } } static int prompt_continue(life_cntx *cntx) { if ( cntx->in && isatty(fileno(cntx->in)) ) { char line[8]; prompt_for_string(cntx, "Hit return to continue:", line, sizeof(line)); } return 1; } #ifndef LIB_BIGLIFE #define LIB_BIGLIFE "lib/biglife" #endif static const char * lib_biglife = LIB_BIGLIFE; static int prompt_for_filename(life_cntx *cntx, const char *prompt, char *file, size_t size) { char line[1024]; while ( 1 ) { prompt_for_string(cntx, prompt, line, sizeof(line)); switch ( line[0] ) { case '\0': return 0; case '*': { char buf[1024]; const char *d = line[1] ? line + 2 : lib_biglife; sprintf(buf, "echo -n 'PWD: '; pwd; echo 'DIR: %s'; ls %s", d, d); system(buf); } break; case '?': fprintf(cntx->err, "\ \n\ Default repository is '%s'. \n\ \n\ Commands are: \n\ \t * \t Runs ls. \n\ \t cd \t Changes directory. ('cd ' => 'cd $HOME')\n\ \t - \t Use last filename: '%s'. \n\ \t ? \t This help message. \n\ \t \t A filename.\n\ \t \t If doesn't have a '/' in it assume \t \t its under the repository.\n\ ", lib_biglife, file); break; case 'c': if ( strncmp(line, "cd ", 3) == 0 ) { chdir(line[3] ? line + 3 : getenv("HOME")); } else { goto file_name; } break; case '-': if ( file[0] ) return 1; break; default: file_name: if ( strchr(line, '/') ) { strcpy(file, line); } else { sprintf(file, "%s/%s", lib_biglife, line); } return 1; break; } } while ( 1 ); return 1; } /*****************************************************************/ /* status */ int life_status_line(life_cntx *cntx, int row, char *out) { if ( ! out ) return 0; switch ( row ) { case 0: sprintf(out, "X%7d", cntx->cx); break; case 1: sprintf(out, "Y%7d", cntx->cy); break; case 2: sprintf(out, "G%7lu", (unsigned long) cntx->src->generation); break; case 3: sprintf(out, "C%7ld", (unsigned long) cntx->src->n_chunks); break; case 4: sprintf(out, "c%7ld", (unsigned long) cntx->src->n_cells); break; case 5: sprintf(out, "Z%7d", cntx->zoom); break; case 7: sprintf(out, "RANGE: "); break; case 8: sprintf(out, "x%7d", cntx->src->min.p.x <= cntx->src->max.p.x ? cntx->src->min.p.x * life_chunk_SIZE : 0); break; case 9: sprintf(out, "y%7d", cntx->src->min.p.y <= cntx->src->max.p.y ? cntx->src->min.p.y * life_chunk_SIZE : 0); break; case 10: sprintf(out, "X%7d", cntx->src->min.p.x <= cntx->src->max.p.x ? cntx->src->max.p.x * life_chunk_SIZE + life_chunk_SIZE - 1: 0); break; case 11: sprintf(out, "Y%7d", cntx->src->min.p.y <= cntx->src->max.p.y ? cntx->src->max.p.y * life_chunk_SIZE + life_chunk_SIZE - 1: 0); break; default: sprintf(out, " "); break; case 13: return 0; } return 1; } /*****************************************************************/ /* display */ static const char *top_level_prompt = "biglife"; static const char *current_prompt = "biglife"; void life_show_prompt(life_cntx *cntx, const char *prompt) { if ( ! prompt ) { prompt = current_prompt; } current_prompt = prompt; if ( cntx && cntx->show_prompt ) { cntx->show_prompt(cntx, prompt); } } void life_display_status(life_cntx *cntx) { if ( cntx && cntx->display_status ) { cntx->display_status(cntx); } life_show_prompt(cntx, 0); } void life_display_chunks(life_cntx *cntx) { life_display_status(cntx); if ( cntx && cntx->display_chunks ) { life_array_cleanup(cntx->src); cntx->display_chunks(cntx); } } /*****************************************************************/ /* Command processing. */ #define cmd cntx->cmd #define file cntx->file #define parm1 cntx->parm1 #define parm2 cntx->parm2 #define line cntx->line #define src cntx->src #define dst cntx->dst #define cx cntx->cx #define cy cntx->cy #define dx cntx->dx #define dy cntx->dy #define zoom cntx->zoom #define rtn cntx->rtn void life_cntx_init(life_cntx *cntx) { if ( ! src ) { src = &cntx->_src; life_array_init(src); } if ( ! dst ) { dst = &cntx->_dst; life_array_init(dst); } if ( ! cntx->in ) { cntx->in = stdin; } if ( ! cntx->out ) { cntx->out = stdout; } if ( ! cntx->err ) { cntx->err = stderr; } } int life_read_and_run_command(life_cntx *cntx) { if ( life_display_status(cntx), prompt_for_string(cntx, current_prompt, line, sizeof(line)) ) { return life_run_command(cntx, line); } return 0; } int life_run_commands(life_cntx *cntx) { rtn = 0; life_display_chunks(cntx); while ( life_display_status(cntx), prompt_for_string(cntx, top_level_prompt, line, sizeof(line)) ) { if ( life_run_command(cntx, line) ) break; } return rtn; } #ifdef line #undef line #endif const char life_command_keys[] = "123qQCzZxtTiIjJkKmMuUoOnN,transcript ) { fprintf(cntx->transcript, "%s\n", line); } } cmdp = cmd; while ( *cmdp ) { int cmdc; switch ( cmdc = *(cmdp ++) ) { /***************************************************/ /* Random seed */ case 'S': { int rs; if ( parm1 >= 1 ) { rs = getpid() ^ time(0); } else { rs = parm1; } srand(rs); if ( cntx->transcript ) { fprintf(cntx->transcript, "S %d\n", rs); } } break; /***************************************************/ /* Transcript */ case 't': if ( cntx->transcript ) { fprintf(cntx->err, "WARNING: Transcript already open.\n"); fclose(cntx->transcript); cntx->transcript = 0; } { int errors = 0; do { if ( prompt_for_filename(cntx, "Transcript", file, sizeof(file)) ) { if ( (cntx->transcript = fopen(file, "w")) ) { int rs = getpid() ^ time(0); fprintf(cntx->transcript, "# biglife transcript 1.0\n"); fprintf(cntx->transcript, "S %d\n", rs); srand(getpid()); parm1 = parm2 = 1; } else { fprintf(cntx->err, "Cannot write '%s'\n", file); errors ++; } } else { break; } } while ( errors ); } break; case 'T': if ( cntx->transcript ) { fclose(cntx->transcript); cntx->transcript = 0; } else { fprintf(cntx->err, "Transcript not open.\n"); } break; /***************************************************/ /* Comment. */ case '#': cmdp = ""; break; /***************************************************/ /* Quit. */ case 'q': case 'Q': rtn = 0; return 1; break; /***************************************************/ /* Movement */ case 'z': zoom -= parm1; break; case 'Z': zoom += parm1; break; case 'g': cx = parm1; cy = parm2; break; case '1': case '2': case '3': { int i; for ( i = 0; i <= parm1; i ++ ) { switch ( cmdc ) { case '1': case '2': life_array_set_cell(src, cx, cy, cmdc - '1'); break; case '3': life_array_toggle_cell(src, cx, cy); break; } cx += dx; cy += dy; } if ( parm2 > 1 ) { cx -= dx * parm1; cy -= dy * parm1; } } break; case 'I': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case 'i': dx = 0; dy = - parm1; cy += dy; break; case 'J': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case 'j': dx = -parm1; dy = 0; cx += dx; break; case 'K': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case 'k': dx = parm1; dy = 0; cx += dx; break; case 'M': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case 'm': dx = 0; dy = parm1; cy += dy; break; case 'U': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case 'u': dx = -parm1; dy = -parm1; cx += dx; cy += dy; break; life_array_toggle_cell(src, cx, cy); case 'O': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case 'o': dx = +parm1; dy = -parm1; cx += dx; cy += dy; break; case 'N': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case 'n': dx = -parm1; dy = +parm1; cx += dx; cy += dy; break; case '<': life_array_toggle_cell(src, cx, cy); /* FALL THROUGH */ case ',': dx = +parm1; dy = +parm1; cx += dx; cy += dy; break; /***************************************************/ case 'x': { life_array *tmp; tmp = src; src = dst; dst = tmp; } break; case 'C': life_array_clear(src); life_array_clear(dst); break; case 'r': case '4': { int i, j; int x, y; y = cy - parm2 / 2; for ( i = parm2; i -- > 0; y ++ ) { x = cx - parm2 / 2; for ( j = parm2; j -- > 0; x ++ ) { if ( (rand() >> 8 & 32767) * 100 / 32767 < parm1 ) { if ( cmdc == '4' ) { life_array_toggle_cell(src, x, y); } else { life_array_set_cell(src, x, y, 1); } } } } life_array_cleanup(src); } break; case 'd': for ( i = parm2; i -- > 0; ) { int j; for ( j = 0; j < parm1; j ++ ) { life_cntx_iterate(cntx); } if ( i && parm2 ) { life_display_chunks(cntx); } } break; case '\r': case '\n': /* FALL THROUGH */ case 'p': for ( i = parm1; i -- > 0; ) { life_cntx_iterate(cntx); #if 0 /* Stop iterating if nothing changed */ if ( src->n_cells == dst->n_cells ) { i = 0; } #endif if ( i ) life_display_chunks(cntx); } break; case 'l': { int errors = 0; do { if ( prompt_for_filename(cntx, "Load", file, sizeof(file)) ) { errors = life_array_load_file(src, cx, cy, file); } else { break; } } while ( errors ); } break; case 's': { int errors = 0; do { if ( prompt_for_filename(cntx, "Save", file, sizeof(file)) ) { errors = life_array_save_file(src, cx, cy, parm1, parm2, file); } else { break; } } while ( errors ); } break; case 'R': { int errors = 0; do { if ( prompt_for_filename(cntx, "Run commands", file, sizeof(file)) ) { life_cntx new_cntx = *cntx; if ( (new_cntx.in = fopen(file, "r")) ) { new_cntx.out = 0; new_cntx.transcript = 0; errors = life_run_commands(&new_cntx); fclose(new_cntx.in); } else { fprintf(cntx->err, "Cannot read '%s'\n", file); errors ++; } } else { break; } } while ( errors ); } break; case 'e': if ( cntx->err ) { _life_chunk_print(&life_chunk_errors, cntx->err); if ( life_chunk_LIVE(&life_chunk_errors) ) exit(1); } /* FALL THROUGH */ prompt_continue: prompt_continue(cntx); break; case 'h': case '?': default: if ( cntx->err ) fprintf(cntx->err, "\ Commands are:\n\ g x y \t Goto chunk x,y. \n\ i n \t Move up n chunks; n is 1 by default. \n\ m n \t Move down n chunks. Shift toggles cell before move\n\ j n \t Move left n chunks. \n\ k n \t Move left n chunks. \n\ 1 n \t Clear cell at cursor. \n\ 2 n \t Set cell at cursor. \n\ 3 n \t Toggle cell at cursor. \n\ p \t Print n iterations. \n\ x \t Undo last iteration. \n\ d n \t Do n iterations and print. \n\ r d n \t Randomize n square chunks at density d. \n\ z \t Zoom in/(out) (shift). \n\ s sx sy \t Save a file of size sx sy; save all cells by default. \n\ l \t Load a file. \n\ C \t Clear all cells. \n\ t \t Create a transcript to a file. 'T' closes the transcript.\n\ R \t Run transcript from a file. \n\ S n \t Set random seed. \n\ q \t Quit. \n\ \n\ "); #if 0 #... \t Comment. \n\ e \t Print error calculation. \n\ #endif goto prompt_continue; } life_display_chunks(cntx); } return 0; } #undef cmd #undef file #undef parm1 #undef parm2 #ifdef line #undef line #endif #undef src #undef dst #undef cx #undef cy #undef dx #undef dy #undef zoom #undef rtn /*****************************************************************/ /* EOF */ biglife1.1/src/biglife/biglife.gdb0100644000175200017560000000024407001125046017402 0ustar stephensstepheng# $Id: biglife.gdb,v 1.4 1999/10/13 15:49:58 stephensk Exp $ #break main break run_commands break prompt_for_filename #break do_next #break do_chunk #disable 2 run biglife1.1/src/biglife/biglife.h0100644000175200017560000001331307013432113017075 0ustar stephensstepheng/* $Id: biglife.h,v 1.4 1999/11/14 04:02:19 stephensk Exp $ */ #ifndef _biglife_biglife_h #define _biglife_biglife_h /* Copyright 1998, 1999, Kurt A. Stephens http://www.acm.org/~stephensk */ #include /* FILE */ /**********************************************************/ typedef union life_pos { struct { short x, y; } p; unsigned long l; } life_pos; #define X(P) (P).p.x #define Y(P) (P).p.y #define HASH(P) (P).l /* ** A life_chunk represents an 8 x 8 pixel subimage. ** A life_chunk can only exist in a life_array if it has at least ** one non-zero pixel. ** (Actually, empty life_chunks do exist but only for a short time.) */ #ifndef life_chunk_SIZE_LOG2 #define life_chunk_SIZE_LOG2 3 #define life_chunk_SIZE (1 << life_chunk_SIZE_LOG2) #define life_chunk_SIZE_MASK (life_chunk_SIZE-1) #endif #if life_chunk_SIZE <= 8 typedef unsigned char life_chunk_word; #else #error Cannot implement life_chunk_SIZE > 8 #endif typedef struct life_chunk_bm { life_chunk_word b[life_chunk_SIZE]; } life_chunk_bm; typedef struct life_chunk { struct life_chunk *next; /* The next chunk in the hash bucket (or free list) */ life_pos p; /* The position of the chunk */ life_chunk_word b[life_chunk_SIZE]; /* 8 x 8 bits */ /* The bitmap of the chunk */ life_chunk_word changed; /* Did the chunk change? */ short n_bits; /* Number of bits in the chunk? < 0 if not yet computed. Used for zoomed out view. */ } life_chunk; #define life_chunk_CLEAR(e) (*(((long*)(e)->b)+1) = *((long*)(e)->b) = (e)->n_bits = 0) /* Clear out the chunk */ #define life_chunk_LIVE(e) (*(((long*)(e)->b)+1) || *((long*)(e)->b)) /* Is the chunk alive? */ #define life_chunk_modified(e) ((e)->n_bits = -1) /**********************************************************/ /* The "life" array. */ typedef struct life_array { life_chunk *cache; /* Last chunk looked up. */ #ifndef life_array_SIZE_ #define life_array_SIZE_ 1023 #endif life_chunk *chunks[life_array_SIZE_]; /* Only live life_chunks exist here */ life_chunk *new_chunks[life_array_SIZE_]; /* New chunks created during do_chunk, some might be dead. */ short add_to_new_chunks; /* non-zero if life_chunk_get should add to new_chunks hash table */ short needs_cleanup; /* non-zero if life_array needs clean up */ unsigned long n_chunks; /* Number of live chunks. */ unsigned long n_cells; /* Live cells. */ life_pos min, max; /* Min and max of chunks positions. */ unsigned long generation; /* Generation. */ } life_array; #define life_array_SIZE(A) life_array_SIZE_ /**********************************************************/ /* Chunk array iteration */ #define life_chunk_LOOP(src,chunks,chunk,PRE)\ { \ int chunk_i; \ for ( chunk_i = life_array_SIZE(src); chunk_i --; ) { \ life_chunk **cp = &(src->chunks[chunk_i]), *next_chunk = *cp, *chunk; \ PRE; \ while ( (chunk = next_chunk) ) { \ next_chunk = chunk->next; \ #define life_chunk_LOOP_END }}} extern const life_chunk life_chunk_zero; extern life_chunk life_chunk_errors; /**********************************************************/ /* evaluation context */ typedef struct life_cntx { FILE *in, *out, *err, *transcript; char line[128]; life_array _src, *src, _dst, *dst; int cx, cy, zoom; int dx, dy; char cmd[16]; char file[1024]; char *cmdp; int parm1, parm2; int rtn; /* Display primitives */ void (*term_clear)(struct life_cntx *cntx); void (*display_status)(struct life_cntx *cntx); void (*show_prompt)(struct life_cntx *cntx, const char *prompt); void (*display_chunks)(struct life_cntx *cntx); void *data[4]; } life_cntx; /**********************************************************/ /* state table */ extern life_chunk_word life_trans_table[1 << 9]; /* initialized by life_init() */ /**********************************************************/ /* public functions */ void life_init(); void life_array_init(life_array *a); void life_array_clear(life_array *a); life_chunk *life_array_get(life_array *a, int x, int y, int add); int life_array_get_cell(life_array *a, long cx, long cy); void life_array_toggle_cell(life_array *a, long cx, long cy); void life_array_set_cell(life_array *a, long cx, long cy, int value); int life_chunk_n_bits(life_chunk *c); void life_array_cleanup(life_array *dst); void life_array_iterate(life_array *src, life_array *dst); int life_array_chunk_loop(life_array *src, int (*fp)(life_array *src, life_chunk *c, void *data), void *data); /**********************************************************/ /* Display */ int life_status_line(life_cntx *cntx, int row, char *buf); void life_term_display_status(life_cntx *cntx); void life_display_status(life_cntx *cntx); void life_display_chunks(life_cntx *cntx); /**********************************************************/ /* I/O */ void life_chunk_print(life_array *src, int x, int y, FILE *fp); void _life_chunk_print(life_chunk *c, FILE *fp); int life_array_save_file(life_array *src, int x, int y, int xs, int ys, const char *file); int life_array_load_file(life_array *dst, int x, int y, const char *file); /* Translate a bit sequence into a string for printing */ extern char life_bit_string[0x100][life_chunk_SIZE + 1]; #define life_BIT_STRING(X) life_bit_string[X] extern char life_bit_string9[0x200][10]; #define life_BIT_STRING9(X) life_bit_string9[X] /**********************************************************/ /* Command execution */ extern const char life_command_keys[]; void life_cntx_init(life_cntx *cntx); int life_run_command(life_cntx *cntx, char *line); int life_run_commands(life_cntx *cntx); int life_read_and_run_command(life_cntx *cntx); /**********************************************************/ /* EOF */ #endif biglife1.1/src/biglife/biglife.in0100644000175200017560000000011106663227005017260 0ustar stephensstepheng# $Id: biglife.in,v 1.2 1999/02/19 09:25:25 stephensk Exp $ r n 45 e q biglife1.1/src/biglife/blgtk.c0100644000175200017560000000632307013432113016575 0ustar stephensstepheng#ifndef __rcs_id__ #ifndef __rcs_id_biglife_gbiglife_c__ #define __rcs_id_biglife_gbiglife_c__ static const char __rcs_id_biglife_gbiglife_c[] = "$Id: blgtk.c,v 1.2 1999/11/14 04:02:19 stephensk Exp $"; #endif #endif /* __rcs_id__ */ /* gbiglife.c */ /* Copyright 1998, 1999, Kurt A. Stephens http://www.acm.org/~stephensk */ #include "biglife.h" #include "gtklife.h" #include "term.h" #include #include #include #include #include #include /***********************************************************************/ /* main */ static life_cntx *cntx; static void gtk_display_chunks(life_cntx *cntx) { GtkLife *w = GTK_LIFE(cntx->data[0]); gtk_life_set_cntx(w, cntx); gtk_life_draw(GTK_WIDGET(w), NULL); } static void quit() { gtk_exit(0); } static gint KeyPress(GtkWidget *widget, GdkEventKey *event) { gint keyval = event->keyval; //fprintf(stderr, "KeyPress(%p, %x ('%c')\n", widget, keyval, keyval); switch ( keyval ) { case GDK_Left: keyval = 'j'; break; case GDK_Right: keyval = 'k'; break; case GDK_Up: keyval = 'i'; break; case GDK_Down: keyval = 'm'; break; } #if 0 if ( islower(keyval) && SHIFTED ) { keyval = toupper(keyval); } #endif if ( strchr(life_command_keys, keyval) ) { char line[3]; line[0] = keyval; line[1] = '\0'; life_run_command(cntx, line); life_display_chunks(cntx); return TRUE; } return FALSE; } static void gtk_command_ready(gpointer data, gint source, GdkInputCondition condition) { life_cntx *cntx = data; if ( life_read_and_run_command(cntx) ) { quit(); } } int main(int argc, char **argv) { life_cntx _cntx; cntx = &_cntx; gdk_set_use_xshm(1); gtk_init(&argc, &argv); /* Initialize random generator */ srand(time(0) ^ getpid()); /* Initialize life system */ life_init(); /* Set up stdin command context. */ memset(cntx, 0, sizeof(*cntx)); life_cntx_init(cntx); /* Set GTK display. */ { GtkWidget *window; GtkWidget *vbox; GtkWidget *drawing_area; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(quit), NULL); gtk_widget_set_events(window, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); drawing_area = gtk_life_new(cntx->src); gtk_widget_set_events(drawing_area, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); gtk_signal_connect(GTK_OBJECT(window), "key_press_event", (GtkSignalFunc) KeyPress, NULL); #if 0 vbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0); #else vbox = drawing_area; #endif gtk_container_add(GTK_CONTAINER(window), vbox); gtk_widget_show(drawing_area); gtk_widget_show(window); cntx->display_chunks = gtk_display_chunks; cntx->display_status = life_term_display_status; cntx->show_prompt = life_term_show_prompt; cntx->data[0] = drawing_area; } /* Register cntx->in for async input */ gtk_input_add_full(fileno(cntx->in), GDK_INPUT_READ, gtk_command_ready, NULL, cntx, NULL); life_display_chunks(cntx); /* Run app. */ gtk_main(); return 0; } biglife1.1/src/biglife/blterm.c0100644000175200017560000001145207013432113016756 0ustar stephensstepheng#ifndef __rcs_id__ #ifndef __rcs_id_biglife_blterm_c__ #define __rcs_id_biglife_blterm_c__ static const char __rcs_id_biglife_blterm_c[] = "$Id: blterm.c,v 1.3 1999/11/14 04:02:19 stephensk Exp $"; #endif #endif /* __rcs_id__ */ /* Copyright 1998, 1999, Kurt A. Stephens http://www.acm.org/~stephensk */ #include "biglife.h" #include "term.h" #include #include #include #include #include #include #include /*****************************************************************/ /* Terminal support */ /*****************************************************************/ /* Local tables */ static char ascii_grey[] = " 123456789ABCDEF"; #define ascii_grey_scale (sizeof(ascii_grey)-1) /*************************************************************************/ void life_term_display_chunks(life_cntx *cntx) { life_array *src = cntx->src; int cursx = cntx->cx; int cursy = cntx->cy; int zoom = cntx->zoom; FILE *out = cntx->err; int cx = (cursx - life_chunk_SIZE / 2) >> life_chunk_SIZE_LOG2, cy = (cursy - life_chunk_SIZE / 2) >> life_chunk_SIZE_LOG2; const char *colsep = " "; const char *rowsep = "\n"; #if 0 const char spaces[] = " "; #endif int P_W = 3, P_H = 2; if ( ! out ) return; /* Calculate the number of chunks to display based on term size. */ P_W = life_term_w - (9 /* left border */ + 2 /* right border */); P_W /= life_chunk_SIZE; P_H = life_term_h - (1 /* top border */ + 3 /* bottom border and prompt*/); P_H /= life_chunk_SIZE; /* Print the chunks */ colsep = rowsep = ""; /* Home the cursor */ life_term_home(out); { int i, j, k; int r, c; int row = 0; /* Top heading */ fprintf(out, " +"); for ( j = -P_W / 2, c = P_W; c -- > 0; j ++ ) { if ( 0 && j == 0 ) { fprintf(out, "Y %6d%s", cursx, colsep); } else { fprintf(out, "--------%s", colsep); } } fprintf(out, "+\n"); row = 0; for ( i = -P_H / 2, r = P_H; r -- > 0; i ++ ) { for ( k = 0; k < life_chunk_SIZE; k ++ ) { int cdy = (cy + i) * life_chunk_SIZE + k; char stat[16]; /* Side annotation. */ life_status_line(cntx, row, stat); fprintf(out, "%s|", stat); row ++; for ( j = -P_W / 2, c = P_W; c -- > 0; j ++ ) { int cdx = (cx + j) * life_chunk_SIZE; if ( zoom < 0 ) { int l; int zy = cy + i * life_chunk_SIZE + k; /* scan horzontally for each chunk */ fprintf(out, "%s", colsep); for ( l = 0; l < life_chunk_SIZE; l ++ ) { int zx = cx + j * life_chunk_SIZE + l; /* Show cursor. */ if ( zy * life_chunk_SIZE <= cursy && cursy < (zy + 1) * life_chunk_SIZE && zx * life_chunk_SIZE <= cursx && cursx < (zx + 1) * life_chunk_SIZE ) { fprintf(out, "x"); } else { life_chunk *c = life_array_get(src, zx, zy, 0); unsigned int v = life_chunk_n_bits(c); /* Scale it to grey scale value. */ v = (v * ascii_grey_scale + ascii_grey_scale - 1) / (life_chunk_SIZE * life_chunk_SIZE); if ( v >= ascii_grey_scale ) v = ascii_grey_scale - 1; fprintf(out, "%c", ascii_grey[v]); } } } else { life_chunk *c = life_array_get(src, cx + j, cy + i, 0); if ( cdy == cursy && cdx <= cursx && cursx < cdx + life_chunk_SIZE ) { char buf[32]; int bx = cursx - cdx; strcpy(buf, life_BIT_STRING(c->b[k])); buf[bx] = (c->b[k] & (1 << bx)) ? 'X' : 'x'; fprintf(out, "%s%s", colsep, buf); } else { fprintf(out, "%s%s", colsep, life_BIT_STRING(c->b[k])); } } } fprintf(out, "|\n"); } fprintf(out, "%s", rowsep); } /* Bottom heading */ fprintf(out, " +"); for ( j = -P_W / 2, c = P_W; c -- > 0; j ++ ) { if ( 0 && j == 0 ) { fprintf(out, "Y %6d%s", cursx, colsep); } else { fprintf(out, "--------%s", colsep); } } fprintf(out, "+\n"); } //fprintf(out, "P_W %d P_H %d\n", P_W, P_H); } /*****************************************************************/ static life_cntx *sig_cntx; static void term_redraw() { life_term_get_size(); if ( sig_cntx ) { life_display_chunks(sig_cntx); } } int main(int argc, char **argv) { life_cntx _cntx, *cntx = &_cntx; /* Get terminal size */ life_term_get_size(); #ifdef SIGWINCH sig_cntx = cntx; signal(SIGWINCH, &term_redraw); #endif /* Set up stdin command context. */ memset(cntx, 0, sizeof(*cntx)); life_cntx_init(cntx); /* Set up terminal display */ cntx->term_clear = life_term_clear; cntx->display_chunks = life_term_display_chunks; /* Initialize random generator */ srand(time(0) ^ getpid()); /* Initialize life system */ life_init(); /* Run commands from stdin */ return life_run_commands(cntx); } /*****************************************************************/ biglife1.1/src/biglife/gtklife.c0100644000175200017560000003147107013432114017122 0ustar stephensstepheng#include "gtklife.h" static GtkWidgetClass *parent_class = NULL; static void gtk_life_class_init(GtkWidgetClass *klass); static void gtk_life_init(GtkLife *w); static void gtk_life_realize(GtkWidget *w); //static void gtk_life_draw(GtkWidget *w, GdkRectangle *area); static void gtk_life_size_request(GtkWidget *w, GtkRequisition *req); static void gtk_life_size_allocate(GtkWidget *widget, GtkAllocation *req); static gint gtk_life_configure(GtkWidget *widget, GdkEventConfigure *event); static gint gtk_life_expose(GtkWidget *w, GdkEventExpose *event); static void gtk_life_destroy(GtkObject *w); guint gtk_life_get_type(void) { static guint type = 0; if ( ! type ) { GtkTypeInfo info = { "GtkLife", sizeof(GtkLife), sizeof(GtkLifeClass), (GtkClassInitFunc) gtk_life_class_init, (GtkObjectInitFunc) gtk_life_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL }; type = gtk_type_unique(gtk_widget_get_type(), &info); } return type; } static void gtk_life_class_init(GtkWidgetClass *cls) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass *) cls; widget_class = (GtkWidgetClass *) cls; parent_class = gtk_type_class(gtk_widget_get_type()); object_class->destroy = gtk_life_destroy; widget_class->realize = gtk_life_realize; widget_class->draw = gtk_life_draw; widget_class->size_request = gtk_life_size_request; widget_class->size_allocate = gtk_life_size_allocate; widget_class->configure_event = gtk_life_configure; widget_class->expose_event = gtk_life_expose; } static void gtk_life_init(GtkLife *w) { /* GtkWidget *widget = (GtkWidget*) w; */ w->src = 0; w->cx = w->cy = 0; w->zoom = 0; w->needs_redraw = 2; w->use_pixmap = 0; w->pixmap = 0; } GtkWidget *gtk_life_new(life_array *src) { GtkLife *w; w = (GtkLife*) gtk_type_new(gtk_life_get_type()); w->src = src; return (GtkWidget*) w; } static void gtk_life_realize(GtkWidget *widget) { GtkLife *w; GdkWindowAttr a; gint a_mask; g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_LIFE(widget)); w = GTK_LIFE(widget); GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); a.window_type = GDK_WINDOW_CHILD; a.x = widget->allocation.x; a.y = widget->allocation.y; a.width = widget->allocation.width; a.height = widget->allocation.height; a.wclass = GDK_INPUT_OUTPUT; a.visual = gtk_widget_get_visual(widget); a.colormap = gtk_widget_get_colormap(widget); a.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK; a_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &a, a_mask); gdk_window_set_user_data(widget->window, w); widget->style = gtk_style_attach(widget->style, widget->window); gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); } void gtk_life_set_src(GtkLife *life, life_array *src) { g_return_if_fail(life != NULL); g_return_if_fail(GTK_IS_LIFE(life)); if ( life->src != src && life->needs_redraw < 1) life->needs_redraw = 1; life->src = src; } void gtk_life_set_position(GtkLife *life, int cx, int cy) { g_return_if_fail(life != NULL); g_return_if_fail(GTK_IS_LIFE(life)); if ( (life->cx != cx || life->cy != cy) && life->needs_redraw < 2 ) life->needs_redraw = 2; life->cx = cx; life->cy = cy; } void gtk_life_set_zoom(GtkLife *life, int zoom) { g_return_if_fail(life != NULL); g_return_if_fail(GTK_IS_LIFE(life)); if ( life->zoom != zoom && life->needs_redraw < 1 ) life->needs_redraw = 2; life->zoom = zoom; } void gtk_life_set_cntx(GtkLife *life, life_cntx *cntx) { g_return_if_fail(life != NULL); g_return_if_fail(GTK_IS_LIFE(life)); if ( life->cntx != cntx && life->needs_redraw < 2 ) life->needs_redraw = 2; life->cntx = cntx; } #ifndef USE_BM_CACHE #define USE_BM_CACHE 0 #endif #if USE_BM_CACHE /***********************************************************************/ /* Use a cache of GdkBitmaps for each life_chunk_bm */ #ifndef bmc_size #define bmc_size 101 #endif #ifndef USE_BITMAP #define USE_BITMAP 1 #endif #if USE_BITMAP #define GBM GdkBitmap #else #define GBM GdkPixmap #endif static struct bitmap_cache { life_chunk_bm lbm; GBM *gbm; } bmc[bmc_size]; static GBM* lbm_to_gbm (GdkWindow *window, life_chunk_bm *bm) { /* Compute a hash of the life_chunk_bm */ unsigned long hash = 0; { unsigned long *x = (void*) bm; switch ( sizeof(*bm)/sizeof(*x) ) { default: abort(); case 4: hash ^= x[3]; case 3: hash ^= x[2]; case 2: hash ^= x[1]; case 1: hash ^= x[0]; } } hash %= bmc_size; /* ** If there is no GdkBitmap for the life_chunk_bm, ** create one and store it in the hash. */ if ( ! bmc[hash].gbm ) { fill_cache: bmc[hash].lbm = *bm; #if USE_BITMAP bmc[hash].gbm = gdk_bitmap_create_from_data(window, (gchar*) &bmc[hash].lbm, life_chunk_SIZE, life_chunk_SIZE); #else { GdkColormap *cmap = gdk_window_get_colormap(window); GdkColor *black = 0, *white = 0; GdkColor _black = { 0, 0, 0, 0 }; GdkColor _white = { 0, 0xffff, 0xffff, 0xffff }; black = &_black; white = &_white; gdk_color_alloc(cmap, black); gdk_color_alloc(cmap, white); bmc[hash].gbm = gdk_pixmap_create_from_data(window, (gchar*) &bmc[hash].lbm, life_chunk_SIZE, life_chunk_SIZE, 1, black, white ); } #endif } else if ( memcmp(&bmc[hash].lbm, bm, sizeof(*bm)) != 0 ) { /* ** If a GdkBitmap existed but doesn't match bm. ** free it and create a new one. */ #if USE_BITMAP gdk_bitmap_unref(bmc[hash].gbm); #else gdk_pixmap_unref(bmc[hash].gbm); #endif goto fill_cache; } return bmc[hash].gbm; } #endif /***********************************************************************/ /* drawing */ static void gtk_life_allocate_pixmap(GtkWidget *widget, gint width, gint height) { GtkLife *w = GTK_LIFE(widget); if ( w->pixmap && (w->pixmap_w != width || w->pixmap_h != height) ) { gdk_pixmap_unref(w->pixmap); w->pixmap = 0; } if ( w->use_pixmap && ! w->pixmap ) { w->pixmap = gdk_pixmap_new(widget->window, w->pixmap_w = width, w->pixmap_h = height, -1); //fprintf(stderr, "%p allocate_pixmap %p\n", widget, w->pixmap); } } void gtk_life_draw(GtkWidget *widget, GdkRectangle *area) { GtkLife *w; if ( 0 ) { static int count; fprintf(stderr, "gtk_life_draw(%d)\n", ++ count); } g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_LIFE(widget)); if ( ! GTK_WIDGET_DRAWABLE(widget) ) return; w = GTK_LIFE(widget); g_return_if_fail(w->src != NULL); /* Load from cntx if available */ if ( w->cntx ) { gtk_life_set_src(w, w->cntx->src); gtk_life_set_position(w, w->cntx->cx, w->cntx->cy); gtk_life_set_zoom(w, w->cntx->zoom); } { int cursx = w->cx; int cursy = w->cy; life_array *src = w->src; GdkWindow *window = widget->window; GdkDrawable *drawable; GdkGC *gc = widget->style->fg_gc[GTK_STATE_NORMAL]; gint term_w, term_h; int P_W, P_H; int cx, cy; int i, j; int r, c; term_w = widget->allocation.width; term_h = widget->allocation.height; if ( w->use_pixmap ) { gtk_life_allocate_pixmap(widget, term_w, term_h); } if ( w->use_pixmap && w->pixmap ) { drawable = w->pixmap; //fprintf(stderr, "%p draw w->pixmap = %p\n", w, w->pixmap); } else { drawable = window; } /* Non-incremental update */ gdk_draw_rectangle(drawable, widget->style->bg_gc[GTK_WIDGET_STATE(widget)], TRUE, 0, 0, widget->allocation.width, widget->allocation.height ); /* Zoomed in */ if ( w->zoom > 0 ) { r = w->zoom + 1; c = w->zoom == 1 ? r : w->zoom; cy = cursy - term_h / r / 2; for ( j = - r / 2; j < term_h; j += r, cy ++ ) { cx = cursx - term_w / r / 2; for ( i = - r / 2; i < term_w; i += r, cx ++ ) { int on_cursor = cy == cursy && cx == cursx; if ( life_array_get_cell(src, cx, cy) ) { gdk_draw_rectangle(drawable, gc, 1, i, j, c, c); } if ( on_cursor ) { gdk_draw_rectangle(drawable, widget->style->bg_gc[GTK_STATE_SELECTED], 0, i - 1, j - 1, r, r); } } } } else if ( w->zoom < 0 ) { /* Zoom out */ cy = cursy >> life_chunk_SIZE_LOG2; cy = cy - term_h / 2; #if 0 /* do each pixel */ for ( j = 0; j < term_w; j ++, cy ++ ) { cx = cursx >> life_chunk_SIZE_LOG2; cx = cx - term_w / 2; for ( i = 0; i < term_w; i ++, cx ++ ) { life_chunk *c = life_array_get(src, cx, cy, 0); if ( life_chunk_LIVE(c) ) { gdk_draw_point(drawable, gc, i, j); } } } #else /* Do each live chunk */ cx = cursx >> life_chunk_SIZE_LOG2; cx = cx - term_w / 2; life_array_cleanup(src); life_chunk_LOOP(src, chunks, c, (void)0); { i = c->p.p.x - cx; j = c->p.p.y - cy; g_assert(life_chunk_LIVE(c)); if ( 0 <= i && i < term_w && 0 <= j && j < term_h ) { gdk_draw_point(drawable, gc, i, j); } } life_chunk_LOOP_END; #endif } else { /* No Zoom */ cx = cursx >> life_chunk_SIZE_LOG2, cy = cursy >> life_chunk_SIZE_LOG2; /* Calculate the number of chunks to display based on term size. */ P_W = term_w; P_W /= life_chunk_SIZE; P_H = term_h; P_H /= life_chunk_SIZE; for ( i = -P_H / 2, r = 0; r < P_H; i ++, r ++ ) { int dy = r * life_chunk_SIZE; for ( j = -P_W / 2, c = 0; c < P_W; j ++, c ++ ) { int dx = c * life_chunk_SIZE; life_chunk *c = life_array_get(src, cx + j, cy + i, 0); #if USE_BM_CACHE GBM *bm = lbm_to_gbm(window, (life_chunk_bm*) &c->b); #if USE_BITMAP gdk_draw_bitmap(drawable, gc, bm, 0, 0, dx, dy, life_chunk_SIZE, life_chunk_SIZE); #else gdk_draw_pixmap(drawable, gc, bm, 0, 0, dx, dy, life_chunk_SIZE, life_chunk_SIZE); #endif #else /* Use dumb single pixel routines */ if ( life_chunk_n_bits(c) ) { int k, l; //fprintf(stderr, "draw CHUNK %d %d %d\n", cx - j, cy - i, life_chunk_n_bits(c)); for ( k = 0; k < life_chunk_SIZE; k ++ ) { for ( l = 0; l < life_chunk_SIZE; l ++ ) { if ( c->b[k] & (1 << l) ) { gdk_draw_point(drawable, gc, dx + l, dy + k); } } } } #endif } /* Draw cursor */ //gdk_draw_line(drawable, gc); } } } /* Draw pixmap to window */ if ( w->use_pixmap && w->pixmap ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], w->pixmap, 0, 0, 0, 0, widget->allocation.height, widget->allocation.width); } } static void gtk_life_size_request(GtkWidget *widget, GtkRequisition *req) { GTK_WIDGET_CLASS(parent_class)->size_request(widget, req); req->width = 64; req->height = 64; } static void gtk_life_size_allocate(GtkWidget *widget, GtkAllocation *req) { #if 0 //fprintf(stderr, "%p size_allocation\n", widget); gtk_life_allocate_pixmap(widget, req->width, req->height); #endif GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, req); } static gint gtk_life_configure(GtkWidget *widget, GdkEventConfigure *event) { GtkLife *w; #define return return FALSE g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_LIFE(widget)); g_return_if_fail(event != NULL); #undef return w = GTK_LIFE(widget); //fprintf(stderr, "%p configure\n", w); #if 0 gtk_life_allocate_pixmap(widget, widget->allocation.width, widget->allocation.height); #endif GTK_WIDGET_CLASS(parent_class)->configure_event(widget, event); return TRUE; } static gint gtk_life_expose(GtkWidget *widget, GdkEventExpose *event) { GtkLife *w; #define return return FALSE g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_LIFE(widget)); g_return_if_fail(event != NULL); #undef return if ( event->count > 0 ) return(FALSE); w = GTK_LIFE(widget); //fprintf(stderr, "%p expose\n", w); if ( w->use_pixmap && w->pixmap ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], w->pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); } else { gtk_life_draw(widget, NULL); } return TRUE; } static void gtk_life_destroy(GtkObject *widget) { GtkLife *w; g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_LIFE(widget)); w = GTK_LIFE(widget); if ( w->pixmap ) { gdk_pixmap_unref(w->pixmap); w->pixmap = 0; } GTK_OBJECT_CLASS(parent_class)->destroy(widget); } biglife1.1/src/biglife/gtklife.h0100644000175200017560000000223407031471015017125 0ustar stephensstepheng#ifndef _biglife_gtklife_h #define _biglife_gtklife_h /* $Id: gtklife.h,v 1.3 1999/12/26 19:52:45 stephensk Exp $ */ #include #include #include "biglife.h" #ifdef __cplusplus extern "C" { #endif guint gtk_life_get_type(void); #define GTK_LIFE(obj) \ GTK_CHECK_CAST(obj, gtk_life_get_type(), GtkLife) #define GTK_LIFE_CLASS(klass) \ GTK_CHECK_CLASS_CAST(klass, gtk_life_get_type(), GtkLifeClass) #define GTK_IS_LIFE(obj) \ GTK_CHECK_TYPE(obj, gtk_life_get_type()) typedef struct _GtkLife GtkLife; typedef struct _GtkLifeClass GtkLifeClass; struct _GtkLife { GtkWidget vbox; gint use_pixmap; GdkPixmap *pixmap; gint pixmap_w, pixmap_h; life_cntx *cntx; life_array *src; gint cx, cy; gint zoom; int needs_redraw; }; struct _GtkLifeClass { GtkWidgetClass parent_class; }; GtkWidget *gtk_life_new(life_array *src); void gtk_life_set_cntx(GtkLife *w, life_cntx *cntx); void gtk_life_set_src(GtkLife *w, life_array *src); void gtk_life_set_position(GtkLife *w, int cx, int cy); void gtk_life_set_zoom(GtkLife *w, int zoom); void gtk_life_draw(GtkWidget *widget, GdkRectangle *area); #ifdef __cplusplus } #endif #endif biglife1.1/src/biglife/life.c0100644000175200017560000000060407010516430016407 0ustar stephensstephengmain(){char z[2][24][80],*a,*b,*c,*d,*e;int q,p=-1,x,y,i,k;srand(time(0));while (1){for(strcpy(d=z[b=e=z[q=p][22],a=b-80,c=z[p],p=!p][y=23]," life.c (c) 1999 \ stephensk@acm.org \033[H");y--;c=b,b=a,a=y-1?a-80:e)for((d-=80)[x=79]=10;x--;)i =x?x-1:78,k=x-78?x+1:0,d[x]=" *\n"[q<0?rand()>>8&1:(k=a[i]+a[x]+a[k]+b[i]+b[k]+ c[i]+c[x]+c[k])-276?!(k-286):b[x]/42];write(1,z+p,1878);sleep(1);}} biglife1.1/src/biglife/term.c0100644000175200017560000000340407031470771016452 0ustar stephensstepheng#ifndef __rcs_id__ #ifndef __rcs_id_biglife_blterm_c__ #define __rcs_id_biglife_blterm_c__ static const char __rcs_id_biglife_blterm_c[] = "$Id: term.c,v 1.2 1999/12/26 19:52:25 stephensk Exp $"; #endif #endif /* __rcs_id__ */ /* Copyright 1998, 1999, Kurt A. Stephens http://www.acm.org/~stephensk */ #include "term.h" #include #include #include #include #include /*****************************************************************/ /* Terminal query */ int life_term_w = 80, life_term_h = 24; void life_term_get_size() { FILE *fp; int h = -1, w = -1; const char *e; if ( (fp = popen("stty size", "r")) ) { fscanf(fp, "%d %d", &h, &w); pclose(fp); } if ( h <= 0 ) { if ( (e = getenv("LINES")) ) h = atoi(e); } if ( w <= 0 ) { if ( (e = getenv("COLUMNS")) ) w = atoi(e); } if ( h > 0 ) { life_term_h = h; } if ( w > 0 ) { life_term_w = w; } //fprintf(stderr, "term [%d, %d]\n", life_term_w, life_term_h); } void life_term_home(FILE *out) { fprintf(out, "\033[H"); fflush(out); } void life_term_clear(life_cntx *cntx) { fprintf(cntx->err, "\033[H\033[J"); fflush(cntx->err); } void life_term_display_status(life_cntx *cntx) { char buf[16]; int row = 0; if ( cntx->err && isatty(fileno(cntx->err)) ) { life_term_clear(cntx); while ( life_status_line(cntx, row, buf) ) { fprintf(cntx->err, "%s\n", buf); row ++; } } } void life_term_show_prompt(life_cntx *cntx, const char *prompt) { if ( cntx->in && isatty(fileno(cntx->in)) && cntx->err && isatty(fileno(cntx->err)) ) { fprintf(cntx->err, "\r%s %s \033[K", prompt, strchr(prompt, ':') ? "" : "('?' for help):"); fflush(cntx->err); } } biglife1.1/src/biglife/term.h0100644000175200017560000000107107013432114016442 0ustar stephensstepheng#ifndef _biglife_TERM_H #define _biglife_TERM_H #ifndef __rcs_id__ #ifndef __rcs_id_biglife_term_h__ #define __rcs_id_biglife_term_h__ static const char __rcs_id_biglife_term_h[] = "$Id: term.h,v 1.1 1999/11/14 04:02:20 stephensk Exp $"; #endif #endif /* __rcs_id__ */ #include "biglife.h" #include extern int life_term_w, life_term_h; void life_term_get_size(); void life_term_clear(life_cntx *cntx); void life_term_home(FILE *out); void life_term_display_status(life_cntx *cntx); void life_term_show_prompt(life_cntx *cntx, const char *prompt); #endif biglife1.1/src/biglife/lib/0040755000175200017560000000000007236675451016120 5ustar stephensstephengbiglife1.1/src/biglife/lib/CVS/0040755000175200017560000000000007236675451016553 5ustar stephensstephengbiglife1.1/src/biglife/lib/CVS/Root0100644000175200017560000000003407236675451017413 0ustar stephensstepheng:local://cvs/ioncvs/cvsroot biglife1.1/src/biglife/lib/CVS/Repository0100644000175200017560000000003107236675451020644 0ustar stephensstephenghome/ion/src/biglife/lib biglife1.1/src/biglife/lib/CVS/Entries0100644000175200017560000000001607236675451020101 0ustar stephensstephengD/biglife//// biglife1.1/src/biglife/lib/biglife/0040755000175200017560000000000007236675451017521 5ustar stephensstephengbiglife1.1/src/biglife/lib/biglife/CVS/0040755000175200017560000000000007236675451020154 5ustar stephensstephengbiglife1.1/src/biglife/lib/biglife/CVS/Root0100644000175200017560000000003407236675451021014 0ustar stephensstepheng:local://cvs/ioncvs/cvsroot biglife1.1/src/biglife/lib/biglife/CVS/Repository0100644000175200017560000000004107236675451022246 0ustar stephensstephenghome/ion/src/biglife/lib/biglife biglife1.1/src/biglife/lib/biglife/CVS/Entries0100644000175200017560000000434307236675451021511 0ustar stephensstepheng/acorn/1.1/Wed Oct 13 15:49:58 1999// /bakery/1.1/Wed Oct 13 15:49:58 1999// /barberpole/1.1/Wed Oct 13 15:49:58 1999// /barge/1.1/Wed Oct 13 15:49:58 1999// /beacon/1.1/Wed Oct 13 15:49:58 1999// /beehive/1.1/Wed Oct 13 15:49:58 1999// /bhepto/1.1/Wed Oct 13 15:49:58 1999// /biboat/1.1/Wed Oct 13 15:49:58 1999// /bigs/1.1/Wed Oct 13 15:49:58 1999// /biloaf/1.1/Wed Oct 13 15:49:58 1999// /bipond/1.1/Wed Oct 13 15:49:58 1999// /blinker/1.1/Wed Oct 13 15:49:58 1999// /block/1.1/Wed Oct 13 15:49:58 1999// /boat/1.1/Wed Oct 13 15:49:59 1999// /canoe/1.1/Wed Oct 13 15:49:59 1999// /century/1.1/Wed Oct 13 15:49:59 1999// /clock/1.1/Wed Oct 13 15:49:59 1999// /clock2/1.1/Wed Oct 13 15:49:59 1999// /eater/1.1/Wed Oct 13 15:49:59 1999// /fleet/1.1/Wed Oct 13 15:49:59 1999// /flipflop/1.1/Wed Oct 13 15:49:59 1999// /flotilla/1.1/Wed Oct 13 15:49:59 1999// /flyingmachine/1.1/Wed Oct 13 15:49:59 1999// /flyingmachineb/1.1/Wed Oct 13 15:49:59 1999// /flyingmachinex/1.1/Wed Oct 13 15:49:59 1999// /galaxy/1.1/Wed Oct 13 15:49:59 1999// /glider/1.1/Wed Oct 13 15:49:59 1999// /glidergun/1.1/Wed Oct 13 15:49:59 1999// /hat/1.1/Wed Oct 13 15:50:00 1999// /herschel/1.1/Wed Oct 13 15:50:00 1999// /hexadec/1.1/Wed Oct 13 15:50:00 1999// /honeyfarm/1.1/Wed Oct 13 15:50:00 1999// /interchange/1.1/Wed Oct 13 15:50:00 1999// /loaf/1.1/Wed Oct 13 15:50:00 1999// /mango/1.1/Wed Oct 13 15:50:00 1999// /p15/1.1/Wed Oct 13 15:50:00 1999// /paperclip/1.1/Wed Oct 13 15:50:00 1999// /pentadec/1.1/Wed Oct 13 15:50:00 1999// /pihepto/1.1/Wed Oct 13 15:50:00 1999// /pond/1.1/Wed Oct 13 15:50:00 1999// /puffer/1.1/Wed Oct 13 15:50:00 1999// /pulsar/1.1/Wed Oct 13 15:50:01 1999// /rpent/1.1/Wed Oct 13 15:50:01 1999// /shillelagh/1.1/Wed Oct 13 15:50:01 1999// /ship/1.1/Wed Oct 13 15:50:01 1999// /shiptie/1.1/Wed Oct 13 15:50:01 1999// /shuttle/1.1/Wed Oct 13 15:50:01 1999// /snake/1.1/Wed Oct 13 15:50:01 1999// /spacerake/1.1/Wed Oct 13 15:50:01 1999// /spaceship/1.1/Wed Oct 13 15:50:01 1999// /spaceshiph/1.1/Wed Oct 13 15:50:01 1999// /spaceshipm/1.1/Wed Oct 13 15:50:01 1999// /switchengine/1.1/Wed Oct 13 15:50:01 1999// /toad/1.1/Wed Oct 13 15:50:01 1999// /ttetro/1.1/Wed Oct 13 15:50:01 1999// /tub/1.1/Wed Oct 13 15:50:01 1999// /tumbler/1.1/Wed Oct 13 15:50:02 1999// D biglife1.1/src/biglife/lib/biglife/acorn0100644000175200017560000000010307001125046020511 0ustar stephensstepheng # # ## ### EOF Name: Acorn Discoverer: Charles Corderman biglife1.1/src/biglife/lib/biglife/bakery0100644000175200017560000000004707001125046020673 0ustar stephensstepheng # # # ### # # EOF Name: Bakery biglife1.1/src/biglife/lib/biglife/barberpole0100644000175200017560000000014007001125046021525 0ustar stephensstepheng## # # # # # # # # # # # # ## EOF Period: 2 biglife1.1/src/biglife/lib/biglife/barge0100644000175200017560000000002407001125046020471 0ustar stephensstepheng # # # # # # EOF biglife1.1/src/biglife/lib/biglife/beacon0100644000175200017560000000003607001125046020643 0ustar stephensstepheng ## ## ## ## EOF Period: 2 biglife1.1/src/biglife/lib/biglife/beehive0100644000175200017560000000002107001125046021015 0ustar stephensstepheng ## # # ## EOF biglife1.1/src/biglife/lib/biglife/bhepto0100644000175200017560000000040107001125046020671 0ustar stephensstepheng # ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # EOF Name: B Heptomino Shuttle Period: 46 biglife1.1/src/biglife/lib/biglife/biboat0100644000175200017560000000006307001125046020654 0ustar stephensstepheng # # # ## ## # # # EOF Name: Biboat biglife1.1/src/biglife/lib/biglife/bigs0100644000175200017560000000006507001125046020342 0ustar stephensstepheng ## # # # ## ## # # # ## EOF Name: Big S biglife1.1/src/biglife/lib/biglife/biloaf0100644000175200017560000000010007001125046020640 0ustar stephensstepheng ## # # # # # ## # # # # # EOF Name: Biloaf biglife1.1/src/biglife/lib/biglife/bipond0100644000175200017560000000010107001125046020660 0ustar stephensstepheng ## # # # # ## ## # # # # ## EOF Name: Bipond biglife1.1/src/biglife/lib/biglife/blinker0100644000175200017560000000002207001125046021035 0ustar stephensstepheng### EOF Period: 2 biglife1.1/src/biglife/lib/biglife/block0100644000175200017560000000002707001125046020506 0ustar stephensstepheng## ## EOF Name: Block biglife1.1/src/biglife/lib/biglife/boat0100644000175200017560000000001707001125047020341 0ustar stephensstepheng ## # # # EOF biglife1.1/src/biglife/lib/biglife/canoe0100644000175200017560000000003407001125047020500 0ustar stephensstepheng ## # # # # ## EOF biglife1.1/src/biglife/lib/biglife/century0100644000175200017560000000004107001125047021102 0ustar stephensstepheng # ## ## # EOF Name: Century biglife1.1/src/biglife/lib/biglife/clock0100644000175200017560000000003507001125047020507 0ustar stephensstepheng # ## ## # EOF Period: 2 biglife1.1/src/biglife/lib/biglife/clock20100644000175200017560000000016007001125047020570 0ustar stephensstepheng ## ## #### # # ## # # # ## ## # # # ## # # # #### ## ## EOF Period: 4 biglife1.1/src/biglife/lib/biglife/eater0100644000175200017560000000003607001125047020515 0ustar stephensstepheng ## # ### # EOF Period: 2 biglife1.1/src/biglife/lib/biglife/fleet0100644000175200017560000000004107001125047020510 0ustar stephensstepheng## # # ## # EOF Name: Fleet biglife1.1/src/biglife/lib/biglife/flipflop0100644000175200017560000000007607001125047021234 0ustar stephensstepheng # # # # ## ## # # # # EOF Period: 2 biglife1.1/src/biglife/lib/biglife/flotilla0100644000175200017560000000030007001125047021215 0ustar stephensstepheng #### ###### #### ## ## # # # # # # ############# #### ###### #### ## ## EOF Name: Flotilla Period: 4 biglife1.1/src/biglife/lib/biglife/flyingmachine0100644000175200017560000000016207001125047022232 0ustar stephensstepheng #### # # # ## # # ### ## # # # # # #### EOF Name: Flying Machine biglife1.1/src/biglife/lib/biglife/flyingmachineb0100644000175200017560000000065607001125047022404 0ustar stephensstepheng ## # # # # # ###### ## ## ## ## # #### ## # # ## # ## # ## # # ## ## # #### # # ## ## ## ## ## # # # # # ###### EOF Name: Flying Machine Blocker biglife1.1/src/biglife/lib/biglife/flyingmachinex0100644000175200017560000000016207001125047022422 0ustar stephensstepheng ## ## # # #### ## # ## # # ## # ## # #### ## # ## EOF biglife1.1/src/biglife/lib/biglife/galaxy0100644000175200017560000000014707001125047020705 0ustar stephensstepheng###### ## ###### ## ## ## ## ## ## ## ## ## ## ###### ## ###### EOF Period: 8 biglife1.1/src/biglife/lib/biglife/glider0100644000175200017560000000004607001125047020664 0ustar stephensstepheng### # # EOF Name: Glider Period: 4 biglife1.1/src/biglife/lib/biglife/glidergun0100644000175200017560000000215307001125047021377 0ustar stephensstepheng # # # # # # ## # # ## ## # # # ### ## # ### # ## # # # # # # ## # ## # # # # # # ## ## # # # # # ## # # # ### # # EOF Name: Glider Gun Discoverer: R. William Gosper, Jr., Robert April, Micheal Beeler, Richard Howell, Rich Schroeppel, Micheal Speciner. biglife1.1/src/biglife/lib/biglife/hat0100644000175200017560000000004207001125050020160 0ustar stephensstepheng # # # # # ## ## EOF Name: Hat biglife1.1/src/biglife/lib/biglife/herschel0100644000175200017560000000005607001125050021206 0ustar stephensstepheng# ### # # # EOF Name: "Herschel" pentomino biglife1.1/src/biglife/lib/biglife/hexadec0100644000175200017560000000010007001125050021000 0ustar stephensstepheng ## # # ## #### # # ## ## EOF Name: Hexadecimalbiglife1.1/src/biglife/lib/biglife/honeyfarm0100644000175200017560000000003607001125050021377 0ustar stephensstepheng####### EOF Name: Honey farm biglife1.1/src/biglife/lib/biglife/interchange0100644000175200017560000000005607001125050021700 0ustar stephensstepheng # # # # # # ## ## EOF Name: Interchange biglife1.1/src/biglife/lib/biglife/loaf0100644000175200017560000000002407001125050020325 0ustar stephensstepheng ## # # # # # EOF biglife1.1/src/biglife/lib/biglife/mango0100644000175200017560000000003007001125050020502 0ustar stephensstepheng ## # # # # ## EOF biglife1.1/src/biglife/lib/biglife/p150100644000175200017560000000155407001125050020022 0ustar stephensstepheng ## ## ## ## # ## ## # ## # ### ### # ## # # # ## ## # # # # # # # # # # # ## # # # # ## ## ## ### ### ### ### # # # # ### ### ### ### ## ## ## # # # # ## # # # # # # # # # # # ## ## # # # ## # ### ### # ## # ## ## # ## ## ## ## EOF Period: 15 biglife1.1/src/biglife/lib/biglife/paperclip0100644000175200017560000000006507001125050021370 0ustar stephensstepheng ## # # # ## ## # # # ## EOF Name: Paper clip biglife1.1/src/biglife/lib/biglife/pentadec0100644000175200017560000000012407001125050021170 0ustar stephensstepheng # # # # ### ###### ### # # # # EOF Name: Pentadecathlon Period: 15 biglife1.1/src/biglife/lib/biglife/pihepto0100644000175200017560000000004507001125050021057 0ustar stephensstepheng### # # # # EOF Name: Pi Heptomino biglife1.1/src/biglife/lib/biglife/pond0100644000175200017560000000002607001125050020346 0ustar stephensstepheng ## # # # # ## EOF biglife1.1/src/biglife/lib/biglife/puffer0100644000175200017560000000024107001125050020674 0ustar stephensstepheng ### ### # # # # # ### # # # # # # # # EOF Name: B Heptomino Puffer Train Discoverer: John Horton Conway biglife1.1/src/biglife/lib/biglife/pulsar0100644000175200017560000000003207001125051020712 0ustar stephensstepheng##### # # EOF Period: 3 biglife1.1/src/biglife/lib/biglife/rpent0100644000175200017560000000004107001125051020534 0ustar stephensstepheng ## ## # EOF Name: R Pentomino biglife1.1/src/biglife/lib/biglife/shillelagh0100644000175200017560000000002607001125051021523 0ustar stephensstepheng## # # # # ## EOF biglife1.1/src/biglife/lib/biglife/ship0100644000175200017560000000003207001125051020347 0ustar stephensstepheng ## # # ## EOF Name: Ship biglife1.1/src/biglife/lib/biglife/shiptie0100644000175200017560000000006407001125051021056 0ustar stephensstepheng## # # ## ## # # ## EOF Name: Shiptie biglife1.1/src/biglife/lib/biglife/shuttle0100644000175200017560000000017507001125051021104 0ustar stephensstepheng # ## ## ## ## ## ### ## ## ## ## ## ## # EOF Name: Shuttle biglife1.1/src/biglife/lib/biglife/snake0100644000175200017560000000001607001125051020507 0ustar stephensstepheng# ## ## # EOF biglife1.1/src/biglife/lib/biglife/spacerake0100644000175200017560000000262007001125051021347 0ustar stephensstepheng ## #### ## ## # # #### # ## # # # # # # ## # ## # ## ## # # # # # ## ### #### # # # # # # # # # # #### EOF Name: Space Rake biglife1.1/src/biglife/lib/biglife/spaceship0100644000175200017560000000011207001125051021362 0ustar stephensstepheng # # # # # # ##### EOF Name: Lightweight Spaceship Period: 4 biglife1.1/src/biglife/lib/biglife/spaceshiph0100644000175200017560000000012007001125051021531 0ustar stephensstepheng ## # # # # # ###### EOF Name: Heavyweight Spaceship Period: 4 biglife1.1/src/biglife/lib/biglife/spaceshipm0100644000175200017560000000011307001125051021540 0ustar stephensstepheng # # # # # # ##### EOF Name: Middleweight Spaceship Period: 4 biglife1.1/src/biglife/lib/biglife/switchengine0100644000175200017560000000007707001125051022104 0ustar stephensstepheng # # # # # ## # EOF Name: Switch Engine Period: 48 biglife1.1/src/biglife/lib/biglife/toad0100644000175200017560000000002707001125051020337 0ustar stephensstepheng ### ### EOF Period: 2 biglife1.1/src/biglife/lib/biglife/ttetro0100644000175200017560000000003607001125051020731 0ustar stephensstepheng### # EOF Name: T Tetromino biglife1.1/src/biglife/lib/biglife/tub0100644000175200017560000000001607001125051020200 0ustar stephensstepheng # # # # EOF biglife1.1/src/biglife/lib/biglife/tumbler0100644000175200017560000000007307001125052021064 0ustar stephensstepheng ## ## ## ## # # # # # # # # # # ## ## EOF Period: 14 biglife1.1/src/GUM_BUILD_ROOT0100644000175200017560000000060607306140324016065 0ustar stephensstepheng# $Id: GUM_BUILD_ROOT,v 1.3 2001/04/07 10:26:24 stephens Exp $ # Build options DEBUG=YES #OPTIMIZE=NO # output root is ../gumo GUM_GENERATED_ROOT:=$(shell cd $(GUM_BUILD_ROOT)/../gumo && /bin/pwd)# # Quick install. GUM_GENERATED_LIB_DIR=$(INSTALL_DIR_LIB)# # Pick up /iimp stuff PATH:=/iimp/bin:$(PATH) INCLUDE_DIRS_GLOBAL:=$(GUM_BUILD_ROOT) /iimp/include# LIB_DIRS_GLOBAL:=/iimp/lib# biglife1.1/README0100644000175200017560000000717407306140327014033 0ustar stephensstephengbiglife 1.1 README ============================================================================== Copyright (c) 1997-2001 Kurt A. Stephens and Ion, Inc., All Rights Reserved. http://www.acm.org/~stephensk Kurt A. Stephens and Ion, Inc. MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. Kurt A. Stephens and Ion, Inc. SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. $Id: COPYRIGHT,v 1.3 2001/04/03 18:37:16 stephens Exp $ ============================================================================== biglife 1.1 README ============================================================================== $Id: README,v 1.3 1999/11/14 04:02:19 stephensk Exp $ Biglife Copyright 1998, 1999, Kurt A. Stephens http://www.acm.org/~stephensk The biglife library implements Conway's "Game-of-Life" using sparse bitmap arrays. It achieves its speed by unrolling the four nested loops of a naive implementation into 9 different types of bitwise operations and by not processing empty areas. A naive implementations can be used for validation of the fast routines. Currently supported displays are: ANSI terminals (vt100) and GTK+ libraries. Each life_array object is a hash table containing 8x8 bitmaps (life_chunk) indexed by chunk position. Each life_chunk has a chunk coordinate (x,y). Each coordinate element is a short and the hash of the position is a unsigned long concatenation of the coordinate. This allows an effective board size of 524288/524288 (memory permitting). Empty life_chunks, chunks with no live cells are not stored in the life_array, except when determining chunks adjacent to live chunks. Live chunks have at least one live cell. The storage overhead is 8 bytes for the 4 bytes of position and 4 bytes of linked list. This is %50 overhead over a full bit array representation. If we moved up to 16x16 bit chunks (64 bytes) the overhead would be %17.5 but there might be some very sparse chunks due to "gliders" going off to infinity. Iteration algorithm: 1. For each live chunk (C) 2. Find chunks neighboring C (CS[3][3]) 3. Create a new empty chunk (NC) 4. For each cell in chunk C (S) 5. Compute the number of neighbor cells of cell S. 6. Compute the corresponding cell in NC based on the number of neighbor cells for S. 7. For all neighbororing chunks created by step 2, 8. Do steps 3-6. 9. Filter out all dead chunks. A state table (life_trans_table[]) is used to map the 9 cell states into a new center cell state. The index into life_trans_table is the following bits: +---+---+---+ | | | | | 0 | 1 | 2 | | | | | +---+-V-+---+ | | | | | 3 > 4 < 5 | | | | | +---+-^-+---+ | | | | | 6 | 7 | 8 | | | | | +---+---+---+ Bit 4 is the center cell, all other cells are represented by other bits. The state of a cell and all neighbors is represented in 9 bits. For each cell in the life chunk, create a index into the state table from the neighboring cells. This is done using bitwise operations for speed. The display algorithm: 1. Choose a viewport in the chunks. 2. Clear the window. 3. Iterate through the chunks in the window without allocating dead chunks and blit each. Incremental display: TO BE IMPLEMENTED: Toggle the update bit in the chunk if its different from a last chunk. Only draw chunks that have changed as long as the viewport is the same. Commands: Please type '?-RETURN' at the command prompt for a description of each command. biglife1.1/COPYRIGHT0100644000175200017560000000113107306140324014426 0ustar stephensstephengCopyright (c) 1997-2001 Kurt A. Stephens and Ion, Inc., All Rights Reserved. http://www.acm.org/~stephensk Kurt A. Stephens and Ion, Inc. MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. Kurt A. Stephens and Ion, Inc. SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. $Id: COPYRIGHT,v 1.3 2001/04/03 18:37:16 stephens Exp $ biglife1.1/CHANGES0100644000175200017560000000014407306140324014131 0ustar stephensstephengbiglife 1.1 CHANGES ============================================================================== biglife1.1/TOC0100644000175200017560000001605007306140327013514 0ustar stephensstephengbiglife 1.1 Table of Contents ============================================================================== biglife1.1: total 7 drwxr-xr-x 3 stephens stepheng 1024 Jun 2 05:32 . drwxr-xr-x 3 stephens stepheng 1024 Jun 2 05:32 .. -rw-r--r-- 1 stephens stepheng 100 Jun 2 05:32 CHANGES -rw-r--r-- 1 stephens stepheng 601 Jun 2 05:32 COPYRIGHT -rw-r--r-- 1 stephens stepheng 781 Jun 2 05:32 README -rw-r--r-- 1 stephens stepheng 109 Jun 2 05:32 TOC drwxr-xr-x 3 stephens stepheng 1024 Jun 2 05:32 src biglife1.1/src: total 4 drwxr-xr-x 3 stephens stepheng 1024 Jun 2 05:32 . drwxr-xr-x 3 stephens stepheng 1024 Jun 2 05:32 .. -rw-r--r-- 1 stephens stepheng 390 Jun 2 05:32 GUM_BUILD_ROOT drwxr-xr-x 4 stephens stepheng 1024 Jun 2 05:32 biglife biglife1.1/src/biglife: total 88 drwxr-xr-x 4 stephens stepheng 1024 Jun 2 05:32 . drwxr-xr-x 3 stephens stepheng 1024 Jun 2 05:32 .. drwxr-xr-x 2 stephens stepheng 1024 Feb 2 21:29 CVS -rw-r--r-- 1 stephens stepheng 1036 Nov 13 1999 Makefile -rw-r--r-- 1 stephens stepheng 294 Nov 13 1999 PKG -rw-r--r-- 1 stephens stepheng 2829 Nov 13 1999 README -rw-r--r-- 1 stephens stepheng 40837 Dec 26 1999 biglife.c -rw-r--r-- 1 stephens stepheng 164 Oct 13 1999 biglife.gdb -rw-r--r-- 1 stephens stepheng 5835 Nov 13 1999 biglife.h -rw-r--r-- 1 stephens stepheng 73 Feb 19 1999 biglife.in -rw-r--r-- 1 stephens stepheng 3283 Nov 13 1999 blgtk.c -rw-r--r-- 1 stephens stepheng 4906 Nov 13 1999 blterm.c -rw-r--r-- 1 stephens stepheng 13113 Nov 13 1999 gtklife.c -rw-r--r-- 1 stephens stepheng 1180 Dec 26 1999 gtklife.h drwxr-xr-x 4 stephens stepheng 1024 Feb 2 21:29 lib -rw-r--r-- 1 stephens stepheng 388 Nov 5 1999 life.c -rw-r--r-- 1 stephens stepheng 1796 Dec 26 1999 term.c -rw-r--r-- 1 stephens stepheng 569 Nov 13 1999 term.h biglife1.1/src/biglife/CVS: total 5 drwxr-xr-x 2 stephens stepheng 1024 Feb 2 21:29 . drwxr-xr-x 4 stephens stepheng 1024 Jun 2 05:32 .. -rw-r--r-- 1 stephens stepheng 580 Feb 2 21:29 Entries -rw-r--r-- 1 stephens stepheng 21 Feb 2 21:29 Repository -rw-r--r-- 1 stephens stepheng 28 Feb 2 21:29 Root biglife1.1/src/biglife/lib: total 4 drwxr-xr-x 4 stephens stepheng 1024 Feb 2 21:29 . drwxr-xr-x 4 stephens stepheng 1024 Jun 2 05:32 .. drwxr-xr-x 2 stephens stepheng 1024 Feb 2 21:29 CVS drwxr-xr-x 3 stephens stepheng 1024 Feb 2 21:29 biglife biglife1.1/src/biglife/lib/CVS: total 5 drwxr-xr-x 2 stephens stepheng 1024 Feb 2 21:29 . drwxr-xr-x 4 stephens stepheng 1024 Feb 2 21:29 .. -rw-r--r-- 1 stephens stepheng 14 Feb 2 21:29 Entries -rw-r--r-- 1 stephens stepheng 25 Feb 2 21:29 Repository -rw-r--r-- 1 stephens stepheng 28 Feb 2 21:29 Root biglife1.1/src/biglife/lib/biglife: total 62 drwxr-xr-x 3 stephens stepheng 1024 Feb 2 21:29 . drwxr-xr-x 4 stephens stepheng 1024 Feb 2 21:29 .. drwxr-xr-x 2 stephens stepheng 1024 Feb 2 21:29 CVS -rw-r--r-- 1 stephens stepheng 67 Oct 13 1999 acorn -rw-r--r-- 1 stephens stepheng 39 Oct 13 1999 bakery -rw-r--r-- 1 stephens stepheng 96 Oct 13 1999 barberpole -rw-r--r-- 1 stephens stepheng 20 Oct 13 1999 barge -rw-r--r-- 1 stephens stepheng 30 Oct 13 1999 beacon -rw-r--r-- 1 stephens stepheng 17 Oct 13 1999 beehive -rw-r--r-- 1 stephens stepheng 257 Oct 13 1999 bhepto -rw-r--r-- 1 stephens stepheng 51 Oct 13 1999 biboat -rw-r--r-- 1 stephens stepheng 53 Oct 13 1999 bigs -rw-r--r-- 1 stephens stepheng 64 Oct 13 1999 biloaf -rw-r--r-- 1 stephens stepheng 65 Oct 13 1999 bipond -rw-r--r-- 1 stephens stepheng 18 Oct 13 1999 blinker -rw-r--r-- 1 stephens stepheng 23 Oct 13 1999 block -rw-r--r-- 1 stephens stepheng 15 Oct 13 1999 boat -rw-r--r-- 1 stephens stepheng 28 Oct 13 1999 canoe -rw-r--r-- 1 stephens stepheng 33 Oct 13 1999 century -rw-r--r-- 1 stephens stepheng 29 Oct 13 1999 clock -rw-r--r-- 1 stephens stepheng 112 Oct 13 1999 clock2 -rw-r--r-- 1 stephens stepheng 30 Oct 13 1999 eater -rw-r--r-- 1 stephens stepheng 33 Oct 13 1999 fleet -rw-r--r-- 1 stephens stepheng 62 Oct 13 1999 flipflop -rw-r--r-- 1 stephens stepheng 192 Oct 13 1999 flotilla -rw-r--r-- 1 stephens stepheng 114 Oct 13 1999 flyingmachine -rw-r--r-- 1 stephens stepheng 430 Oct 13 1999 flyingmachineb -rw-r--r-- 1 stephens stepheng 114 Oct 13 1999 flyingmachinex -rw-r--r-- 1 stephens stepheng 103 Oct 13 1999 galaxy -rw-r--r-- 1 stephens stepheng 38 Oct 13 1999 glider -rw-r--r-- 1 stephens stepheng 1131 Oct 13 1999 glidergun -rw-r--r-- 1 stephens stepheng 34 Oct 13 1999 hat -rw-r--r-- 1 stephens stepheng 46 Oct 13 1999 herschel -rw-r--r-- 1 stephens stepheng 64 Oct 13 1999 hexadec -rw-r--r-- 1 stephens stepheng 30 Oct 13 1999 honeyfarm -rw-r--r-- 1 stephens stepheng 46 Oct 13 1999 interchange -rw-r--r-- 1 stephens stepheng 20 Oct 13 1999 loaf -rw-r--r-- 1 stephens stepheng 24 Oct 13 1999 mango -rw-r--r-- 1 stephens stepheng 876 Oct 13 1999 p15 -rw-r--r-- 1 stephens stepheng 53 Oct 13 1999 paperclip -rw-r--r-- 1 stephens stepheng 84 Oct 13 1999 pentadec -rw-r--r-- 1 stephens stepheng 37 Oct 13 1999 pihepto -rw-r--r-- 1 stephens stepheng 22 Oct 13 1999 pond -rw-r--r-- 1 stephens stepheng 161 Oct 13 1999 puffer -rw-r--r-- 1 stephens stepheng 26 Oct 13 1999 pulsar -rw-r--r-- 1 stephens stepheng 33 Oct 13 1999 rpent -rw-r--r-- 1 stephens stepheng 22 Oct 13 1999 shillelagh -rw-r--r-- 1 stephens stepheng 26 Oct 13 1999 ship -rw-r--r-- 1 stephens stepheng 52 Oct 13 1999 shiptie -rw-r--r-- 1 stephens stepheng 125 Oct 13 1999 shuttle -rw-r--r-- 1 stephens stepheng 14 Oct 13 1999 snake -rw-r--r-- 1 stephens stepheng 1424 Oct 13 1999 spacerake -rw-r--r-- 1 stephens stepheng 74 Oct 13 1999 spaceship -rw-r--r-- 1 stephens stepheng 80 Oct 13 1999 spaceshiph -rw-r--r-- 1 stephens stepheng 75 Oct 13 1999 spaceshipm -rw-r--r-- 1 stephens stepheng 63 Oct 13 1999 switchengine -rw-r--r-- 1 stephens stepheng 23 Oct 13 1999 toad -rw-r--r-- 1 stephens stepheng 30 Oct 13 1999 ttetro -rw-r--r-- 1 stephens stepheng 14 Oct 13 1999 tub -rw-r--r-- 1 stephens stepheng 59 Oct 13 1999 tumbler biglife1.1/src/biglife/lib/biglife/CVS: total 7 drwxr-xr-x 2 stephens stepheng 1024 Feb 2 21:29 . drwxr-xr-x 3 stephens stepheng 1024 Feb 2 21:29 .. -rw-r--r-- 1 stephens stepheng 2275 Feb 2 21:29 Entries -rw-r--r-- 1 stephens stepheng 33 Feb 2 21:29 Repository -rw-r--r-- 1 stephens stepheng 28 Feb 2 21:29 Root