Diffstat (limited to 'noncore/games/go/goplayutils.c') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/games/go/goplayutils.c | 1317 |
1 files changed, 1317 insertions, 0 deletions
diff --git a/noncore/games/go/goplayutils.c b/noncore/games/go/goplayutils.c new file mode 100644 index 0000000..9e2ce4c --- a/dev/null +++ b/noncore/games/go/goplayutils.c @@ -0,0 +1,1317 @@ +/* The go player utilities */ +/* Ported from Pascal to C by Todd R. Johnson */ +/* From the original Pascal file: +Copyright (c) 1983 by Three Rivers Computer Corp. + +Written: January 17, 1983 by Stoney Ballard +*/ + +#include "goplayutils.h" +#include "amigo.h" +#include "go.h" + +extern struct bRec goboard[19][19]; + +intBoard claim, extra, bord, ndbord, sGroups, threatBord, + groupIDs, connectMap, protPoints; +boolBoard groupSeen, legal; +short maxGroupID; +pointList pList, pList1, plist2, plist3, pPlist; +intList nlcGroup, aList; +sgRec sList[401]; +groupRec gList[maxGroup]; +short killFlag, + numCapt, + utilPlayLevel, + treeLibLim; +sType mySType; +short showTrees; +short sGlist[maxGroup+1]; +short depthLimit; +intBoard markBoard; +short marker; + +short adjInAtari, adj2Libs, + intersectNum, spanNum, libMark; +playRec playStack[1025]; +short playMark, + newGID, + tryLevel, + grpMark, + gMap[maxGroup]; +short dbStop, inGenState; + + pause() +{ /* pause */ +/* if (dbStop and ! inGenState) + { + while ! tabswitch do; + repeat + if (tabYellow) + dbStop = false; + until ! tabswitch; + } */ +} /* pause */ + +sstone(w, x, y, numb) +short w, x, y, numb; +{ /* sstone */ + if (w == 1) + placestone(mySType, x, y); + else if (mySType == WHITE) + placestone(BLACK, x, y); + else + placestone(WHITE, x, y); +} /* sstone */ + +rstone(x, y) +short x, y; +{ /* rstone */ + removestone(x, y); +} /* rstone */ + +initBoolBoard(bb) +boolBoard bb; +{ /* initBoolBoard */ + short i, j; +#ifdef DEBUG + printf( "initBoolBoard\n" ); +#endif + for (i = 0; i <= maxPoint; i++) + for (j = 0; j <= maxPoint; j++) + bb[i][j] = FALSE; +} /* initBoolBoard */ + +sortLibs() +{ /* sortLibs */ + short i, j, t; +#ifdef DEBUG + printf( "sortLibs\n" ); +#endif + for (i = 1; i <= maxGroupID; i++) + sGlist[i] = i; + for (i = 1; i < maxGroupID; i++) + for (j = i + 1; j <= maxGroupID; j++) + if (gList[sGlist[i]].libC > gList[sGlist[j]].libC) + { + t = sGlist[i]; + sGlist[i] = sGlist[j]; + sGlist[j] = t; + } +} /* sortLibs */ + +spanGroupspan(x, y, libs, lookFor) +short x, y, lookFor; +pointList *libs; + { /* span */ + markBoard[x][y] = marker; + if (bord[x][y] == 0) + { + libs->indx = libs->indx + 1; + libs->p[libs->indx].px = x; + libs->p[libs->indx].py = y; + } + else if (bord[x][y] == lookFor) + { + groupSeen[x][y] = TRUE; + if ((x > 0) && (markBoard[x - 1][y] != marker)) + spanGroupspan(x - 1, y, libs, lookFor); + if ((y > 0) && (markBoard[x][y - 1] != marker)) + spanGroupspan(x, y - 1, libs, lookFor); + if ((x < maxPoint) && (markBoard[x + 1][y] != marker)) + spanGroupspan(x + 1, y, libs, lookFor); + if ((y < maxPoint) && (markBoard[x][y + 1] != marker)) + spanGroupspan(x, y + 1, libs, lookFor); + } + else if (gList[gMap[groupIDs[x][y]]].libC == 1) + adjInAtari = TRUE; + else if ((gList[gMap[groupIDs[x][y]]].libC == 2) && + (! gList[gMap[groupIDs[x][y]]].isLive)) + adj2Libs = TRUE; + } /* span */ + +spanGroup(x, y, libs) +short x, y; +pointList *libs; +{ /* spanGroup */ + short lookFor; +#ifdef DEBUG + printf( "spanGroup\n" ); +#endif + marker = marker + 1; + if (marker == 0) + { + initArray(markBoard); + marker = 1; + } + adjInAtari = FALSE; + adj2Libs = FALSE; + lookFor = bord[x][y]; + libs->indx = 0; + spanGroupspan(x, y, libs, lookFor); +} /* spanGroup */ + +sSpanGroupspan(x, y, libs, lookFor) +short x, y, lookFor; +sPointList *libs; + { /* span */ + markBoard[x][y] = marker; + if (bord[x][y] == 0) + { + libs->indx += 1; + if (libs->indx <= maxSPoint) + { + libs->p[libs->indx].px = x; + libs->p[libs->indx].py = y; + } + } + else if (bord[x][y] == lookFor) + { + groupSeen[x][y] = TRUE; + if ((x > 0) && (markBoard[x - 1][y] != marker)) + sSpanGroupspan(x - 1, y, libs, lookFor); + if ((y > 0) && (markBoard[x][y - 1] != marker)) + sSpanGroupspan(x, y - 1, libs, lookFor); + if ((x < maxPoint) && (markBoard[x + 1][y] != marker)) + sSpanGroupspan(x + 1, y, libs, lookFor); + if ((y < maxPoint) && (markBoard[x][y + 1] != marker)) + sSpanGroupspan(x, y + 1, libs, lookFor); + } + else if (gList[gMap[groupIDs[x][y]]].libC == 1) + adjInAtari = TRUE; + else if ((gList[gMap[groupIDs[x][y]]].libC == 2) && + (! gList[gMap[groupIDs[x][y]]].isLive)) + adj2Libs = TRUE; + } /* span */ + +sSpanGroup(x, y, libs) +short x, y; +sPointList *libs; +{ /* sSpanGroup */ + short lookFor; +#ifdef DEBUG + printf( "sSpanGroup\n" ); +#endif + marker = marker + 1; + if (marker == 0) + { + initArray(markBoard); + marker = 1; + } + adjInAtari = FALSE; + adj2Libs = FALSE; + lookFor = bord[x][y]; + libs->indx = 0; + sSpanGroupspan(x, y, libs, lookFor); +} /* sSpanGroup */ + +LAspan(x, y, me, him, iL) +short x, y, me, him; +intList *iL; + { /* span */ +#ifdef DEBUG + printf( "LAspan\n" ); +#endif + markBoard[x][y] = marker; + if (bord[x][y] == me) + { + if ((x > 0) && (markBoard[x - 1][y] != marker)) + LAspan(x - 1, y, me, him, iL); + if ((x < maxPoint) && (markBoard[x + 1][y] != marker)) + LAspan(x + 1, y, me, him, iL); + if ((y > 0) && (markBoard[x][y - 1] != marker)) + LAspan(x, y - 1, me, him, iL); + if ((y < maxPoint) && (markBoard[x][y + 1] != marker)) + LAspan(x, y + 1, me, him, iL); + } + else if (bord[x][y] == him) + if (gList[gMap[groupIDs[x][y]]].groupMark != grpMark) + { + gList[gMap[groupIDs[x][y]]].groupMark = grpMark; + iL->indx = iL->indx + 1; + iL->v[iL->indx] = gMap[groupIDs[x][y]]; + } + } /* span */ + +listAdjacents(x, y, iL) +short x, y; +intList *iL; +{ /* listAdjacents */ + short me, him; +#ifdef DEBUG + printf( "listAdjacents\n" ); +#endif + grpMark = grpMark + 1; + marker = marker + 1; + if (marker == 0) + { + initArray(markBoard); + marker = 1; + } + iL->indx = 0; + me = bord[x][y]; + him = -me; + LAspan(x, y, me , him, iL); +} /* listAdjacents */ + +LDspan(x, y, me, diags) +short x, y, me; +sPointList *diags; + { /* span */ +#ifdef DEBUG + printf( "LDspan\n" ); +#endif + markBoard[x][y] = marker; + if ((x > 0) && (y > 0) && + (bord[x - 1][y - 1] == 0) && + (bord[x][y - 1] != me) && + (bord[x - 1][y] != me) && + (markBoard[x - 1][y - 1] != marker)) + { + markBoard[x - 1][y - 1] = marker; + diags->indx = diags->indx + 1; + if (diags->indx <= maxSPoint) + { + diags->p[diags->indx].px = x - 1; + diags->p[diags->indx].py = y - 1; + } + } + if ((x < maxPoint) && (y > 0) && + (bord[x + 1][y - 1] == 0) && + (bord[x][y - 1] != me) && + (bord[x + 1][y] != me) && + (markBoard[x + 1][y - 1] != marker)) + { + markBoard[x + 1][y - 1] = marker; + diags->indx = diags->indx + 1; + if (diags->indx <= maxSPoint) + { + diags->p[diags->indx].px = x + 1; + diags->p[diags->indx].py = y - 1; + } + } + if ((x > 0) && (y < maxPoint) && + (bord[x - 1][y + 1] == 0) && + (bord[x][y + 1] != me) && + (bord[x - 1][y] != me) && + (markBoard[x - 1][y + 1] != marker)) + { + markBoard[x - 1][y + 1] = marker; + diags->indx = diags->indx + 1; + if (diags->indx <= maxSPoint) + { + diags->p[diags->indx].px = x - 1; + diags->p[diags->indx].py = y + 1; + } + } + if ((x < maxPoint) && (y < maxPoint) && + (bord[x + 1][y + 1] == 0) && + (bord[x][y + 1] != me) && + (bord[x + 1][y] != me) && + (markBoard[x + 1][y + 1] != marker)) + { + markBoard[x + 1][y + 1] = marker; + diags->indx = diags->indx + 1; + if (diags->indx <= maxSPoint) + { + diags->p[diags->indx].px = x + 1; + diags->p[diags->indx].py = y + 1; + } + } + if ((x > 0) && (bord[x - 1][y] == me) && + (markBoard[x - 1][y] != marker)) + LDspan(x - 1, y, me, diags); + if ((x < maxPoint) && (bord[x + 1][y] == me) && + (markBoard[x + 1][y] != marker)) + LDspan(x + 1, y, me, diags); + if ((y > 0) && (bord[x][y - 1] == me) && + (markBoard[x][y - 1] != marker)) + LDspan(x, y - 1, me, diags); + if ((y < maxPoint) && (bord[x][y + 1] == me) && + (markBoard[x][y + 1] != marker)) + LDspan(x, y + 1, me , diags); +} /* span */ + +listDiags(x, y, diags) +short x, y; +sPointList *diags; +{ /* listDiags */ + short me; +#ifdef DEBUG + printf( "listDiags\n" ); +#endif + me = bord[x][y]; + diags->indx = 0; + marker = marker + 1; + if (marker == 0) + { + initArray(markBoard); + marker = 1; + } + LDspan(x, y, me, diags); +} /* listDiags */ + +intersectPlist(p1, p2, pr) +pointList *p1, *p2, *pr; +{ /* intersectPlist */ + short i, j, k; +#ifdef DEBUG + printf( "intersectPlist\n" ); +#endif + marker = marker + 1; + if (marker == 0) + { + initArray(markBoard); + marker = 1; + } + pr->indx = 0; + for (i = 1; i <= p1->indx; i++) + markBoard[p1->p[i].px][p1->p[i].py] = marker; + j = 0; + for (i = 1; i <= p2->indx; i++) + if (markBoard[p2->p[i].px][p2->p[i].py] == marker) + { + j = j + 1; + pr->p[j] = p2->p[i]; + } + pr->indx = j; +} /* intersectPlist */ + +initArray(ary) +intBoard ary; +{ /* initArray */ + short i, j; + for (i = 0; i <= maxPoint; i++) + for (j = 0; j <= maxPoint; j++) + ary[i][j] = 0; +} /* initArray */ + +initState() +{ /* initState */ + short i, j; + for (i = 0; i <= maxPoint; i++) + for (j = 0; j <= maxPoint; j++) + { + extra[i][j] = 0; + claim[i][j] = 0; + groupIDs[i][j] = 0; + connectMap[i][j] = 0; + protPoints[i][j] = 0; + } +} /* initState */ + +copyArray( dest, src ) +intBoard dest, src; +{ + short x, y; + for (y = 0; y <= maxPoint; y++) + for (x = 0; x <= maxPoint; x++) + dest[x][y] = src[x][y]; +} + +/* + generates a one-point spread in the force field array (claim) + + the spread from a single point after four calls is: + + 1 + 2 2 2 + 2 4 6 4 2 + 2 4 8 10 8 4 2 + 1 2 6 10 62 10 6 2 1 + 2 4 8 10 8 4 2 + 2 4 6 4 2 + 2 2 2 + 1 + +*/ +stake() +{ + short x, y; + initArray( extra ); + for (y = 0; y <= maxPoint; y++) + for (x = 0; x <= maxPoint; x++) + { + extra[x][y] = extra[x][y] + claim[x][y]; + if (claim[x][y] > 0) + { + if (x > 0) extra[x-1][y] += 1; + if (y > 0) extra[x][y-1] += 1; + if (x < maxPoint) extra[x+1][y] += 1; + if (y < maxPoint) extra[x][y+1] += 1; + } + else if (claim[x][y] < 0) + { + if (x > 0) extra[x-1][y] -= 1; + if (y > 0) extra[x][y-1] -= 1; + if (x < maxPoint) extra[x+1][y] -= 1; + if (y < maxPoint) extra[x][y+1] -= 1; + } + } + copyArray( claim, extra ); +} /* stake */ + +/* + sets up claim from the current board position +*/ +spread() +{ + short x, y; + for (y = 0; y <= maxPoint; y++) + for (x = 0; x <= maxPoint; x++) + claim[x][y] = ndbord[x][y] * 50; + stake(); + stake(); + stake(); + stake(); +} /* spread */ + +/* + gList is initialized with the size, loc, and libCount of each group + groupIDs contains the serial numbers of the groups. +*/ +Resspan(x, y, gID, gSize, libCount, who) +short x, y, gID, *gSize, *libCount, who; + { /* span */ + if ((bord[x][y] == 0) && + (markBoard[x][y] != marker)) /* a liberty */ + { + markBoard[x][y] = marker; + *libCount = *libCount + 1; + } + else if ((bord[x][y] == who) && + (groupIDs[x][y] == 0)) + { + groupIDs[x][y] = gID; + *gSize = *gSize + 1; + if (x > 0) + Resspan(x - 1, y, gID, gSize, libCount, who); + if (x < maxPoint) + Resspan(x + 1, y, gID, gSize, libCount, who); + if (y > 0) + Resspan(x, y - 1, gID, gSize, libCount, who); + if (y < maxPoint) + Resspan(x, y + 1, gID, gSize, libCount, who); + } + } /* span */ + +respreicen() +{ /* respreicen */ + short i, j, gID, libCount, gSize, who; + gID = 0; +#ifdef DEBUG + printf( "respreicen\n" ); +#endif + for (i = 0; i <= maxPoint; i++) + for (j = 0; j <= maxPoint; j++) + groupIDs[i][j] = 0; + for (i = 0; i <= maxPoint; i++) + for (j = 0; j <= maxPoint; j++) + if ((bord[i][j] != 0) && /* a stone there */ + (groupIDs[i][j] == 0)) /* not seen yet */ + { + marker = marker + 1; + if (marker == 0) + { + initArray(markBoard); + marker = 1; + } + gID = gID + 1; + libCount = 0; + gSize = 0; + who = bord[i][j]; + Resspan(i, j, gID, &gSize, &libCount, who); /* span the group, collecting info */ + gList[gID].groupMark = 0; + gList[gID].atLevel = 0; + gList[gID].isLive = FALSE; /* we don't know yet */ + gList[gID].isDead = FALSE; + gList[gID].numEyes = -1; + gList[gID].size = gSize; + gList[gID].libC = libCount; + gList[gID].lx = i; + gList[gID].ly = j; + gMap[gID] = gID; /* set up identity map */ + } + maxGroupID = gID; + newGID = gID; + grpMark = 0; +} /* respreicen */ + +/* + play z at [x, y]. + killFlag is set true if anything is killed. +*/ +killGroup(x, y, me, him) +short x, y, me, him; + { /* killGroup */ +#ifdef DEBUG + printf( "killGroup\n" ); +#endif + playMark = playMark + 1; + /* record this kill */ + playStack[playMark].kind = rem; + playStack[playMark].uval.rem.who = him; + playStack[playMark].uval.rem.xl = x; + playStack[playMark].uval.rem.yl = y; + playStack[playMark].gID = groupIDs[x][y]; + playStack[playMark].uval.rem.sNumber = goboard[x][y].mNum; + if (showTrees) + rstone(x, y); + numCapt = numCapt + 1; + bord[x][y] = 0; + groupIDs[x][y] = 0; + if (x > 0) + { + if (bord[x - 1][y] == me) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]]; + } + else if (bord[x - 1][y] == him) + killGroup(x - 1, y, me , him); + } + if (x < maxPoint) + { + if (bord[x + 1][y] == me) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]]; + } + else if (bord[x + 1][y] == him) + killGroup(x + 1, y, me, him); + } + if (y > 0) + { + if (bord[x][y - 1] == me) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]]; + } + else if (bord[x][y - 1] == him) + killGroup(x, y - 1, me, him); + } + if (y < maxPoint) + { + if (bord[x][y + 1] == me) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]]; + } + else if (bord[x][y + 1] == him) + killGroup(x, y + 1, me, him); + } + } /* killGroup */ + +mergeGroup(sGID, myGID) +short sGID, myGID; + { /* mergeGroup */ + short i; +#ifdef DEBUG + printf( "mergeGroup\n" ); +#endif + for (i = 1; i <= newGID; i++) + if (gMap[i] == sGID) + { + playMark = playMark + 1; + playStack[playMark].kind = reMap; + playStack[playMark].gID = i; + playStack[playMark].uval.reMap.oldGID = sGID; + gMap[i] = myGID; + } + } /* mergeGroup */ + +tryPlay(x, y, z) +short x, y, z; +{ /* plei */ + short i, me, him, myGID; + short isNew; +#ifdef DEBUG + printf( "tryPlay\n" ); +#endif + me = z; + him = -me; + killFlag = FALSE; /* set true if something is killed */ + numCapt = 0; + tryLevel = tryLevel + 1; + isNew = FALSE; + bord[x][y] = z; /* play the stone */ + if ((x > 0) && (bord[x - 1][y] == me)) /* connect to adjacent group */ + myGID = gMap[groupIDs[x - 1][y]]; + else if ((x < maxPoint) && (bord[x + 1][y] == me)) + myGID = gMap[groupIDs[x + 1][y]]; + else if ((y > 0) && (bord[x][y - 1] == me)) + myGID = gMap[groupIDs[x][y - 1]]; + else if ((y < maxPoint) && (bord[x][y + 1] == me)) + myGID = gMap[groupIDs[x][y + 1]]; + else /* nobody to connect to */ + { + newGID = newGID + 1; + isNew = TRUE; + myGID = newGID; + gList[myGID].groupMark = 0; + gList[myGID].atLevel = tryLevel; + gList[myGID].isLive = FALSE; + gList[myGID].numEyes = -1; + gList[myGID].size = -1; + gList[myGID].lx = x; + gList[myGID].ly = y; + gMap[myGID] = myGID; + } + groupIDs[x][y] = myGID; + playMark = playMark + 1; + /* record this move */ + playStack[playMark].kind = add; + playStack[playMark].uval.add.who = me; + playStack[playMark].uval.add.xl = x; + playStack[playMark].uval.add.yl = y; + playStack[playMark].gID = myGID; + playStack[playMark].uval.add.sNumber = 0; + if (isNew) + playStack[playMark].uval.add.nextGID = newGID - 1; + else + playStack[playMark].uval.add.nextGID = newGID; + if (showTrees) + sstone(me, x, y, 0); + /* merge adjacent groups */ + if ((x > 0) && (bord[x - 1][y] == me) && + (gMap[groupIDs[x - 1][y]] != myGID)) + mergeGroup(gMap[groupIDs[x - 1][y]], myGID); + if ((x < maxPoint) && (bord[x + 1][y] == me) && + (gMap[groupIDs[x + 1][y]] != myGID)) + mergeGroup(gMap[groupIDs[x + 1][y]], myGID); + if ((y > 0) && (bord[x][y - 1] == me) && + (gMap[groupIDs[x][y - 1]] != myGID)) + mergeGroup(gMap[groupIDs[x][y - 1]], myGID); + if ((y < maxPoint) && (bord[x][y + 1] == me) && + (gMap[groupIDs[x][y + 1]] != myGID)) + mergeGroup(gMap[groupIDs[x][y + 1]], myGID); + /* kill opposing groups, listing affected groups */ + nlcGroup.indx = 1; + nlcGroup.v[1] = myGID; /* init list to include me */ + if ((x > 0) && (bord[x - 1][y] == him) && + (gList[gMap[groupIDs[x - 1][y]]].libC == 1)) + { + killFlag = TRUE; + killGroup(x - 1, y, me, him); + } + if ((x < maxPoint) && (bord[x + 1][y] == him) && + (gList[gMap[groupIDs[x + 1][y]]].libC == 1)) + { + killFlag = TRUE; + killGroup(x + 1, y, me, him); + } + if ((y > 0) && (bord[x][y - 1] == him) && + (gList[gMap[groupIDs[x][y - 1]]].libC == 1)) + { + killFlag = TRUE; + killGroup(x, y - 1, me, him); + } + if ((y < maxPoint) && (bord[x][y + 1] == him) && + (gList[gMap[groupIDs[x][y + 1]]].libC == 1)) + { + killFlag = TRUE; + killGroup(x, y + 1, me, him); + } + /* list groups adjacent to me */ + if ((x > 0) && (bord[x - 1][y] == him)) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]]; + } + if ((x < maxPoint) && (bord[x + 1][y] == him)) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]]; + } + if ((y > 0) && (bord[x][y - 1] == him)) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]]; + } + if ((y < maxPoint) && (bord[x][y + 1] == him)) + { + nlcGroup.indx = nlcGroup.indx + 1; + nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]]; + } + /* fix liberty count for affected groups */ + grpMark = grpMark + 1; + for (i = 1; i <= nlcGroup.indx; i++) + if (gList[nlcGroup.v[i]].groupMark != grpMark) + { + if (gList[nlcGroup.v[i]].atLevel != tryLevel) + { + playMark = playMark + 1; + playStack[playMark].kind = chLib; + playStack[playMark].gID = nlcGroup.v[i]; + playStack[playMark].uval.chLib.oldLevel = + gList[nlcGroup.v[i]].atLevel; + playStack[playMark].uval.chLib.oldLC = + gList[nlcGroup.v[i]].libC; + } + gList[nlcGroup.v[i]].groupMark = grpMark; + gList[nlcGroup.v[i]].atLevel = tryLevel; + spanGroup(gList[nlcGroup.v[i]].lx, gList[nlcGroup.v[i]].ly, &pPlist); + gList[nlcGroup.v[i]].libC = pPlist.indx; + } +} /* plei */ + +saveState() +{ /* saveState */ + playMark = 0; + tryLevel = 0; + newGID = maxGroupID; +} /* saveState */ + +/* + undoes a move sequence back to uMark +*/ +undoTo(uMark) +short uMark; +{ /* undoTo */ + short i, xl, yl; +#ifdef DEBUG + printf( "undoTo\n" ); +#endif + for (i = playMark; i >= uMark + 1; i--) + if (playStack[i].kind == rem) + { + xl = playStack[i].uval.rem.xl; + yl = playStack[i].uval.rem.yl; + bord[xl][yl] = playStack[i].uval.rem.who; + groupIDs[xl][yl] = playStack[i].gID; + if (showTrees) + sstone(playStack[i].uval.rem.who, xl, yl, + playStack[i].uval.rem.sNumber); + } + else if (playStack[i].kind == add) + { + xl = playStack[i].uval.add.xl; + yl = playStack[i].uval.add.yl; + bord[xl][yl] = 0; + groupIDs[xl][yl] = 0; + tryLevel = tryLevel - 1; + newGID = playStack[i].uval.add.nextGID; + if (showTrees) + rstone(xl, yl); + } + else if (playStack[i].kind == reMap) + gMap[playStack[i].gID] = playStack[i].uval.reMap.oldGID; + else /* change libs of group - gID is pre-mapped */ + { + gList[playStack[i].gID].libC = playStack[i].uval.chLib.oldLC; + gList[playStack[i].gID].atLevel = playStack[i].uval.chLib.oldLevel; + } + playMark = uMark; +} /* undoTo */ + +/* + restores the state of the world after trying a move sequence +*/ +restoreState() +{ /* restoreState */ +#ifdef DEBUG + printf( "restoreState\n" ); +#endif + if (playMark > 0) + { + undoTo(0); + playMark = 0; + tryLevel = 0; + } +} /* restoreState */ + +/* exception bpt; */ + + +/* + returns true if (the group (at gx, gy) is saveable. + if so, returns the point to play at in savex, savey +*/ +short saveable(gx, gy, savex, savey) +short gx, gy, *savex, *savey; +{ /* saveable */ + short me, him, gx1, gx2, i, j, smark, mark2, tl, result; + char sChar; + sPointList dList; + point tp; + short libList[maxSPoint+1]; +#ifdef DEBUG + printf( "saveable\n" ); +#endif + dbStop = TRUE; + me = bord[gx][gy]; + him = -me; + if (me == 1) + sChar = '|'; + else + sChar = '>'; +/* write(sChar); */ + spanGroup(gx, gy, &plist3); /* find my liberties */ + if (adjInAtari) /* one of my options is to kill */ + { + listAdjacents(gx, gy, &aList); + for (i = 1; i <= aList.indx; i++) + if (gList[aList.v[i]].libC == 1) + { + spanGroup(gList[aList.v[i]].lx, gList[aList.v[i]].ly, + &pList1); /* find it's liberty */ + plist3.indx = plist3.indx + 1; + plist3.p[plist3.indx].px = pList1.p[1].px; + plist3.p[plist3.indx].py = pList1.p[1].py; + } + } + for (i = 1; i <= maxSPoint; i++) + libList[i] = -1; + if ((utilPlayLevel > 4) && + (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* account for diags */ + { + listDiags(gx, gy, &dList); + j = 0; + i = plist3.indx; + while ((j < dList.indx) && + (i < maxSPoint)) + { + j = j + 1; + i = i + 1; + libList[i] = 100; + plist3.p[i].px = dList.p[j].px; + plist3.p[i].py = dList.p[j].py; + } + plist3.indx = i; + } + if (plist3.indx > 1) /* sort by decreasing lib count */ + { + for (i = 1; i <= plist3.indx; i++) + if (libList[i] != 100) + { + mark2 = playMark; + tryPlay(plist3.p[i].px, plist3.p[i].py, me); + libList[i] = gList[gMap[groupIDs[gx][gy]]].libC; + if (libList[i] > treeLibLim) /* i'm safe */ + { + *savex = plist3.p[i].px; + *savey = plist3.p[i].py; + result = TRUE; + goto one; + } + undoTo(mark2); + } + for (i = 1; i <= plist3.indx - 1; i++) + for (j = i + 1; j <= plist3.indx; j++) + if (libList[i] < libList[j]) + { + tl = libList[i]; + libList[i] = libList[j]; + libList[j] = tl; + tp = plist3.p[i]; + plist3.p[i] = plist3.p[j]; + plist3.p[j] = tp; + } + } + for (i = 1; i <= plist3.indx; i++) + { + *savex = plist3.p[i].px; + *savey = plist3.p[i].py; + if (legal[*savex][*savey]) + { + smark = playMark; + tryPlay(*savex, *savey, me); + pause(); + if (gList[gMap[groupIDs[*savex][*savey]]].libC > 1) + if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim) + { + restoreState(); +/* sClearChar(sChar, rXor); */ + return TRUE; + } + else if (gList[gMap[groupIDs[gx][gy]]].libC > 1) + if (! killable(gx, gy, &gx1, &gx2)) + { + restoreState(); +/* sClearChar(sChar, rXor); */ + return TRUE; + } + undoTo(smark); + } + } + result = FALSE; +one: + restoreState(); +/* sClearChar(sChar, rXor); */ + return result; +} /* saveable */ + +/* + marks unsavable groups as dead +*/ +markDead() +{ /* markDead */ + short i, j, gx, gy, result; +#ifdef DEBUG + printf( "markDead\n" ); +#endif + for (i = 1; i <= maxGroupID; i++) + if (killable(gList[i].lx, gList[i].ly, &gx, &gy)) + result = ! saveable(gList[i].lx, gList[i].ly, &gx, &gy); + else + result = FALSE; + for (i = 0; i <= maxPoint; i++) + for (j = 0; j <= maxPoint; j++) + if (bord[i][j] == 0) + ndbord[i][j] = 0; + else if (gList[groupIDs[i][j]].isDead) + ndbord[i][j] = 0; + else + ndbord[i][j] = bord[i][j]; +} /* markDead */ + +/* + marks groups with two eyes as live +*/ +MLspan(x, y, saw1, sawm1, size, sMark) +short x, y, *saw1, *sawm1, *size, sMark; + { /* span */ + if (ndbord[x][y] == 1) + *saw1 = TRUE; + else if (ndbord[x][y] == -1) + *sawm1 = TRUE; + else if (sGroups[x][y] == 0) + { + sGroups[x][y] = sMark; + *size = *size + 1; + if (x > 0) + MLspan(x - 1, y, saw1, sawm1, size, sMark); + if (x < maxPoint) + MLspan(x + 1, y, saw1, sawm1, size, sMark); + if (y > 0) + MLspan(x, y - 1, saw1, sawm1, size, sMark); + if (y < maxPoint) + MLspan(x, y + 1, saw1, sawm1, size, sMark); + } + } /* span */ + +short CLspan(x, y, numEyes, who) +short x, y, *numEyes, who; + { /* span */ + markBoard[x][y] = marker; + if (ndbord[x][y] == 0) + { + if ((sList[sGroups[x][y]].sm != marker) && + (sList[sGroups[x][y]].w == who)) + { + sList[sGroups[x][y]].sm = marker; + if (sList[sGroups[x][y]].s > 6) + return TRUE; + *numEyes = *numEyes + 1; + if (*numEyes > 1) + return TRUE; + } + } + else if (bord[x][y] == who) + { + if ((x > 0) && + (markBoard[x - 1][y] != marker)) + if (CLspan(x - 1, y, numEyes, who)) return TRUE; + if ((x < maxPoint) && + (markBoard[x + 1][y] != marker)) + if (CLspan(x + 1, y, numEyes, who)) return TRUE; + if ((y > 0) && + (markBoard[x][y - 1] != marker)) + if (CLspan(x, y - 1, numEyes, who)) return TRUE; + if ((y < maxPoint) && + (markBoard[x][y + 1] != marker)) + if (CLspan(x, y + 1, numEyes, who)) return TRUE; + } + return FALSE; + } /* span */ + +short checkLive(x, y) +short x, y; + { /* checkLive */ + short numEyes, who; +#ifdef DEBUG + printf( "checkLive\n" ); +#endif + numEyes = 0; + who = bord[x][y]; + marker = marker + 1; + return CLspan(x, y, &numEyes, who); + } /* checkLive */ + +markLive() +{ /* markLive */ + short i, j, size, sMark = 0; + short saw1, sawm1; +#ifdef DEBUG + printf( "markLive\n" ); +#endif + initArray(sGroups); + for (i = 0; i <= maxPoint; i++) + for (j = 0; j <= maxPoint; j++) + if ((sGroups[i][j] == 0) && + (ndbord[i][j] == 0)) + { + size = 0; + sMark = sMark + 1; + sawm1 = FALSE; + saw1 = FALSE; + MLspan(i, j, &saw1, &sawm1, &size, sMark); + sList[sMark].s = size; + sList[sMark].sm = 0; + if (sawm1) + if (saw1) + sList[sMark].w = 0; + else + sList[sMark].w = -1; + else if (saw1) + sList[sMark].w = 1; + else + sList[sMark].w = 0; + } + for (i = 1; i <= maxGroupID; i++) + if (! gList[i].isDead) + gList[i].isLive = checkLive(gList[i].lx, gList[i].ly); +} /* markLive */ + +/* + generates the connection map and the protected point map. +*/ +genConnects() +{ /* genConnects */ + short x, y, numStones; +#ifdef DEBUG + printf( "genConnects\n" ); +#endif + for (x = 0; x <= maxPoint; x++) + for (y = 0; y <= maxPoint; y++) + { + connectMap[x][y] = 0; + protPoints[x][y] = 0; + } + for (x = 0; x <= maxPoint; x++) + for (y = 0; y <= maxPoint; y++) + if (bord[x][y] == 1) /* map connections to this stone */ + { + if (x > 0) /* direct connection */ + connectMap[x - 1][y] += 1; + if (x < maxPoint) + connectMap[x + 1][y] += 1; + if (y > 0) + connectMap[x][y - 1] += 1; + if (y < maxPoint) + connectMap[x][y + 1] += 1; + if ((x > 0) && (y > 0) && /* diagonal connection */ + (bord[x - 1][y] == 0) && (bord[x][y - 1] == 0)) + connectMap[x - 1][y - 1] += 1; + if ((x < maxPoint) && (y > 0) && + (bord[x + 1][y] == 0) && (bord[x][y - 1] == 0)) + connectMap[x + 1][y - 1] += 1; + if ((x < maxPoint) && (y < maxPoint) && + (bord[x + 1][y] == 0) && (bord[x][y + 1] == 0)) + connectMap[x + 1][y + 1] += 1; + if ((x > 0) && (y < maxPoint) && + (bord[x - 1][y] == 0) && (bord[x][y + 1] == 0)) + connectMap[x - 1][y + 1] += 1; + if ((x > 1) && (claim[x - 1][y] > 3)) /* one point jump */ + connectMap[x - 2][y] += 1; + if ((x < (maxPoint - 1)) && (claim[x + 1][y] > 3)) + connectMap[x + 2][y] += 1; + if ((y > 1) && (claim[x][y - 1] > 3)) + connectMap[x][y - 2] += 1; + if ((y < (maxPoint - 1)) && (claim[x][y + 1] > 3)) + connectMap[x][y + 2] += 1; + if ((x > 1) && (y > 0) && /* knight's move */ + (claim[x - 1][y] > 3) && (claim[x - 1][y - 1] > 3)) + connectMap[x - 2][y - 1] += 1; + if ((x > 0) && (y > 1) && + (claim[x][y - 1] > 3) && (claim[x - 1][y - 1] > 3)) + connectMap[x - 1][y - 2] += 1; + if ((x < (maxPoint - 1)) && (y > 0) && + (claim[x + 1][y] > 3) && (claim[x + 1][y - 1] > 3)) + connectMap[x + 2][y - 1] += 1; + if ((x < maxPoint) && (y > 1) && + (claim[x][y - 1] > 3) && (claim[x + 1][y - 1] > 3)) + connectMap[x + 1][y - 2] += 1; + if ((x > 1) && (y < maxPoint) && + (claim[x - 1][y] > 3) && (claim[x - 1][y + 1] > 3)) + connectMap[x - 2][y + 1] += 1; + if ((x > 0) && (y < (maxPoint - 1)) && + (claim[x][y + 1] > 3) && (claim[x - 1][y + 1] > 3)) + connectMap[x - 1][y + 2] += 1; + if ((x < (maxPoint - 1)) && (y < maxPoint) && + (claim[x + 1][y] > 3) && (claim[x + 1][y + 1] > 3)) + connectMap[x + 2][y + 1] += 1; + if ((x < maxPoint) && (y < (maxPoint - 1)) && + (claim[x][y + 1] > 3) && (claim[x + 1][y + 1] > 3)) + connectMap[x + 1][y + 2] += 1; + } + else if (bord[x][y] == 0) /* see if protected point */ + { + numStones = 0; + if (x == 0) + numStones = numStones + 1; + if (y == 0) + numStones = numStones + 1; + if (x == maxPoint) + numStones = numStones + 1; + if (y == maxPoint) + numStones = numStones + 1; + if ((x > 0) && (bord[x - 1][y] == 1)) + numStones = numStones + 1; + if ((y > 0) && (bord[x][y - 1] == 1)) + numStones = numStones + 1; + if ((x < maxPoint) && (bord[x + 1][y] == 1)) + numStones = numStones + 1; + if ((y < maxPoint) && (bord[x][y + 1] == 1)) + numStones = numStones + 1; + if (numStones == 4) + protPoints[x][y] = 1; + else if (numStones == 3) + { + if ((x > 0) && + ((bord[x - 1][y] == 0) || + ((bord[x - 1][y] == -1) && + (gList[groupIDs[x - 1][y]].libC == 1)))) + protPoints[x][y] = 1; + else if ((x < maxPoint) && + ((bord[x + 1][y] == 0) || + ((bord[x + 1][y] == -1) && + (gList[groupIDs[x + 1][y]].libC == 1)))) + protPoints[x][y] = 1; + else if ((y > 0) && + ((bord[x][y - 1] == 0) || + ((bord[x][y - 1] == -1) && + (gList[groupIDs[x][y - 1]].libC == 1)))) + protPoints[x][y] = 1; + else if ((y < maxPoint) && + ((bord[x][y + 1] == 0) || + ((bord[x][y + 1] == -1) && + (gList[groupIDs[x][y + 1]].libC == 1)))) + protPoints[x][y] = 1; + } + } + for (x = 0; x <= maxPoint; x++) + for (y = 0; y <= maxPoint; y++) + if (bord[x][y] != 0) + { + connectMap[x][y] = 0; + protPoints[x][y] = 0; + } +} /* genConnects */ + +/* + generates the whole state of the game. +*/ +genState() +{ /* genState */ +#ifdef DEBUG + printf( "genState\n" ); +#endif + inGenState = TRUE; + respreicen(); + markDead(); + markLive(); + spread(); + genConnects(); +#ifdef DEBUG +/* printBoard( claim, "claim" ); */ +/* printBoard( bord, "bord" ); */ +/* printBoard( ndbord, "ndbord" ); + printBoard( sGroups, "sGroups" ); + printBoard( groupIDs, "groupIDs" ); + printBoard( connectMap, "connectMap" ); + printBoard( protPoints, "protPoints" ); */ +#endif + inGenState = FALSE; +} /* genState */ + +/* + generates a value for the [x, y] location that appears to get larger + for points that are saddle points in the influence graph (klein) +*/ +short tencen(x, y) +short x, y; +{ /* tencen */ + short a, b, c, d, w, z; +#ifdef DEBUG + printf( "tencen\n" ); +#endif + if (claim[x][y] > -1) /* if (he does not influence this area, return 50 */ + { + return 50; + } + w = claim[x][y]; /* w <= -1 */ + a = iNil; + if (x > 0) + if (claim[x - 1][y] > -1) /* if (neighbor is not influenced by him */ + a = claim[x - 1][y] - w; /* score is sum of his influence on central */ + b = iNil; /* point and my influence on this neighbor */ + if (y > 0) + if (claim[x][y - 1] > -1) + b = claim[x][y - 1] - w; + c = iNil; + if (x < maxPoint) + if (claim[x + 1][y] > -1) + c = claim[x + 1][y] - w; + d = iNil; + if (y < maxPoint) + if (claim[x][y + 1] > -1) + d = claim[x][y + 1] - w; + z = a; /* z = max(a, b, c, d) */ + if (z != iNil) + { + if ((b != iNil) && + (b > z)) + z = b; + } + else + z = b; + if (z != iNil) + { + if ((c != iNil) && + (c > z)) + z = c; + } + else + z = c; + if (z != iNil) + { + if ((d != iNil) && + (d > z)) + z = d; + } + else + z = d; + if ((z != iNil) && + ((x == 0) || + (y == 0) || + (x == maxPoint) || + (y == maxPoint))) + z = z * 2; /* double z if (on the edge of the board ?? */ + if (z != iNil) + return z; + else + return 50; +} /* tencen */ + +initGPUtils() +{ /* initGPUtils */ +#ifdef DEBUG + printf( "initGPUtils\n" ); +#endif + initArray(markBoard); + initState(); + marker = 0; + playMark = 0; + gList[0].isLive = FALSE; + gList[0].isDead = FALSE; + gList[0].libC = 0; + gList[0].size = 0; + gList[0].numEyes = 0; + gList[0].lx = -1; + gList[0].ly = -1; + gMap[0] = 0; + dbStop = FALSE; + inGenState = FALSE; +} /* initGPUtils */ + |