home *** CD-ROM | disk | FTP | other *** search
- /*****
- *
- * File: cellmargolus.c
- *
- * Cellsim, cellular automata simulator
- *
- * Routines specific to Margolus 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
- *****/
-
-
-
- static int Phase; /* Local phase variable, calculated from
- * current time in the simulator */
-
- /* Local nhood-specific routines */
- int
- get_address_marg(), to_nhood_marg(), to_index_marg(), rotate_marg(),
- auto_marg(), learn_marg(), auto_marg_odd(), auto_marg_even();
-
-
- set_params_marg()
- { /* set nhood-dependent parameters */
- N = 5;
- TMASK = (AMASK << (4*L)) | (AMASK << (3*L)) | (AMASK << (2*L));
- TMASK2 = (AMASK << (3*L)) | (AMASK << (2*L)) | (AMASK << L);
- get_address = get_address_marg;
- to_nhood = to_nhood_marg;
- to_index = to_index_marg;
- rotate = rotate_marg;
- auto_screen = auto_step = auto_marg;
- learn = learn_marg;
- }
-
-
- to_nhood_marg(a, buf) /* Margolus t-table index to ascii
- * string */
- int a;
- char buf[];
-
- {
- uncnvrt(a, string); /* integer to ascii */
-
- buf[0] = string[0]; /* c */
- buf[1] = string[1]; /* ccw */
- buf[2] = string[2]; /* opp */
- buf[3] = string[3]; /* cw */
- buf[4] = string[4]; /* phase */
- buf[5] = NULL; /* '\0' end of string */
-
- } /* to_nhood_marg */
-
-
- int
- to_index_marg(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[0]; /* c */
- string[1] = nhood[1]; /* ccw */
- string[2] = nhood[2]; /* opp */
- string[3] = nhood[3]; /* cw */
- string[4] = nhood[4]; /* phase */
- string[5] = NULL;
-
- return (cnvrt(string));
-
- } /* to_index_marg */
-
-
- rotate_marg(nhood) /* rotate ascii nhood 90 degrees */
- char nhood[];
- {
- char temp;
- temp = nhood[0];
- nhood[0] = nhood[1]; /* cw -> c */
- nhood[1] = nhood[2]; /* opp -> cw */
- nhood[2] = nhood[3]; /* ccw -> opp */
- nhood[3] = temp; /* c -> ccw */
- /* nhood[4] doesn't need to change, since it is phase */
- } /* rotate_marg */
-
-
- /* margolus updating that alternates between even-grid and odd-grid */
- auto_marg(steps)
- int steps;
- {
- int i, k, (*f1)(), (*f2)();
-
- Phase = stime%S;
- if (stime%2) {
- f1 = auto_marg_odd;
- f2 = auto_marg_even;
- }
- else {
- f1 = auto_marg_even;
- f2 = auto_marg_odd;
- }
- if (steps%2) {
- for (i=0; i < steps-1; i += 2) {
- k = f1();
- if (k) return k;
- k = f2();
- if (k) return k;
- }
- return f1();
- }
- else {
- for (i=0; i<steps; i += 2) {
- k = f1();
- if (k) return k;
- k = f2();
- if (k) return k;
- }
- }
- return 0;
- }
-
-
- /* margolus updating when origin is at (0,0) */
- auto_marg_even()
-
- {
- register unsigned char *cptr, *iptr;/* ptrs to arrays */
-
- register unsigned char *taa; /* ptr to t-func array */
- register int a, aa; /* array pointer vars */
- register char l = L; /* count variables */
- int tmask = TMASK, tmask2 = TMASK2;
- register short mb = -B, pb = B;
- register short j;
- register State value;
- /* register */ int *sc;
- register int pbp1 = pb+1;
- register margolus_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.phase = Phase;
- nbors.time = stime;
- }
-
- 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 */
- taa = ta;
- sc = statecount;
-
- for (j = 0; j < S; j++) /* clear state counts */
- sc[j] = 0;
-
- /* don't need to initialize top and bottom buffers, since
- * with origin at (0,0), Margolus neighborhood has no
- * wraparound
- */
-
- /* now traverse the array */
-
- cptr = &ca[BM1];
- iptr = &ia[BM1];
-
- for (i = 0; i < RCOUNT; i += 2) {
-
-
- for (j=0; j < pb; j += 2) {
- cptr++;
- iptr++;
-
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[pb];
- nbors.opp = cptr[pbp1];
- nbors.cw = cptr[1];
- nbors.y = i;
- nbors.x = j;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a = 0;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[pb]; /* ccw */
- a <<= l;
- a |= cptr[pbp1]; /* opp */
- a <<= l;
- a |= cptr[1]; /* cw */
- a <<= l;
- a |= Phase;
-
- /* now process cell */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- cptr++;
- iptr++; /* now do the next guy over in this block */
- if (function) {
- a = nbors.c;
- nbors.c = nbors.cw;
- nbors.cw = nbors.opp;
- nbors.opp = nbors.ccw;
- nbors.ccw = a;
- nbors.x = j+1;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- aa = a;
- a &= tmask;
- a >>= l;
- a |= (aa&(AMASK<<l))<<(3*l);
- a |= Phase;
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- } /* column for loop */
-
-
- /* that's all for this row */
- /* now do odd row */
-
-
- for (j=0; j < pb; j += 2) {
- cptr++;
- iptr++;
-
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[1];
- nbors.opp = cptr[mb + 1];
- nbors.cw = cptr[mb];
- nbors.y = i+1;
- nbors.x = j;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a = 0;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[1]; /* ccw */
- a <<= l;
- a |= cptr[mb + 1]; /* opp */
- a <<= l;
- a |= cptr[mb]; /* cw */
- a <<= l;
- a |= Phase;
-
- /* now process cell */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- cptr++;
- iptr++; /* now do the next guy over in this block */
- if (function) {
- a = nbors.c;
- nbors.c = nbors.ccw;
- nbors.ccw = nbors.opp;
- nbors.opp = nbors.cw;
- nbors.cw = a;
- nbors.x = j+1;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- aa = a;
- a &= tmask2;
- a <<= l;
- a |= (aa>>(3*l))&(AMASK<<l);
- a |= Phase;
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- } /* column for loop */
-
-
- /* that's all for this row */
-
- } /* row for(...) loop */
-
- 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 */
- Phase = (Phase+1)%S;
-
- if (SOCKET_INUSE)
- send_sock();
-
-
- return (0);
-
- } /* auto_marg_even */
-
-
- /* margolus updating when origin is at (1,1) */
- auto_marg_odd()
- {
- register unsigned char *cptr, *iptr;/* ptrs to arrays */
-
- register unsigned char *taa; /* ptr to t-func array */
- register int a, aa; /* array pointer vars */
- register char l = L; /* count variables */
- int tmask = TMASK, tmask2 = TMASK2;
- register short mb = -B, pb = B;
- register short j;
- register State value;
- register int *sc;
- register int hv; /* horizontal/vertical low bit */
- register margolus_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.phase = Phase;
- nbors.time = stime;
- }
- /* printf("inside auto_marg_odd()\n"); */
-
- if (before_function) {
- array_info.array = ca;
- array_info.time = stime;
- array_info.size = B;
- 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 += 2) {
- cptr++;
- iptr++;
-
-
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[mb];
- nbors.opp = cptr[-1];
- nbors.cw = cptr[pb - 1];
- nbors.y = i;
- nbors.x = 0;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
-
- a = 0;
-
- /* initial left edge cell load */
-
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[mb]; /* ccw */
- a <<= l;
- a |= cptr[-1]; /* wrap opp */
- a <<= l;
- a |= cptr[pb - 1]; /* wrap cw */
- a <<= l;
- a |= Phase;
-
- /* now process cell */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- /* now do central cells of this row, two at a time */
-
- for (j = 1; j < pb-1; j += 2) {
- cptr++;
- iptr++;
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[1];
- nbors.opp = cptr[mb + 1];
- nbors.cw = cptr[mb];
- nbors.x = j;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a = 0;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[1]; /* ccw */
- a <<= l;
- a |= cptr[mb + 1]; /* opp */
- a <<= l;
- a |= cptr[mb]; /* cw */
- a <<= l;
- a |= Phase;
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- cptr++;
- iptr++;
- if (function) {
- a = nbors.c;
- nbors.c = nbors.ccw;
- nbors.ccw = nbors.opp;
- nbors.opp = nbors.cw;
- nbors.cw = a;
- nbors.x = j+1;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- aa = a;
- a &= tmask2;
- a <<= l;
- /* a |= (aa&AMASK)<<(3*l); */
- a |= (aa>>(3*l))&(AMASK<<l);
- a |= Phase;
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- } /* column for loop */
-
-
- cptr++;
- iptr++; /* now do the right edge cell */
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[mb + 1];
- nbors.opp = cptr[-TBM1];
- nbors.cw = cptr[mb];
- nbors.x = pb-1;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a = 0;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[mb + 1]; /* ccw */
- a <<= l;
- a |= cptr[-TBM1]; /* wrap opp */
- a <<= l;
- a |= cptr[mb]; /* wrap cw */
- a <<= l;
- a |= Phase;
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- /* that's all for this row */
- /* now do odd row */
-
- cptr++;
- iptr++;
-
- a = 0;
-
- /* initial left edge cell load */
-
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[pb - 1];
- nbors.opp = cptr[TBM1];
- nbors.cw = cptr[pb];
- nbors.y = i+1;
- nbors.x = 0;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[pb - 1]; /* wrap ccw */
- a <<= l;
- a |= cptr[TBM1]; /* wrap opp */
- a <<= l;
- a |= cptr[pb]; /* cw */
- a <<= l;
- a |= Phase;
-
- /* now process cell */
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- /* now do central cells of this row, two at a time */
-
- for (j = 1; j < pb-1; j += 2) {
- cptr++;
- iptr++;
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[pb];
- nbors.opp = cptr[pb + 1];
- nbors.cw = cptr[1];
- nbors.x = j;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a = 0;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[pb]; /* ccw */
- a <<= l;
- a |= cptr[pb + 1]; /* opp */
- a <<= l;
- a |= cptr[1]; /* cw */
- a <<= l;
- a |= Phase;
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- cptr++;
- iptr++;
- if (function) {
- a = nbors.c;
- nbors.c = nbors.cw;
- nbors.cw = nbors.opp;
- nbors.opp = nbors.ccw;
- nbors.ccw = a;
- nbors.x = j+1;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- aa = a;
- a &= tmask;
- a >>= l;
- a |= (aa&(AMASK<<l))<<(3*l);
- a |= Phase;
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
- } /* column for loop */
-
-
- cptr++;
- iptr++; /* now do the right edge cell */
- if (function) {
- nbors.c = cptr[0];
- nbors.ccw = cptr[pb];
- nbors.opp = cptr[1];
- nbors.cw = cptr[mb + 1];
- nbors.x = pb-1;
- *iptr = value = (unsigned char)update_function(&nbors);
- }
- else {
- a = 0;
- a |= cptr[0]; /* c */
- a <<= l;
- a |= cptr[pb]; /* ccw */
- a <<= l;
- a |= cptr[1]; /* wrap opp */
- a <<= l;
- a |= cptr[mb + 1]; /* wrap cw */
- a <<= l;
- a |= Phase;
-
- if ((*iptr = value = taa[a]) == UNDEF)
- return (cptr - ca);
- }
- sc[value]++;
-
-
- /* that's all for this row */
- /* now do odd row */
-
- } /* row for(...) loop */
-
- if (after_function) {
- array_info.array = ia;
- array_info.time = stime;
- array_info.size = B;
- after_function(&array_info);
- }
-
- swap_data(); /* image array is now current */
-
- show_time(++stime); /* advance time */
- Phase = (Phase+1)%S;
-
- if (SOCKET_INUSE)
- send_sock();
-
-
- return (0);
-
- } /* auto_marg_odd */
-
-
- get_address_marg(x, y) /* get index at given ca location */
- unsigned short x, y;
- {
- int a, cp;
- int lwrap = (x == 0 ? B : 0), rwrap = (x == BM1 ? -B : 0);
-
- Phase = stime%S;
- a = 0;
- cp = y * B + x + B;
-
- if (((stime%2) && ((x%2) == 0) && ((y%2) == 0)) ||
- (((stime%2) == 0) && (x%2) && (y%2))) { /* lower right */
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[cp - B]; /* ccw */
- a <<= L;
- a += ca[cp + lwrap - BPL1]; /* opp (wrap if needed) */
- a <<= L;
- a += ca[cp + lwrap - 1]; /* cw (wrap if needed) */
- a <<= L;
- a |= Phase;
- }
- if (((stime%2) && ((x%2) == 0) && (y%2)) ||
- (((stime%2) == 0) && (x%2) && ((y%2) == 0))) { /* upper right */
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[cp + lwrap - 1]; /* ccw (wrap if needed) */
- a <<= L;
- a += ca[cp + lwrap + BM1]; /* opp (wrap if needed) */
- a <<= L;
- a += ca[cp + B]; /* cw */
- a <<= L;
- a |= Phase;
- }
- if (((stime%2) && (x%2) && ((y%2 == 0))) ||
- (((stime%2) == 0) && ((x%2) == 0) && (y%2))) { /* lower left */
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[cp + rwrap + 1]; /* ccw (wrap if needed) */
- a <<= L;
- a += ca[cp + rwrap - BM1]; /* opp (wrap if needed) */
- a <<= L;
- a += ca[cp - B]; /* cw */
- a <<= L;
- a |= Phase;
- }
- if (((stime%2) && (x%2) && (y%2)) ||
- (((stime%2) == 0) && ((x%2) == 0) && ((y%2) == 0))) { /* upper left */
- a += ca[cp]; /* c */
- a <<= L;
- a += ca[cp + B]; /* ccw */
- a <<= L;
- a += ca[cp + rwrap + BPL1]; /* opp (wrap if needed) */
- a <<= L;
- a += ca[cp + rwrap + 1]; /* cw (wrap if needed) */
- a <<= L;
- a |= Phase;
- }
- return (a);
-
- } /* get_address_marg */
-
-
-
- get_nbors_marg(nb, x, y) /* get nbors at given ca location */
- margolus_nbors *nb;
- unsigned short x, y;
- {
- int cp;
- int lwrap = (x == 0 ? B : 0), rwrap = (x == BM1 ? -B : 0);
-
- cp = y * B + x + B;
-
- if (((stime%2) && ((x%2) == 0) && ((y%2) == 0)) ||
- (((stime%2) == 0) && (x%2) && (y%2))) { /* lower right */
- nb->c = ca[cp]; /* c */
- nb->ccw = ca[cp - B]; /* ccw */
- nb->opp = ca[cp + lwrap - BPL1]; /* opp (wrap if needed) */
- nb->cw = ca[cp + lwrap - 1]; /* cw (wrap if needed) */
- }
- if (((stime%2) && ((x%2) == 0) && (y%2)) ||
- (((stime%2) == 0) && (x%2) && ((y%2) == 0))) { /* upper right */
- nb->c = ca[cp]; /* c */
- nb->ccw = ca[cp + lwrap - 1]; /* ccw (wrap if needed) */
- nb->opp = ca[cp + lwrap + BM1]; /* opp (wrap if needed) */
- nb->cw = ca[cp + B]; /* cw */
- }
- if (((stime%2) && (x%2) && ((y%2 == 0))) ||
- (((stime%2) == 0) && ((x%2) == 0) && (y%2))) { /* lower left */
- nb->c = ca[cp]; /* c */
- nb->ccw = ca[cp + rwrap + 1]; /* ccw (wrap if needed) */
- nb->opp = ca[cp + rwrap - BM1]; /* opp (wrap if needed) */
- nb->cw = ca[cp - B]; /* cw */
- }
- if (((stime%2) && (x%2) && (y%2)) ||
- (((stime%2) == 0) && ((x%2) == 0) && ((y%2) == 0))) { /* upper left */
- nb->c = ca[cp]; /* c */
- nb->ccw = ca[cp + B]; /* ccw */
- nb->opp = ca[cp + rwrap + BPL1]; /* opp (wrap if needed) */
- nb->cw = ca[cp + rwrap + 1]; /* cw (wrap if needed) */
- }
- nb->phase = Phase;
- nb->time = stime;
- nb->x = x;
- nb->y = y;
- nb->parm1 = parm1;
- nb->parm2 = parm2;
- return;
-
- } /* get_nbors_marg */
-
-
- learn_marg()
- {
- clear_msg();
- show_msg("Not implemented");
- return;
-
- } /* learn_marg */
-