#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
void addrootl(rootp)
struct root *rootp;
{
struct link *linkp;
linkp = (struct link *) locate(rootp, rootlist);
linkp = (struct link *) insert(rootp, linkp);
rootp->rootlp = linkp;
}
void uprootl(rootp)
struct root *rootp;
{
struct link *linkp;
linkp = rootp->rootlp;
if(linkp->loc == rootp) linkp = (struct link *) delete(linkp);
}
void distinct(unsigned index, struct root *diff[])
{
unsigned i, jndex, k, j, *point;
struct root *rootp;
point = NEWS(index);
for (i=0; i<NLIBS; ++i) {
jndex = *point;
if (jndex) diff[i] = dir[jndex];
else diff[i] = 0;
++point;
}
for (i=1; i<NLIBS; ++i) { /* Hey, I meant to do that */
rootp = diff[i];
if (rootp) {
k = i - 1; /* because of this */
for (j=0; j<=k; ++j) {
point = (unsigned *) diff[j];
if (rootp == (struct root *) point) diff[i] = 0;
}
}
}
}
/* undo */
void untrans(unsigned trlistp)
{
unsigned typ, ptr, *p, val, segptr, offset;
if (peek(trlistp, NEXTL)) {
trlistp = xttaillist(trlistp);
do {
typ = peek(trlistp, LEVEL);
if (typ == 1) { /* transaction was add to list ... delete to undo */
ptr = peek(trlistp, (LEVEL+2));
xtdelete(ptr);
}
else if (typ == 2) { /* trans was delink from list ... relink to undo */
ptr = peek(trlistp, (LEVEL+2));
xtrelink(ptr);
}
else if (typ == 3) { /* trans was unsigned assign ... reassign to undo */
p = peek(trlistp, (LEVEL+2));
val = peek(trlistp, (LEVEL+4));
*p = val;
}
else if (typ == 4) { /* trans was unsigned poke ... reassign to undo */
segptr = peek(trlistp, (LEVEL+2));
offset = peek(trlistp, (LEVEL+4));
val = peek(trlistp, (LEVEL+6));
poke(segptr, offset, val);
}
trlistp = peek(trlistp, PREVL);
} while (peek(trlistp, PREVL));
}
}
struct move *unmove(movep)
struct move *movep;
{
struct move *freep;
if (movep) {
freelist(movep->caps);
freelist(movep->merges);
freelist(movep->suicaps);
xtfreelist(movep->transact);
freep = movep;
movep = movep->prevm;
freelarge(freep);
}
return (movep);
}
unsigned ndist(index)
unsigned index;
{
unsigned number, i, *point;
struct root *diff[NLIBS];
number = 0;
distinct(index, diff);
point = (unsigned *) diff;
for (i=1; i<=NLIBS; ++i) {
if (*point) ++number;
++point;
}
return (number);
}
void unmergeroot(index)
unsigned index;
{
struct root *rootp;
struct link *mergep, *head, *stonep, *movelp, *libp;
unsigned jndex;
struct link *hmerge;
jndex = index; /* useless */
hmerge = movep->merges->nextl;
if (hmerge) {
mergep = taillist(movep->merges);
do {
rootp = mergep->loc;
addrootl(rootp);
stonep = rootp->neighbs;
if (stonep) {
do {
jndex = stonep->loc;
if (jndex) dir[jndex] = rootp;
stonep = stonep->nextl;
}
while (stonep);
}
mergep = mergep->prevl;
rootp = mergep->loc;
}
while (rootp);
}
}
void uncreroot(index)
unsigned index;
{
struct root *rootp;
unsigned i;
rootp = dir[index];
uprootl(rootp);
dir[index] = 0;
freelist(rootp->neighbs);
freelist(rootp->liberties);
freelist(rootp->spaces);
freelist(rootp->friends);
freelist(rootp->enemies);
freelist(rootp->contacts);
freelarge(rootp);
}
void unremcap(index)
unsigned index;
{
struct root *rootp, *head;
struct link *ptr, *point, *listp, *stonep;
unsigned jndex, i;
jndex = index; /* useless */
listp = movep->caps->nextl;
if (listp) {
do {
rootp = listp->loc;
addrootl(rootp);
head = rootp;
stonep = rootp->neighbs->nextl;
if (stonep) {
do {
jndex = stonep->loc;
dir[jndex] = head;
colour = flip(colour);
add(jndex);
if (colour == BLK) ++bstones;
else ++wstones;
colour = flip(colour);
stonep = stonep->nextl;
}
while (stonep);
}
listp = listp->nextl;
}
while (listp);
}
nopen -= movep->ncap;
if (colour == BLK) {
wcaps -= movep->ncap;
}
if (colour == WHT) {
bcaps -= movep->ncap;
}
}
void unchsui(index)
unsigned index;
{
struct root *rootp, *head;
struct link *ptr, *point, *listp, *stonep;
unsigned jndex, i;
jndex = index; /* useless */
listp = movep->suicaps->nextl;
if (listp) {
do {
rootp = listp->loc;
addrootl(rootp);
head = rootp;
stonep = rootp->neighbs->nextl;
if (stonep) {
do {
jndex = stonep->loc;
dir[jndex] = head;
add(jndex);
stonep = stonep->nextl;
}
while (stonep);
}
listp = listp->nextl;
}
while (listp);
}
nopen -= movep->nsuicap - 1;
if (colour == BLK) {
bcaps -= movep->nsuicap;
bstones += movep->nsuicap;
}
if (colour == WHT) {
wcaps -= movep->nsuicap;
wstones += movep->nsuicap;
}
}
unsigned adjacent(unsigned index, unsigned jndex)
{
unsigned adj;
unsigned *point, i;
adj = 0;
point = NEWS(index);
for (i=0; i<NLIBS; ++i) {
if (jndex == *point) adj = 1;
++point;
}
return(adj);
}
unsigned eyesteal(index, jndex)
unsigned index;
unsigned jndex;
{
unsigned tesuji;
unsigned ix, iy, jx, jy, kndex, lndex;
tesuji = 0;
xy(index, &ix, &iy);
xy(jndex, &jx, &jy);
kndex = fxy(ix, jy);
if (!dir[kndex]) {
lndex = fxy(jx, iy);
if (!dir[lndex]) tesuji = 1;
}
return(tesuji);
}
unsigned evaleye(index, bw)
unsigned index, bw;
{
unsigned num;
unsigned *point;
unsigned i, jndex, poked;
unsigned diagvec[NDIAGS];
num = 0;
poked = 0;
if (dir[index]) {
/*if (dir[index]->clr == bw) */
poked = 1;
}
if (!poked) {
point = NEWS(index);
for (i=0; i<NLIBS; ++i) {
jndex = *point;
if (jndex) {
if (dir[jndex]) {
if (dir[jndex]->clr == bw) ++num;
else poked = 1;
}
}
++point;
}
}
if (!poked) {
diags(index, diagvec);
point = diagvec;
for (i=0; i<NDIAGS; ++i) {
jndex = *point;
if (jndex) {
if (dir[jndex]) {
if (dir[jndex]->clr != bw) {
if (eyesteal(index, jndex)) poked = 1;
}
}
}
++point;
}
}
if (poked) num = 0;
return(num);
}
void freroot(rootp)
struct root *rootp;
{
unsigned jndex;
if (rootp) {
freelist(rootp->neighbs);
freelist(rootp->liberties);
freelist(rootp->spaces);
freelist(rootp->friends);
freelist(rootp->enemies);
freelist(rootp->contacts);
freelarge(rootp);
}
}
void freroots(listr)
struct link *listr;
{
struct root *rootp;
struct link *listp;
if (listr) {
listp = listr;
do {
rootp = listp->loc;
freroot(rootp);
listp = listp->nextl;
}
while (listp);
}
}
void fretrans(unsigned trlistp)
{
unsigned typ, ptr;
if (peek(trlistp, NEXTL)) {
trlistp = xttaillist(trlistp);
do {
typ = peek(trlistp, LEVEL);
ptr = peek(trlistp, (LEVEL+2));
if (typ == 2) { /* trans was delink from list ... free to forget */
freeextra(ptr);
}
trlistp = peek(trlistp, PREVL);
} while (peek(trlistp, PREVL));
}
}
void forget(n)
unsigned n;
{
struct move *ptr, *fmove;
unsigned i;
fmove = movep;
for (i = 1; i <= n; ++i) {
if (fmove) fmove = fmove->prevm;
}
if (fmove) {
ptr = fmove;
fmove = fmove->prevm;
if (fmove) {
/*freenets(fmove);*/
freroots(fmove->suicaps);
freroots(fmove->caps);
freroots(fmove->merges);
fretrans(fmove->transact);
fmove = unmove(fmove);
ptr->prevm = 0;
}
}
}
void chinsui(index)
unsigned index;
{
struct root *rootp;
unsigned *point;
struct link *stonep, *capp;
unsigned i, jndex;
movep->nsuicap = 1;
point = NEWS(index);
for (i=1; i<=NLIBS; ++i) {
jndex = *point;
if (jndex) {
rootp = dir[jndex];
if (rootp) {
if (rootp->clr == colour) {
if (rootp->nlib == 1) {
uprootl(rootp);
movep->nsuicap += rootp->nsto;
nopen += rootp->nsto;
capp = (struct link *) locate(rootp, movep->suicaps);
capp = (struct link *) insert(rootp, capp);
stonep = rootp->neighbs->nextl;
if (stonep) {
do {
jndex = stonep->loc;
dir[jndex] = 0;
del(jndex);
stonep = stonep->nextl;
} while (stonep);
}
}
}
}
}
++point;
}
if (colour == WHT) {
wcaps += movep->nsuicap;
wstones -= movep->nsuicap;
}
if (colour == BLK) {
bcaps += movep->nsuicap;
bstones -= movep->nsuicap;
}
scrindex = index;
}
unsigned suichk(index)
unsigned index;
{
unsigned sui;
struct root *rootp;
unsigned *point;
unsigned ratp;
unsigned i, immedlib, caplib, conlib, jndex, alone;
sui = 0;
/* immedlib true for immediate liberties */
immedlib = 0;
point = NEWS(index);
for (i=1; i<=NLIBS; ++i) {
jndex = *point;
if (jndex) {
immedlib |= (dir[jndex] == 0);
}
++point;
}
if (!immedlib) { /* no immediate liberties */
/* caplib true if there will be captures */
caplib = 0;
point = NEWS(index);
for (i=1; i<=NLIBS; ++i) {
jndex = *point;
if (jndex) {
rootp = dir[jndex];
if (rootp) {
if (rootp->clr != colour) {
if (rootp->nlib == 1) caplib |= 1;
}
}
}
++point;
}
if (!caplib) { /* no liberties by making capture */
/* conlib true if friends with nlib > 1 */
alone = 1;
point = NEWS(index);
conlib = 0;
for (i=1; i<=NLIBS; ++i) {
jndex = *point;
if (jndex) {
rootp = dir[jndex];
if (rootp) {
if (rootp->clr == colour) {
alone = 0;
conlib |= (rootp->nlib > 1);
}
}
}
++point;
}
sui = !conlib;
if (sui && chinese && !alone && suilegal) {
sui = 0;
chinsui(index);
del(index);
}
} /* endif !caplib */
} /* endif !immedlib */
return (sui);
}
struct move *addmove(movep, index)
struct move *movep;
unsigned index;
{
struct move *lastmove;
if (movep) {
lastmove = movep;
movep = (struct move *) allolarge();
if (movep) {
movep->nextm = 0;
lastmove->nextm = movep;
movep->prevm = lastmove;
}
}
else {
movep = (struct move *) allolarge();
if (movep) {
movep->nextm = 0;
movep->prevm = 0;
}
}
if (movep) {
movep->midx = index;
movep->ncap = 0;
movep->caps = (struct link *) insert(0, 0);
movep->merges = (struct link *) insert(0, 0);
movep->komove = 0;
movep->nsuicap = 0;
movep->suicaps = (struct link *) insert(0, 0);
movep->transact = xtinsert(0, 0);
xthistp = xtlocate(kount, xthistp);
xthistp = xtinsert(kount, xthistp);
poke(xthistp, LEVEL, index);
}
return (movep);
}
unsigned kochk(index)
unsigned index;
{
unsigned ko;
struct move *ptr;
ko = 0;
if (movep) {
ptr = movep->prevm;
if (ptr) {
ko = (ptr->komove == index);
}
}
return (ko);
}
void kogen(index)
unsigned index;
{
struct root *rootp;
unsigned flag;
rootp = dir[index];
if (rootp) {
flag = ((movep->ncap == 1) && (rootp->nlib == 1) && (rootp->nsto == 1));
if (flag) {
rootp = (struct root *) movep->caps->nextl->loc;
movep->komove = rootp->neighbs->nextl->loc;
}
}
}
void merger(index)
unsigned index;
{
struct root *rootp, *firstroot;
struct link *mergep;
unsigned *point;
struct root *diff[NLIBS];
unsigned i;
distinct(index, diff);
point = (unsigned *) diff;
firstroot = dir[index];
for (i = 1; i <= NLIBS; ++i) {
rootp = (struct root *) *point;
if (rootp) {
if (rootp->clr == firstroot->clr) {
mergep = (struct link *) locate(rootp, movep->merges);
mergep = (struct link *) insert(rootp, mergep);
}
}
++point;
}
}
void mergeroot(index)
unsigned index;
{
struct root *rootp, *head;
struct link *point, *mergep, *stonep;
unsigned i, jndex;
head = dir[index];
merger(index);
mergep = movep->merges->nextl;
if (mergep) {
do {
rootp = (struct root *) mergep->loc;
uprootl(rootp);
jndex = rootp->ridx;
stonep = rootp->neighbs->nextl;
if (stonep) {
do {
jndex = stonep->loc;
dir[jndex] = head;
stonep = stonep->nextl;
} while (stonep);
}
mergep = mergep->nextl;
} while (mergep);
}
}
void remcap(index)
unsigned index;
{
struct root *rootp;
unsigned *point;
struct link *stonep, *capp;
unsigned i, jndex;
point = NEWS(index);
for (i=1; i<=NLIBS; ++i) {
jndex = *point;
if (jndex) {
rootp = dir[jndex];
if (rootp) {
if (rootp->clr != colour) {
if (rootp->nlib == 1) {
uprootl(rootp);
movep->ncap += rootp->nsto;
nopen += rootp->nsto;
capp = (struct link *) locate(rootp, movep->caps);
capp = (struct link *) insert(rootp, capp);
stonep = rootp->neighbs->nextl;
if (stonep) {
do {
jndex = stonep->loc;
dir[jndex] = 0;
del(jndex);
if (colour == BLK) --wstones;
else --bstones;
stonep = stonep->nextl;
} while (stonep);
}
}
}
}
}
++point;
}
if (colour == WHT) bcaps += movep->ncap;
if (colour == BLK) wcaps += movep->ncap;
}
void creroot(index)
unsigned index;
{
struct root *rootp;
struct link *point;
unsigned i, jndex;
rootp = (struct root *) allolarge();
if (rootp) {
dir[index] = rootp;
rootp->neighbs = (struct link *) insert(0, 0);
rootp->liberties = (struct link *) insert(0, 0);
rootp->spaces = (struct link *) insert(0, 0);
rootp->friends = (struct link *) insert(0, 0);
rootp->enemies = (struct link *) insert(0, 0);
rootp->contacts = (struct link *) insert(0, 0);
rootp->clr = colour;
rootp->nsto = 1;
rootp->nlib = 0;
rootp->ridx = index;
rootp->incmod = 0;
rootp->reallive = 1;
rootp->realdead = 0;
addrootl(rootp);
}
}
unsigned doit(index)
unsigned index;
{
unsigned valid;
unsigned *ptr, indexok;
unsigned time;
ntrans = 0;
valid = 0;
occ = 0;
sui = 0;
ko = 0;
keybreak(0);
if (maxclk) if (*clkptr >= maxclk) timeattn = 999;
if ((index >= 0) && (index <= nsize2)) {
occ = (unsigned) dir[index];
/*++kount;*/
if (!occ) {
movep = addmove(movep, index);
if (index) {
ko = kochk(index);
if (!ko) {
remcap(index);
sui = suichk(index);
if (!sui) {
if (!movep->nsuicap) {
--nopen;
creroot(index);
mergeroot(index);
}
life(index);
add(index);
/*countlibs();*/
kogen(index);
if (colour == BLK) ++bstones;
else ++wstones;
if (envon) {
if (colour == BLK) {
if (movep->ncap) wdead -= movep->ncap;
}
else {
if (movep->ncap) bdead -= movep->ncap;
}
score();
}
if (timer) hundelay(timer);
}
}
}
}
valid = !(occ || ko || sui);
if (sui || ko) {
if (index) {
del(index);
/*if (kount) {*/
xthistp = xtlocate(kount, xthistp);
if (xtmember(kount, xthistp)) xthistp = xtdelete(xthistp);
/*}*/
movep = (struct move *) unmove(movep);
}
}
/*if (!valid) --kount;*/
if (valid) {
/*if (kount > 1) {*/ /* does this do anything? */
mkeyes(index);
mkspans(index);
mksphere(index);
/*}*/
if (index) scrindex = index;
++kount;
colour = flip(colour);
++ndoits;
}
}
return (valid);
}
unsigned undoit()
{
unsigned index;
unsigned time;
keybreak(0);
index = 0;
if (movep) {
if(movep->prevm) colour = flip(colour);
index = movep->midx;
if (index && movep->prevm) {
if (colour == BLK) --bstones;
else --wstones;
if (envon) {
/*unlinkjz(index);*/
if (colour == BLK) {
if (movep->ncap) wdead += movep->ncap;
}
else {
if (movep->ncap) bdead += movep->ncap;
}
}
untrans(movep->transact);
/*uneyes(index);*/
unlife(index);
/*uncountlibs();*/
if (!movep->nsuicap) {
unmergeroot(index);
uncreroot(index);
unremcap(index);
del(index);
++nopen;
}
if (movep->nsuicap) {
unchsui(index);
}
score();
}
if (movep->prevm) {
--kount;
xthistp = xtlocate(kount, xthistp);
if (xtmember(kount, xthistp)) xthistp = xtdelete(xthistp);
movep = unmove(movep);
if (timer) hundelay(timer);
}
}
if (movep->midx) scrindex = movep->midx;
return (index);
}