home *** CD-ROM | disk | FTP | other *** search
- /*****
- *
- * File: cellvonn.c
- *
- * Cellsim, cellular automata simulator
- *
- * Routines specific to vonNeumann 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_v(), to_nhood_v(), to_index_v(), rotate_v(),
- auto_v(), learn_v();
-
-
- /*
- * Set basic nhood-specific vars and function-pointers
- */
- set_params_v()
- {
- N = 5;
- TMASK = (AMASK << (3 * L)) | (AMASK << (2 * L));
- get_address = get_address_v;
- to_nhood = to_nhood_v;
- to_index = to_index_v;
- rotate = rotate_v;
- auto_screen = auto_step = auto_v;
- learn = learn_v;
- }
-
-
- /* transition function table access routines */
- /* Note: cnvrt and uncnvrt are also called by the other neighborhood routines */
-
- cnvrt(str) /* convert t-table index string to int */
- char str[]; /* ptr to index string */
-
- {
- int a, i;
-
- a = 0;
-
- for (i = 0; i < N; i++) {
- a <<= L;
- a += to_state(str[i]);
- }
-
- return (a);
-
- } /* cnvrt */
-
-
- uncnvrt(a, str) /* index string from t-table index */
- int a;
- char str[];
- {
- int i;
- for (i = N - 1; i >= 0; i--) {
- str[i] = to_char(a & AMASK);
- a >>= L;
- }
- str[N] = NULL;
- } /* uncnvrt */
-
-
- to_nhood_v(a, buf) /* von-N t-table index to ascii c-clock
- * string */
- int a;
- char buf[];
-
- {
- uncnvrt(a, string); /* integer to ascii */
-
- buf[0] = string[1]; /* c */
- buf[1] = string[3]; /* t */
- buf[2] = string[2]; /* r */
- buf[3] = string[4]; /* b */
- buf[4] = string[0]; /* l */
- buf[5] = NULL; /* '\0' end of string */
-
- } /* to_nhood_v */
-
-
-
- int
- to_index_v(nhood) /* encode t-table index of ascii nhood */
- char nhood[];
-
- {
- int k;
-
- for (k = 0; k < N; k++) /* check for input errors */
- if (!is_state(nhood[k]))
- return (TABLE_ERR);
-
- /* encoding for von-N neighborhood */
-
- string[0] = nhood[4]; /* l */
- string[1] = nhood[0]; /* c */
- string[2] = nhood[2]; /* r */
- string[3] = nhood[1]; /* t */
- string[4] = nhood[3]; /* b */
- string[5] = NULL;
-
- return (cnvrt(string));
-
- } /* to_index_v */
-
-
- rotate_v(nhood) /* rotate ascii nhood 90 degrees */
- char nhood[];
- {
- char temp;
- temp = nhood[4];
- nhood[4] = nhood[3]; /* b -> l */
- nhood[3] = nhood[2]; /* r -> b */
- nhood[2] = nhood[1]; /* t -> r */
- nhood[1] = temp; /* l -> t */
- } /* rotate_v */
-
-
- auto_v(steps) /* run the automaton for <steps> time steps */
- int steps; /* cycle counter */
-
- {
- register unsigned char *cptr, *iptr;/* ptrs to arrays */
-
- register unsigned char *taa; /* ptr to t-func array */
- register int a; /* array pointer vars */
- register char l = L; /* count variables */
- int tmask = TMASK;
- register short mb = -B, pb = B;
- register short j;
- register State value;
- /* register */ int *sc;
- register vonn_nbors nbors;
- array_info_struct array_info;
-
- int i, k;
-
- /* cycle through the array "steps" times */
-
- if (function) {
- nbors.parm1 = parm1;
- nbors.parm2 = parm2;
- nbors.time = stime;
- }
-
- for (k = 0; k < steps; k++) {
-
- if (before_function) {
- array_info.array = ca;
- array_info.time = stime;
- array_info.parm1 = parm1;
- array_info.parm2 = parm2;
- before_function(&array_info);
- }
-
- cptr = ca; /* load register copies */
- taa = ta;
- sc = statecount;
-
- for (j = 0; j < S; j++) /* clear state counts */
- sc[j] = 0;
-
- /* initialize top and bottom buffers */
-
- for (i = 0; i < B; i++) {
- cptr[i] = cptr[BSQR + i];
- cptr[BBUF + i] = cptr[ABASE + i];
- }
-
- /* now traverse the array */
-
- cptr = &ca[BM1];
- iptr = &ia[BM1];
-
- for (i = 0; i < RCOUNT; i++) {
- cptr++;
- iptr++;
-
- a = 0;
-
- /* initial left edge cell load */
-
- if (function) {
- nbors.l = cptr[pb - 1];
- nbors.c = cptr[0];
- nbors.r = cptr[1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = 0;
- nbors.y = i;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
-
- a |= cptr[pb - 1]; /* wrap l */
- a <<= l;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[1]; /* r */
- a <<= l;
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
-
- /* now process cell */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- cptr++;
- iptr++; /* now do one normal cell */
-
- if (function) {
- nbors.l = cptr[-1];
- nbors.c = cptr[0];
- nbors.r = cptr[1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = 1;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= tmask;
- a |= (cptr[1] << l); /* r */
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- /* now do central cells of this row, four at a time */
-
- for (j = 4; j < pb; j += 4) {
- cptr++;
- iptr++; /***** ONE *****/
-
- if (function) {
- nbors.l = cptr[-1];
- nbors.c = cptr[0];
- nbors.r = cptr[1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = j-2;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= tmask;
- a |= (cptr[1] << l); /* r */
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- cptr++;
- iptr++; /***** TWO *****/
-
- if (function) {
- nbors.l = cptr[-1];
- nbors.c = cptr[0];
- nbors.r = cptr[1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = j-1;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= tmask;
- a |= (cptr[1] << l); /* r */
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- cptr++;
- iptr++; /***** THREE *****/
-
- if (function) {
- nbors.l = cptr[-1];
- nbors.c = cptr[0];
- nbors.r = cptr[1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = j;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= tmask;
- a |= (cptr[1] << l); /* r */
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- cptr++;
- iptr++; /***** FOUR *****/
-
- if (function) {
- nbors.l = cptr[-1];
- nbors.c = cptr[0];
- nbors.r = cptr[1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = j+1;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= tmask;
- a |= (cptr[1] << l); /* r */
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
- } /* column for loop */
-
- cptr++;
- iptr++; /* now do one more normal cell */
- if (function) {
- nbors.l = cptr[-1];
- nbors.c = cptr[0];
- nbors.r = cptr[1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = pb - 2;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= tmask;
- a |= (cptr[1] << l); /* r */
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- cptr++;
- iptr++; /* now do the right edge cell */
-
- if (function) {
- nbors.l = cptr[-1];
- nbors.c = cptr[0];
- nbors.r = cptr[mb + 1];
- nbors.t = cptr[mb];
- nbors.b = cptr[pb];
- nbors.x = pb - 1;
- /* nbors.y doesn't need to be changed */
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a &= tmask;
- a |= (cptr[mb + 1] << l); /* wrap r neighbor */
- a |= cptr[mb]; /* t */
- a <<= l;
- a |= cptr[pb]; /* b */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- /* that's all for this row */
-
- } /* row for(...) loop */
- if (after_function) {
- array_info.array = ia;
- array_info.time = stime;
- 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();
-
- } /* steps for loop */
- return 0;
- } /* auto_v */
-
-
- get_address_v(x, y) /* get index at given ca location */
- unsigned short x, y;
- {
- int a, cp;
-
- a = 0;
- cp = y * B + x + B;
-
- a += ca[x == 0 ? cp + BM1 : cp - 1];/* l (wraparound if needed) */
- a <<= L;
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[x == BM1 ? cp - BM1 : cp + 1]; /* r (wraparound if needed) */
- a <<= L;
- a += ca[cp - B]; /* t */
- a <<= L;
- a += ca[cp + B]; /* b */
-
- return (a);
-
- } /* get_address_v */
-
-
-
- get_nbors_v(nb, x, y) /* get nbors at given ca location */
- vonn_nbors *nb;
- unsigned short x, y;
- {
- int cp;
-
- cp = y * B + x + B;
-
- nb->l = ca[x == 0 ? cp + BM1 : cp - 1];/* l (wraparound if needed) */
- nb->c = ca[cp]; /* c */
- nb->r = ca[x == BM1 ? cp - BM1 : cp + 1]; /* r (wraparound if needed) */
- nb->t = ca[cp - B]; /* t */
- nb->b = ca[cp + B]; /* b */
- nb->x = x;
- nb->y = y;
- nb->parm1 = parm1;
- nb->parm2 = parm2;
- nb->time = stime;
-
- return;
-
- } /* get_nbors_v */
-
-
- learn_v()
- { /* learn trans rule for VonNeumann
- * nhood */
- int a, cp; /* array pointer vars */
- int r, t, b; /* 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++;
- r = cp + 1; /* initialize r offset */
- t = cp - B; /* initialize t offset */
- b = cp + B; /* initialize b offset */
-
- a = 0;
- x = 0;
-
- /* initial left edge cell load */
-
- a += ca[cp + BM1]; /* wrap l */
- a <<= L;
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[r]; /* r */
- a <<= L;
- a += ca[t]; /* t */
- a <<= L;
- a += ca[b]; /* b */
-
- /* 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++;
- r++;
- t++;
- b++;
-
- a &= TMASK;
- a += (ca[r] << L);
- a += ca[t];
- a <<= L;
- a += ca[b];
-
- if (!(derive(x, y, a, &ia[cp]))) {
- swap_data();
- return;
- }
- } /* central cell for loop */
-
-
- /* now do the right edge cell */
-
- x = BM1;
-
- cp++;
- t++;
- b++;
-
- a &= TMASK;
- a += (ca[cp - BM1] << L); /* wrap r neighbor */
- a += ca[t];
- a <<= L;
- a += ca[b];
-
- 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_v */
-