Got something to write about? Check out our Article Builder.

View \LIFE.C

C souce code for the game of Go

Submitted By: WEBMASTER
Rating: starstarstarhalf star (Rate It)


#include <dos.h>
#include <conio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <alloc.h>
#include <graphics.h>
#define EXTCDECL extern
#include "goh.c"

#define TRACENETS 0 /* 1 for printout */


/*
unsigned xxxx(jndex)
unsigned jndex;
{
 struct root *rootp;
 unsigned value;
 value = 0;
 if (jndex) {
  value = 0;
  rootp = dir[jndex];
  if (rootp) {
   if ((colour == BLK) && (rootp->clr == WHT)) value = 1;
   if ((colour == WHT) && (rootp->clr == BLK)) value = 1;
  }
 }
 return (value);
}

unsigned *diarota(index)
unsigned index;
{
 unsigned *diagp, *kp, *point;
 unsigned north, east, west, south, neast;
 kp = &env10[0];
 diagp = kp;
 point = NEWS(index);
 north = *point;
 ++point;
 west = *point;
 ++point;
 east = *point;
 ++point;
 south = *point;
 *kp = east;
 ++kp;
 if (north && east)
  *kp = (north + 1);
 else *kp = 0;
 neast = *kp;
 ++kp;
 *kp = north;
 ++kp;
 if (north && west)
  *kp = (north - 1);
 else *kp = 0;
 ++kp;
 *kp = west;
 ++kp;
 if (south && west)
  *kp = (south - 1);
 else *kp = 0;
 ++kp;
 *kp = south;
 ++kp;
 if (south && east)
  *kp = (south + 1);
 else *kp = 0;
 ++kp;
 *kp = east;
 ++kp;
 *kp = neast;
 return (diagp);
}

unsigned fourex(index)
unsigned index;
{
 unsigned value;
 unsigned bit, i, j, jndex, *point;
 value = 0;
 point = diarota(index);
 jndex = *point;
 for (i = 1;  i <= 4;  ++i) {
  bit = xxxx(jndex);
  ++point;
  jndex = *point;
  bit += xxxx(jndex);
  ++point;
  jndex = *point;
  bit += xxxx(jndex);
  if (bit == 3)
   ++value;
 }
 return (value);
}

unsigned *diagonal(index)
unsigned index;
{
 unsigned *diagp, *kp, *point;
 unsigned north, east, west, south;
 kp = &env10[0];
 diagp = kp;
 point = NEWS(index);
 north = *point;
 ++point;
 west = *point;
 ++point;
 east = *point;
 ++point;
 south = *point;
 if (north && west)
  *kp = (north - 1);
 else *kp = 0;
 ++kp;
 *kp = north;
 ++kp;
 if (north && east)
  *kp = (north + 1);
 else *kp = 0;
 ++kp;
 *kp = west;
 ++kp;
 *kp = east;
 ++kp;
 if (south && west)
  *kp = (south - 1);
 else *kp = 0;
 ++kp;
 *kp = south;
 ++kp;
 if (south && east)
  *kp = (south + 1);
 else *kp = 0;
 return (diagp);
}

unsigned teerex(index)
unsigned index;
{
 unsigned value;
 unsigned bit, i, j, jndex, *point;
 value = 0;
 point = diagonal(index);
 ++point;
 jndex = *point;
 for (i = 1;  i <= 4;  ++i) {
  bit = xxxx(jndex);
  ++point;
  jndex = *point;
  bit += xxxx(jndex);
  ++point;
  jndex = *point;
  bit += xxxx(jndex);
  if (bit == 3)
   ++value;
 }
 return (value);
}
*/



#if DDD
 #if DDD == 3 /* 3D */
 void diags(unsigned index, unsigned *diagp)
 {
  unsigned *kp, *point;
  unsigned north, west, east, south, up, down;
  kp = diagp;
  point = NEWS(index);
  down = *point;
  ++point;
  north = *point;
  ++point;
  west = *point;
  ++point;
  east = *point;
  ++point;
  south = *point;
  ++point;
  up = *point;
  if (down && north) *kp = down - nsize;
  else *kp = 0;
  ++kp;
  if (down && west) *kp = down - 1;
  else *kp = 0;
  ++kp;
  if (down && east) *kp = down + 1;
  else *kp = 0;
  ++kp;
  if (down && south) *kp = down + nsize;
  else *kp = 0;
  ++kp;
  if (north && west) *kp = north - 1;
  else *kp = 0;
  ++kp;
  if (north && east) *kp = north + 1;
  else *kp = 0;
  ++kp;
  if (south && west) *kp = south - 1;
  else *kp = 0;
  ++kp;
  if (south && east) *kp = south + 1;
  else *kp = 0;
  ++kp;
  if (up && north) *kp = up - nsize;
  else *kp = 0;
  ++kp;
  if (up && west) *kp = up - 1;
  else *kp = 0;
  ++kp;
  if (up && east) *kp = up + 1;
  else *kp = 0;
  ++kp;
  if (up && south) *kp = up + nsize;
  else *kp = 0;
 }
 #else     /* 2.5D  universal but slow ... suitable for 2D and 3D too */
 void diags(unsigned index, unsigned *diagp)
 {
  unsigned *kp, *point1, *point2;
  unsigned i, j, value, jndex, kndex;
  unsigned list, listp;
  list = xtinsert(0, 0);
  listp = list;
  kp = diagp;
  for (i=1; i<=NDIAGS; ++i) {
   *kp = 0;
   ++kp;
  }
  point1 = NEWS(index);
  for (i=1; i<=NLIBS; ++i) {
   jndex = *point1;
   if (jndex) {
    point2 = NEWS(jndex);
    for (j=1; j<=NLIBS; ++j) {
     kndex = *point2;
     if (kndex) {
      listp = xtlocate(kndex, listp);
      if (!xtmember(kndex, listp)) {
       listp = xtinsert(kndex, listp);
       poke(listp, LEVEL, 1);
      }
      else {
       value = peek(listp, LEVEL);
       ++value;
       poke(listp, LEVEL, value);
      }
     }
     ++point2;
    }
   }
   ++point1;
  }
  listp = peek(list, NEXTL);
  kp = diagp;
  if (listp) {
   do {
    jndex = peek(listp, LOC);
    value = peek(listp, LEVEL);
    if (value > 1) {
     if (jndex != index) {
      *kp = jndex;
      ++kp;
     }
    }
    listp = peek(listp, NEXTL);
   } while (listp);
  }
  xtfreelist(list);
 }
 #endif
#endif
#if ((!DONUT)&&(!DDD))
void diags(unsigned index, unsigned *diagp)
{
 unsigned *kp, *point;
 unsigned north, east, west, south;
 kp = diagp;
 point = NEWS(index);
 north = *point;
 ++point;
 west = *point;
 ++point;
 east = *point;
 ++point;
 south = *point;
 if (north && west) *kp = (north - 1);
 else *kp = 0;
 ++kp;
 if (north && east) *kp = (north + 1);
 else *kp = 0;
 ++kp;
 if (south && west) *kp = (south - 1);
 else *kp = 0;
 ++kp;
 if (south && east) *kp = (south + 1);
 else *kp = 0;
}
#endif
#if DONUT
void diags(unsigned index, unsigned *diagp)
{
 unsigned *kp, *point, *joint;
 unsigned north, south;
 kp = diagp;
 point = NEWS(index);
 north = *point;
 ++point; /* west */
 ++point; /* east */
 ++point;
 south = *point;
 joint = NEWS(north);
 *kp = joint[1]; /* NWES == 0123  (North, West, East, South) */
 ++kp;
 joint = NEWS(north);
 *kp = joint[2];
 ++kp;
 joint = NEWS(south);
 *kp = joint[1];
 ++kp;
 joint = NEWS(south);
 *kp = joint[2];
}
#endif


void addstone(index, colour)
unsigned index;
unsigned colour;
{
 unsigned *point;
 unsigned i, jndex;
 struct root *rooti, *rootp;
 struct link *whrneib;
 struct link *whrlib;
 struct link *whrspc;
 struct link *whrfrd;
 struct link *whrnmy;
 struct link *whrctc;
 struct link *opponent;
 point = NEWS(index);
 for (i=1; i<=NLIBS; ++i) {
  jndex = *point;
  if (jndex) {
   rootp = dir[jndex];
   if (rootp) {
    if (colour != rootp->clr) {
     whrlib = (struct link *) locate(index, rootp->liberties);
     if (member(index, whrlib)) {
      whrlib = (struct link *) delete(whrlib);
      --rootp->nlib;
     }
     whrctc = (struct link *)locate(index, rootp->contacts);
     if (!member(index, whrctc)) {
      whrctc = (struct link *) insert(index, whrctc);
     }
    }
   }
  }
  ++point;
 }
}

void remstone(index, colour)
unsigned index;
unsigned colour;
{
 unsigned *point;
 unsigned i, jndex;
 struct root *rooti, *rootp;
 struct link *whrneib;
 struct link *whrlib;
 struct link *whrspc;
 struct link *whrfrd;
 struct link *whrnmy;
 struct link *whrctc;
 struct link *opponent;
 point = NEWS(index);
 for (i=1; i<=NLIBS; ++i) {
  jndex = *point;
  if (jndex) {
   rootp = dir[jndex];
   if (rootp) {
    if (colour != rootp->clr) {
     whrlib = (struct link *) locate(index, rootp->liberties);
     if (!member(index, whrlib)) {
      whrlib = (struct link *) insert(index, whrlib);
      ++rootp->nlib;
     }
     whrctc = (struct link *) locate(index, rootp->contacts);
     if (member(index, whrctc)) {
      whrctc = (struct link *) delete(whrctc);
     }
    }
   }
  }
  ++point;
 }
}

void addextra(index, colour)
unsigned index;
unsigned colour;
{
 unsigned *point;
 unsigned diagvec[NDIAGS];
 unsigned i, jndex;
 struct root *rooti, *rootp;
 struct link *whrneib;
 struct link *whrlib;
 struct link *whrspc;
 struct link *whrfrd;
 struct link *whrnmy;
 struct link *whrctc;
 struct link *opponent;
 diags(index, diagvec);
 point = diagvec;
 for (i=1; i<=NDIAGS; ++i) {
  jndex = *point;
  if (jndex) {
   rootp = dir[jndex];
   if (rootp) {
    whrspc = locate(index, rootp->spaces);
    if (member(index, whrspc)) whrspc = delete(whrspc);
    if (rootp->clr == colour) {
     whrneib = locate(index, rootp->neighbs);
     if (!member(index, whrneib)) {
      if (dir[index] != rootp) {
       whrfrd = locate(index, rootp->friends);
       whrfrd = insert(index, whrfrd);
      }
     }
    }
    else {
     whrctc = locate(index, rootp->contacts);
     if (!member(index, whrctc)) {
      whrnmy = locate(index, rootp->enemies);
      whrnmy = insert(index, whrnmy);
     }
    }
   }
  }
  ++point;
 }
}

void remextra(index, colour)
unsigned index;
unsigned colour;
{
 unsigned *point;
 unsigned diagvec[NDIAGS];
 unsigned i, jndex;
 struct root *rooti, *rootp;
 struct link *whrneib;
 struct link *whrlib;
 struct link *whrspc;
 struct link *whrfrd;
 struct link *whrnmy;
 struct link *whrctc;
 struct link *opponent;
 jndex = colour; /* useless */
 diags(index, diagvec);
 point = diagvec;
 for (i=1; i<=NDIAGS; ++i) {
  jndex = *point;
  if (jndex) {
   rootp = dir[jndex];
   if (rootp) {
    whrlib = locate(index, rootp->liberties);
    if (!member(index, whrlib)) {
     whrspc = locate(index, rootp->spaces);
     whrspc = insert(index, whrspc);
    }
    whrfrd = locate(index, rootp->friends);
    if (member(index, whrfrd)) whrfrd = delete(whrfrd);
    whrctc = locate(index, rootp->contacts);
    if (!member(index, whrctc)) {
     whrnmy = locate(index, rootp->enemies);
     if (member(index, whrnmy)) whrnmy = delete(whrnmy);
    }
   }
  }
  ++point;
 }
}

void envel(index,indexes)
unsigned index;
struct link *indexes;
{
 struct root *rootp;
 unsigned kount;
 rootp = dir[index];
 if (rootp) {
  kount = 0;
  kount += merge(indexes, rootp->liberties);
  kount += merge(indexes, rootp->spaces);
 }
}



/*
unsigned cthree(nel, netp, npart, partitions, index, jndex,
                          kndex, corny, abort)
unsigned nel, netp, npart, partitions, index, jndex, kndex, corny;
unsigned *abort;
{
 unsigned inserted, where;
 unsigned netstone;
 unsigned rootxp;
 struct root *rootp;
 *abort = 0;
 inserted = 0;
 if (xtmember(index, xtlocate(index, partitions))) {
  if (xtmember(jndex, xtlocate(jndex, partitions))) {
   if (xtmember(kndex, xtlocate(kndex, partitions))) {
    if (peek(xtlocate(kndex, partitions), LEVEL) == npart) {
     where = xtlocate(corny, partitions);
     if (!member(corny, where)) {
      rootxp = peek(netp, ROOTS);
      rootxp = peek(rootxp, NEXTL);
      rootp = peek(rootxp, LOC);
      netstone = rootp->ridx;
      if (corny == netstone) *abort = 1;
      if (!*abort) {
       if (nel > 3) {
        where = xtinsert(corny, where);
        poke(where, LEVEL, npart);
        inserted = corny;
       }
      }
     }
    }
   }
  }
 }
 return(inserted);
}

unsigned corner(nel, netp, npart, partitions, abort)
unsigned nel, netp, npart, partitions;
unsigned *abort;
{
 unsigned inserted;
 unsigned partp, partno, index, jndex, kndex, corny;
 inserted = 0;
 corny = 1;
 index = 2;
 jndex = nsize + 1;
 kndex = nsize + 2;
 inserted = cthree(nel, netp, npart, partitions, index, jndex, kndex, corny, abort);
 if (!inserted && !*abort) {
  corny = nsize;
  index = nsize - 1;
  jndex = nsize + nsize - 1;
  kndex = nsize + nsize;
  inserted = cthree(nel, netp, npart, partitions, index, jndex, kndex, corny, abort);
  if (!inserted && !*abort) {
   corny = nsize2 - nsize + 1;
   index = corny - nsize;
   jndex = index + 1;
   kndex = corny + 1;
   inserted = cthree(nel, netp, npart, partitions, index, jndex, kndex, corny, abort);
   if (!inserted && !*abort) {
    corny = nsize2;
    index = corny - nsize - 1;
    jndex = index + 1;
    kndex = corny - 1;
    inserted = cthree(nel, netp, npart, partitions, index, jndex, kndex, corny, abort);
   }
  }
 }
 return(inserted);
}

void deathshape(netp, npart, partitions, vitals)
unsigned netp, npart, partitions, vitals;
{
 unsigned partp, partno, jndex, nelements, inserted;
 unsigned index, kndex, death, dont;
 int px, py, sumx, sumy, var, tempx, tempy, temp, min, n3, n5;
 unsigned rootxes;
 struct root *rootp;
 partp = peek(partitions, NEXTL);
 if (partp) {
  nelements = 0;
  do {
   partno = peek(partp, LEVEL);
   if (partno == npart) {
    ++nelements;
    poke(partp, (LEVEL+2), 0);  /* no death spots to start */

   }
   partp = peek(partp, NEXTL);
  } while (partp);
  dont = 0;
  inserted = 0;
  if ((nelements >= 3) && (nelements <= 5)) {
   inserted = corner(nelements, netp, npart, partitions, &dont);
  }
  if (!dont) {
   if (inserted) ++nelements;
   death = 0;
   if ((nelements >= 1) && (nelements <= 6)) {
    sumx = 0;
    sumy = 0;
    partp = peek(partitions, NEXTL);
    do {
     partno = peek(partp, LEVEL);
     if (partno == npart) {
      jndex = peek(partp, LOC);
      xy(jndex, &px, &py);
      sumx += px;
      sumy += py;
     }
     partp = peek(partp, NEXTL);
    } while (partp);
    var = 0;
    partp = peek(partitions, NEXTL);
    do {
     partno = peek(partp, LEVEL);
     if (partno == npart) {
      jndex = peek(partp, LOC);
      xy(jndex, &px, &py);
      tempx = nelements * px - sumx;
      tempx *= tempx;
      tempy = nelements * py - sumy;
      tempy *= tempy;
      var += tempx * tempx + tempy * tempy;
     }
     partp = peek(partp, NEXTL);
    } while (partp);
    /*
    newline();
    printf("var n %d %d", var, nelements);
    */

    /* first handle the 8 cases of rectangular six in corner */
    if ((var == 872) && (nelements == 4)) {
     n3 = 4 * nsize - 3;
     n5 = n3 - 2;
     if ((sumx == 7) && (sumy == 9)) {
      index = 2;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
     else if ((sumx == 9) && (sumy == 7)) {
      index = nsize + 1;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
     else if ((sumx == n3) && (sumy == 9)) {
      index = (nsize - 1) * nsize + 2;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
     else if ((sumx == n5) && (sumy == 7)) {
      index = (nsize - 2) * nsize + 1;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
     else if ((sumx == 7) && (sumy == n5)) {
      index = nsize - 1;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
     else if ((sumx == 9) && (sumy == n3)) {
      index = nsize + nsize;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
     else if ((sumx == n3) && (sumy == n5)) {
      index = nsize2 - 1;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
     else if ((sumx == n5) && (sumy == n3)) {
      index = nsize2 - nsize;
      if (!dir[index]) {
       xtinsert(index, xtlocate(index, vitals));
       death = 2;
      }
     }
    }
    /* next take care of 4-in-a-row with opponent inside */
    if (!death && (nelements==4)) {
     if ((var==576) || (var==872) || (var==2624)) {
      jndex = 0;
      kndex = 0;
      partp = peek(partitions, NEXTL);
      do {
       partno = peek(partp, LEVEL);
       if (partno == npart) {
        index = peek(partp, LOC);
        xy(index, &px, &py);
        tempx = nelements * px - sumx;
        tempx *= tempx;
        tempy = nelements * py - sumy;
        tempy *= tempy;
        temp = tempx * tempx + tempy * tempy;
        if (temp <= 82) {
         if (!jndex) jndex = index;
         else kndex = index;
        }
       }
       partp = peek(partp, NEXTL);
      } while (partp);
      /* first take care of bent four in corner */
      temp = 0;
      if (jndex == 1) temp = kndex;
      if (jndex == nsize) temp = kndex;
      if (jndex == (nsize2-nsize+1)) temp = kndex;
      if (jndex == nsize2) temp = kndex;
      if (!temp) {
       if (kndex == 1) temp = jndex;
       if (kndex == nsize) temp = jndex;
       if (kndex == (nsize2-nsize+1)) temp = jndex;
       if (kndex == nsize2) temp = jndex;
      }
      if (!temp) {
       if (dir[jndex]) temp = kndex;
       if (dir[kndex]) temp = jndex;
      }
      if (temp) {
       death = 3;
       xtinsert(temp, xtlocate(temp, vitals));
      }
     }
    }

    /* next take care of 5 with opponent inside */
    if (!death && (nelements==5)) {
     if ((var==3060) || (var==3910) || (var==6870)) {
      jndex = 0;
      kndex = 0;
      partp = peek(partitions, NEXTL);
      do {
       partno = peek(partp, LEVEL);
       if (partno == npart) {
        index = peek(partp, LOC);
        xy(index, &px, &py);
        tempx = nelements * px - sumx;
        tempx *= tempx;
        tempy = nelements * py - sumy;
        tempy *= tempy;
        temp = tempx * tempx + tempy * tempy;
        if (temp <= 256) {
         if (!jndex) jndex = index;
         else kndex = index;
        }
       }
       partp = peek(partp, NEXTL);
      } while (partp);
      temp = 0;
      if (dir[jndex]) temp = kndex;
      if (dir[kndex]) temp = jndex;
      if (temp) {
       death = 3;
       xtinsert(temp, xtlocate(temp, vitals));
      }
     }
    }

    if (nelements <= 2) death = 4;
    if (nelements == 3) death = 1;
    else if (nelements == 4) {
     if (var==128) death = 2;
     if (var==596) death = 1;
    }
    else if (nelements == 5) {
     if ((var==2500) || (var==2020)) death = 1;
    }
    else if (nelements == 6) {
     if (var == 7308) death = 1;
    }
    if (death == 1) {
     index = 0;
     min = 100;
     partp = peek(partitions, NEXTL);
     do {
      partno = peek(partp, LEVEL);
      if (partno == npart) {
       jndex = peek(partp, LOC);
       xy(jndex, &px, &py);
       tempx = nelements * px - sumx;
       tempx *= tempx;
       tempy = nelements * py - sumy;
       tempy *= tempy;
       temp = tempx * tempx + tempy * tempy;
       if (temp < min) {
        index = jndex;
        min = temp;
       }
      }
      partp = peek(partp, NEXTL);
     } while (partp);
     if (!dir[index]) xtinsert(index, xtlocate(index, vitals));
    }
   }
   if (death) {
    partp = peek(partitions, NEXTL);
    do {
     partno = peek(partp, LEVEL);
     if (partno == npart) {
      ++nelements;
      poke(partp, (LEVEL+2), 1)/* partition contains death spot */
     }
     partp = peek(partp, NEXTL);
    } while (partp);
   }

  }
  if (inserted) {
   xtdelete(xtlocate(inserted, partitions));
  }
 }
}
*/



unsigned edge(index)
unsigned index;
{
 unsigned edgy;
 unsigned xp, xm, yp, ym;
 int x, y;
 edgy = 0;
 /*
 if (index <= nsize) edgy = 1;
 if ((((index-1)/nsize)*nsize) == index-1) edgy = 1;
 if ((index/nsize)*nsize == index) edgy = 1;
 if (index > nsize2-nsize) edgy = 1;
 */

 /*xy(index, &x, &y);*/
 x = X[index];
 y = Y[index];
 if (x == 1) edgy += 1;
 if (x == nsize) edgy += 2;
 if (y == 1) edgy += 4;
 if (y == nsize) edgy += 8;
 return(edgy);
}

void suifix(index)
unsigned index;
{
 unsigned jndex;
 struct link *suicapp, *stonep;
 struct root *rootp;
 index = index;
 suicapp = movep->suicaps->nextl;
 if (suicapp) {
  do {
   rootp = suicapp->loc;
   stonep = rootp->neighbs->nextl;
   do {
    jndex = stonep->loc;
    remstone(jndex, colour);
    if (envon) remextra(jndex, colour);
    stonep = stonep->nextl;
   } while (stonep);
   suicapp = suicapp->nextl;
  } while (suicapp);
 }
}

void unsuifix(index)
unsigned index;
{
 unsigned jndex;
 struct link *suicapp, *stonep;
 struct root *rootp;
 index = index;
 suicapp = movep->suicaps->nextl;
 if (suicapp) {
  do {
   rootp = suicapp->loc;
   stonep = rootp->neighbs->nextl;
   do {
    jndex = stonep->loc;
    addstone(jndex, colour);
    if (envon) addextra(jndex, colour);
    stonep = stonep->nextl;
   } while (stonep);
   suicapp = suicapp->nextl;
  } while (suicapp);
 }
}



void life(index)
unsigned index;
{
 struct root *rootp, *rooti;
 struct link *mergep, *capp;
 struct link *stonep, *where;
 struct link *whrneib;
 struct link *whrlib;
 struct link *whrspc;
 struct link *whrfrd;
 struct link *whrnmy;
 struct link *whrctc;
 struct link *opponent;
 unsigned *point;
 unsigned diagvec[NDIAGS];
 unsigned i, jndex;
 unsigned inenv, dia;
 unsigned temp;
 rooti = dir[index];
 if (rooti) {
  rooti->nsto = 0;
  rooti->nlib = 0;
  whrneib = rooti->neighbs;
  whrlib = rooti->liberties;
  whrspc = rooti->spaces;
  whrfrd = rooti->friends;
  whrnmy = rooti->enemies;
  whrctc = rooti->contacts;
  mergep = movep->merges->nextl;
  if (mergep) {
   if (!mergep->nextl && !movep->ncap && !movep->nsuicap) {
    /* only one root merged - use incremental modification */
    rootp = mergep->loc;
    rooti->incmod = rootp;
    rooti->nsto = rootp->nsto;
    temp = rootp->neighbs;
    rootp->neighbs = rooti->neighbs;
    rooti->neighbs = temp;
    whrneib = temp;
    /* replace old stones by most recently played stone */
    insert(rootp->ridx, locate(rootp->ridx, rootp->neighbs));
    rooti->nlib = rootp->nlib;
    temp = rootp->liberties;
    rootp->liberties = rooti->liberties;
    rooti->liberties = temp;
    whrlib = temp;
    merge(rooti->contacts, rootp->contacts);
   }
   else {
    do {
     rootp = mergep->loc;
     rooti->nsto += merge(rooti->neighbs, rootp->neighbs);
     rooti->nlib += merge(rooti->liberties, rootp->liberties);
     merge(rooti->contacts, rootp->contacts);
     mergep = mergep->nextl;
    }
    while (mergep);
   }
  }
  whrneib = locate(index, whrneib);
  whrneib = insert(index, whrneib);
  ++rooti->nsto;
  addstone(index, rooti->clr);
  capp = movep->caps->nextl;
  if (capp) {
   do {
    rootp = capp->loc;
    where = rootp->neighbs;
    do {
     jndex = where->loc;
     if (jndex) {
      remstone(jndex, rootp->clr);
     }
     where = where->nextl;
    }
    while (where);
    capp = capp->nextl;
   }
   while (capp);
  }
  whrlib = locate(index, rooti->liberties);
  if (member(index, whrlib)) {
   whrlib = delete(whrlib);
   --rooti->nlib;
  }
  point = NEWS(index);
  for (i=1; i<=NLIBS; ++i) {
   jndex = *point;
   if (jndex) {
    rootp = dir[jndex];
    if (!rootp) {
     whrlib = locate(jndex, whrlib);
     if (!member(jndex, whrlib)) {
      whrlib = insert(jndex, whrlib);
      ++rooti->nlib;
      rootp = rooti->incmod;
      if (rootp) {
       insert(jndex, locate(jndex, rootp->liberties));
      }
     }
    }
    else if (rootp->clr != rooti->clr) {
     whrctc = locate(jndex, whrctc);
     whrctc = insert(jndex, whrctc);
    }
   }
   ++point;
  }
  if (!envon) return;
  mergep = movep->merges->nextl;
  if (mergep) {
   do {
    rootp = mergep->loc;
    xmerge(rooti->friends, rootp->friends, rooti->neighbs);
    xmerge(rooti->spaces, rootp->spaces, rooti->liberties);
    xmerge(rooti->enemies, rootp->enemies, rooti->contacts);
    mergep = mergep->nextl;
   }
   while (mergep);
  }
  whrneib = rooti->neighbs->nextl;
  if (whrneib) {
   do {
    jndex = whrneib->loc;
    whrfrd = locate(jndex, rooti->friends);
    if (member(jndex, whrfrd)) whrfrd = delete(whrfrd);
    whrneib = whrneib->nextl;
   }
   while (whrneib);
  }
  whrneib = rooti->neighbs;
  addextra(index, rooti->clr);
  capp = movep->caps->nextl;
  if (capp) {
   do {
    rootp = capp->loc;
    where = rootp->neighbs;
    do {
     jndex = where->loc;
     if (jndex) {
      remextra(jndex, rootp->clr);
     }
     where = where->nextl;
    }
    while (where);
    capp = capp->nextl;
   }
   while (capp);
  }
  diags(index, diagvec);
  point = diagvec;
  for (i=1; i<=NDIAGS; ++i) {
   jndex = *point;
   if (jndex) {
    rootp = dir[jndex];
    if (!rootp) {
     whrlib = locate(jndex, whrlib);
     if (!member(jndex, whrlib)) {
      whrspc = locate(jndex, whrspc);
      whrspc = insert(jndex, whrspc);
     }
    }
    else if (rootp->clr == rooti->clr) {
     if (rooti != rootp) {
      whrneib = locate(jndex, whrneib);
      if (!member(jndex, whrneib)) {
       whrfrd = locate(jndex, whrfrd);
       whrfrd = insert(jndex, whrfrd);
      }
     }
    }
    else {
     whrctc = locate(jndex, whrctc);
     if (!member(jndex, whrctc)) {
      whrnmy = locate(jndex, whrnmy);
      whrnmy = insert(jndex, whrnmy);
     }
    }
   }
   ++point;
  }
 }
 else suifix(index);
}

void unlife(index)
unsigned index;
{
 struct root *rootp, *rooti;
 struct link *mergep, *capp;
 struct link *stonep, *where;
 struct link *whrneib;
 struct link *whrlib;
 struct link *whrspc;
 struct link *whrfrd;
 struct link *whrnmy;
 struct link *whrctc;
 struct link *opponent;
 unsigned *point;
 unsigned i, jndex;
 unsigned inenv, dia;
 struct link *temp;
 rooti = dir[index];
 if (rooti) {
  rootp = rooti->incmod;
  if (rootp) {

   temp = (unsigned) rootp->neighbs;
   rootp->neighbs = rooti->neighbs;
   rooti->neighbs = temp;
   where = locate(index, rootp->neighbs);
   if (member(index, where)) where = delete(where);

   temp = rootp->liberties;
   rootp->liberties = rooti->liberties;
   rooti->liberties = temp;
   whrlib = rootp->liberties;
   whrlib = insert(index, locate(index, whrlib));
   where = rooti->liberties->nextl;
   if (where) {
    do {
     jndex = where->loc;
     whrlib = locate(jndex, whrlib);
     if (member(jndex, whrlib)) whrlib = delete(whrlib);
     where = where->nextl;
    } while (where);
   }
  }
  capp = movep->caps->nextl;
  if (capp) {
   do {
    rootp = (struct root *)capp->loc;
    where = rootp->neighbs;
    do {
     jndex = where->loc;
     if (jndex) {
      addstone(jndex, rootp->clr);
     }
     where = where->nextl;
    }
    while (where);
    capp = capp->nextl;
   }
   while (capp);
  }
  remstone(index, rooti->clr);


  if (envon) {
   capp = movep->caps->nextl;
   if (capp) {
    do {
     r