#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 TREE 0
/*
double log(double x);
double exp(double x);
*/
double prob(index, jndex, candidates) /* for blocking or extending */
unsigned index; /* this one must exist */
unsigned jndex; /* this one may be vapour */
unsigned candidates;
{
int area;
int joined, canjoin, blocked;
int x, y, ix, iy, jx, jy, dx, dy, absdx, absdy;
int ndigits, ibit, nbins, ibin, sum, carry, numon;
int kx, ky, viable;
unsigned kndex, max, min, num, nways, ntotal, nocc;
double dprob, sumprob, prio;
int dist, mt, cutoff;
cutoff = 2;
dist = howfar(index, jndex);
sumprob = 1;
if (dist == 2) return(sumprob);
sumprob = 0.0;
if (dist > xdist) return(sumprob);
nways = 0;
ntotal = 0;
xy(index, &ix, &iy);
xy(jndex, &jx, &jy);
dx = jx - ix;
dy = jy - iy;
if (dx < 0) absdx = -dx;
else absdx = dx;
if (dy < 0) absdy = -dy;
else absdy = dy;
ndigits = absdx + absdy;
/* nbins = (absdx + 1) * (absdy + 1);*/
mt = 1;
/* check for empty field */
for (x=0; x<=absdx; ++x) {
for (y=0; y<=absdy; ++y) {
if (dx < 0) kx = ix - x;
else kx = ix + x;
if (dy < 0) ky = iy - y;
else ky = iy + y;
kndex = fxy(kx, ky);
if ((kndex != index) && (kndex != jndex)) {
if (dir[kndex]) {
mt = 0;
}
}
}
}
/*
if ((dist > cutoff) && mt) {
sumprob = 1.0;
for (ibit=1; ibit<ndigits; ++ibit) sumprob *= 0.5;
for (ibit=1; ibit<ndigits; ++ibit) sumprob *= ibit+1;
if (absdx) for (ibit=1; ibit<=absdx; ++ibit) sumprob /= ibit;
if (absdy) for (ibit=1; ibit<=absdy; ++ibit) sumprob /= ibit;
midway(index, jndex, candidates);
return(sumprob);
}
*/
mt = 0; /* if no candidates desired use above commented-out code */
if ((dist > cutoff) && !mt) {
/* initialize array of paths point accumulators */
for (x=0; x<=absdx; ++x) {
for (y=0; y<=absdy; ++y) {
ibin = x * (absdy+1) + y;
hits[ibin] = 0;
if (dx < 0) kx = ix - x;
else kx = ix + x;
if (dy < 0) ky = iy - y;
else ky = iy + y;
kndex = fxy(kx, ky);
location[ibin] = kndex;
}
}
/* one pass */
joined = 0;
/* initialize digits of binary counter and start counting */
for (ibit=1; ibit<=ndigits; ++ibit) binary[ibit] = 0;
do {
carry = 1;
numon = 0;
for (ibit=1; ibit<=ndigits; ++ibit) {
sum = binary[ibit] + carry;
carry = 0;
if (sum == 1) binary[ibit] = 1;
else if (sum == 2) {
binary[ibit] = 0;
carry = 1;
}
numon += binary[ibit];
}
if (numon == absdx) {
++ntotal;
x = 0;
y = 0;
viable = 1;
for (ibit=1; ibit<ndigits; ++ibit) {
if (binary[ibit]) ++x;
else ++y;
ibin = x * (absdy+1) + y;
kndex = location[ibin];
path[ibit] = ibin;
if (dir[kndex]) {
if (dir[kndex]->clr != dir[index]->clr) viable = 0;
}
}
if (viable) {
++nways;
for (ibit=1; ibit<ndigits; ++ibit) ++hits[path[ibit]];
for (ibit=1; ibit<ndigits; ++ibit) path[ibit] = location[path[ibit]];
nocc = 0;
dprob = 1.0;
for (ibit=1; ibit<ndigits; ++ibit) {
kndex = path[ibit];
prio = 0.5;
if (dir[kndex]) {
if (dir[kndex]->clr == dir[index]->clr) {
++nocc;
prio = 1.0;
}
}
dprob *= prio;
}
sumprob += dprob;
joined = (nocc == (ndigits-1));
if (col80) {
for (ibit=1; ibit<ndigits; ++ibit) curon(path[ibit]);
hundelay(timer);
for (ibit=1; ibit<ndigits; ++ibit) curof(path[ibit]);
}
}
}
} while (!carry && !joined);
if (!nways) return(sumprob);
if (joined) {
sumprob = 1.0;
return(sumprob);
}
max = 0;
for (x=0; x<=absdx; ++x) {
for (y=0; y<=absdy; ++y) {
ibin = x * (absdy+1) + y;
num = hits[ibin];
kndex = location[ibin];
if (!dir[kndex]) {
if (num > max) max = num;
}
}
}
if (max) {
for (x=0; x<=absdx; ++x) {
for (y=0; y<=absdy; ++y) {
ibin = x * (absdy+1) + y;
num = hits[ibin];
kndex = location[ibin];
if (!dir[kndex]) {
if (num == max) {
candidates = xtlocate(kndex, candidates);
candidates = xtinsert(kndex, candidates);
}
}
}
}
}
}
/*
if ((dist <= cutoff) && (dist >= 4)) {
canjoin = join(index, jndex, candidates, 0);
if (canjoin) area = nbins;
}
*/
return(sumprob);
}
double cond(index, jndex, candidates) /* for joining */
unsigned index; /* must exist on board */
unsigned jndex; /* also must exist on board */
unsigned candidates;
{
int area;
int joined, canjoin, blocked;
int x, y, ix, iy, jx, jy, dx, dy, absdx, absdy, xa, ya, xb, yb;
int ndigits, ibit, nbins, ibin, sum, carry, numon;
int kx, ky, viable;
unsigned kndex, max, min, num, nways, ntotal, nocc, jis, jjs;
double sumprob, prio, pmax, probi, probj;
unsigned unprob, candis, candip;
int dist, mt, cutoff;
dist = manhat(index, jndex);
sumprob = 1.0;
if (dist == 1) return(sumprob);
sumprob = 0.0;
if (dist > xdist/2) return(sumprob);
candis = xtinsert(0, 0);
candip = candis;
xy(index, &ix, &iy);
xy(jndex, &jx, &jy);
dx = jx - ix;
dy = jy - iy;
if (dx < 0) absdx = -dx;
else absdx = dx;
if (dy < 0) absdy = -dy;
else absdy = dy;
/* ndigits = absdx + absdy;*/
/*nbins = (absdx + 1) * (absdy + 1);*/
xa = 0;
xb = absdx;
ya = 0;
yb = absdy;
if (absdx < absdy) {
if (xa > 0) --xa;
if (xb < nsize) ++xb;
}
if (absdy < absdx) {
if (xa > 0) --ya;
if (yb < nsize) ++yb;
}
max = 0;
for (x=xa; x<=xb; ++x) {
for (y=ya; y<=yb; ++y) {
if (dx < 0) kx = ix - x;
else kx = ix + x;
if (dy < 0) ky = iy - y;
else ky = iy + y;
kndex = fxy(kx, ky);
if ((kndex != index) && (kndex != jndex)) {
if (!dir[kndex]) {
if (manhat(index, kndex) < dist) {
if (manhat(jndex, kndex) < dist) {
jis = xtinsert(0, 0);
jjs = xtinsert(0 ,0);
probi = prob(index, kndex, jis);
probj = prob(jndex, kndex, jjs);
sumprob = probi * probj;
if (col80) {
newline();
coords(kndex);
printf(" %f %f %f", probi, probj, sumprob);
}
xtfreelist(jjs);
xtfreelist(jis);
unprob = sumprob * 30000.0;
candip = xtlocate(kndex, candip);
candip = xtinsert(kndex, candip);
poke(candip, LEVEL, unprob);
if (unprob > max) {
max = unprob;
}
}
}
}
}
}
}
candip = peek(candis, NEXTL);
sumprob = max;
sumprob /= 30000.0;
if (candip && max) {
do {
kndex = peek(candip, LOC);
unprob = peek(candip, LEVEL);
if (unprob == max) {
candidates = xtlocate(kndex, candidates);
candidates = xtinsert(kndex, candidates);
}
candip = peek(candip, NEXTL);
} while (candip);
}
xtfreelist(candis);
return(sumprob);
}
int loser(unsigned index)
{
int crummo;
int valid;
unsigned killer;
crummo = 0;
/*if (binside[index] || winside[index]) crummo = 1;*/
if (!crummo) {
crummo = 1;
valid = doit(index);
if (valid) {
crummo = qkill(index);
/*if (!crummo) crummo = fourex(index);*/
index = undoit();
}
}
if (!crummo) {
doit(0);
crummo = 1;
valid = doit(index);
if (valid) {
/*++maxhead;*/
crummo = qkill(index);
/*--maxhead;*/
index = undoit();
}
undoit();
}
return(crummo);
}
unsigned gotejnlf()
{
unsigned index;
unsigned opdex, jndex, kndex, lndex;
unsigned newies, oldies, newp, oldp;
unsigned joiners, joinerp;
int z, dist, min, gotta, valid;
blurb(" gotejnlf");
index = 0;
opdex = movep->midx;
if (!opdex) return(index);
oldies = xtinsert(0, 0);
for (z=2; z<=8; ++z) {
if (col80) {
newline();
printf(" z=%d", z);
}
newies = xtinsert(0, 0);
ring(opdex, z, newies);
/* first check for gottajoins between newies and oldies */
newp = peek(newies, NEXTL);
if (newp && !index) {
do {
jndex = peek(newp, LOC);
if (dir[jndex]) {
if (dir[jndex]->clr == colour) {
oldp = peek(oldies, NEXTL);
if (oldp) {
do {
kndex = peek(oldp, LOC);
if (dir[kndex]->clr == colour) {
joiners = xtinsert(0, 0);
gotta = gottajoin(jndex, kndex, joiners);
if(col80) {
newline();
printf(" gottajoin:%d", gotta);
coords(jndex);
coords(kndex);
}
if (dir[jndex]->reallive && dir[kndex]->reallive) gotta = 0;
if (!dir[jndex]->reallive && !dir[kndex]->reallive) gotta = 0;
if (gotta) {
/* select joiner closest to enemy (ok to enemy's last stone) */
joinerp = peek(joiners, NEXTL);
if (joinerp) {
min = 100;
do {
lndex = peek(joinerp, LOC);
if (!loser(lndex)) {
dist = howfar(lndex, opdex);
if (dist < min) {
min = dist;
index = lndex;
}
}
joinerp = peek(joinerp, NEXTL);
} while (joinerp);
}
}
xtfreelist(joiners);
}
oldp = peek(oldp, NEXTL);
} while (oldp && !index);
}
}
}
newp = peek(newp, NEXTL);
} while (newp && !index);
}
/* then check for gottajoins between newies and newies */
newp = peek(newies, NEXTL);
if (newp && !index) {
do {
jndex = peek(newp, LOC);
if (jndex) {
if (dir[jndex]->clr == colour) {
oldp = peek(newp, NEXTL);
if (oldp) {
do {
kndex = peek(oldp, LOC);
if (dir[kndex]->clr == colour) {
joiners = xtinsert(0, 0);
gotta = gottajoin(jndex, kndex, joiners);
if (col80) {
newline();
printf(" gottajoin:%d", gotta);
coords(jndex);
coords(kndex);
}
if (dir[jndex]->reallive && dir[kndex]->reallive) gotta = 0;
if (!dir[jndex]->reallive && !dir[kndex]->reallive) gotta = 0;
if (gotta) {
/* select joiner closest to enemy (ok to enemy's last stone) */
joinerp = peek(joiners, NEXTL);
if (joinerp) {
min = 100;
do {
lndex = peek(joinerp, LOC);
if (!loser(lndex)) {
dist = howfar(lndex, opdex);
if (dist < min) {
min = dist;
index = lndex;
}
}
joinerp = peek(joinerp, NEXTL);
} while (joinerp);
}
}
xtfreelist(joiners);
}
oldp = peek(oldp, NEXTL);
} while (oldp && !index);
}
}
}
newp = peek(newp, NEXTL);
} while (newp && !index);
/* merge newies with oldies */
oldp = oldies;
newp = peek(newies, NEXTL);
do {
jndex = peek(newp, LOC);
oldp = xtlocate(jndex, oldp);
oldp = xtinsert(jndex, oldp);
newp = peek(newp, NEXTL);
} while (newp);
}
xtfreelist(newies);
}
xtfreelist(oldies);
return(index);
}
unsigned gotejoin()
{
unsigned index;
unsigned opdex, jndex, kndex, lndex;
unsigned newies, oldies, newp, oldp;
unsigned joiners, joinerp;
int z, dist, min, gotta, valid;
blurb(" gotejoin");
index = 0;
opdex = movep->midx;
if (!opdex) return(index);
oldies = xtinsert(0, 0);
for (z=2; z<=8; ++z) {
if (col80) {
newline();
printf(" z=%d", z);
}
newies = xtinsert(0, 0);
ring(opdex, z, newies);
/* first check for gottajoins between newies and oldies */
newp = peek(newies, NEXTL);
if (newp && !index) {
do {
jndex = peek(newp, LOC);
if (dir[jndex]) {
if (dir[jndex]->clr == colour) {
oldp = peek(oldies, NEXTL);
if (oldp) {
do {
kndex = peek(oldp, LOC);
if (dir[kndex]->clr == colour) {
joiners = xtinsert(0, 0);
gotta = gottajoin(jndex, kndex, joiners);
if(col80) {
newline();
printf(" gottajoin:%d", gotta);
coords(jndex);
coords(kndex);
}
if ((partinfo[gloparts[jndex]&255]&2) && (partinfo[gloparts[kndex]&255]&2)) gotta = 0;
if (!(partinfo[gloparts[jndex]&255]&2) && !(partinfo[gloparts[kndex]&255]&2)) gotta = 0;
if (gotta) {
/* select joiner closest to enemy (ok to enemy's last stone) */
joinerp = peek(joiners, NEXTL);
if (joinerp) {
min = 100;
do {
lndex = peek(joinerp, LOC);
if (!loser(lndex)) {
dist = howfar(lndex, opdex);
if (dist < min) {
min = dist;
index = lndex;
}
}
joinerp = peek(joinerp, NEXTL);
} while (joinerp);
}
}
xtfreelist(joiners);
}
oldp = peek(oldp, NEXTL);
} while (oldp && !index);
}
}
}
newp = peek(newp, NEXTL);
} while (newp && !index);
}
/* then check for gottajoins between newies and newies */
newp = peek(newies, NEXTL);
if (newp && !index) {
do {
jndex = peek(newp, LOC);
if (jndex) {
if (dir[jndex]->clr == colour) {
oldp = peek(newp, NEXTL);
if (oldp) {
do {
kndex = peek(oldp, LOC);
if (dir[kndex]->clr == colour) {
joiners = xtinsert(0, 0);
gotta = gottajoin(jndex, kndex, joiners);
if (col80) {
newline();
printf(" gottajoin:%d", gotta);
coords(jndex);
coords(kndex);
}
if ((partinfo[gloparts[jndex]&255]&2) && (partinfo[gloparts[kndex]&255]&2)) gotta = 0;
if (!(partinfo[gloparts[jndex]&255]&2) && !(partinfo[gloparts[kndex]&255]&2)) gotta = 0;
if (gotta) {
/* select joiner closest to enemy (ok to enemy's last stone) */
joinerp = peek(joiners, NEXTL);
if (joinerp) {
min = 100;
do {
lndex = peek(joinerp, LOC);
if (!loser(lndex)) {
dist = howfar(lndex, opdex);
if (dist < min) {
min = dist;
index = lndex;
}
}
joinerp = peek(joinerp, NEXTL);
} while (joinerp);
}
}
xtfreelist(joiners);
}
oldp = peek(oldp, NEXTL);
} while (oldp && !index);
}
}
}
newp = peek(newp, NEXTL);
} while (newp && !index);
/* merge newies with oldies */
oldp = oldies;
newp = peek(newies, NEXTL);
do {
jndex = peek(newp, LOC);
oldp = xtlocate(jndex, oldp);
oldp = xtinsert(jndex, oldp);
newp = peek(newp, NEXTL);
} while (newp);
}
xtfreelist(newies);
}
xtfreelist(oldies);
return(index);
}
/*
int gottajoin(index, jndex, joiners)
unsigned index, jndex, joiners;
{
int gotta, canjoin, dist;
unsigned js;
gotta = 0;
dist = howfar(index, jndex);
if (dist > 7) return(gotta);
js = xtinsert(0, 0);
canjoin = join(index, jndex, js, 1);
xtfreelist(js);
if (canjoin) {
doit(0);
js = xtinsert(0, 0);
gotta = block(index, jndex, js, 1);
xtfreelist(js);
undoit();
}
if (gotta) {
canjoin = join(index, jndex, joiners, 0);
}
return(gotta);
}
*/
int gottajoin(index, jndex, joiners)
unsigned index, jndex, joiners;
{
int gotta, canjoin, dist;
unsigned js, bs;
double pr, cpr;
gotta = 0;
dist = howfar(index, jndex);
if (dist > 7) return(gotta);
if (dist > 5) {
js = xtinsert(0, 0);
pr = prob(index, jndex, js);
xtfreelist(js);
if ((pr > 0.20) && (pr < 1.0)) gotta = 1;
}
else {
js = xtinsert(0, 0);
canjoin = join(index, jndex, js, 1);
xtfreelist(js);
if (canjoin) {
doit(0);
bs = xtinsert(0, 0);
gotta = block(index, jndex, bs, 1);
xtfreelist(bs);
undoit();
}
}
if (gotta) {
/*cpr =*/ cond(index, jndex, joiners);
}
return(gotta);
}
unsigned goteblock()
{
unsigned index;
unsigned opdex, jndex, kndex, lndex;
unsigned newies, oldies, newp, oldp;
unsigned blockers, blockerp;
int z, dist, min, gotta, valid;
blurb(" goteblock");
index = 0;
opdex = movep->midx;
if (!opdex) return(index);
for (z=3; z<=4; ++z) {
if (col80) {
newline();
printf(" z=%d", z);
}
newies = xtinsert(0, 0);
ring(opdex, z, newies);
/* check for gottablocks between opdex and newies */
newp = peek(newies, NEXTL);
if (newp && !index) {
do {
jndex = peek(newp, LOC);
if (dir[jndex]) {
if (dir[jndex]->clr != colour) {
blockers = xtinsert(0, 0);
gotta = gottablock(jndex, opdex, blockers);
if (col80) {
newline();
printf(" gottablock:%d", gotta);
coords(jndex);
coords(opdex);
}
if (gotta) {
/* select blocker closest to enemy (ok to enemy's last stone) */
blockerp = peek(blockers, NEXTL);
if (blockerp) {
min = 100;
do {
lndex = peek(blockerp, LOC);
if (!loser(lndex)) {
dist = howfar(lndex, opdex);
if (dist < min) {
min = dist;
index = lndex;
}
}
blockerp = peek(blockerp, NEXTL);
} while (blockerp);
}
}
xtfreelist(blockers);
}
}
newp = peek(newp, NEXTL);
} while (newp && !index);
}
xtfreelist(newies);
}
return(index);
}
int gottablock(index, jndex, blockers)
unsigned index, jndex, blockers;
{
int gotta, canblock, dist;
unsigned js;
double pr, cpr;
gotta = 0;
dist = howfar(index, jndex);
if (dist > 7) return(gotta);
js = xtinsert(0, 0);
pr = prob(index, jndex, js);
xtfreelist(js);
if ((pr > 0.20) && (pr < 1.0)) gotta = 1;
if (gotta) {
/*cpr =*/ prob(index, jndex, blockers);
}
return(gotta);
}
unsigned connect()
{
unsigned index;
unsigned jndex, kndex, lndex, dist;
unsigned whose, ruts, rutp, rutq, accounts, accountp, jbs, jbp;
struct link *rootlp, *stonep;
struct root *rootp;
struct link *stoneq;
struct root *rootq;
unsigned min, max, mindex, mjndex, swapo, z;
unsigned killer;
int area, valid, cankill;
index = 0;
accounts = xtinsert(0, 0);
ruts = xtinsert(0, 0);
rutp = ruts;
rootlp = rootlist->nextl;
do {
rootp = rootlp->loc;
jndex = rootp->ridx;
rutp = xtlocate(jndex, rutp);
rutp = xtinsert(jndex, rutp);
rootlp = rootlp->nextl;
} while (rootlp);
for (whose=BLK; whose<=WHT; ++whose) {
swapo = 0;
if (colour != whose) swapo = 1;
/*if ((((kount/2)/2)*2) == (kount/2)) { /* switch join/block */*/
if (swapo) doit(0);
rutp = peek(ruts, NEXTL);
if (rutp) {
do {
jndex = peek(rutp, LOC);
rootp = dir[jndex];
if (rootp->clr == whose) {
stonep = rootp->neighbs->nextl;
do {
kndex = stonep->loc;
rutq = peek(rutp, NEXTL);
if (rutq) {
min = 100;
mindex = 0;
mjndex = 0;
do {
jndex = peek(rutq, LOC);
rootq = dir[jndex];
if (rootq->clr == whose) {
stoneq = rootq->neighbs->nextl;
do {
lndex = stoneq->loc;
dist = howfar(lndex, kndex);
if (dist < min) {
min = dist;
mindex = kndex;
mjndex = lndex;
}
stoneq = stoneq->nextl;
} while (stoneq);
}
rutq = peek(rutq, NEXTL);
} while (rutq);
if (mindex && mjndex) {
if (howfar(mindex, mjndex) > 3) {
jbs = xtinsert(0, 0);
area = probjoin(mindex, mjndex, jbs, 0);
if (area) {
credit(area, accounts, jbs);
}
xtfreelist(jbs);
}
}
}
stonep = stonep->nextl;
} while (stonep);
}
rutp = peek(rutp, NEXTL);
} while (rutp);
}
if (swapo) undoit();
/*}*/
}
accountp = peek(accounts, NEXTL);
if (accountp) {
max = 0;
do {
kndex = peek(accountp, LOC);
valid = doit(kndex);
if (valid) {
cankill = qkill(kndex);
if (!cankill) {
area = peek(accountp, LEVEL);
if (area > max) {
max = area;
}
}
else poke(accountp, LEVEL, 0);
kndex = undoit();
}
else poke(accountp, LEVEL, 0);
accountp = peek(accountp, NEXTL);
} while (accountp);
/* select one closest to opponent's last move */
min = 100;
lndex = movep->midx;
if (max && lndex) {
accountp = peek(accounts, NEXTL);
do {
kndex = peek(accountp, LOC);
area = peek(accountp, LEVEL);
if (area == max) {
z = howfar(kndex, lndex);
if (z < min) index = kndex;
}
accountp = peek(accountp, NEXTL);
} while (accountp);
}
}
xtfreelist(ruts);
xtfreelist(accounts);
if (index && col80) {
newline();
printf(" connector area:%d ", max);
coords(index);
}
return(index);
}
void midway