/* Spheres of influence */
#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"
void glom(unsigned i); /* prototype */
void glom(unsigned i)
{
unsigned j, jndex, *point;
struct root *rootp;
rootp = dir[i];
if (!rootp) ++pinfo[2];
else {
++pinfo[3];
if (!rootp->realdead) pinfo[0] = 0;
if (rootp->reallive) pinfo[1] = 1;
}
gloparts[i] = npart;
point = NEWS(i);
for (j=0; j<NLIBS; ++j) {
jndex = *point;
if (jndex) {
if (!gloparts[jndex]) {
if (gbw == (whose[jndex] >> 8)) {
glom(jndex);
}
}
}
++point;
}
}
unsigned neutral(unsigned index)
{
unsigned bw; /* ownership of neutral point 0 if no owner */
unsigned i, jndex, *point, jbw, jinfo, partno;
unsigned deadp[3], livep[3];
deadp[BLK] = 1;
deadp[WHT] = 1;
livep[BLK] = 0;
livep[WHT] = 0;
point = NEWS(index);
for (i=0; i<NLIBS; ++i) {
jndex = *point;
if (jndex) {
partno = gloparts[jndex];
if (partno) {
jinfo = partinfo[partno];
jbw = jinfo >> 8;
if (jbw) {
if (!(jinfo & 1)) deadp[jbw] = 0;
if (jinfo & 2) livep[jbw] = 1;
}
}
}
++point;
}
if (deadp[WHT] && livep[BLK]) bw = BLK;
else if (deadp[BLK] && livep[WHT]) bw = WHT;
else bw = 0;
return(bw);
}
void rescale()
{
/* this sets scale for spans */
unsigned i, max, dist;
max = 0;
for (i=1; i<=nsize2; ++i) {
dist = whose[i] & 255;
if (dist > max) max = dist;
}
newline();
printf(" rescale dist %d", max);
}
void evaluate() /* global partitioning */
{
unsigned i, value, bw;
npart = 0;
for (i=1; i<=nsize2; ++i) gloparts[i] = 0;
for (i=1; i<=nsize2; ++i) {
gbw = 0;
if (!gloparts[i]) {
gbw = whose[i] >> 8;
if (gbw) {
pinfo[0] = 1; /* dead: false if any root not realdead */
pinfo[1] = 0; /* live: true if any root realdead */
pinfo[2] = 0; /* nvac: count number of vacant points */
pinfo[3] = 0; /* nocc: count number of occupied points */
++npart;
glom(i);
value = (gbw << 8) + pinfo[0] + (pinfo[1] << 1);
partinfo[npart] = value;
partnvac[npart] = pinfo[2];
partnocc[npart] = pinfo[3];
partindx[npart] = i;
}
}
}
numparts = npart;
/* first compute score without considering neutral points */
sphscore[BLK] = wcaps; /* black counts whites removed from board by capture */
sphscore[WHT] = bcaps;
for (i=1; i<=numparts; ++i) {
bw = partinfo[i] >> 8;
if (partinfo[i] & 2) sphscore[bw] += partnvac[i];
if (partinfo[i] & 1) sphscore[flip(bw)] += partnvac[i] + 2 * partnocc[i];
}
/* now account for ownership of neutral points */
for (i=1; i<=nsize2; ++i) {
if (!(whose[i]>>8)) {
bw = neutral(i);
if (bw) {
++sphscore[bw];
gloparts[i] |= bw << 8; /* put owner of neutral point in high byte */
}
}
}
}
unsigned scandist(unsigned index, unsigned bw)
{
unsigned dist;
unsigned indexes;
dist = 1;
indexes = xtinsert(0, 0);
do {
++dist;
cring(index, dist, indexes, bw);
} while ((dist < MAXSCALE) && !peek(indexes, NEXTL));
xtfreelist(indexes);
return(dist);
}
void mksphere(unsigned index)
{
struct link *frontier, *fp;
struct link *interior, *ip;
/*struct link *domicile, *dp;*/
struct link *libs, *lp;
struct link *capp, *neighbp;
struct root *rootp;
unsigned jndex, kndex;
unsigned *point, i;
unsigned jclr, ojclr; /* new and old assessment of whose point */
unsigned jdst, ojdst; /* new and old assessment of dist to point */
unsigned change; /* 1 if possession of point has changed */
unsigned alter; /* 1 if whose[] needs to be updated */
if (!sphron) return; /* return if not selected */
/*if (!index) return; /* if pass, nothing changes */*/
/* Chinese suicide not supported */
/* first change dist of captured stones to 255 using uzgvmod */
/* to make sure that change gets undone */
capp = movep->caps->nextl;
if (capp) {
do {
rootp = (struct root *) capp->loc;
neighbp = rootp->neighbs->nextl;
do {
jndex = neighbp->loc;
jclr = flip(whose[jndex] >> 8);
uzgvmod(&whose[jndex], (jclr<<8)+scandist(jndex, jclr));
neighbp = neighbp->nextl;
} while (neighbp);
capp = capp->nextl;
} while (capp);
}
frontier = insert(0, 0);
interior = insert(0, 0);
/*domicile = insert(0, 0);*/
/* start with frontier as stone just played */
insert(index, frontier);
ojclr = whose[index] >> 8; /* get old possessor */
jclr = colour; /* potential new possessor */
uzgvmod(&whose[index], (jclr<<8)); /* indicate possession of index */
do {
/* go through frontier and accumulate lib positions in libs */
libs = insert(0, 0); /* store all libs of frontier here */
lp = libs;
fp = frontier->nextl;
if (fp) {
do {
jndex = fp->loc; /* jndex is point on the frontier */
point = NEWS(jndex); /* pointer to liberty positions */
for (i=0; i<NLIBS; ++i) {
kndex = *point; /* kndex is in lib posn of jndex */
if (kndex) { /* ensure point on board */
if (!dir[kndex]) { /* must be empty (no stone) */
lp = locate(kndex, lp); /* put it in libs */
lp = insert(kndex, lp);
}
}
++point;
}
fp = fp->nextl;
} while (fp);
}
/* put frontier in interior */
ip = interior;
fp = frontier->nextl;
if (fp) {
do {
jndex = fp->loc; /* from frontier */
ip = locate(jndex, ip);
ip = insert(jndex, ip); /* to interior */
fp = fp->nextl;
} while (fp);
}
freelist(frontier); /* a bit of a swap here */
frontier = insert(0, 0); /* new (empty) frontier */
/*dp = domicile;*/
ip = interior;
fp = frontier;
/* test libs not in interior for change */
lp = libs->nextl;
if (lp) {
do {
jndex = lp->loc; /* jndex of lib of old frontier */
ip = locate(jndex, ip);
if (!member(jndex, ip)) { /* no good if in interior */
/* has possession of point jndex changed due to index? */
change = 0;
alter = 0;
ojclr = whose[jndex] >> 8; /* get old possessor */
ojdst = whose[jndex] & 255; /* get old distance */
jclr = colour; /* may be set neutral later */
jdst = howfar(index, jndex); /* dist to index */
if (!ojclr && (ojdst == jdst)) jclr = 0; /* stay neutral */
if (jdst < ojdst) {
if (jclr != ojclr) change = 1;
alter = 1;
}
if (jdst == ojdst) {
if (jclr != ojclr) {
change = 1;
alter = 1;
jclr = 0;
}
}
if (alter || change) {
fp = locate(jndex, fp); /* put change in new frontier */
fp = insert(jndex, fp);
/*
if (jclr == colour) {
dp = locate(jndex, dp); /* extent of influence of index */
dp = insert(jndex, dp);
}
*/
}
if (alter) uzgvmod(&whose[jndex], (jclr<<8)+jdst);
if (!change) {
ip = locate(jndex, ip); /* if no change then interior */
ip = insert(jndex, ip);
}
}
lp = lp->nextl;
} while (lp);
}
freelist(libs);
} while (frontier->nextl);
freelist(interior);
freelist(frontier);
}
void evaperim()
{
unsigned i, index, jndex, *point, bw, whoj;
for (index=1; index<=nsize2; ++index) {
perisphr[index] = 0;
if (!dir[index]) {
bw = whose[index] >> 8;
if (!bw) perisphr[index] = 1;
else {
point = NEWS(index);
for (i=0; i<NLIBS; ++i) {
jndex = *point;
if (jndex) {
whoj = whose[jndex] >> 8;
if (whoj) {
if (whoj != bw) {
perisphr[index] = 1;
break;
}
}
}
++point;
}
}
}
}
}
unsigned owner(unsigned index)
{
unsigned bw;
unsigned numpart;
bw = whose[index] >> 8;
if (bw) {
numpart = gloparts[index] & 255;
if (partinfo[numpart]&1) bw = flip(bw);
if (!((partinfo[numpart]&2) || (partinfo[numpart]&1))) bw = 0;
}
else bw = gloparts[index] >> 8;
return(bw);
}
unsigned alive(unsigned index)
{
unsigned bw;
unsigned numpart;
bw = whose[index] >> 8;
if (bw) {
numpart = gloparts[index] & 255;
if (!(partinfo[numpart]&2)) bw = 0;
}
else bw = gloparts[index] >> 8;
return(bw);
}
unsigned dead(unsigned index)
{
unsigned bw;
unsigned numpart;
bw = whose[index] >> 8;
if (bw) {
numpart = gloparts[index] & 255;
if (partinfo[numpart]&1) bw = 0;
}
else bw = gloparts[index] >> 8;
return(!bw);
}