home *** CD-ROM | disk | FTP | other *** search
- /*****
- *
- * File: cellmoore.c
- *
- * Cellsim, cellular automata simulator
- *
- * Routines specific to Moore nhood
- *
- *****/
-
- #include "cellnborhoods.h"
-
- /*
- *
- * Cellsim copyright 1989, 1990 by Chris Langton and Dave Hiebeler
- * (cgl@lanl.gov, hiebeler@heretic.lanl.gov)
- *
- * This package may be freely distributed, as long as you don't:
- * - remove this notice
- * - try to make money by doing so
- * - prevent others from copying it freely
- * - distribute modified versions without clearly documenting your changes
- * and notifying us
- *
- * Please contact either of the authors listed above if you have questions
- * or feel an exception to any of the above restrictions is in order.
- *
- * If you make changes to the code, or have suggestions for changes,
- * let us know! If we use your suggestion, you will receive full credit
- * of course.
- */
-
- /*****
- * Cellsim history:
- *
- * Cellsim was originally written on Apollo workstations by Chris Langton.
- *
- * Sun versions:
- *
- * - version 1.0
- * by C. Ferenbaugh and C. Langton
- * released 09/02/88
- *
- * - version 1.5
- * by Dave Hiebeler and C. Langton May - June 1989
- * released 07/03/89
- *
- * - version 2.0
- * by Dave Hiebeler and C. Langton July - August 1989
- * never officially released (unofficially released 09/08/89)
- *
- * - version 2.5
- * by Dave Hiebeler and C. Langton September '89 - February 1990
- * released 02/26/90
- *****/
-
-
- /* Local nhood-specific routines */
- int
- get_address_m(), to_nhood_m(), to_index_m(), rotate_m(),
- auto_m(), learn_m();
-
-
- set_params_m()
- { /* set nhood-dependent parameters */
- N = 9;
- TMASK = AMASK | (AMASK << L) | (AMASK << (2 * L));
- TMASK |= (TMASK << (3 * L));
- get_address = get_address_m;
- to_nhood = to_nhood_m;
- to_index = to_index_m;
- rotate = rotate_m;
- auto_screen = auto_step = auto_m;
- learn = learn_m;
- }
-
-
- auto_m(step) /* run the automaton <step> steps */
- int step;
-
- {
- /* local variables */
- register unsigned char *cptr, *iptr;/* ptrs to arrays */
- register unsigned char *taa; /* ptr to t-func array */
-
-
- register int a; /* array pointer vars */
- int i, k;
- register int j; /* count vars */
- register State value;
- /* register */ int *sc;
- register char l = L;
- register int pb = B, mb = -B;
- register moore_nbors nbors;
- array_info_struct array_info;
-
- /* process the array "step" times */
-
- if (function) {
- nbors.parm1 = (cell_value)parm1;
- nbors.parm2 = (cell_value)parm2;
- nbors.time = (cell_value)stime;
- }
- for (k = 0; k < step; k++) {
-
- if (before_function) {
- array_info.array = ca;
- array_info.time = stime;
- array_info.size = B;
- array_info.parm1 = parm1;
- array_info.parm2 = parm2;
- before_function(&array_info);
- }
-
- cptr = ca; /* load register copies */
- iptr = ia;
- taa = ta;
- sc = statecount;
-
- for (j = 0; j < S; j++) /* clear state counts */
- sc[j] = 0;
-
- /* first - initialize top and bottom "wrap" buffers */
-
- for (i = 0; i < B; i++) {
- cptr[i] = cptr[BSQR + i];
- cptr[BBUF + i] = cptr[ABASE + i];
- }
-
- /* now - traverse the array row by row */
-
- cptr = &ca[BM1]; /* preset cell pointer */
- iptr = &ia[BM1];
-
- for (i = 0; i < RCOUNT; i++) {
-
- /* initialize neighbor pointers */
-
- cptr++;
- iptr++;
- a = 0;
-
- /* now - do the left edge cell load */
-
- if (function) {
- nbors.tl = (cell_value)cptr[-1];
- nbors.l = (cell_value)cptr[pb - 1];
- nbors.bl = (cell_value)cptr[TBM1];
- nbors.t = (cell_value)cptr[mb];
- nbors.c = (cell_value)cptr[0];
- nbors.b = (cell_value)cptr[pb];
- nbors.tr = (cell_value)cptr[mb + 1];
- nbors.r = (cell_value)cptr[1];
- nbors.br = (cell_value)cptr[pb + 1];
- nbors.x = (cell_value)0;
- nbors.y = (cell_value)i;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a |= cptr[-1]; /* tl wrap */
- a <<= l;
- a |= cptr[pb - 1]; /* l wrap */
- a <<= l;
- a |= cptr[TBM1]; /* bl wrap */
- a <<= l;
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[pb]; /* b */
- a <<= l;
- a |= cptr[mb + 1]; /* tr */
- a <<= l;
- a |= cptr[1]; /* r */
- a <<= l;
- a |= cptr[pb + 1]; /* br */
-
- /* now get image */
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- /* now do the central cells of this row */
-
- for (j = 2; j < pb; j++) {
-
- cptr++;
- iptr++;
-
- if (function) {
- nbors.tl = (cell_value)cptr[mb - 1];
- nbors.l = (cell_value)cptr[-1];
- nbors.bl = (cell_value)cptr[pb - 1];
- nbors.t = (cell_value)cptr[mb];
- nbors.c = (cell_value)cptr[0];
- nbors.b = (cell_value)cptr[pb];
- nbors.tr = (cell_value)cptr[mb + 1];
- nbors.r = (cell_value)cptr[1];
- nbors.br = (cell_value)cptr[pb + 1];
- nbors.x = (cell_value)j-1;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= TMASK;
- a <<= l;
- a |= cptr[mb + 1];
- a <<= l;
- a |= cptr[1];
- a <<= l;
- a |= cptr[pb + 1];
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- } /* central cell for loop */
-
- /* and now do the right edge cell */
-
- cptr++;
- iptr++;
-
- if (function) {
- nbors.tl = (cell_value)cptr[mb - 1];
- nbors.l = (cell_value)cptr[-1];
- nbors.bl = (cell_value)cptr[pb - 1];
- nbors.t = (cell_value)cptr[mb];
- nbors.c = (cell_value)cptr[0];
- nbors.b = (cell_value)cptr[pb];
- nbors.tr = (cell_value)cptr[-TBM1];
- nbors.r = (cell_value)cptr[mb + 1];
- nbors.br = (cell_value)cptr[1];
- nbors.x = (cell_value)pb - 1;
- /* nbors.y still doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= TMASK;
- a <<= l;
- a |= cptr[-TBM1]; /* wrap tr */
- a <<= l;
- a |= cptr[mb + 1]; /* wrap r */
- a <<= l;
- a |= cptr[1]; /* wrap br */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- /* that's all for this row */
-
- } /* row for loop */
-
- /* that's all for the array */
- /* now increment time and swap current and image arrays */
-
- if (after_function) {
- array_info.array = ia;
- array_info.time = stime;
- array_info.size = B;
- array_info.parm1 = parm1;
- array_info.parm2 = parm2;
- after_function(&array_info);
- }
-
- swap_data(); /* image array is now current */
-
- show_time(++stime); /* advance time */
-
- if (SOCKET_INUSE)
- send_sock();
-
-
- } /* step for loop */
-
-
- return (0);
-
- } /* auto_m */
-
-
-
- int
- to_index_m(nhood) /* encode t-table index of ascii nhood */
- char nhood[];
-
- {
- int i;
-
- for (i = 0; i < N; i++) /* check for input errors */
- if (!is_state(nhood[i]))
- return (TABLE_ERR);
-
- /* encoding for Moore neighborhood */
-
- string[0] = nhood[1]; /* tl */
- string[1] = nhood[8]; /* l */
- string[2] = nhood[7]; /* bl */
- string[3] = nhood[2]; /* t */
- string[4] = nhood[0]; /* c */
- string[5] = nhood[6]; /* b */
- string[6] = nhood[3]; /* tr */
- string[7] = nhood[4]; /* r */
- string[8] = nhood[5]; /* br */
-
- return (cnvrt(string)); /* convert index string to int */
-
- } /* to_index_m */
-
-
-
- rotate_m(nhood) /* rotate ascii nhood 90 degrees */
- char nhood[];
- {
- char temp;
- temp = nhood[8];
- nhood[8] = nhood[6]; /* b -> l */
- nhood[6] = nhood[4]; /* r -> b */
- nhood[4] = nhood[2]; /* t -> r */
- nhood[2] = temp; /* l -> t */
- temp = nhood[7];
- nhood[7] = nhood[5]; /* br -> bl */
- nhood[5] = nhood[3]; /* tr -> br */
- nhood[3] = nhood[1]; /* tl -> tr */
- nhood[1] = temp; /* bl -> tl */
- } /* rotate_m */
-
-
- to_nhood_m(a, buf) /* Moore t-table index to ascii c-clock
- * string */
- int a;
- char buf[];
-
- {
- uncnvrt(a, string); /* index string from t-table index */
-
- buf[0] = string[4]; /* c */
- buf[1] = string[0]; /* tl */
- buf[2] = string[3]; /* t */
- buf[3] = string[6]; /* tr */
- buf[4] = string[7]; /* r */
- buf[5] = string[8]; /* br */
- buf[6] = string[5]; /* b */
- buf[7] = string[2]; /* bl */
- buf[8] = string[1]; /* l */
- buf[9] = NULL; /* '\0' end of string */
-
- } /* to_nhood_m */
-
-
-
-
- get_address_m(x, y) /* get index at given ca location */
- unsigned short x, y;
- {
- int a, cp, lwrap = (x == 0 ? B : 0), rwrap = (x == BM1 ? -B : 0);
-
- a = 0;
- cp = y * B + x + ABASE;
-
- a += ca[cp + lwrap - BPL1]; /* tl (wraparound if needed) */
- a <<= L;
- a += ca[cp + lwrap - 1]; /* l (wraparound if needed) */
- a <<= L;
- a += ca[cp + lwrap + BM1]; /* bl (wraparound if needed) */
- a <<= L;
- a += ca[cp - B]; /* t */
- a <<= L;
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[cp + B]; /* b */
- a <<= L;
- a += ca[cp + rwrap - BM1]; /* tr (wraparound if needed) */
- a <<= L;
- a += ca[cp + rwrap + 1]; /* r (wraparound if needed) */
- a <<= L;
- a += ca[cp + rwrap + BPL1]; /* br (wraparound if needed) */
-
- return (a);
-
- } /* get_address_m */
-
-
-
- get_nbors_m(nb,x, y) /* get nbors at given ca location */
- moore_nbors *nb;
- unsigned short x, y;
- {
- int cp, lwrap = (x == 0 ? B : 0), rwrap = (x == BM1 ? -B : 0);
-
- cp = y * B + x + ABASE;
-
- nb->tl = ca[cp + lwrap - BPL1]; /* tl (wraparound if needed) */
- nb->l = ca[cp + lwrap - 1]; /* l (wraparound if needed) */
- nb->bl = ca[cp + lwrap + BM1]; /* bl (wraparound if needed) */
- nb->t = ca[cp - B]; /* t */
- nb->c = ca[cp]; /* c */
- nb->b = ca[cp + B]; /* b */
- nb->tr = ca[cp + rwrap - BM1]; /* tr (wraparound if needed) */
- nb->r = ca[cp + rwrap + 1]; /* r (wraparound if needed) */
- nb->br = ca[cp + rwrap + BPL1]; /* br (wraparound if needed) */
- nb->x = x;
- nb->y = y;
- nb->time = stime;
- nb->parm1 = parm1;
- nb->parm2 = parm2;
-
- return;
-
- } /* get_nbors_m */
-
-
- learn_m()
- { /* learn trans rule for Moore nhood */
- int a, cp; /* array pointer vars */
- int tr, br, r; /* new neighbor offsets */
- int i, x, y; /* count variables */
-
-
- /* swap current and image arrays */
-
- swap_data();
-
- /* initialize top and bottom buffers */
-
- for (i = 0; i < B; i++) {
- ca[i] = ca[BSQR + i];
- ca[BBUF + i] = ca[ABASE + i];
- }
-
-
- /* now traverse the array */
-
- cp = BM1; /* preset cell ptr */
-
- for (y = 0; y < RCOUNT; y++) {
-
- cp++;
-
- tr = cp - BM1; /* initialize tr offset */
- r = cp + 1; /* initialize tr offset */
- br = cp + BPL1; /* initialize tr offset */
-
- a = 0;
- x = 0;
-
- /* initial left edge cell load */
-
- a += ca[cp - 1]; /* tl wrap */
- a <<= L;
- a += ca[cp + BM1]; /* l wrap */
- a <<= L;
- a += ca[cp + TBM1]; /* bl wrap */
- a <<= L;
- a += ca[cp - B]; /* t */
- a <<= L;
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[cp + B]; /* b */
- a <<= L;
- a += ca[tr]; /* tr */
- a <<= L;
- a += ca[r]; /* r */
- a <<= L;
- a += ca[br]; /* br */
-
- /* now process cell */
-
- if (!(derive(x, y, a, &ia[cp]))) {
- swap_data();
- return;
- }
- /* now do central cells of this row */
-
- for (x = 1; x < BM1; x++) {
-
- cp++;
- tr++;
- r++;
- br++;
-
- a &= TMASK;
- a <<= L;
- a += ca[tr];
- a <<= L;
- a += ca[r];
- a <<= L;
- a += ca[br];
-
- if (!(derive(x, y, a, &ia[cp]))) {
- swap_data();
- return;
- }
- } /* central cell for loop */
-
-
- /* now do the right edge cell */
-
- x = BM1;
-
- cp++;
-
- a &= TMASK;
- a <<= L;
- a += ca[cp - TBM1]; /* wrap tr */
- a <<= L;
- a += ca[cp - BM1]; /* wrap r */
- a <<= L;
- a += ca[cp + 1]; /* wrap br */
-
- if (!(derive(x, y, a, &ia[cp]))) {
- swap_data();
- return;
- }
- } /* row for loop */
-
- swap_data(); /* switch arrays back */
- copy_data(); /* copy image to backup */
-
- } /* learn_m */
-