home *** CD-ROM | disk | FTP | other *** search
- /*
- * Life search program - actual search routines.
- * Author: David I. Bell.
- * Based on the algorithms by Dean Hickerson that were
- * included with the "xlife 2.0" distribution. Thanks!
- */
-
- #include "lifesrc.h"
-
-
- /*
- * IMPLIC flag values.
- */
- typedef unsigned char FLAGS;
- #define N0IC0 ((FLAGS) 0x01) /* new cell 0 ==> current cell 0 */
- #define N0IC1 ((FLAGS) 0x02) /* new cell 0 ==> current cell 1 */
- #define N1IC0 ((FLAGS) 0x04) /* new cell 1 ==> current cell 0 */
- #define N1IC1 ((FLAGS) 0x08) /* new cell 1 ==> current cell 1 */
- #define N0ICUN0 ((FLAGS) 0x10) /* new cell 0 ==> current unknown neighbors 0 */
- #define N0ICUN1 ((FLAGS) 0x20) /* new cell 0 ==> current unknown neighbors 1 */
- #define N1ICUN0 ((FLAGS) 0x40) /* new cell 1 ==> current unknown neighbors 0 */
- #define N1ICUN1 ((FLAGS) 0x80) /* new cell 1 ==> current unknown neighbors 1 */
-
-
- /*
- * Table of transitions.
- * Given the state of a cell and its neighbors in one generation,
- * this table determines the state of the cell in the next generation.
- * The table is indexed by the descriptor value of a cell.
- */
- static STATE transit[256];
-
-
- /*
- * Table of implications.
- * Given the state of a cell and its neighbors in one generation,
- * this table determines deductions about the cell and its neighbors
- * in the previous generation.
- * The table is indexed by the descriptor value of a cell.
- */
- static FLAGS implic[256];
-
-
- /*
- * Data about the cells.
- */
- CELL *celltable[MAXCELLS]; /* table of usual cells */
- CELL *auxtable[AUXCELLS]; /* table of auxillary cells */
- CELL *settable[MAXCELLS]; /* table of cells whose value is set */
- CELL **newset; /* where to add new cells into setting table */
- CELL **nextset; /* next cell in setting table to examine */
- CELL **baseset; /* base of changeable part of setting table */
- CELL *searchlist; /* current list of cells to search */
- CELL *fullsearchlist; /* complete list of cells to search */
- CELL *newcells; /* cells ready for allocation */
- CELL *deadcell; /* boundary cell value */
- int newcellcount; /* number of cells ready for allocation */
- int auxcellcount; /* number of cells in auxillary table */
-
-
- /*
- * Current parameter values for the program.
- */
- BOOL debug; /* enable debugging output (if compiled so) */
- BOOL nowait; /* don't wait for commands after loading */
- BOOL setall; /* set all cells from initial file */
- BOOL rowsym; /* enable row symmetry */
- BOOL colsym; /* enable column symmetry */
- BOOL parent; /* only look for parents */
- BOOL allobjects; /* look for all objects including subperiods */
- STATUS curstatus; /* current status for display */
- int curgen; /* current generation for display */
- int rowmax; /* maximum number of rows */
- int colmax; /* maximum number of columns */
- int genmax; /* maximum number of generations */
- int rowtrans; /* translation of rows */
- int coltrans; /* translation of columns */
- int maxcount; /* maximum number of cells in generation 0 */
- int cellcount; /* number of live cells in generation 0 */
- long dumpfreq; /* how often to perform dumps */
- long dumpcount; /* counter for dumps */
- long viewfreq; /* how often to view results */
- long viewcount; /* counter for viewing */
- long foundcount; /* number of objects found */
- char *dumpfile; /* dump file name */
- char *initfile; /* file containing initial cells */
- char *loadfile; /* file to load state from */
- char *outputfile; /* file to output results to */
-
-
- static STATE states[NSTATES] = {OFF, ON, UNK};
-
-
- /*
- * Local procedures
- */
- static void inittransit();
- static void initimplic();
- static void linkcell();
- static STATE transition();
- static STATE choose();
- static FLAGS implication();
- static CELL *symcell();
- static CELL *allocatecell();
- static CELL *backup();
- static CELL *getunknown();
- static STATUS setcell();
- static STATUS consistify();
- static STATUS consistify10();
- static STATUS examinenext();
- static STATUS go();
- static int getdesc();
- static int sumtodesc();
-
-
- /*
- * Initialize the table of cells.
- * Each cell in the active area is set to unknown state.
- * Boundary cells are set to zero state.
- */
- void
- initcells()
- {
- int row, col, gen;
- int nrow, ncol;
- int i;
- BOOL edge;
- CELL *cell;
-
- if ((rowmax <= 0) || (rowmax > ROWMAX) ||
- (colmax <= 0) || (colmax > COLMAX) ||
- (genmax <= 0) || (genmax > GENMAX) ||
- (rowtrans < 0) || (rowtrans > TRANSMAX) ||
- (coltrans < 0) || (coltrans > TRANSMAX))
- {
- ttyclose();
- fprintf(stderr, "ROW, COL, GEN, or TRANS out of range\n");
- exit(1);
- }
-
- /*
- * The first allocation of a cell MUST be deadcell.
- * Then allocate the cells in the cell table.
- */
- deadcell = allocatecell();
- for (i = 0; i < MAXCELLS; i++)
- celltable[i] = allocatecell();
-
- /*
- * Link the cells together.
- */
- for (col = 0; col <= colmax+1; col++) {
- for (row = 0; row <= rowmax+1; row++) {
- for (gen = 0; gen < genmax; gen++) {
- edge = ((row == 0) || (col == 0) ||
- (row > rowmax) || (col > colmax));
-
- cell = findcell(row, col, gen);
- cell->gen = gen;
- cell->row = row;
- cell->col = col;
-
- /*
- * If this is not an edge cell, then its state
- * is unknown and it needs linking to its
- * neighbors.
- */
- if (!edge) {
- linkcell(cell);
- cell->state = UNK;
- cell->free = TRUE;
- }
-
- /*
- * Map time forwards and backwards,
- * wrapping around at the ends.
- */
- cell->past = findcell(row, col,
- (gen+genmax-1) % genmax);
- cell->future = findcell(row, col,
- (gen+1) % genmax);
-
- /*
- * If this is not an edge cell, then
- * set up symmetry for it.
- */
- if ((rowsym || colsym) && !edge)
- cell->csym = symcell(cell);
-
- }
- }
- }
-
- /*
- * If there is a translation, then implement it.
- */
- if (rowtrans || coltrans) {
- for (col = 0; col <= colmax+1; col++) {
- for (row = 0; row <= rowmax+1; row++) {
- cell = findcell(row, col, genmax-1);
- nrow = row + rowtrans;
- ncol = col + coltrans;
- cell->future = findcell(nrow, ncol, 0);
- linkcell(cell->future);
-
- cell = findcell(row, col, 0);
- nrow = row - rowtrans;
- ncol = col - coltrans;
- cell->past = findcell(nrow, ncol, genmax-1);
- linkcell(cell->past);
- }
- }
- }
-
- /*
- * Build the search table list.
- * This list is built backwards from the intended search order.
- * Do searches from the middle row outwards, and from the left
- * to the right columns. However, since we try OFF cells first,
- * reverse the row order again to try to make thin objects.
- */
- searchlist = NULL;
- for (gen = genmax - 1; gen >= 0; gen--) {
- for (col = colmax; col > 0; col--) {
- for (row = (rowmax + 1) / 2; row > 0; row--) {
- cell = findcell(row, col, gen);
- cell->search = searchlist;
- searchlist = cell;
- if (rowsym || (row * 2 == rowmax + 1))
- continue;
- cell = findcell(rowmax + 1 - row, col, gen);
- cell->search = searchlist;
- searchlist = cell;
- }
- }
- }
- fullsearchlist = searchlist;
-
- newset = settable;
- nextset = settable;
- baseset = settable;
-
- curgen = 0;
- curstatus = OK;
- inittransit();
- initimplic();
- }
-
-
- /*
- * Set the state of a cell to the specified state.
- * The state is either ON or OFF.
- * Returns ERROR if the setting is inconsistent.
- * If the cell is newly set, then it is added to the set table.
- */
- static STATUS
- setcell(cell, state, free)
- CELL *cell;
- STATE state;
- BOOL free;
- {
- if (cell->state == state) {
- DPRINTF4("setcell %d %d %d to state %s already set\n",
- cell->row, cell->col, cell->gen,
- (state == ON) ? "on" : "off");
- return OK;
- }
-
- if (cell->state != UNK) {
- DPRINTF4("setcell %d %d %d to state %s inconsistent\n",
- cell->row, cell->col, cell->gen,
- (state == ON) ? "on" : "off");
- return ERROR;
- }
-
- if ((state == ON) && (cell->gen == 0)) {
- if (maxcount && (cellcount >= maxcount)) {
- DPRINTF2("setcell %d %d 0 on exceeds maxcount\n",
- cell->row, cell->col);
- return ERROR;
- }
- cellcount++;
- }
-
- DPRINTF5("setcell %d %d %d to %s, %s successful\n",
- cell->row, cell->col, cell->gen,
- (free ? "free" : "forced"), ((state == ON) ? "on" : "off"));
-
- cell->state = state;
- cell->free = free;
- *newset++ = cell;
-
- return OK;
- }
-
-
- /*
- * Calculate the current descriptor for a cell.
- */
- static int
- getdesc(cell)
- register CELL *cell;
- {
- int sum;
-
- sum = cell->cul->state + cell->cu->state + cell->cur->state;
- sum += cell->cdl->state + cell->cd->state + cell->cdr->state;
- sum += cell->cl->state + cell->cr->state;
-
- return ((sum & 0x88) ? (sum + cell->state * 2 + 0x11) :
- (sum * 2 + cell->state));
- }
-
-
- /*
- * Return the descriptor value for a cell and the sum of its neighbors.
- */
- static int
- sumtodesc(state, sum)
- STATE state;
- {
- return ((sum & 0x88) ? (sum + state * 2 + 0x11) : (sum * 2 + state));
- }
-
-
- /*
- * Consistify a cell.
- * This means examine this cell in the previous generation, and
- * make sure that the previous generation can validly produce the
- * current cell. Returns ERROR if the cell is inconsistent.
- */
- static STATUS
- consistify(cell)
- CELL *cell;
- {
- CELL *prevcell;
- int desc;
- STATE state;
- FLAGS flags;
-
- /*
- * If we are searching for parents and this is generation 0, then
- * the cell is consistent with respect to the previous generation.
- */
- if (parent && (cell->gen == 0))
- return OK;
-
- /*
- * First check the transit table entry for the previous
- * generation. Make sure that this cell matches the ON or
- * OFF state demanded by the transit table. If the current
- * cell is unknown but the transit table knows the answer,
- * then set the now known state of the cell.
- */
- prevcell = cell->past;
- desc = getdesc(prevcell);
- state = transit[desc];
- if (state != cell->state) {
- switch (state) {
- case ON:
- if (cell->state == OFF) {
- DPRINTF3("Transit inconsistently forces cell %d %d %d on\n",
- cell->row, cell->col,
- cell->gen);
- return ERROR;
- }
-
- if (cell->gen == 0) {
- if (maxcount &&
- (cellcount >= maxcount))
- {
- DPRINTF2("Transit forcing cell %d %d 0 exceeds maxcount\n",
- cell->row, cell->col);
- return ERROR;
- }
- cellcount++;
- }
-
- DPRINTF3("Transit forces cell %d %d %d on\n",
- cell->row, cell->col, cell->gen);
- cell->state = ON;
- cell->free = FALSE;
- *newset++ = cell;
- break;
-
- case OFF:
- if (cell->state == ON) {
- DPRINTF3("Transit inconsistently forces cell %d %d %d off\n",
- cell->row, cell->col,
- cell->gen);
- return ERROR;
- }
- DPRINTF3("Transit forces cell %d %d %d off\n",
- cell->row, cell->col, cell->gen);
- cell->state = OFF;
- cell->free = FALSE;
- *newset++ = cell;
- break;
- }
- }
-
- /*
- * Now look up the previous generation in the implic table.
- * If this cell implies anything about the cell or its neighbors
- * in the previous generation, then handle that.
- */
- flags = implic[desc];
- if ((flags == 0) || (cell->state == UNK))
- return OK;
-
- DPRINTF1("Implication flags %x\n", flags);
-
- if ((flags & N0IC0) && (cell->state == OFF) &&
- (setcell(prevcell, OFF, FALSE) != OK))
- return ERROR;
-
- if ((flags & N1IC1) && (cell->state == ON) &&
- (setcell(prevcell, ON, FALSE) != OK))
- return ERROR;
-
- state = UNK;
- if (((flags & N0ICUN0) && (cell->state == OFF))
- || ((flags & N1ICUN0) && (cell->state == ON)))
- state = OFF;
-
- if (((flags & N0ICUN1) && (cell->state == OFF))
- || ((flags & N1ICUN1) && (cell->state == ON)))
- state = ON;
-
- if (state == UNK) {
- DPRINTF0("Implications successful\n");
- return OK;
- }
-
- /*
- * For each unknown neighbor, set its state as indicated.
- * Return an error if any neighbor is inconsistent.
- */
- DPRINTF4("Forcing unknown neighbors of cell %d %d %d %s\n",
- prevcell->row, prevcell->col, prevcell->gen,
- ((state == ON) ? "on" : "off"));
-
- if ((prevcell->cul->state == UNK) &&
- (setcell(prevcell->cul, state, FALSE) != OK))
- return ERROR;
-
- if ((prevcell->cu->state == UNK) &&
- (setcell(prevcell->cu, state, FALSE) != OK))
- return ERROR;
-
- if ((prevcell->cur->state == UNK) &&
- (setcell(prevcell->cur, state, FALSE) != OK))
- return ERROR;
-
- if ((prevcell->cl->state == UNK) &&
- (setcell(prevcell->cl, state, FALSE) != OK))
- return ERROR;
-
- if ((prevcell->cr->state == UNK) &&
- (setcell(prevcell->cr, state, FALSE) != OK))
- return ERROR;
-
- if ((prevcell->cdl->state == UNK) &&
- (setcell(prevcell->cdl, state, FALSE) != OK))
- return ERROR;
-
- if ((prevcell->cd->state == UNK) &&
- (setcell(prevcell->cd, state, FALSE) != OK))
- return ERROR;
-
- if ((prevcell->cdr->state == UNK) &&
- (setcell(prevcell->cdr, state, FALSE) != OK))
- return ERROR;
-
- DPRINTF0("Implications successful\n");
-
- return OK;
- }
-
-
- /*
- * See if a cell and its neighbors are consistent with the cell and its
- * neighbors in the next generation.
- */
- static STATUS
- consistify10(cell)
- CELL *cell;
- {
- if (consistify(cell) != OK)
- return ERROR;
-
- cell = cell->future;
- if (consistify(cell) != OK)
- return ERROR;
- if (consistify(cell->cul) != OK)
- return ERROR;
- if (consistify(cell->cu) != OK)
- return ERROR;
- if (consistify(cell->cur) != OK)
- return ERROR;
- if (consistify(cell->cl) != OK)
- return ERROR;
- if (consistify(cell->cr) != OK)
- return ERROR;
- if (consistify(cell->cdl) != OK)
- return ERROR;
- if (consistify(cell->cd) != OK)
- return ERROR;
- if (consistify(cell->cdr) != OK)
- return ERROR;
- return OK;
- }
-
-
- /*
- * Examine the next choice of cell settings.
- */
- static STATUS
- examinenext()
- {
- CELL *cell;
-
- /*
- * If there are no more cells to examine, then what we have
- * is consistent.
- */
- if (nextset == newset)
- return CONSISTENT;
-
- /*
- * Get the next cell to examine, and check it out for symmetry
- * and for consistency with its previous and next generations.
- */
- cell = *nextset++;
-
- DPRINTF4("Examining saved cell %d %d %d (%s) for consistency\n",
- cell->row, cell->col, cell->gen,
- (cell->free ? "free" : "forced"));
-
- if ((rowsym || colsym) &&
- (setcell(cell->csym, cell->state, FALSE) != OK))
- return ERROR;
-
- return consistify10(cell);
- }
-
-
- /*
- * Set a cell to the specified value and determine all consequences we
- * can from the choice. Consequences are a contradiction or a consistency.
- */
- STATUS
- proceed(cell, state, free)
- CELL *cell;
- STATE state;
- BOOL free;
- {
- int status;
-
- if (setcell(cell, state, free) != OK)
- return ERROR;
-
- for (;;) {
- status = examinenext();
- if (status == ERROR)
- return ERROR;
- if (status == CONSISTENT)
- return OK;
- }
- }
-
-
- /*
- * Back up the list of set cells to undo choices.
- * Returns the cell which is to be tried for the other possibility.
- * Returns NULL_CELL on an "object cannot exist" error.
- */
- static CELL *
- backup()
- {
- CELL *cell;
-
- searchlist = fullsearchlist;
-
- while (newset != baseset) {
- cell = *--newset;
-
- DPRINTF5("backing up cell %d %d %d, was %s, %s\n",
- cell->row, cell->col, cell->gen,
- ((cell->state == ON) ? "on" : "off"),
- (cell->free ? "free": "forced"));
-
- if ((cell->state == ON) && (cell->gen == 0))
- cellcount--;
-
- if (!cell->free) {
- cell->state = UNK;
- cell->free = TRUE;
- continue;
- }
- nextset = newset;
- return cell;
- }
- nextset = baseset;
- return NULL_CELL;
- }
-
-
- /*
- * Do checking based on setting the specified cell.
- * Returns ERROR if an inconsistency was found.
- */
- static STATUS
- go(cell, state, free)
- CELL *cell;
- STATE state;
- BOOL free;
- {
- STATUS status;
-
- for (;;) {
- status = proceed(cell, state, free);
- if (status == OK)
- return OK;
-
- cell = backup();
- if (cell == NULL_CELL)
- return ERROR;
-
- free = FALSE;
- state = 1 - cell->state;
- cell->state = UNK;
- }
- }
-
-
- /*
- * Find another unknown cell.
- * Returns NULL_CELL if there are no more unknown cells.
- */
- static CELL *
- getunknown()
- {
- register CELL *cell;
-
- for (cell = searchlist; cell; cell = cell->search) {
- if (cell->state == UNK) {
- searchlist = cell;
- return cell;
- }
- }
- return NULL_CELL;
- }
-
-
- /*
- * Choose a state for an unknown cell, either OFF or ON.
- * For billiard table stuff, this can be changed to choose the same state
- * as the majority of other generations.
- */
- static STATE
- choose(cell)
- CELL *cell;
- {
- return OFF;
- }
-
-
- /*
- * The top level search routine.
- * Returns if an object is found, or is impossible.
- */
- STATUS
- search()
- {
- CELL *cell;
- BOOL free;
- STATE state;
-
- cell = getunknown();
- if (cell == NULL_CELL) {
- cell = backup();
- if (cell == NULL_CELL)
- return ERROR;
- free = FALSE;
- state = 1 - cell->state;
- cell->state = UNK;
- } else {
- state = choose(cell);
- free = TRUE;
- }
-
- for (;;) {
- if (go(cell, state, free) != OK)
- return NOTEXIST;
-
- if (dumpfreq && (++dumpcount >= dumpfreq)) {
- dumpcount = 0;
- dumpstate(dumpfile);
- }
-
- if (viewfreq && (++viewcount >= viewfreq)) {
- viewcount = 0;
- printgen(curgen);
- }
-
- if (ttycheck())
- getcommands();
-
- cell = getunknown();
- if (cell == NULL_CELL)
- return FOUND;
-
- state = choose(cell);
- free = TRUE;
- }
- }
-
-
- /*
- * Check to see if any other generation is identical to generation 0.
- * This is used to detect and weed out all objects with subperiods.
- * (For example, stable objects or period 2 objects when using -g4.)
- * Returns TRUE if there is an identical generation.
- */
- BOOL
- subperiods()
- {
- int row;
- int col;
- int gen;
- CELL *cellg0;
- CELL *cellgn;
-
- for (gen = 1; gen < genmax; gen++) {
- if (genmax % gen)
- continue;
- for (row = 1; row <= rowmax; row++) {
- for (col = 1; col <= colmax; col++) {
- cellg0 = findcell(row, col, 0);
- cellgn = findcell(row, col, gen);
- if (cellg0->state != cellgn->state)
- goto nextgen;
- }
- }
- return TRUE;
- nextgen:;
- }
- return FALSE;
- }
-
-
- /*
- * Return a cell which is symmetric to the given cell.
- * It is not necessary to know all symmetric cells to a single cell,
- * as long as all symmetric cells are chained in a loop. Thus a single
- * pointer is good enough even for the case of both row and column symmetry.
- * Returns NULL_CELL if there is no symmetry.
- */
- static CELL *
- symcell(cell)
- CELL *cell;
- {
- int row;
- int col;
- int nrow;
- int ncol;
-
- if (!rowsym && !colsym)
- return NULL_CELL;
-
- row = cell->row;
- col = cell->col;
- nrow = rowmax + 1 - row;
- ncol = colmax + 1 - col;
-
- /*
- * If there is symmetry on only one axis, then this is easy.
- */
- if (!colsym)
- return findcell(nrow, col, cell->gen);
-
- if (!rowsym)
- return findcell(row, ncol, cell->gen);
-
- /*
- * Here is there is both row and column symmetry.
- * First see if the cell is in the middle row or middle column,
- * and if so, then this is easy.
- */
- if ((nrow == row) || (ncol == col))
- return findcell(nrow, ncol, cell->gen);
-
- /*
- * The cell is really in one of the four quadrants, and therefore
- * has four cells making up the symmetry. Link this cell to the
- * symmetrical cell in the next quadrant clockwise.
- */
- if ((row < nrow) == (col < ncol))
- return findcell(row, ncol, cell->gen);
- else
- return findcell(nrow, col, cell->gen);
- }
-
-
- /*
- * Link a cell to its eight neighbors in the same generation, and also
- * link those neighbors back to this cell.
- */
- static void
- linkcell(cell)
- CELL *cell;
- {
- int row;
- int col;
- int gen;
- CELL *paircell;
-
- row = cell->row;
- col = cell->col;
- gen = cell->gen;
-
- paircell = findcell(row - 1, col - 1, gen);
- cell->cul = paircell;
- paircell->cdr = cell;
-
- paircell = findcell(row - 1, col, gen);
- cell->cu = paircell;
- paircell->cd = cell;
-
- paircell = findcell(row - 1, col + 1, gen);
- cell->cur = paircell;
- paircell->cdl = cell;
-
- paircell = findcell(row, col - 1, gen);
- cell->cl = paircell;
- paircell->cr = cell;
-
- paircell = findcell(row, col + 1, gen);
- cell->cr = paircell;
- paircell->cl = cell;
-
- paircell = findcell(row + 1, col - 1, gen);
- cell->cdl = paircell;
- paircell->cur = cell;
-
- paircell = findcell(row + 1, col, gen);
- cell->cd = paircell;
- paircell->cu = cell;
-
- paircell = findcell(row + 1, col + 1, gen);
- cell->cdr = paircell;
- paircell->cul = cell;
- }
-
-
- /*
- * Find a cell given its coordinates.
- * Most coordinates range from 0 to colmax+1, 0 to rowmax+1, and 0 to genmax-1.
- * Cells within this range are quickly found by indexing into celltable.
- * Cells outside of this range are handled by searching an auxillary table,
- * and are dynamically created as necessary.
- */
- CELL *
- findcell(row, col, gen)
- {
- register CELL *cell;
- int i;
-
- /*
- * If the cell is a normal cell, then we know where it is.
- */
- if ((row >= 0) && (row <= rowmax + 1) &&
- (col >= 0) && (col <= colmax + 1) &&
- (gen >= 0) && (gen < genmax))
- {
- return celltable[(col * (rowmax + 2) + row) * genmax + gen];
- }
-
- /*
- * See if the cell is already allocated in the auxillary table.
- */
- for (i = 0; i < auxcellcount; i++) {
- cell = auxtable[i];
- if ((cell->row == row) && (cell->col == col) &&
- (cell->gen == gen))
- return cell;
- }
-
- /*
- * Need to allocate the cell and add it to the auxillary table.
- */
- cell = allocatecell();
- cell->row = row;
- cell->col = col;
- cell->gen = gen;
-
- auxtable[auxcellcount++] = cell;
-
- return cell;
- }
-
-
- /*
- * Allocate a new cell.
- * The cell is initialized as if it was a boundary cell.
- * Warning: The first allocation MUST be of the deadcell.
- */
- static CELL *
- allocatecell()
- {
- CELL *cell;
-
- /*
- * Allocate a new chunk of cells if there are none left.
- */
- if (newcellcount <= 0) {
- newcells = (CELL *) malloc(sizeof(CELL) * ALLOCSIZE);
- if (newcells == NULL) {
- ttyclose();
- fprintf(stderr, "Cannot allocate cell structure\n");
- exit(1);
- }
- newcellcount = ALLOCSIZE;
- }
- newcellcount--;
- cell = newcells++;
-
- /*
- * If this is the first allocation, then make deadcell be this cell.
- */
- if (deadcell == NULL)
- deadcell = cell;
-
- /*
- * Fill in the cell as if it was a boundary cell.
- */
- cell->state = OFF;
- cell->free = FALSE;
- cell->gen = -1;
- cell->row = -1;
- cell->col = -1;
- cell->past = deadcell;
- cell->future = deadcell;
- cell->cul = deadcell;
- cell->cu = deadcell;
- cell->cur = deadcell;
- cell->cl = deadcell;
- cell->cr = deadcell;
- cell->cdl = deadcell;
- cell->cd = deadcell;
- cell->cdr = deadcell;
- cell->csym = deadcell;
-
- return cell;
- }
-
-
- /*
- * Initialize the implication table.
- */
- static void
- initimplic()
- {
- STATE state;
- int OFFcount;
- int ONcount;
- int sum;
- int desc;
- int i;
-
- for (i = 0; i < NSTATES; i++) {
- state = states[i];
- for (OFFcount = 8; OFFcount >= 0; OFFcount--) {
- for (ONcount = 0; ONcount + OFFcount <= 8; ONcount++) {
- sum = ONcount + (8 - ONcount - OFFcount) * UNK;
- desc = sumtodesc(state, sum);
- implic[desc] =
- implication(state, OFFcount, ONcount);
- }
- }
- }
- }
-
-
- /*
- * Initialize the transition table.
- */
- static void
- inittransit()
- {
- int state;
- int OFFcount;
- int ONcount;
- int sum;
- int desc;
- int i;
-
- for (i = 0; i < NSTATES; i++) {
- state = states[i];
- for (OFFcount = 8; OFFcount >= 0; OFFcount--) {
- for (ONcount = 0; ONcount + OFFcount <= 8; ONcount++) {
- sum = ONcount + (8 - ONcount - OFFcount) * UNK;
- desc = sumtodesc(state, sum);
- transit[desc] =
- transition(state, OFFcount, ONcount);
- }
- }
- }
- }
-
-
- /*
- * Determine the transition of a cell depending on its known neighbor counts.
- * The unknown neighbor count is implicit since there are eight neighbors.
- */
- static STATE
- transition(state, OFFcount, ONcount)
- STATE state;
- unsigned int OFFcount;
- unsigned int ONcount;
- {
- switch (state) {
- case OFF:
- if (OFFcount > 5)
- return OFF;
- if (ONcount > 3)
- return OFF;
- if ((ONcount == 3) && (OFFcount == 5))
- return ON;
- return UNK;
-
- case ON:
- if (ONcount > 3)
- return OFF;
- if (OFFcount > 6)
- return OFF;
- if ((ONcount == 2) &&
- ((OFFcount == 5) || (OFFcount == 6)))
- return ON;
- if ((ONcount == 3) && (OFFcount == 5))
- return ON;
- return UNK;
-
- case UNK:
- if (ONcount > 3)
- return OFF;
- if (OFFcount > 6)
- return OFF;
- if ((ONcount == 3) && (OFFcount == 5))
- return ON;
- return UNK;
-
- default:
- return UNK;
- }
- }
-
-
- /*
- * Determine the implications of a cell depending on its known neighbor counts.
- * The unknown neighbor count is implicit since there are eight neighbors.
- */
- static FLAGS
- implication(state, OFFcount, ONcount)
- STATE state;
- unsigned int OFFcount;
- unsigned int ONcount;
- {
- unsigned int UNKcount;
- FLAGS flags;
-
- UNKcount = 8 - OFFcount - ONcount;
- flags = 0;
- if (ONcount == 3)
- flags |= N1ICUN0;
- if ((ONcount == 3) && (UNKcount == 1))
- flags |= N0ICUN1;
-
- switch (state) {
- case OFF:
- if ((ONcount == 2) && (UNKcount == 1))
- flags |= N0ICUN0;
- if (OFFcount == 5)
- flags |= N1ICUN1;
- break;
-
- case ON:
- if (OFFcount == 6)
- flags |= N1ICUN1;
- if ((ONcount == 1) && (UNKcount == 1))
- flags |= N0ICUN0;
- break;
-
- case UNK:
- if (OFFcount == 6)
- flags |= (N1ICUN1 | N1IC1);
- if ((ONcount == 2) && (UNKcount == 0))
- flags |= (N0IC0 | N1IC1);
- break;
- }
- if (UNKcount == 0)
- flags &= ~(N0ICUN0 | N0ICUN1 | N1ICUN0 | N1ICUN1);
- return flags;
- }
-
- /* END CODE */
-