home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / cellsim / v2_5 / src / cllmrgls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-26  |  17.4 KB  |  828 lines

  1. /*****
  2.  *
  3.  * File: cellmargolus.c
  4.  *
  5.  * Cellsim, cellular automata simulator
  6.  *
  7.  * Routines specific to Margolus nhood *
  8.  *
  9.  *****/
  10.  
  11. #include "cellnborhoods.h"
  12.  
  13. /*
  14.  *
  15.  * Cellsim copyright 1989, 1990 by Chris Langton and Dave Hiebeler
  16.  * (cgl@lanl.gov, hiebeler@heretic.lanl.gov)
  17.  *
  18.  * This package may be freely distributed, as long as you don't:
  19.  * - remove this notice
  20.  * - try to make money by doing so
  21.  * - prevent others from copying it freely
  22.  * - distribute modified versions without clearly documenting your changes
  23.  *   and notifying us
  24.  *
  25.  * Please contact either of the authors listed above if you have questions
  26.  * or feel an exception to any of the above restrictions is in order.
  27.  *
  28.  * If you make changes to the code, or have suggestions for changes,
  29.  * let us know!  If we use your suggestion, you will receive full credit
  30.  * of course.
  31.  */
  32.  
  33. /*****
  34.  * Cellsim history:
  35.  *
  36.  * Cellsim was originally written on Apollo workstations by Chris Langton.
  37.  *
  38.  * Sun versions:
  39.  *
  40.  * - version 1.0
  41.  *   by C. Ferenbaugh and C. Langton
  42.  *   released 09/02/88
  43.  *
  44.  * - version 1.5
  45.  *   by Dave Hiebeler and C. Langton  May - June 1989
  46.  *   released 07/03/89
  47.  *
  48.  * - version 2.0
  49.  *   by Dave Hiebeler and C. Langton  July - August 1989
  50.  *   never officially released (unofficially released 09/08/89)
  51.  *
  52.  * - version 2.5
  53.  *   by Dave Hiebeler and C. Langton  September '89 - February 1990
  54.  *   released 02/26/90
  55.  *****/
  56.  
  57.  
  58.  
  59. static int Phase;        /* Local phase variable, calculated from
  60.                  * current time in the simulator */
  61.  
  62. /* Local nhood-specific routines */
  63. int 
  64.     get_address_marg(), to_nhood_marg(), to_index_marg(), rotate_marg(),
  65.     auto_marg(), learn_marg(), auto_marg_odd(), auto_marg_even();
  66.  
  67.  
  68. set_params_marg()
  69. {                    /* set nhood-dependent parameters */
  70.     N = 5;
  71.     TMASK = (AMASK << (4*L)) | (AMASK << (3*L)) | (AMASK << (2*L));
  72.     TMASK2 = (AMASK << (3*L)) | (AMASK << (2*L)) | (AMASK << L);
  73.     get_address = get_address_marg;
  74.     to_nhood = to_nhood_marg;
  75.     to_index = to_index_marg;
  76.     rotate = rotate_marg;
  77.     auto_screen = auto_step = auto_marg;
  78.     learn = learn_marg;
  79. }
  80.  
  81.  
  82. to_nhood_marg(a, buf)            /* Margolus t-table index to ascii
  83.                      * string */
  84.     int     a;
  85.     char    buf[];
  86.  
  87. {
  88.     uncnvrt(a, string);            /* integer to ascii */
  89.  
  90.     buf[0] = string[0];            /* c */
  91.     buf[1] = string[1];            /* ccw */
  92.     buf[2] = string[2];            /* opp */
  93.     buf[3] = string[3];            /* cw */
  94.     buf[4] = string[4];            /* phase */
  95.     buf[5] = NULL;            /* '\0' end of string */
  96.  
  97. } /* to_nhood_marg */
  98.  
  99.  
  100. int 
  101. to_index_marg(nhood)            /* encode t-table index of ascii nhood */
  102.     char    nhood[];
  103.  
  104. {
  105.     int     k;
  106.  
  107.     for (k = 0; k < N; k++)        /* check for input errors */
  108.     if (!is_state(nhood[k]))
  109.         return (TABLE_ERR);
  110.  
  111.     /* encoding for von-N neighborhood */
  112.  
  113.     string[0] = nhood[0];        /* c */
  114.     string[1] = nhood[1];        /* ccw */
  115.     string[2] = nhood[2];        /* opp */
  116.     string[3] = nhood[3];        /* cw */
  117.     string[4] = nhood[4];        /* phase */
  118.     string[5] = NULL;
  119.  
  120.     return (cnvrt(string));
  121.  
  122. } /* to_index_marg */
  123.  
  124.  
  125. rotate_marg(nhood)            /* rotate ascii nhood 90 degrees */
  126.     char    nhood[];
  127. {
  128.     char    temp;
  129.     temp = nhood[0];
  130.     nhood[0] = nhood[1];        /* cw -> c */
  131.     nhood[1] = nhood[2];        /* opp -> cw */
  132.     nhood[2] = nhood[3];        /* ccw -> opp */
  133.     nhood[3] = temp;            /* c -> ccw */
  134.     /* nhood[4] doesn't need to change, since it is phase */
  135. } /* rotate_marg */
  136.  
  137.  
  138. /* margolus updating that alternates between even-grid and odd-grid */
  139. auto_marg(steps)
  140. int steps;
  141. {
  142.     int i, k, (*f1)(), (*f2)();
  143.  
  144.     Phase = stime%S;
  145.     if (stime%2) {
  146.     f1 = auto_marg_odd;
  147.     f2 = auto_marg_even;
  148.     }
  149.     else {
  150.     f1 = auto_marg_even;
  151.     f2 = auto_marg_odd;
  152.     }
  153.     if (steps%2) {
  154.     for (i=0; i < steps-1; i += 2) {
  155.         k = f1();
  156.         if (k) return k;
  157.         k = f2();
  158.         if (k) return k;
  159.     }
  160.     return f1();
  161.     }
  162.     else {
  163.     for (i=0; i<steps; i += 2) {
  164.         k = f1();
  165.         if (k) return k;
  166.         k = f2();
  167.         if (k) return k;
  168.     }
  169.     }
  170.     return 0;
  171. }
  172.         
  173.    
  174. /* margolus updating when origin is at (0,0) */
  175. auto_marg_even()
  176.  
  177. {
  178.     register unsigned char *cptr, *iptr;/* ptrs to arrays */
  179.  
  180.     register unsigned char *taa;    /* ptr to t-func array  */
  181.     register int a, aa;            /* array pointer vars   */
  182.     register char l = L;        /* count variables      */
  183.     int     tmask = TMASK, tmask2 = TMASK2;
  184.     register short mb = -B, pb = B;
  185.     register short j;
  186.     register State value;
  187.     /* register */ int *sc;
  188.     register int pbp1 = pb+1;
  189.     register margolus_nbors nbors;
  190.     array_info_struct array_info;
  191.  
  192.     int     i, k;
  193.  
  194.     /* cycle through the array "steps" times */
  195.  
  196.  
  197.     if (function) {
  198.     nbors.parm1 = parm1;
  199.     nbors.parm2 = parm2;
  200.     nbors.phase = Phase;
  201.     nbors.time = stime;
  202.     }
  203.  
  204.     if (before_function) {
  205.     array_info.array = ca;
  206.     array_info.time = stime;
  207.     array_info.size = B;
  208.     array_info.parm1 = parm1;
  209.     array_info.parm2 = parm2;
  210.     before_function(&array_info);
  211.     }
  212.     
  213.     cptr = ca;            /* load register copies */
  214.     taa = ta;
  215.     sc = statecount;
  216.  
  217.     for (j = 0; j < S; j++)        /* clear state counts */
  218.     sc[j] = 0;
  219.  
  220.     /* don't need to initialize top and bottom buffers, since
  221.      * with origin at (0,0), Margolus neighborhood has no
  222.      * wraparound
  223.      */
  224.     
  225.     /* now traverse the array */
  226.     
  227.     cptr = &ca[BM1];
  228.     iptr = &ia[BM1];
  229.  
  230.     for (i = 0; i < RCOUNT; i += 2) {
  231.  
  232.  
  233.     for (j=0; j < pb; j += 2) {
  234.         cptr++;
  235.         iptr++;
  236.  
  237.         if (function) {
  238.         nbors.c = cptr[0];
  239.         nbors.ccw = cptr[pb];
  240.         nbors.opp = cptr[pbp1];
  241.         nbors.cw = cptr[1];
  242.         nbors.y = i;
  243.         nbors.x = j;
  244.         *iptr = value = (unsigned char)update_function(&nbors);
  245.         }
  246.         else {
  247.         a = 0;
  248.         a |= cptr[0];        /* c */
  249.         a <<= l;
  250.         a |= cptr[pb];        /* ccw  */
  251.         a <<= l;
  252.         a |= cptr[pbp1];    /* opp  */
  253.         a <<= l;
  254.         a |= cptr[1];        /* cw  */
  255.         a <<= l;
  256.         a |= Phase;
  257.         
  258.         /* now process cell */
  259.         
  260.         if ((*iptr = value = taa[a]) == UNDEF)
  261.             return (cptr - ca);
  262.         }
  263.         sc[value]++;
  264.         
  265.         
  266.         cptr++;
  267.         iptr++;        /* now do the next guy over in this block */
  268.         if (function) {
  269.         a = nbors.c;
  270.         nbors.c = nbors.cw;
  271.         nbors.cw = nbors.opp;
  272.         nbors.opp = nbors.ccw;
  273.         nbors.ccw = a;
  274.         nbors.x = j+1;
  275.         *iptr = value = (unsigned char)update_function(&nbors);
  276.         }
  277.         else {
  278.         aa = a;
  279.         a &= tmask;
  280.         a >>= l;
  281.         a |= (aa&(AMASK<<l))<<(3*l);
  282.         a |= Phase;
  283.         
  284.         if ((*iptr = value = taa[a]) == UNDEF)
  285.             return (cptr - ca);
  286.         }
  287.         sc[value]++;
  288.         
  289.         
  290.     } /* column for loop */
  291.     
  292.     
  293.     /* that's all for this row */
  294.     /* now do odd row */
  295.  
  296.     
  297.     for (j=0; j < pb; j += 2) {
  298.         cptr++;
  299.         iptr++;
  300.  
  301.         if (function) {
  302.         nbors.c = cptr[0];
  303.         nbors.ccw = cptr[1];
  304.         nbors.opp = cptr[mb + 1];
  305.         nbors.cw = cptr[mb];
  306.         nbors.y = i+1;
  307.         nbors.x = j;
  308.         *iptr = value = (unsigned char)update_function(&nbors);
  309.         }
  310.         else {
  311.         a = 0;
  312.         a |= cptr[0];        /* c */
  313.         a <<= l;
  314.         a |= cptr[1];        /* ccw  */
  315.         a <<= l;
  316.         a |= cptr[mb + 1];    /* opp  */
  317.         a <<= l;
  318.         a |= cptr[mb];        /* cw  */
  319.         a <<= l;
  320.         a |= Phase;
  321.         
  322.         /* now process cell */
  323.         
  324.         if ((*iptr = value = taa[a]) == UNDEF)
  325.             return (cptr - ca);
  326.         }
  327.         sc[value]++;
  328.         
  329.         
  330.         cptr++;
  331.         iptr++;        /* now do the next guy over in this block */
  332.         if (function) {
  333.         a = nbors.c;
  334.         nbors.c = nbors.ccw;
  335.         nbors.ccw = nbors.opp;
  336.         nbors.opp = nbors.cw;
  337.         nbors.cw = a;
  338.         nbors.x = j+1;
  339.         *iptr = value = (unsigned char)update_function(&nbors);
  340.         }
  341.         else {
  342.         aa = a;
  343.         a &= tmask2;
  344.         a <<= l;
  345.         a |= (aa>>(3*l))&(AMASK<<l);
  346.         a |= Phase;
  347.         
  348.         if ((*iptr = value = taa[a]) == UNDEF)
  349.             return (cptr - ca);
  350.         }
  351.         sc[value]++;
  352.         
  353.         
  354.     } /* column for loop */
  355.  
  356.  
  357.     /* that's all for this row */
  358.         
  359.     } /* row for(...) loop */
  360.  
  361.     if (after_function) {
  362.     array_info.array = ia;
  363.     array_info.time = stime;
  364.     array_info.size = B;
  365.     array_info.parm1 = parm1;
  366.     array_info.parm2 = parm2;
  367.     after_function(&array_info);
  368.     }
  369.     
  370.     swap_data();            /* image array is now current */
  371.     
  372.     show_time(++stime);        /* advance time */
  373.     Phase = (Phase+1)%S;
  374.  
  375.     if (SOCKET_INUSE)
  376.     send_sock();
  377.  
  378.  
  379.     return (0);
  380.  
  381. } /* auto_marg_even */
  382.  
  383.  
  384. /* margolus updating when origin is at (1,1) */
  385. auto_marg_odd()
  386. {
  387.     register unsigned char *cptr, *iptr;/* ptrs to arrays */
  388.  
  389.     register unsigned char *taa;    /* ptr to t-func array  */
  390.     register int a, aa;            /* array pointer vars   */
  391.     register char l = L;        /* count variables      */
  392.     int     tmask = TMASK, tmask2 = TMASK2;
  393.     register short mb = -B, pb = B;
  394.     register short j;
  395.     register State value;
  396.     register int *sc;
  397.     register int hv;        /* horizontal/vertical low bit */
  398.     register margolus_nbors nbors;
  399.     array_info_struct array_info;
  400.     
  401.     int     i, k;
  402.  
  403.     /* cycle through the array "steps" times */
  404.  
  405.  
  406.     if (function) {
  407.     nbors.parm1 = parm1;
  408.     nbors.parm2 = parm2;
  409.     nbors.phase = Phase;
  410.     nbors.time = stime;
  411.     }
  412.     /* printf("inside auto_marg_odd()\n"); */
  413.  
  414.     if (before_function) {
  415.     array_info.array = ca;
  416.     array_info.time = stime;
  417.     array_info.size = B;
  418.     before_function(&array_info);
  419.     }
  420.     
  421.     cptr = ca;            /* load register copies */
  422.     taa = ta;
  423.     sc = statecount;
  424.     
  425.     for (j = 0; j < S; j++)        /* clear state counts */
  426.     sc[j] = 0;
  427.     
  428.     /* initialize top and bottom buffers */
  429.     
  430.     for (i = 0; i < B; i++) {
  431.     cptr[i] = cptr[BSQR + i];
  432.     cptr[BBUF + i] = cptr[ABASE + i];
  433.     }
  434.     
  435.     /* now traverse the array */
  436.     
  437.     cptr = &ca[BM1];
  438.     iptr = &ia[BM1];
  439.     
  440.     for (i = 0; i < RCOUNT; i += 2) {
  441.     cptr++;
  442.     iptr++;
  443.     
  444.  
  445.     if (function) {
  446.         nbors.c = cptr[0];
  447.         nbors.ccw = cptr[mb];
  448.         nbors.opp = cptr[-1];
  449.         nbors.cw = cptr[pb - 1];
  450.         nbors.y = i;
  451.         nbors.x = 0;
  452.         *iptr = value = (unsigned char)update_function(&nbors);
  453.     }
  454.     else {
  455.         
  456.         a = 0;
  457.     
  458.         /* initial left edge cell load */
  459.     
  460.         a |= cptr[0];        /* c */
  461.         a <<= l;
  462.         a |= cptr[mb];        /* ccw */
  463.         a <<= l;
  464.         a |= cptr[-1];        /* wrap opp  */
  465.         a <<= l;
  466.         a |= cptr[pb - 1];        /* wrap cw  */
  467.         a <<= l;
  468.         a |= Phase;
  469.     
  470.         /* now process cell */
  471.     
  472.         if ((*iptr = value = taa[a]) == UNDEF)
  473.         return (cptr - ca);
  474.     }
  475.     sc[value]++;
  476.     
  477.     
  478.     /* now do central cells of this row, two at a time */
  479.     
  480.     for (j = 1; j < pb-1; j += 2) {
  481.         cptr++;
  482.         iptr++;
  483.         if (function) {
  484.         nbors.c = cptr[0];
  485.         nbors.ccw = cptr[1];
  486.         nbors.opp = cptr[mb + 1];
  487.         nbors.cw = cptr[mb];
  488.         nbors.x = j;
  489.         *iptr = value = (unsigned char)update_function(&nbors);
  490.         }
  491.         else {
  492.         a = 0;
  493.         a |= cptr[0];        /* c */
  494.         a <<= l;
  495.         a |= cptr[1];        /* ccw  */
  496.         a <<= l;
  497.         a |= cptr[mb + 1];        /* opp  */
  498.         a <<= l;
  499.         a |= cptr[mb];        /* cw  */
  500.         a <<= l;
  501.         a |= Phase;
  502.         if ((*iptr = value = taa[a]) == UNDEF)
  503.             return (cptr - ca);
  504.         }
  505.         sc[value]++;
  506.         
  507.         cptr++;
  508.         iptr++;
  509.         if (function) {
  510.         a = nbors.c;
  511.         nbors.c = nbors.ccw;
  512.         nbors.ccw = nbors.opp;
  513.         nbors.opp = nbors.cw;
  514.         nbors.cw = a;
  515.         nbors.x = j+1;
  516.         *iptr = value = (unsigned char)update_function(&nbors);
  517.         }
  518.         else {
  519.         aa = a;
  520.         a &= tmask2;
  521.         a <<= l;
  522.         /* a |= (aa&AMASK)<<(3*l); */
  523.         a |= (aa>>(3*l))&(AMASK<<l);
  524.         a |= Phase;
  525.         
  526.         if ((*iptr = value = taa[a]) == UNDEF)
  527.             return (cptr - ca);
  528.         }
  529.         sc[value]++;
  530.         
  531.     } /* column for loop */
  532.  
  533.  
  534.     cptr++;
  535.     iptr++;            /* now do the right edge cell */
  536.     if (function) {
  537.         nbors.c = cptr[0];
  538.         nbors.ccw = cptr[mb + 1];
  539.         nbors.opp = cptr[-TBM1];
  540.         nbors.cw = cptr[mb];
  541.         nbors.x = pb-1;
  542.         *iptr = value = (unsigned char)update_function(&nbors);
  543.     }
  544.     else {
  545.         a = 0;
  546.         a |= cptr[0];        /* c */
  547.         a <<= l;
  548.         a |= cptr[mb + 1];        /* ccw */
  549.         a <<= l;
  550.         a |= cptr[-TBM1];        /* wrap opp */
  551.         a <<= l;
  552.         a |= cptr[mb];        /* wrap cw */
  553.         a <<= l;
  554.         a |= Phase;
  555.     
  556.         if ((*iptr = value = taa[a]) == UNDEF)
  557.         return (cptr - ca);
  558.     }
  559.     sc[value]++;
  560.     
  561.     
  562.     /* that's all for this row */
  563.     /* now do odd row */
  564.     
  565.     cptr++;
  566.     iptr++;
  567.     
  568.     a = 0;
  569.     
  570.     /* initial left edge cell load */
  571.  
  572.     if (function) {
  573.         nbors.c = cptr[0];
  574.         nbors.ccw = cptr[pb - 1];
  575.         nbors.opp = cptr[TBM1];
  576.         nbors.cw = cptr[pb];
  577.         nbors.y = i+1;
  578.         nbors.x = 0;
  579.         *iptr = value = (unsigned char)update_function(&nbors);
  580.     }
  581.     else {
  582.         a |= cptr[0];        /* c */
  583.         a <<= l;
  584.         a |= cptr[pb - 1];        /* wrap ccw */
  585.         a <<= l;
  586.         a |= cptr[TBM1];        /* wrap opp  */
  587.         a <<= l;
  588.         a |= cptr[pb];        /* cw  */
  589.         a <<= l;
  590.         a |= Phase;
  591.     
  592.         /* now process cell */
  593.     
  594.         if ((*iptr = value = taa[a]) == UNDEF)
  595.         return (cptr - ca);
  596.     }
  597.     sc[value]++;
  598.     
  599.     
  600.     /* now do central cells of this row, two at a time */
  601.     
  602.     for (j = 1; j < pb-1; j += 2) {
  603.         cptr++;
  604.         iptr++;
  605.         if (function) {
  606.         nbors.c = cptr[0];
  607.         nbors.ccw = cptr[pb];
  608.         nbors.opp = cptr[pb + 1];
  609.         nbors.cw = cptr[1];
  610.         nbors.x = j;
  611.         *iptr = value = (unsigned char)update_function(&nbors);
  612.         }
  613.         else {
  614.         a = 0;
  615.         a |= cptr[0];        /* c */
  616.         a <<= l;
  617.         a |= cptr[pb];        /* ccw  */
  618.         a <<= l;
  619.         a |= cptr[pb + 1];    /* opp  */
  620.         a <<= l;
  621.         a |= cptr[1];        /* cw  */
  622.         a <<= l;
  623.         a |= Phase;
  624.         if ((*iptr = value = taa[a]) == UNDEF)
  625.             return (cptr - ca);
  626.         }
  627.         sc[value]++;
  628.         
  629.         cptr++;
  630.         iptr++;
  631.         if (function) {
  632.         a = nbors.c;
  633.         nbors.c = nbors.cw;
  634.         nbors.cw = nbors.opp;
  635.         nbors.opp = nbors.ccw;
  636.         nbors.ccw = a;
  637.         nbors.x = j+1;
  638.         *iptr = value = (unsigned char)update_function(&nbors);
  639.         }
  640.         else {
  641.         aa = a;
  642.         a &= tmask;
  643.         a >>= l;
  644.         a |= (aa&(AMASK<<l))<<(3*l);
  645.         a |= Phase;
  646.         
  647.         if ((*iptr = value = taa[a]) == UNDEF)
  648.             return (cptr - ca);
  649.         }
  650.         sc[value]++;
  651.         
  652.     } /* column for loop */
  653.     
  654.  
  655.     cptr++;
  656.     iptr++;            /* now do the right edge cell */
  657.     if (function) {
  658.         nbors.c = cptr[0];
  659.         nbors.ccw = cptr[pb];
  660.         nbors.opp = cptr[1];
  661.         nbors.cw = cptr[mb + 1];
  662.         nbors.x = pb-1;
  663.         *iptr = value = (unsigned char)update_function(&nbors);
  664.     }
  665.     else {
  666.         a = 0;
  667.         a |= cptr[0];        /* c */
  668.         a <<= l;
  669.         a |= cptr[pb];        /* ccw */
  670.         a <<= l;
  671.         a |= cptr[1];        /* wrap opp */
  672.         a <<= l;
  673.         a |= cptr[mb + 1];        /* wrap cw */
  674.         a <<= l;
  675.         a |= Phase;
  676.     
  677.         if ((*iptr = value = taa[a]) == UNDEF)
  678.         return (cptr - ca);
  679.     }
  680.     sc[value]++;
  681.     
  682.     
  683.     /* that's all for this row */
  684.     /* now do odd row */
  685.     
  686.     } /* row for(...) loop */
  687.  
  688.     if (after_function) {
  689.     array_info.array = ia;
  690.     array_info.time = stime;
  691.     array_info.size = B;
  692.     after_function(&array_info);
  693.     }
  694.     
  695.     swap_data();            /* image array is now current */
  696.     
  697.     show_time(++stime);        /* advance time */
  698.     Phase = (Phase+1)%S;
  699.     
  700.     if (SOCKET_INUSE)
  701.     send_sock();
  702.     
  703.  
  704.     return (0);
  705.  
  706. } /* auto_marg_odd */
  707.  
  708.  
  709. get_address_marg(x, y)            /* get index at given ca location */
  710.     unsigned short x, y;
  711. {
  712.     int     a, cp;
  713.     int lwrap = (x == 0 ? B : 0), rwrap = (x == BM1 ? -B : 0);
  714.  
  715.     Phase = stime%S;
  716.     a = 0;
  717.     cp = y * B + x + B;
  718.  
  719.     if (((stime%2) && ((x%2) == 0) && ((y%2) == 0)) ||
  720.     (((stime%2) == 0) && (x%2) && (y%2))) {    /* lower right */
  721.     a += ca[cp];        /* c */
  722.     a <<= L;
  723.     a += ca[cp - B];    /* ccw */
  724.     a <<= L;
  725.     a += ca[cp + lwrap - BPL1];    /* opp (wrap if needed) */
  726.     a <<= L;
  727.     a += ca[cp + lwrap - 1];    /* cw (wrap if needed) */
  728.     a <<= L;
  729.     a |= Phase;
  730.     }
  731.     if (((stime%2) && ((x%2) == 0) && (y%2)) ||
  732.     (((stime%2) == 0) && (x%2) && ((y%2) == 0))) {    /* upper right */
  733.     a += ca[cp];            /* c */
  734.     a <<= L;
  735.     a += ca[cp + lwrap - 1];    /* ccw (wrap if needed) */
  736.     a <<= L;
  737.     a += ca[cp + lwrap + BM1];    /* opp (wrap if needed) */
  738.     a <<= L;
  739.     a += ca[cp + B];        /* cw */
  740.     a <<= L;
  741.     a |= Phase;
  742.     }
  743.     if (((stime%2) && (x%2) && ((y%2 == 0))) ||
  744.     (((stime%2) == 0) && ((x%2) == 0) && (y%2))) {    /* lower left */
  745.     a += ca[cp];            /* c */
  746.     a <<= L;
  747.     a += ca[cp + rwrap + 1];    /* ccw (wrap if needed) */
  748.     a <<= L;
  749.     a += ca[cp + rwrap - BM1];    /* opp (wrap if needed) */
  750.     a <<= L;
  751.     a += ca[cp - B];        /* cw */
  752.     a <<= L;
  753.     a |= Phase;
  754.     }
  755.     if (((stime%2) && (x%2) && (y%2)) ||
  756.     (((stime%2) == 0) && ((x%2) == 0) && ((y%2) == 0))) { /* upper left */
  757.     a += ca[cp];            /* c */
  758.     a <<= L;
  759.     a += ca[cp + B];        /* ccw */
  760.     a <<= L;
  761.     a += ca[cp + rwrap + BPL1];    /* opp (wrap if needed) */
  762.     a <<= L;
  763.     a += ca[cp + rwrap + 1];    /* cw (wrap if needed) */
  764.     a <<= L;
  765.     a |= Phase;
  766.     }
  767.     return (a);
  768.  
  769. } /* get_address_marg */
  770.  
  771.  
  772.  
  773. get_nbors_marg(nb, x, y)        /* get nbors at given ca location */
  774. margolus_nbors *nb;
  775. unsigned short x, y;
  776. {
  777.     int     cp;
  778.     int lwrap = (x == 0 ? B : 0), rwrap = (x == BM1 ? -B : 0);
  779.  
  780.     cp = y * B + x + B;
  781.  
  782.     if (((stime%2) && ((x%2) == 0) && ((y%2) == 0)) ||
  783.     (((stime%2) == 0) && (x%2) && (y%2))) {    /* lower right */
  784.     nb->c = ca[cp];        /* c */
  785.     nb->ccw = ca[cp - B];    /* ccw */
  786.     nb->opp = ca[cp + lwrap - BPL1];    /* opp (wrap if needed) */
  787.     nb->cw = ca[cp + lwrap - 1];    /* cw (wrap if needed) */
  788.     }
  789.     if (((stime%2) && ((x%2) == 0) && (y%2)) ||
  790.     (((stime%2) == 0) && (x%2) && ((y%2) == 0))) {    /* upper right */
  791.     nb->c = ca[cp];            /* c */
  792.     nb->ccw = ca[cp + lwrap - 1];    /* ccw (wrap if needed) */
  793.     nb->opp = ca[cp + lwrap + BM1];    /* opp (wrap if needed) */
  794.     nb->cw = ca[cp + B];        /* cw */
  795.     }
  796.     if (((stime%2) && (x%2) && ((y%2 == 0))) ||
  797.     (((stime%2) == 0) && ((x%2) == 0) && (y%2))) {    /* lower left */
  798.     nb->c = ca[cp];            /* c */
  799.     nb->ccw = ca[cp + rwrap + 1];    /* ccw (wrap if needed) */
  800.     nb->opp = ca[cp + rwrap - BM1];    /* opp (wrap if needed) */
  801.     nb->cw = ca[cp - B];        /* cw */
  802.     }
  803.     if (((stime%2) && (x%2) && (y%2)) ||
  804.     (((stime%2) == 0) && ((x%2) == 0) && ((y%2) == 0))) { /* upper left */
  805.     nb->c = ca[cp];            /* c */
  806.     nb->ccw = ca[cp + B];        /* ccw */
  807.     nb->opp = ca[cp + rwrap + BPL1];    /* opp (wrap if needed) */
  808.     nb->cw = ca[cp + rwrap + 1];    /* cw (wrap if needed) */
  809.     }
  810.     nb->phase = Phase;
  811.     nb->time = stime;
  812.     nb->x = x;
  813.     nb->y = y;
  814.     nb->parm1 = parm1;
  815.     nb->parm2 = parm2;
  816.     return;
  817.  
  818. } /* get_nbors_marg */
  819.  
  820.  
  821. learn_marg()
  822. {
  823.     clear_msg();
  824.     show_msg("Not implemented");
  825.     return;
  826.  
  827. } /* learn_marg */
  828.