Want to see what people are talking about? See the latest forum posts.

View \TRI.C

C souce code for the game of Go

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


/* areas (triangles) are formed from spans between nodes */
#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 SHOWSPAN 0

unsigned nearedge(unsigned index, unsigned enodes)
{
 unsigned enodep;
 unsigned x, y, jndex;
 unsigned xl, xh, yl, yh;
 enodep = enodes;
 xy(index, &x, &y);
 if (x <= 4) xl = 1; else xl = 0;
 if (x >= (nsize-3)) xh = 1; else xh = 0;
 if (y <= 4) yl = 1; else yl = 0;
 if (y >= (nsize-3)) yh = 1; else yh = 0;
 if (xl) {
  jndex = fxy(1, y);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 1); /* +x indicate virtual point on edge */
 }
 if (xh) {
  jndex = fxy(nsize, y);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 2); /* -x indicate virtual point on edge */
 }
 if (yl) {
  jndex = fxy(x, 1);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 4); /* +y indicate virtual point on edge */
 }
 if (yh) {
  jndex = fxy(x, nsize);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 8); /* -y indicate virtual point on edge */
 }
 if (xl && yl) {
  jndex = fxy(1, 1);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 5); /* +x+y indicate virtual point at corner */
 }
 if (xh && yl) {
  jndex = fxy(nsize, 1);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 6); /*-x+y indicate virtual point at corner */
 }
 if (xl && yh) {
  jndex = fxy(1, nsize);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 9); /* +x-y indicate virtual point at corner */
 }
 if (xh && yh) {
  jndex = fxy(nsize, nsize);
  enodep = xtlocate(jndex, enodep);
  enodep = xtinsert(jndex, enodep);
  poke(enodep, (LEVEL+4), 10); /* -x-y indicate virtual point at corner */
 }
 return(enodep);
}

void glonodes()
{
 struct link *rootlp;
 struct root *rootp;
 struct link *stonep;
 unsigned nodep;
 unsigned enodes, enodep;
 unsigned bw, jndex;
 for (bw=BLK; bw<=WHT; ++bw) {
  xtfreelist(gnodes[bw]);
  gnodes[bw] = xtinsert(0, 0);
  nodep = gnodes[bw];
  rootlp = rootlist->nextl;
  if (rootlp) {
   do {
    rootp = (struct root *) rootlp->loc;
    if (rootp->clr == bw) {
     stonep = rootp->neighbs->nextl;
     do {
      jndex = stonep->loc;
      nodep = xtlocate(jndex, nodep);
      nodep = xtinsert(jndex, nodep);
      poke(nodep, (LEVEL+4), 0); /* indicate node is stone */
      stonep = stonep->nextl;
     } while (stonep);
    }
    rootlp = rootlp->nextl;
   } while (rootlp);
   nodep = peek(gnodes[bw], NEXTL);
   if (nodep) {
    enodes = xtinsert(0, 0);
    enodep = enodes;
    do {
     jndex = peek(nodep, LOC);
     enodep = nearedge(jndex, enodep);
     nodep = peek(nodep, NEXTL);
    } while (nodep);
    enodep = peek(enodes, NEXTL);
    if (enodep) {
     nodep = gnodes[bw];
     do {
      jndex = peek(enodep, LOC);
      nodep = xtlocate(jndex, nodep);
      if (!xtmember(jndex, nodep)) {
       nodep = xtinsert(jndex, nodep);
       poke(nodep, (LEVEL+4), 16); /* indicate vacant node on edge */
      }
      enodep = peek(enodep, NEXTL);
     } while (enodep);
    }
    xtfreelist(enodes);
   }
  }
 }
}

unsigned oldspan(unsigned p, unsigned q, unsigned bw, unsigned *spas)
{
 unsigned allow;
 unsigned xp, yp, xq, yq;
 unsigned xpqmin, xpqmax, ypqmin, ypqmax;
 unsigned a, b;
 unsigned pq, ab;
 unsigned xa, ya, xb, yb;
 unsigned xabmin, xabmax, yabmin, yabmax;
 unsigned xap, xbp, xpa, xqa;
 unsigned yap, ybp, ypa, yqa;
 unsigned apb, aqb, paq, pbq;
 unsigned xpq, xab;
 unsigned extension, colinear;
 int alpha, beta, gamma, delta, c, overlap, dxpa, dypa, x, y, o;
 unsigned spap, jndexp;
 allow = 1;
 xy(p, &xp, &yp);
 xy(q, &xq, &yq);
 xpqmin = min(xp, xq);
 xpqmax = max(xp, xq);
 ypqmin = min(yp, yq);
 ypqmax = max(yp, yq);
 pq = howfar(p, q);
 spap = peek(spas[bw], NEXTL);
 if (spap) {
  do {
   a = peek(spap, LOC);
   jndexp = peek(spap, LEVEL);
   jndexp = peek(jndexp, NEXTL);
   if (jndexp) {
    do {
     b = peek(jndexp, LOC);
     /* do not allow if the spa pq already exists */
     if ((a == p) && (b == q)) allow = 0;
     if (allow) {
      ab = howfar(a, b);
      xy(a, &xa, &ya);
      xy(b, &xb, &yb);
      xabmin = min(xa, xb);
      xabmax = max(xa, xb);
      yabmin = min(ya, yb);
      yabmax = max(ya, yb);
      /* more details if Manhattan extents of spas pq,ab overlap */
      xpa = (xabmin<=xp) && (xp<=xabmax);
      ypa = (yabmin<=yp) && (yp<=yabmax);
      xqa = (xabmin<=xq) && (xq<=xabmax);
      yqa = (yabmin<=yq) && (yq<=yabmax);
      xap = (xpqmin<=xa) && (xa<=xpqmax);
      yap = (ypqmin<=ya) && (ya<=ypqmax);
      xbp = (xpqmin<=xb) && (xb<=xpqmax);
      ybp = (ypqmin<=yb) && (yb<=ypqmax);
      apb = xpa && ypa;
      aqb = xqa && yqa;
      paq = xap && yap;
      pbq = xbp && ybp;
      xpq = xap && xbp && ypa && yqa;
      xab = xpa && xqa && yap && ybp;
      if (apb || aqb || paq || pbq || xpq || xab) {
       /* investigate further if not extension from previous spa */
       dxpa = xa - xp;
       dypa = yp - ya;
       alpha = yb - ya;
       beta = xb - xa;
       gamma = yq - yp;
       delta = xq - xp;
       o = alpha * delta - beta * gamma;
       #if SHOWSPAN
       newline();
       coords(p);
       coords(q);
       coords(a);
       coords(b);
       printf(" oblique:%d", o);
       #endif
       c = beta * dypa - alpha * dxpa;
       if (!o && !c) colinear = 1;
       else colinear = 0;
       extension = (a==p) || (a==q) || (b==p) || (b==q);
       if (extension && colinear) {
        paq = howfar(p, q) - howfar(p, a) - howfar(a, q);
        pbq = howfar(p, q) - howfar(p, b) - howfar(b, q);
        if (!paq && !pbq) allow = 0;
        #if SHOWSPAN
        if (!allow) printf(" !allow:ex&ol");
        #endif
       }
       if (!extension && allow) {
        if (!o) {
         /* pq parallel ab .. do not allow if colinear and overlapping */
         if (colinear) {
          apb = howfar(a, b) - howfar(a, p) - howfar(p, b);
          aqb = howfar(a, b) - howfar(a, q) - howfar(q, b);
          paq = howfar(p, q) - howfar(p, a) - howfar(a, q);
          pbq = howfar(p, q) - howfar(p, b) - howfar(b, q);
          if (!apb || !aqb || !paq || !pbq) allow = 0;
          #if SHOWSPAN
          if (!allow) printf(" !allow:co&ol");
          #endif
         }
        }
        else {
         /* not parallel .. do not allow if intersection x,y inside spas */
         x = beta*delta*dypa - beta*gamma*xp + alpha*delta*xa;
         y = alpha*gamma*dxpa + alpha*delta*yp - gamma*beta*ya;
         if (o < 0) {
          x = -x;
          y = -y;
          o = -o;
         }
         if ((xabmin*o<=x) && (x<=xabmax*o) && (yabmin*o<=y) && (y<=yabmax*o)) {
          if ((xpqmin*o<=x) && (x<=xpqmax*o) && (ypqmin*o<=y) && (y<=ypqmax*o)) {
           if (pq >= ab) {
            allow = 0;
            #if SHOWSPAN
            printf("  disallow ");
            #endif
           }
          }
         }
        }
       }
      }
     }
     jndexp = peek(jndexp, NEXTL);
    } while (jndexp && allow);
   }
   spap = peek(spap, NEXTL);
  } while (spap && allow);
 }
 return(allow);
}

void glospans()
{
 unsigned scale;
 unsigned nodep, spanp, chekp;
 unsigned bw, jndexes, jndexp, jndex, kndexes, kndexp, kndex;
 unsigned nspan, allow;
 if (!spanon) return;
 glonodes();
 for (bw=BLK; bw<=WHT; ++bw) {
  spanp = gspans[bw];
  spanp = peek(spanp, NEXTL);
  if (spanp) {
   do {
    jndexes = peek(spanp, LEVEL);
    if (jndexes) xtfreelist(jndexes);
    spanp = peek(spanp, NEXTL);
   } while (spanp);
  }
  xtfreelist(gspans[bw]);
  gspans[bw] = xtinsert(0, 0);
  spanp = gspans[bw];
  for (scale=2; scale<=MAXSCALE; ++scale) {
   nodep = gnodes[bw];
   nodep = peek(nodep, NEXTL);
   if (nodep) {
    chekp = nodep;
    do {
     jndex = peek(nodep, LOC);
     kndexes = xtinsert(0, 0);
     halfring(jndex, scale, kndexes);
     kndexp = peek(kndexes, NEXTL);
     if (kndexp) {
      do {
       kndex = peek(kndexp, LOC);
       chekp = xtlocate(kndex, chekp);
       if (xtmember(kndex, chekp)) {
        allow = oldspan(jndex, kndex, bw, gspans);
        if (allow) {
         spanp = xtlocate(jndex, spanp);
         if (!xtmember(jndex, spanp)) {
          spanp = xtinsert(jndex, spanp);
          jndexes = xtinsert(0, 0);
          poke(spanp, LEVEL, jndexes);
         }
         jndexes = peek(spanp, LEVEL);
         jndexp = xtlocate(kndex, jndexes);
         jndexp = xtinsert(kndex, jndexp);
         #if SHOWSPAN
         if (col80) {
          newline();
          if (bw == BLK) printf("BLK");
          if (bw == WHT) printf("WHT");
          coords(jndex);
          coords(kndex);
          printf(" %d", scale);
         }
         #endif
        }
       }
       kndexp = peek(kndexp, NEXTL);
      } while (kndexp);
     }
     xtfreelist(kndexes);
     nodep = peek(nodep, NEXTL);
    } while (nodep);
   }
  }
 }
}

unsigned chkedge(unsigned index, unsigned edgy, unsigned bw)
{
 unsigned sup;
 unsigned corner, edge, xp, xm, yp, ym, xon, yon, jndex;
 int x, y, i, j, xinc, yinc, ysav;
 struct root *rootp;
 sup = 0;
 if (!edgeon) return(sup);
 xy(index, &x, &y);
 xp = edgy & 1;
 xm = edgy & 2;
 yp = edgy & 4;
 ym = edgy & 8;
 xon = xp || xm;
 yon = yp || ym;
 corner = xon && yon;
 edge = xon || yon;
 if (corner) edge = 0;
 xinc = 0;
 yinc = 0;
 if (xp) xinc = 1;
 if (xm) xinc = -1;
 if (yp) yinc = 1;
 if (ym) yinc = -1;
 if (corner) {
  ysav = y;
  for (i=1; i<=4; ++i) {
   y = ysav;
   for (j=1; j<=4; ++j) {
    jndex = fxy(x, y);
    rootp = dir[jndex];
    if (rootp) {
     if (rootp->clr == bw) sup = jndex;
    }
    if (sup) break;
    y += yinc;
   }
   if (sup) break;
   x += xinc;
  }
 }
 else if (edge) {
  for (i=1; i<=4; ++i) {
   jndex = fxy(x, y);
   rootp = dir[jndex];
   if (rootp) {
    if (rootp->clr == bw) sup = jndex;
   }
   if (sup) break;
   if (xon) x += xinc;
   else if (yon) y += yinc;
  }
 }
 return(sup);
}

unsigned getnode(unsigned index, unsigned bw)
{
 unsigned indexp; /* use node directory to access index in nodes list */
 unsigned far *farndirp;
 farndirp = farndir;
 if (bw == WHT) farndirp += nsize21;
 farndirp += index;
 indexp = *farndirp;
 return(indexp);
}

void setnode(unsigned index, unsigned bw, unsigned indexp)
{ /* put indexp from nodes list in node directory */
 unsigned seg, off;
 unsigned far *farndirp;
 farndirp = farndir;
 if (bw == WHT) farndirp += nsize21;
 farndirp += index;
 seg = FP_SEG(farndirp);
 off = FP_OFF(farndirp);
 uzxlmod(seg, off, indexp); /* put change in transaction list */
}

unsigned insarea(unsigned areap, unsigned bw, unsigned index, unsigned jndex,
                 unsigned kndex, unsigned spare, unsigned area)
{
 unsigned jndexes, jndexp, nodep, ptr, kndexes, kndexp;
 #if SHOWSPAN
 newline();
 printf("  insarea");
 coords(index);
 coords(jndex);
 coords(kndex);
 #endif
 areap = xtlocate(index, areap);
 if (!xtmember(index, areap)) {
  areap = uzinsert(index, areap);
  jndexes = uzinsert(0, 0);
  poke(areap, LEVEL, jndexes);
 }
 jndexes = peek(areap, LEVEL);
 jndexp = xtlocate(jndex, jndexes);
 if (!xtmember(jndex, jndexp)) {
  jndexp = uzinsert(jndex, jndexp);
  kndexes = uzinsert(0, 0);
  poke(jndexp, (LEVEL+2), kndexes);
 }
 kndexes = peek(jndexp, (LEVEL+2));
 kndexp = xtlocate(kndex, kndexes);
 if (!xtmember(kndex, kndexp)) {
  kndexp = uzinsert(kndex, kndexp);
  poke(kndexp, LEVEL, jndex);
  poke(kndexp, (LEVEL+2), index);
  poke(kndexp, (LEVEL+4), spare);
  poke(kndexp, (LEVEL+6), area);
  nodep = getnode(index, bw);
  ptr = peek(nodep, (LEVEL+2));
  ptr = xtlocate(kndexp, ptr);
  ptr = uzinsert(kndexp, ptr);
  nodep = getnode(jndex, bw);
  ptr = peek(nodep, (LEVEL+2));
  ptr = xtlocate(kndexp, ptr);
  ptr = uzinsert(kndexp, ptr);
  nodep = getnode(kndex, bw);
  ptr = peek(nodep, (LEVEL+2));
  ptr = xtlocate(kndexp, ptr);
  ptr = uzinsert(kndexp, ptr);
 }
 return(areap);
}

void delarea(unsigned kndexp, unsigned bw)
{
 unsigned index, jndex, kndex, ptr, jndexp, jndexes;
 unsigned nodep, areap;
 kndex = peek(kndexp, LOC);
 jndex = peek(kndexp, LEVEL);
 index = peek(kndexp, (LEVEL+2));
 #if SHOWSPAN
 newline();
 printf("  delarea");
 coords(index);
 coords(jndex);
 coords(kndex);
 #endif
 nodep = getnode(index, bw);
 ptr = peek(nodep, (LEVEL+2));
 ptr = xtlocate(kndexp, ptr);
 if (xtmember(kndexp, ptr)) uzdelink(ptr);
 nodep = getnode(jndex, bw);
 ptr = peek(nodep, (LEVEL+2));
 ptr = xtlocate(kndexp, ptr);
 if (xtmember(kndexp, ptr)) uzdelink(ptr);
 nodep = getnode(kndex, bw);
 ptr = peek(nodep, (LEVEL+2));
 ptr = xtlocate(kndexp, ptr);
 if (xtmember(kndexp, ptr)) uzdelink(ptr);
 uzdelink(kndexp);
/*
 areap = areas[bw];
 areap = xtlocate(index, areap);
 if (xtmember(index, areap)) {
  jndexes = peek(areap, LEVEL);
  jndexp = peek(jndexp, NEXTL);
  if (jndexp) {
   ptr = peek(jndexp, (LEVEL+2));
   if (!peek(ptr, NEXTL)) {
    uzdelink(ptr);
    uzdelink(jndexp);
   }
   if (!peek(jndexes, NEXTL)) {
    uzdelink(jndexes);
    /*uzdelink(areap);*/

   }
  }
 }
*/
}

int howbig(unsigned i, unsigned j, unsigned k)
{
 int value;
 int xi, yi, xj, yj, xk, yk;
 xi = X[i];
 yi = Y[i];
 xj = X[j] - xi;
 yj = Y[j] - yi;
 xk = X[k] - xi;
 yk = Y[k] - yi;
 value = xj * yk - yj * xk;
 return(value);
}

unsigned oppvert(unsigned kndex, unsigned index, unsigned kndexp)
{
 unsigned jndex;
 unsigned i, j, k;
 k = peek(kndexp, LOC);
 j = peek(kndexp, LEVEL);
 i = peek(kndexp, (LEVEL+2));
 jndex = i;
 if ((jndex == index) || (jndex == kndex)) {
  jndex = j;
  if ((jndex == index) || (jndex == kndex)) {
   jndex = k;
  }
 }
 return(jndex);
}

unsigned canarea(unsigned index, unsigned jndex, unsigned kndex, unsigned bw)
{ /* index,jndex form new span   check for other triangles on other spans */
 unsigned allow;
 unsigned destroy, kndexp;
 unsigned i, j, k;
 unsigned nodei, nodej, nodek;
 int newarea, oldarea;
 allow = 1;
 destroy = 0;
 nodek = getnode(kndex, bw);
 nodek = peek(nodek, (LEVEL+2));
 nodek = peek(nodek, NEXTL);
 if (nodek) {
  /* check kndex for area shared by index */
  nodei = getnode(index, bw);
  nodei = peek(nodei, (LEVEL+2));
  newarea = howbig(kndex, index, jndex);
  do {
   kndexp = peek(nodek, LOC);
   nodei = xtlocate(kndexp, nodei);
   if (xtmember(kndexp, nodei)) {
    j = oppvert(kndex, index, kndexp);
    oldarea = howbig(kndex, index, j);
    if ((oldarea > 0) && (newarea > 0)) {
     if (oldarea <= newarea) allow = 0;
     else destroy = kndexp;
    }
    if ((oldarea < 0) && (newarea < 0)) {
     if (oldarea >= newarea) allow = 0;
     else destroy = kndexp;
    }
   }
   nodek = peek(nodek, NEXTL);
  } while (nodek && !destroy && allow);
  if (!destroy && allow) {
   /* check kndex for area shared by jndex */
   nodek = getnode(kndex, bw);
   nodek = peek(nodek, (LEVEL+2));
   nodek = peek(nodek, NEXTL);
   nodej = getnode(jndex, bw);
   nodej = peek(nodej, (LEVEL+2));
   newarea = howbig(kndex, jndex, index);
   do {
    kndexp = peek(nodek, LOC);
    nodej = xtlocate(kndexp, nodej);
    if (xtmember(kndexp, nodej)) {
     i = oppvert(kndex, jndex, kndexp);
     oldarea = howbig(kndex, jndex, i);
     if ((oldarea > 0) && (newarea > 0)) {
      if (oldarea <= newarea) allow = 0;
      else destroy = kndexp;
     }
     if ((oldarea < 0) && (newarea < 0)) {
      if (oldarea >= newarea) allow = 0;
      else destroy = kndexp;
     }
    }
    nodek = peek(nodek, NEXTL);
   } while (nodek && !destroy && allow);
  }
  if (destroy) delarea(destroy, bw);
 }
 return(allow);
}

void mkareas(unsigned index, unsigned jndex, unsigned bw)
{ /* make smallest 2 triangles on span index,jndex */
 unsigned kndex;
 unsigned areap;
 unsigned commons, commonp;
 unsigned nodei, nodej, nodek;
 unsigned is, js, ip, jp;
 unsigned ptri, ptrj, ptr;
 unsigned i, j, k;
 unsigned allow;
 int value, minpos, maxneg;
 if (!areaon) return;
 areap = areas[bw];
 nodei = getnode(index, bw);
 nodej = getnode(jndex, bw);
 ptri = peek(nodei, LEVEL);
 ptrj = peek(nodej, LEVEL);
 ptri = peek(ptri, NEXTL);
 ptrj = peek(ptrj, NEXTL);
 if (ptri && ptrj) {
  commons = xtinsert(0, 0);
  is = xtinsert(0, 0);
  js = xtinsert(0, 0);
  commonp = commons;
  ip = is;
  jp = js;
  do {
   ptr = peek(ptri, LOC);
   i = peek(ptr, LEVEL);
   if (i == index) i = peek(ptr, LOC);
   ip = xtlocate(i, ip);
   ip = xtinsert(i, ip);
   ptri = peek(ptri, NEXTL);
  } while (ptri);
  do {
   ptr = peek(ptrj, LOC);
   j = peek(ptr, LEVEL);
   if (j == jndex) j = peek(ptr, LOC);
   jp = xtlocate(j, jp);
   jp = xtinsert(j, jp);
   ptrj = peek(ptrj, NEXTL);
  } while (ptrj);
  maxneg = -BIAS;
  minpos = BIAS;
  jp = peek(js, NEXTL);
  ip = peek(is, NEXTL);
  do {
   k = peek(ip, LOC);
   jp = xtlocate(k, jp);
   if (xtmember(k, jp)) {
    commonp = xtlocate(k, commonp);
    commonp = xtinsert(k, commonp);
    value = howbig(index, jndex, k);
    poke(commonp, LEVEL, value+BIAS);
    if (value < 0) {
     if (value > maxneg) maxneg = value;
    }
    if (value > 0) {
     if (value < minpos) minpos = value;
    }
   }
   ip = peek(ip, NEXTL);
  } while (ip);
  /* now remove all but the smallest positive area and the largest neg */
  commonp = peek(commons, NEXTL);
  if (commonp) {
   do {
    value = peek(commonp, LEVEL) - BIAS;
    if ((value != maxneg) && (value != minpos)) commonp = xtdelete(commonp);
    commonp = peek(commonp, NEXTL);
   } while (commonp);
  }
  commonp = peek(commons, NEXTL);
  if (commonp) {
   do {
    kndex = peek(commonp, LOC);
    value = peek(commonp, LEVEL) - BIAS;
    allow = canarea(index, jndex, kndex, bw);
    if (allow) {
     i = index;
     j = kndex;
     k = jndex;
     if (kndex > jndex) {
      j = jndex;
      k = kndex;
     }
     if (kndex < index) {
      i = kndex;
      j = index;
     }
     areap = insarea(areap, bw, i, j, k, 0, abs(value));
    }
    commonp = peek(commonp, NEXTL);
   } while (commonp);
  }
  xtfreelist(js);
  xtfreelist(is);
  xtfreelist(commons);
 }
}

unsigned insspan(unsigned spanp, unsigned bw, unsigned index, unsigned jndex,
                                                unsigned spare, unsigned pcon)
{
 unsigned jndexes, jndexp, nodep, ptr;
 #if SHOWSPAN
 newline();
 printf("  insspan");
 coords(index);
 coords(jndex);
 #endif
 spanp = xtlocate(index, spanp);
 if (!xtmember(index, spanp)) {
  spanp = uzinsert(index, spanp);
  jndexes = uzinsert(0, 0);
  poke(spanp, LEVEL, jndexes);
 }
 jndexes = peek(spanp, LEVEL);
 jndexp = xtlocate(jndex, jndexes);
 if (!xtmember(jndex, jndexp)) {
  jndexp = uzinsert(jndex, jndexp);
  poke(jndexp, LEVEL, index);
  poke(jndexp, (LEVEL+4), spare);
  poke(jndexp, (LEVEL+6), pcon);
  nodep = getnode(index, bw);
  ptr = peek(nodep, LEVEL);
  ptr = xtlocate(jndexp, ptr);
  ptr = uzinsert(jndexp, ptr);
  nodep = getnode(jndex, bw);
  ptr = peek(nodep, LEVEL);
  ptr = xtlocate(jndexp, ptr);
  ptr = uzinsert(jndexp, ptr);
 }
 mkareas(index, jndex, bw);
 return(spanp);
}

void delspan(unsigned jndexp, unsigned bw)
{
 unsigned index, jndex, ptr;
 unsigned nodep, spanp, nodeq;
 jndex = peek(jndexp, LOC);
 index = peek(jndexp, LEVEL);
 #if SHOWSPAN
 newline();
 printf("  delspan");
 coords(index);
 coords(jndex);
 #endif
 nodep = getnode(index, bw);
 ptr = peek(nodep, LEVEL);
 ptr = xtlocate(jndexp, ptr);
 if (xtmember(jndexp, ptr)) uzdelink(ptr);
 nodeq = getnode(jndex, bw);
 ptr = peek(nodeq, LEVEL);
 ptr = xtlocate(jndexp, ptr);
 if (xtmember(jndexp, ptr)) uzdelink(ptr);
 /* delink areas supported by both index and jndex */

 nodep = peek(nodep, (LEVEL+2));
 nodeq = peek(nodeq, (LEVEL+2));
 nodep = peek(nodep, NEXTL);
 if (nodep) {
  do {
   ptr = peek(nodep, LOC);
   nodeq = xtlocate(ptr, nodeq);
   if (xtmember(ptr, nodeq)) {
    delarea(ptr, bw);
   }
   nodep = peek(nodep, NEXTL);
  } while (nodep);
 }

 uzdelink(jndexp);
 spanp = spans[bw];
 spanp = xtlocate(index, spanp);
 if (xtmember(index, spanp)) {
  ptr = peek(spanp, LEVEL);
  if (!peek(ptr, NEXTL)) {
   uzdelink(ptr);
   uzdelink(spanp);
  }
 }
}

unsigned insnode(unsigned index, unsigned nodep, unsigned edgy, unsigned da)
{ /* insert node for bw==colour */
 nodep = uzinsert(index, nodep); /* insertion of node is a transaction */
 poke(nodep, LEVEL, uzinsert(0, 0)); /* make span list a transaction */
 poke(nodep, (LEVEL+2), uzinsert(0, 0)); /* make area list too */
 poke(nodep, (LEVEL+4), edgy); /* real/virtual */
 poke(nodep, (LEVEL+6), da); /* indicate dead/alive */
 setnode(index, colour, nodep); /* put nodep in node directory at index */
 return(nodep);
}

unsigned delnode(unsigned nodep, unsigned bw)
{
 unsigned jndexp, kndexp, spanlp, arealp;
 unsigned index;
 index = peek(nodep, LOC);
 /* first delink all areas in areas list ... no! only delspan calls delarea */

 arealp = peek(nodep, (LEVEL+2));
 arealp = peek(arealp, NEXTL);
 if (arealp) {
  do {
   kndexp = peek(arealp, LOC);
   delarea(kndexp, bw); /* delarea messes with arealp list */
   arealp = peek(arealp, NEXTL);
  } while (arealp);
 }

 /* then delink areas list */
 uzfreelist(peek(nodep, (LEVEL+2)));
 /* then delink all spans in spans list */
 spanlp = peek(nodep, LEVEL);
 spanlp = peek(spanlp, NEXTL);
 if (spanlp) {
  do