summaryrefslogtreecommitdiff
path: root/noncore/games/go
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (side-by-side diff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /noncore/games/go
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'noncore/games/go') (more/less context) (show whitespace changes)
-rw-r--r--noncore/games/go/.cvsignore2
-rw-r--r--noncore/games/go/Makefile.in158
-rw-r--r--noncore/games/go/README3
-rw-r--r--noncore/games/go/README.AMIGO42
-rw-r--r--noncore/games/go/README.XAMIGO26
-rw-r--r--noncore/games/go/amigo.c656
-rw-r--r--noncore/games/go/amigo.h146
-rw-r--r--noncore/games/go/go.h81
-rw-r--r--noncore/games/go/go.pro19
-rw-r--r--noncore/games/go/goplayer.c1499
-rw-r--r--noncore/games/go/goplayutils.c1317
-rw-r--r--noncore/games/go/goplayutils.h85
-rw-r--r--noncore/games/go/gowidget.cpp449
-rw-r--r--noncore/games/go/gowidget.h111
-rw-r--r--noncore/games/go/killable.c373
-rw-r--r--noncore/games/go/main.cpp35
-rw-r--r--noncore/games/go/qpe-go.control9
17 files changed, 5011 insertions, 0 deletions
diff --git a/noncore/games/go/.cvsignore b/noncore/games/go/.cvsignore
new file mode 100644
index 0000000..6fe2396
--- a/dev/null
+++ b/noncore/games/go/.cvsignore
@@ -0,0 +1,2 @@
+moc_*
+Makefile
diff --git a/noncore/games/go/Makefile.in b/noncore/games/go/Makefile.in
new file mode 100644
index 0000000..27304f1
--- a/dev/null
+++ b/noncore/games/go/Makefile.in
@@ -0,0 +1,158 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = ../bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = go
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = amigo.h \
+ go.h \
+ goplayutils.h \
+ gowidget.h
+SOURCES = amigo.c \
+ goplayer.c \
+ goplayutils.c \
+ killable.c \
+ gowidget.cpp \
+ main.cpp
+OBJECTS = amigo.o \
+ goplayer.o \
+ goplayutils.o \
+ killable.o \
+ gowidget.o \
+ main.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_gowidget.cpp
+OBJMOC = moc_gowidget.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake go.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+amigo.o: amigo.c \
+ go.h \
+ goplayutils.h \
+ amigo.h
+
+goplayer.o: goplayer.c \
+ go.h \
+ goplayutils.h \
+ amigo.h
+
+goplayutils.o: goplayutils.c \
+ goplayutils.h \
+ amigo.h \
+ go.h
+
+killable.o: killable.c \
+ go.h \
+ goplayutils.h \
+ amigo.h
+
+gowidget.o: gowidget.cpp \
+ gowidget.h \
+ amigo.h \
+ go.h \
+ goplayutils.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h
+
+main.o: main.cpp \
+ gowidget.h \
+ amigo.h \
+ go.h \
+ goplayutils.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+moc_gowidget.o: moc_gowidget.cpp \
+ gowidget.h \
+ amigo.h \
+ go.h \
+ goplayutils.h
+
+moc_gowidget.cpp: gowidget.h
+ $(MOC) gowidget.h -o moc_gowidget.cpp
+
+
diff --git a/noncore/games/go/README b/noncore/games/go/README
new file mode 100644
index 0000000..c6fa1f5
--- a/dev/null
+++ b/noncore/games/go/README
@@ -0,0 +1,3 @@
+This Go player For Qtopia is based on Xamigo, which in turn was
+based on Amigo. The original README files are included as README.XAMIGO
+and README.AMIGO.
diff --git a/noncore/games/go/README.AMIGO b/noncore/games/go/README.AMIGO
new file mode 100644
index 0000000..03978e7
--- a/dev/null
+++ b/noncore/games/go/README.AMIGO
@@ -0,0 +1,42 @@
+ This is version 1.0 of AmiGo --- a Go board and player for the Amiga.
+The Amiga interface and board manager were written by Todd R. Johnson.
+The player is a C port of a Pascal player written by Stoney Ballard.
+The interface allows you to play human vs. human, human vs. Amiga, or
+Amiga vs. Amiga.
+
+ The board manager and player could both use some work. Currently,
+you cannot save/load games, take back a move, or automatically score a
+game. It is also limited to a 19 by 19 board. I'm releasing AmiGo
+now because 1) I'm in the final phases of my dissertation and probably
+won't have much time to do any further work on AmiGo, and 2) a lot of
+people have been asking for an Amiga Go player. I am also releasing
+all of the source code so that others can add to and modify AmiGo.
+Note that all of my code in this release is public domain, while the
+ported go player retains the original copyright.
+
+ If you distribute AmiGo, I urge you to include the source
+code. If anyone makes changes, I would appreciate a copy. In fact, I
+am willing to act as a clearinghouse for AmiGo changes.
+
+Todd R. Johnson
+tj@cis.ohio-state.edu
+8/8/89
+
+Here is the message attached to the original USENET posting of Stoney
+Ballard's Pascal code. Note that the board manager mentioned here is
+not included in this distribution.
+
+This go board manager and rudimentary go player was written by
+Stoney Ballard at Perq Systems in 1983-1984. It is written in
+Perq Pascal and utilizes some Perq libraries for I/O. The code
+is offered here if someone is interested to convert it to Unix.
+
+The wonderful part about it is that a game is recorded as a tree
+and can be played forward or backward, branching at any point
+where there were alternate moves.
+
+For some time, this program was also used to generate the go
+boards displayed in the American Go Journal. For this it used
+some large font digits which are now lost.
+
+Fred Hansen
diff --git a/noncore/games/go/README.XAMIGO b/noncore/games/go/README.XAMIGO
new file mode 100644
index 0000000..219b25f
--- a/dev/null
+++ b/noncore/games/go/README.XAMIGO
@@ -0,0 +1,26 @@
+
+ Xamigo 1.1
+
+This is an alpha release of xamigo --- a port (read: quick hack) of the
+Amiga Go program AmiGo. I don't have time to get it real nice now,
+but will spend some more time on it when my thesis is out of the way.
+Sadly this is the second time I've said that :-)
+
+The `readme' from the original distribution is included as README.AMIGO
+
+An Imakefile is included, so you should be able to type
+ xmkmf
+ make
+to build xamigo. Let me know if you have problems with the Imakefile,
+preferably with fixes :-)
+
+You *have* to install the app-defaults file (Xamigo.ad) before you use
+xamigo. This should either go in /usr/lib/X11/app-defaults,
+or in your own app-defaults directory, as file Xamigo (ie lose the '.ad')
+If you do the latter, you have to:
+ setenv XAPPLRESDIR <full path of your app-defaults directory>
+
+Feel free to mail me any comments and suggestions for improvements.
+
+Neil
+neilb@scs.leeds.ac.uk
diff --git a/noncore/games/go/amigo.c b/noncore/games/go/amigo.c
new file mode 100644
index 0000000..cd61013
--- a/dev/null
+++ b/noncore/games/go/amigo.c
@@ -0,0 +1,656 @@
+/* Go started 4/17/88 by Todd R. Johnson */
+/* 8/8/89 cleaned up for first release */
+/* Public Domain */
+
+#include "go.h"
+#include "goplayutils.h"
+#include "amigo.h"
+
+
+extern char *playReason;
+extern short playLevel, showTrees;
+
+struct bRec goboard[19][19]; /*-- The main go board --*/
+
+struct Group GroupList[MAXGROUPS]; /*-- The list of Groups --*/
+short DeletedGroups[4]; /*-- Codes of deleted groups --*/
+
+short GroupCount = 0; /*-- The total number of groups --*/
+short DeletedGroupCount; /*-- The total number of groups --*/
+ /*-- deleted on a move --*/
+short ko, koX, koY;
+short blackTerritory,whiteTerritory;
+short blackPrisoners, whitePrisoners;
+short showMoveReason = FALSE,
+ groupInfo = FALSE,
+ whitePassed = FALSE,
+ blackPassed = FALSE;
+
+
+/* Arrays for use when checking around a point */
+short xVec[4] = {0, 1, 0, -1};
+short yVec[4] = {-1, 0, 1, 0};
+
+short
+member(group, grouplist, cnt)
+ short group;
+ short grouplist[4];
+ short cnt;
+{
+ unsigned short i;
+
+
+ for (i = 0; i < cnt; i++)
+ if (grouplist[i] == group)
+ return TRUE;
+ return FALSE;
+}
+
+/* Does a stone at x, y connect to any groups of color? */
+short
+Connect( color, x, y, fGroups, fCnt, eGroups, eCnt)
+ enum bVal color;
+ short x, y;
+ short fGroups[4], eGroups[4];
+ short *fCnt, *eCnt;
+{
+ unsigned short point = 0;
+ short tx, ty, total = 0;
+ enum bVal opcolor = WHITE;
+
+
+ *fCnt = 0;
+ *eCnt = 0;
+ if (color == WHITE)
+ opcolor = BLACK;
+ for (point = 0; point <= 3; point++ )
+ {
+ tx = x + xVec[point];
+ ty = y + yVec[point];
+ if (!LegalPoint(tx,ty))
+ continue;
+ if (goboard[tx][ty].Val == color)
+ {
+ total++;
+ if (!member(goboard[tx][ty].GroupNum, fGroups, *fCnt))
+ fGroups[(*fCnt)++] = goboard[tx][ty].GroupNum;
+ }
+ else if (goboard[tx][ty].Val == opcolor)
+ {
+ total++;
+ if (!member(goboard[tx][ty].GroupNum, eGroups, *eCnt))
+ eGroups[(*eCnt)++] = goboard[tx][ty].GroupNum;
+ }
+ }
+ return total;
+}
+
+/* Returns the maximum number of liberties for a given intersection */
+short
+Maxlibs(x, y)
+ short x, y;
+{
+ short cnt = 4;
+
+
+ if (x == 0 || x == 18)
+ cnt--;
+ if (y == 0 || y == 18)
+ cnt--;
+ return cnt;
+}
+
+DeleteGroupFromStone(x,y)
+ short x,y;
+{
+ if (goboard[x][y].Val != EMPTY)
+ GroupCapture(goboard[x][y].GroupNum);
+}
+
+/* Determine whether x, y is suicide for color */
+short
+Suicide(color, x, y)
+ enum bVal color;
+ short x, y;
+{
+ enum bVal opcolor = BLACK;
+ short friendlycnt, friendlygroups[4],
+ enemycnt, enemygroups[4],
+ total;
+ short maxlibs, i, libcnt = 0;
+
+
+ if (color == BLACK)
+ opcolor = WHITE;
+ maxlibs = Maxlibs( x, y);
+ total = Connect(color, x, y, friendlygroups, &friendlycnt,
+ enemygroups, &enemycnt);
+
+ if (total < maxlibs)
+ return FALSE;
+
+ /* Check for a capture */
+ for (i = 0; i < enemycnt; i++)
+ if (GroupList[enemygroups[i]].liberties == 1)
+ return FALSE;
+ for (i = 0; i < friendlycnt; i++)
+ libcnt += (GroupList[friendlygroups[i]].liberties - 1);
+ if (libcnt != 0)
+ return FALSE;
+ return TRUE;
+}
+
+/* Returns the number of liberties for x, y */
+short
+StoneLibs(x, y)
+ short x, y;
+{
+ short cnt = 0, tx, ty;
+ unsigned short point;
+
+
+ for (point = 0; point <= 3; point++)
+ {
+ tx = x + xVec[point];
+ ty = y + yVec[point];
+ if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY)
+ cnt++;
+ }
+ return cnt;
+}
+
+void
+EraseMarks()
+{
+ register short i;
+ register struct bRec *gpt = &goboard[0][0];
+
+
+ for (i=0; i<361; gpt++,i++)
+ gpt->marked = FALSE;
+}
+
+/* Place a stone of color at x, y */
+short
+GoPlaceStone(color, x, y)
+ enum bVal color;
+ short x, y;
+{
+ short fgroups[4], egroups[4]; /* group codes surrounding stone */
+ short fcnt, ecnt, i;
+ short lowest = GroupCount + 1;
+
+
+ DeletedGroupCount = 0;
+ if (goboard[x][y].Val != EMPTY || Suicide(color,x,y))
+ return FALSE;
+
+ if (ko && koX == x && koY == y)
+ return FALSE;
+
+ ko = FALSE;
+ placestone(color, x, y);
+ goboard[x][y].Val = color;
+ /* Does the new stone connect to any friendly stone(s)? */
+ Connect(color, x, y, fgroups, &fcnt, egroups, &ecnt);
+ if (fcnt)
+ {
+ /* Find the connecting friendly group with the lowest code */
+ for (i = 0; i < fcnt; i++)
+ if (fgroups[i] <= lowest)
+ lowest = fgroups[i];
+ /*-- Renumber resulting group --*/
+ /*-- Raise the stone count of the lowest by one to account --*/
+ /*-- for new stone --*/
+ goboard[x][y].GroupNum = lowest;
+ GroupList[lowest].count++;
+ for (i = 0; i < fcnt; i++)
+ if (fgroups[i] != lowest)
+ MergeGroups(lowest, fgroups[i]);
+ /* Fix the liberties of the resulting group */
+ CountLiberties(lowest);
+ }
+ else
+ {
+ /* Isolated stone. Create new group. */
+ GroupCount++;
+ lowest = GroupCount;
+ GroupList[lowest].color = color;
+ GroupList[lowest].count = 1;
+ GroupList[lowest].internal = 0;
+ GroupList[lowest].external = StoneLibs( x, y);
+ GroupList[lowest].liberties = GroupList[lowest].external;
+ GroupList[lowest].eyes = 0;
+ GroupList[lowest].alive = 0;
+ GroupList[lowest].territory = 0;
+ goboard[x][y].GroupNum = lowest;
+ }
+ /* Now fix the liberties of enemy groups adjacent to played stone */
+ FixLibs(color, x, y, PLACED); /* Fix the liberties of opcolor */
+ ReEvalGroups(color, x, y, lowest);
+ RelabelGroups();
+ return TRUE;
+}
+
+/* Remove a stone from the board */
+void
+GoRemoveStone(x, y)
+ short x, y;
+{
+ goboard[x][y].Val = EMPTY;
+ goboard[x][y].GroupNum = 0;
+ removestone( x, y);
+}
+
+/* Merges two groups -- Renumbers stones and deletes second group from
+list. Fixes stone count of groups. This does not fix anything else.
+FixLibs must be called to fix liberties, etc. */
+void
+MergeGroups(g1, g2)
+ short g1, g2;
+{
+ short x, y;
+
+
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum == g2)
+ goboard[x][y].GroupNum = g1;
+ GroupList[g1].count += GroupList[g2].count;
+ DeleteGroup( g2 ); /* Removes group from GroupList */
+}
+
+/* Stores a group code to be deleted */
+void
+DeleteGroup(code)
+ short code;
+{
+ DeletedGroups[DeletedGroupCount++] = code;
+}
+
+/* Re-evaluate the groups given the last move. This assumes that the
+last move has been merged into adjoining groups and all liberty counts
+are correct. Handles capture. Checks for Ko. Keeps track of captured
+stones. code is the group number of the stone just played. */
+void
+ReEvalGroups(color, x, y, code)
+ enum bVal color;
+ short x, y, code;
+{
+ short fgroups[4], egroups[4],
+ fcnt, ecnt, i, killcnt = 0, count = 0;
+ enum bVal opcolor = BLACK;
+
+ if (color == BLACK)
+ opcolor = WHITE;
+ /* Check for capture */
+ Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt);
+ if (ecnt)
+ {
+ /* See if any of the groups have no liberties */
+ for (i = 0; i < ecnt; i++)
+ if (GroupList[egroups[i]].liberties == 0)
+ {
+ killcnt++;
+ count = GroupList[egroups[i]].count;
+ GroupCapture( egroups[i]);
+ }
+ }
+ /* Check for ko. koX and koY are set in GroupCapture above. */
+ if (killcnt == 1 && count == 1 && GroupList[ code ].count == 1
+ && GroupList[ code ].liberties == 1)
+ {
+ ko = TRUE;
+ }
+ if (killcnt)
+ intrPrisonerReport( blackPrisoners, whitePrisoners);
+ /* Set eye count for groups */
+ CountEyes();
+}
+
+/* Remove a captured group from the board and fix the liberties of any
+ adjacent groups. Fixes prisoner count. Sets KoX and KoY */
+/*-- update display of captured stones -neilb --*/
+void
+GroupCapture(code)
+ short code;
+{
+ short x, y;
+
+ if (GroupList[code].color == BLACK)
+ blackPrisoners += GroupList[code].count;
+ else
+ whitePrisoners += GroupList[code].count;
+ intrPrisonerReport(blackPrisoners, whitePrisoners);
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum == code)
+ {
+ FixLibs(GroupList[code].color,x,y,REMOVED);
+ GoRemoveStone(x, y);
+ koX = x;
+ koY = y;
+ }
+ DeleteGroup( code);
+}
+
+/* Fix the liberties of groups adjacent to x, y. move indicates
+ whether a stone of color was placed or removed at x, y
+ This does not change liberty counts of friendly groups when a stone
+ is placed. Does not do captures. */
+void
+FixLibs( color, x, y, move)
+ enum bVal color;
+ short x, y, move;
+{
+ short fgroups[4], fcnt, egroups[4], ecnt, i;
+ enum bVal opcolor = BLACK;
+
+ if (color == BLACK)
+ opcolor = WHITE;
+ Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt);
+ if (move == PLACED)
+ for (i = 0; i < ecnt; i++)
+ GroupList[egroups[i]].liberties--;
+ else /* Stone removed so increment opcolor */
+ for (i = 0; i < ecnt; i++)
+ GroupList[egroups[i]].liberties++;
+}
+
+void
+goSetHandicap(handicap)
+ int handicap;
+{
+ if (handicap < 2)
+ return;
+
+ GoPlaceStone(BLACK,3,3);
+ GoPlaceStone(BLACK,15,15);
+
+ if (handicap >= 3)
+ GoPlaceStone(BLACK,15,3);
+ if (handicap >= 4)
+ GoPlaceStone(BLACK,3,15);
+ if (handicap == 5 || handicap == 7 || handicap == 9)
+ GoPlaceStone(BLACK,9,9);
+ if (handicap >= 6)
+ {
+ GoPlaceStone(BLACK,15,9);
+ GoPlaceStone(BLACK,3,9);
+ }
+ if (handicap >= 8)
+ {
+ GoPlaceStone(BLACK,9,15);
+ GoPlaceStone(BLACK,9,3);
+ }
+}
+
+void
+goRestart(handicap)
+ int handicap;
+{
+ register short i;
+ register struct bRec *gpt = &goboard[0][0];
+
+
+ GroupCount = 0;
+ ko = FALSE;
+ blackPrisoners = whitePrisoners = 0;
+ intrPrisonerReport(0, 0);
+ for (i=0; i<361; gpt++,i++)
+ {
+ gpt->Val = EMPTY;
+ gpt->GroupNum = 0;
+ }
+ goSetHandicap(handicap);
+}
+
+
+/* if any groups have been deleted as a result of the last move, this
+ routine will delete the old group numbers from GroupList and
+ reassign group numbers. */
+void
+RelabelGroups()
+{
+ unsigned short i, j, x, y;
+
+ for (i = 0; i < DeletedGroupCount; i++)
+ {
+ /* Relabel all higher groups */
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum > DeletedGroups[i])
+ goboard[x][y].GroupNum--;
+ /* Move the groups down */
+ for (y = DeletedGroups[i]; y < GroupCount; y++)
+ GroupList[y] = GroupList[y+1];
+ /* fix the group numbers stored in the deleted list */
+ for (j = i+1; j < DeletedGroupCount; j++)
+ if (DeletedGroups[j] > DeletedGroups[i])
+ DeletedGroups[j]--;
+ GroupCount--;
+ }
+}
+
+/* Returns liberty count for x, y intersection. Sets marked to true
+ for each liberty */
+short
+CountAndMarkLibs( x, y)
+ short x, y;
+{
+ short tx,ty,i;
+ short cnt = 0;
+
+
+ for (i=0;i<4;i++)
+ {
+ tx = x + xVec[i];
+ ty = y + yVec[i];
+ if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY
+ && goboard[tx][ty].marked == FALSE)
+ {
+ cnt++;
+ goboard[tx][ty].marked = TRUE;
+ }
+ }
+ return cnt;
+}
+
+/* Determine the number of liberties for a group given the group code
+ num */
+void
+CountLiberties( code)
+ short code;
+{
+ short x, y, libcnt = 0;
+
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum == code)
+ libcnt += CountAndMarkLibs( x, y);
+ EraseMarks();
+ GroupList[code].liberties = libcnt;
+}
+
+void
+CheckForEye( x, y, groups, cnt, recheck)
+ short x, y, groups[4], cnt, *recheck;
+{
+ short i;
+
+ for (i = 0; i < (cnt-1); i++)
+ if (groups[i] != groups[i+1])
+ {
+ /* Mark liberty for false eye check */
+ goboard[x][y].marked = TRUE;
+ (*recheck)++;
+ return;
+ }
+ /* It is an eye */
+ GroupList[groups[i]].eyes += 1;
+}
+
+/* Set the eye count for the groups */
+void CountEyes()
+{
+ short i, x, y,
+ wgroups[4], bgroups[4], wcnt, bcnt, max, cnt, recheck = 0, eye;
+
+ for (i = 1; i <= GroupCount; i++)
+ GroupList[i].eyes = 0;
+
+ ForeachPoint(y,x)
+ {
+ if (goboard[x][y].Val != EMPTY)
+ continue;
+ cnt = Connect(WHITE,x,y,wgroups,&wcnt,bgroups,&bcnt);
+ max = Maxlibs( x, y);
+ if (cnt == max && wcnt == 1 && bcnt == 0)
+ GroupList[wgroups[0]].eyes++;
+ else if (cnt == max && bcnt == 1 && wcnt == 0)
+ GroupList[bgroups[0]].eyes++;
+ else if (cnt == max && ( bcnt == 0 || wcnt == 0 ))
+ {
+ goboard[x][y].marked = TRUE;
+ recheck++;
+ }
+ }
+
+ /*-- Now recheck marked liberties to see if two or more one eye --*/
+ /*-- groups contribute to a false eye */
+ if (recheck == 0)
+ return;
+
+ ForeachPoint(y,x)
+ if (goboard[x][y].marked)
+ {
+ recheck--;
+ goboard[x][y].marked = FALSE;
+ Connect( WHITE, x, y, wgroups, &wcnt, bgroups, &bcnt);
+ /* If all the groups have at least one eye then all the
+ groups are safe from capture because of the common
+ liberty at x, y */
+ eye = TRUE;
+ for (i = 0; i < wcnt; i++)
+ if (GroupList[wgroups[i]].eyes == 0)
+ eye = FALSE;
+ if (eye)
+ for (i = 0; i < wcnt; i++)
+ GroupList[wgroups[i]].eyes++;
+ for (i = 0; i < bcnt; i++)
+ if (GroupList[bgroups[i]].eyes == 0)
+ eye = FALSE;
+ if (eye)
+ for (i = 0; i < bcnt; i++)
+ GroupList[bgroups[i]].eyes++;
+ if (recheck == 0)
+ return;
+ }
+}
+
+
+short foo[19][19];
+
+/*----------------------------------------------------------------
+-- CountUp() --
+-- Count up final scores at the end of the game. --
+----------------------------------------------------------------*/
+CountUp( wtotal, btotal )
+ int *wtotal, *btotal;
+{
+ short x,y;
+ short CountFromPoint();
+ short vv;
+ char buff[512];
+
+
+ blackTerritory = whiteTerritory = 0;
+ ForeachPoint(y,x)
+ {
+ goboard[x][y].marked = FALSE;
+ foo[x][y] = CNT_UNDECIDED;
+ }
+ ForeachPoint(y,x)
+ if (goboard[x][y].Val==EMPTY && foo[x][y]==CNT_UNDECIDED)
+ {
+ FillPoints(x,y,CountFromPoint(x,y));
+ }
+
+ *wtotal = whiteTerritory + blackPrisoners;
+ *btotal = blackTerritory + whitePrisoners;
+ /*
+ sprintf(buff,"White : %3d territory + %3d prisoners = %d\n\
+Black : %3d territory + %3d prisoners = %d\n\n%s.\n",
+ whiteTerritory,blackPrisoners,*wtotal,
+ blackTerritory,whitePrisoners,*btotal,
+ (*btotal>*wtotal?"Black wins":(*wtotal>*btotal?"White wins":
+ "A draw")));
+
+
+
+ XtVaSetValues(message,XtNstring,buff,0);
+ printf( "CountUp() %s", buff );
+ */
+}
+
+FillPoints(x,y,val)
+ short x,y,val;
+{
+ int i;
+ short tx,ty;
+
+
+ if ((foo[x][y] = val) == CNT_BLACK_TERR)
+ blackTerritory++;
+ else if (val == CNT_WHITE_TERR)
+ whiteTerritory++;
+ for (i=0;i<4;i++)
+ {
+ tx = x + xVec[i];
+ ty = y + yVec[i];
+ if (!LegalPoint(tx,ty))
+ continue;
+ if (goboard[tx][ty].Val==EMPTY && foo[tx][ty]==CNT_UNDECIDED)
+ FillPoints(tx,ty,val);
+ }
+}
+
+short
+CountFromPoint(x,y)
+ short x,y;
+{
+ int i;
+ short tx,ty;
+ short blkcnt=0,whtcnt=0;
+ short baz;
+
+
+ goboard[x][y].marked = TRUE;
+ for (i=0;i<4;i++)
+ {
+ tx = x + xVec[i];
+ ty = y + yVec[i];
+ if (!LegalPoint(tx,ty))
+ continue;
+ if (goboard[tx][ty].Val == BLACK)
+ blkcnt++;
+ else if (goboard[tx][ty].Val == WHITE)
+ whtcnt++;
+ else
+ {
+ if (goboard[tx][ty].marked)
+ continue;
+ baz = CountFromPoint(tx,ty);
+ if (baz == CNT_NOONE)
+ return CNT_NOONE;
+ else if (baz == CNT_BLACK_TERR)
+ blkcnt++;
+ else if (baz == CNT_WHITE_TERR)
+ whtcnt++;
+ }
+ if (blkcnt && whtcnt)
+ return CNT_NOONE;
+ }
+ if (blkcnt && !whtcnt)
+ return CNT_BLACK_TERR;
+ else if (whtcnt && !blkcnt)
+ return CNT_WHITE_TERR;
+ else
+ return CNT_UNDECIDED;
+}
diff --git a/noncore/games/go/amigo.h b/noncore/games/go/amigo.h
new file mode 100644
index 0000000..5150ac0
--- a/dev/null
+++ b/noncore/games/go/amigo.h
@@ -0,0 +1,146 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+/*=========================================================================
+=== ===
+=== FILE amigo.h ===
+=== ===
+=== CONTENTS prototypes for the various AmiGo routines. ===
+=== added by neilb ===
+=== ===
+=========================================================================*/
+
+#ifndef __amigo_h
+#define __amigo_h
+
+#include "go.h"
+#include "goplayutils.h"
+
+#ifdef __STDC__
+#define PROTO(fp) fp
+#else
+#define PROTO(fp) ()
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* From goplayer.c */
+
+
+
+/* Procedures from amigo.c */
+
+short Connect PROTO((enum bVal, short, short, short[4], short[4], short *, short * ));
+short Maxlibs PROTO((short, short));
+short Suicide PROTO((enum bVal, short, short));
+short StoneLibs PROTO((short, short));
+void EraseMarks PROTO(());
+short GoPlaceStone PROTO((enum bVal, short, short));
+void GoRemoveStone PROTO((short, short));
+void MergeGroups PROTO((short, short));
+void DeleteGroup PROTO((short));
+void ReEvalGroups PROTO((enum bVal, short, short, short));
+void GroupCapture PROTO((short));
+void FixLibs PROTO((enum bVal, short, short, short));
+int CountUp PROTO((int*, int*));
+/*void main PROTO(());*/
+void goRestart PROTO((int));
+void RelabelGroups PROTO(());
+short CountAndMarkLibs PROTO((short, short));
+void CountLiberties PROTO((short));
+void CheckForEye PROTO((short, short, short[4], short, short *));
+void CountEyes PROTO(());
+void printGroupReport PROTO((short, short));
+
+
+/* killable.c */
+
+int tryPlay PROTO(( short, short, short ));
+int sSpanGroup PROTO(( short, short, sPointList * ));
+int spanGroup PROTO(( short, short, pointList *));
+int pause PROTO(());
+
+int genState PROTO(());
+int initGPUtils PROTO(());
+int genBord PROTO((enum bVal));
+
+short genMove PROTO(( enum bVal, short *, short * ));
+short checkPos PROTO(( short, short, short ));
+short takeCorner PROTO(( short *, short * ));
+short extend PROTO(( short *, short * ));
+short noNbrs PROTO(( short, short ));
+short extend2 PROTO(( short *, short * ));
+short lookForSave PROTO(( short *, short * ));
+short lookForSaveN PROTO(( short *, short * ));
+short lookForKill PROTO(( short *, short * ));
+short doubleAtari PROTO(( short *, short * ));
+short lookForAttack PROTO(( short *, short * ));
+short threaten PROTO(( short *, short * ));
+short connectCut PROTO(( short *, short * ));
+short heCanCut PROTO(( short, short ));
+short safeMove PROTO(( short, short ));
+short extendWall PROTO(( short *, short * ));
+short findAttack2 PROTO(( short *, short * ));
+short blockCut PROTO(( short *, short * ));
+short cutHim PROTO(( short *, short * ));
+short atariAnyway PROTO(( short *, short * ));
+short underCut PROTO(( short *, short * ));
+short dropToEdge PROTO(( short *, short * ));
+short pushWall PROTO(( short *, short * ));
+short reduceHisLiberties PROTO(( short *, short * ));
+short dropToEdge2 PROTO(( short *, short * ));
+
+
+/* goplayutils.c */
+
+short saveable PROTO((short, short, short *, short *));
+short killable PROTO((short, short, short *, short *));
+int initBoolBoard PROTO((boolBoard));
+int intersectPlist PROTO((pointList *, pointList *, pointList *));
+int initArray PROTO((intBoard));
+int initState PROTO(());
+int copyArray PROTO((intBoard, intBoard));
+int stake PROTO(());
+int spread PROTO(());
+int respreicen PROTO(());
+int tryPlay PROTO((short, short, short));
+int saveState PROTO(());
+int restoreState PROTO(());
+short tencen PROTO((short, short));
+int genConnects PROTO(());
+int sortLibs PROTO(());
+
+
+/*-- from xinterface.c --*/
+void removestone PROTO((short, short));
+void placestone PROTO((enum bVal, short, short));
+
+void intrMoveReport PROTO((enum bVal,char *,char *));
+void intrPrisonerReport PROTO(( short, short ));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/noncore/games/go/go.h b/noncore/games/go/go.h
new file mode 100644
index 0000000..9aa644b
--- a/dev/null
+++ b/noncore/games/go/go.h
@@ -0,0 +1,81 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+/* AmiGo Include */
+/* MSG types for getinput() */
+
+#ifndef __go_h
+#define __go_h
+
+
+#define INTERSECTIONMSG 1 /* User buttoned an intersection */
+#define QUITMSG 2 /* User buttoned QUIT icon */
+#define PLAYMSG 3
+#define RESTARTMSG 4
+#define PASSMSG 5
+
+#define TRUE 1
+#define FALSE 0
+
+#define MAXGROUPS 100
+
+#define PLACED 0
+#define REMOVED 1
+
+#define numPoints 19
+#define maxPoint numPoints - 1
+
+/*-- definitions used when counting up --*/
+
+#define CNT_UNDECIDED 0
+#define CNT_BLACK_TERR 1
+#define CNT_WHITE_TERR 2
+#define CNT_NOONE 3
+
+/*-- macro functions --*/
+
+#define LegalPoint(x,y) (x>=0 && x<=18 && y>=0 && y<=18)
+#define ForeachPoint(a,b) for(a=0;a<19;a++) for (b=0;b<19;b++)
+
+enum bVal {BLACK, WHITE, EMPTY};
+typedef enum bVal sType;
+struct Group
+{
+ enum bVal color; /* The color of the group */
+ short code, /* The code used to mark stones in the group */
+ count, /* The number of stones in the group */
+ internal, /* The number of internal liberties */
+ external, /* The number of external liberties */
+ liberties, /* The total number of liberties */
+ eyes, /* The number of eyes */
+ alive, /* A judgement of how alive this group is */
+ territory; /* The territory this group controls */
+};
+
+struct bRec
+{
+ enum bVal Val; /* What is at this intersection */
+ short xOfs,
+ yOfs;
+ short mNum;
+ short GroupNum; /* What group the stone belongs to */
+ short marked; /* TRUE or FALSE */
+};
+
+#endif
diff --git a/noncore/games/go/go.pro b/noncore/games/go/go.pro
new file mode 100644
index 0000000..deb90c5
--- a/dev/null
+++ b/noncore/games/go/go.pro
@@ -0,0 +1,19 @@
+DESTDIR = ../bin
+TEMPLATE = app
+CONFIG = qt warn_on release
+HEADERS = amigo.h \
+ go.h \
+ goplayutils.h \
+ gowidget.h
+SOURCES = amigo.c \
+ goplayer.c \
+ goplayutils.c \
+ killable.c \
+ gowidget.cpp \
+ main.cpp
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+TARGET = go
+
+TRANSLATIONS = ../i18n/de/go.ts \ No newline at end of file
diff --git a/noncore/games/go/goplayer.c b/noncore/games/go/goplayer.c
new file mode 100644
index 0000000..88c0f61
--- a/dev/null
+++ b/noncore/games/go/goplayer.c
@@ -0,0 +1,1499 @@
+/* The go player */
+/* Ported from Pascal to C by Todd R. Johnson 4/17/88 */
+/* From the original pascal file:
+Go Move Generator
+Copyright (c) 1983 by Three Rivers Computer Corp.
+
+Written: January 17, 1983 by Stoney Ballard
+Edit History:
+*/
+
+#include "go.h"
+#include "goplayutils.h"
+#include "amigo.h"
+
+#define BIGGEST 32767 /* maximum value for short */
+
+/* From go.c */
+extern struct bRec goboard[19][19];
+extern short ko, koX, koY;
+
+/* From goplayutils.c */
+extern intBoard bord;
+extern intBoard ndbord;
+extern intBoard claim;
+extern intBoard legal;
+extern intBoard connectMap;
+extern intBoard threatBord;
+extern short maxGroupID;
+extern short treeLibLim;
+extern short killFlag;
+extern short depthLimit;
+extern short showTrees;
+extern short utilPlayLevel;
+extern groupRec gList[maxGroup];
+extern short sGlist[maxGroup + 1];
+extern pointList pList;
+extern pointList pList1;
+extern pointList plist2;
+extern pointList plist3;
+extern intBoard groupIDs;
+extern intBoard protPoints;
+extern sType mySType;
+
+
+short saveNLibs;
+pointList dapList1, dapList2, dapList3;
+char *playReason;
+short maxPlayLevel = 7;
+short playLevel = 7;
+
+genBord(color)
+ enum bVal color;
+{
+ short x, y, nomoves = TRUE;
+ char mv[8];
+
+ maxPlayLevel = 7;
+ utilPlayLevel = playLevel;
+ mySType = color;
+ if (playLevel < 2)
+ treeLibLim = 2;
+ else
+ treeLibLim = 3;
+ depthLimit = 100;
+ for (y = 0; y <= 18; y++)
+ for (x = 0; x <= 18; x++)
+ if (goboard[x][y].Val == color)
+ {
+ bord[x][y] = 1;
+ legal[x][y] = FALSE;
+ nomoves = FALSE;
+ }
+ else if (goboard[x][y].Val == EMPTY)
+ {
+ bord[x][y] = 0;
+ legal[x][y] = TRUE;
+ }
+ else
+ {
+ bord[x][y] = -1;
+ legal[x][y] = FALSE;
+ nomoves = FALSE;
+ }
+ if (ko)
+ {
+ legal[koX][koY] = FALSE;
+ }
+
+ if (! nomoves)
+ genState();
+ else
+ initGPUtils();
+}
+
+
+short getMove( x, y )
+short *x, *y;
+{
+ if (takeCorner(x, y)) return TRUE;
+ if (lookForSave(x, y)) return TRUE;
+ if (lookForSaveN(x, y)) return TRUE;
+ if (extend(x, y)) return TRUE;
+ if (lookForKill(x, y)) return TRUE;
+ if (doubleAtari(x, y)) return TRUE;
+ if (lookForAttack(x, y)) return TRUE;
+ if (threaten(x, y)) return TRUE;
+ if (extend2(x, y)) return TRUE;
+ if (connectCut(x, y)) return TRUE;
+ if (blockCut(x, y)) return TRUE;
+ if (cutHim(x, y)) return TRUE;
+ if (extendWall(x, y)) return TRUE;
+ if (findAttack2(x, y)) return TRUE;
+ if (atariAnyway(x, y)) return TRUE;
+ if (underCut(x, y)) return TRUE;
+ if (dropToEdge(x, y)) return TRUE;
+ if (pushWall(x, y)) return TRUE;
+ if (reduceHisLiberties(x, y)) return TRUE;
+ if (dropToEdge2(x, y)) return TRUE;
+ return FALSE;
+}
+
+short genMove( color, x, y )
+enum bVal color;
+short *x, *y;
+{
+ if (playLevel > 2)
+ saveNLibs = TRUE;
+ else
+ saveNLibs = FALSE;
+ genBord(color);
+ if (getMove(x, y))
+ return TRUE;
+ return FALSE;
+}
+
+short checkPos(x, y, field)
+short x, y, field;
+{
+ short ok;
+ ok = (((field == 0) && (claim[x][y] == 0)) ||
+ ((field > 0) &&
+ (claim[x][y] >= 0) && (claim[x][y] <= field)) ||
+ ((field < 0) &&
+ (claim[x][y] <= 0) && (claim[x][y] >= field))) &&
+ (bord[x-1][y] == 0) &&
+ (bord[x+1][y] == 0) &&
+ (bord[x][y-1] == 0) &&
+ (bord[x][y+1] == 0);
+ if (ok) return TRUE; else return FALSE;
+}
+
+short takeCorner( x, y )
+short *x, *y;
+{
+ short field = -1, i;
+ i = 18 - 3;
+ playReason = "takeCorner";
+ while (field != -4)
+ {
+ if (field == -1) field = 0;
+ else if (field == 0) field = 4;
+ else field = -4;
+ if (checkPos(2, 3, field)) { *x = 2; *y = 3; return TRUE; }
+ if (checkPos(3, 2, field)) { *x = 3; *y = 2; return TRUE; }
+ if (checkPos(2, i, field)) { *x = 2; *y = i; return TRUE; }
+ if (checkPos(3, i + 1, field)) { *x = 3; *y = i+1; return TRUE; }
+ if (checkPos(i, i + 1, field)) { *x = i; *y = i+1; return TRUE; }
+ if (checkPos(i + 1, i, field)) { *x = i+1; *y = i; return TRUE; }
+ if (checkPos(i, 2, field)) { *x = i; *y = 2; return TRUE; }
+ if (checkPos(i + 1, 3, field)) { *x = i+1; *y = 3; return TRUE; }
+ if (checkPos(2, 4, field)) { *x = 2; *y = 4; return TRUE; }
+ if (checkPos(4, 2, field)) { *x = 4; *y = 2; return TRUE; }
+ if (checkPos(2, i - 1, field)) { *x = 2; *y = i-1; return TRUE; }
+ if (checkPos(4, i + 1, field)) { *x = 4; *y = i+1; return TRUE; }
+ if (checkPos(i - 1, i + 1, field)) { *x = i-1; *y = i+1; return TRUE; }
+ if (checkPos(i + 1, i - 1, field)) { *x = i+1; *y = i-1; return TRUE; }
+ if (checkPos(i + 1, 4, field)) { *x = i+1; *y = 4; return TRUE; }
+ if (checkPos(i - 1, 2, field)) { *x = i-1; *y = 2; return TRUE; }
+ }
+ return FALSE;
+}
+
+printBoard(brd, name)
+intBoard brd;
+char *name;
+{
+ short x, y;
+ printf( "%s\n", name );
+ for (y = 0; y <= 18; y++)
+ {
+ for (x = 0; x <= 18; x++)
+ printf("%d ", brd[x][y]);
+ printf("\n");
+ }
+}
+
+short noNbrs( x, y )
+short x, y;
+{
+ if (x > 0 && bord[x-1][y] != 0) return FALSE;
+ if (x < 18 && bord[x+1][y] != 0) return FALSE;
+ if (y > 0 && bord[x][y-1] != 0) return FALSE;
+ if (y < 18 && bord[x][y+1] != 0) return FALSE;
+ return TRUE;
+}
+
+short extend(x, y)
+short *x, *y;
+{
+ short i;
+ playReason = "extend";
+ for (i = 2; i <= 18-2; i++)
+ if (claim[2][i] == 0 && noNbrs( 2, i ))
+ {
+ *x = 2;
+ *y = i;
+ return TRUE;
+ }
+ for (i = 2; i <= 18-2; i++)
+ if (claim[i][18-2] == 0 && noNbrs( 2, i ))
+ {
+ *x = i;
+ *y = 18-2;
+ return TRUE;
+ }
+ for (i = 18-2; i >= 2; i--)
+ if (claim[18-2][i] == 0 && noNbrs( 18-2, i ))
+ {
+ *x = 18-2;
+ *y = i;
+ return TRUE;
+ }
+ for (i = 18-2; i >= 2; i--)
+ if (claim[i][2] == 0 && noNbrs( i, 2 ))
+ {
+ *x = i;
+ *y = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+short extend2( x, y )
+short *x, *y;
+{
+ short i, lowest = BIGGEST, value;
+ playReason = "extend2";
+ for (i = 3; i <= 18-3; i++)
+ if (legal[2][i]) /* if there is nobody there */
+ {
+ value = claim[2][i]; /* get influence */
+ if ((value < 7) && /* a reasonable hole in my wall */
+ (value > -5) && /* or a reasonable gap in his */
+ (bord[2][i + 1] == 0) && /* not in contact with any stones */
+ (bord[2][i - 1] == 0))
+ if (value < lowest)
+ {
+ lowest = value; /* lowest gets the smallest value */
+ *x = 2; /* that was seen along all the 3-lines */
+ *y = i; /* x and y save that location */
+ }
+ }
+ for (i = 3; i <= 18-3; i++)
+ if (legal[i][2])
+ {
+ value = claim[i][2];
+ if ((value < 7) &&
+ (value > -5) &&
+ (bord[i + 1][2] == 0) &&
+ (bord[i - 1][2] == 0))
+ if (value < lowest)
+ {
+ lowest = value;
+ *x = i;
+ *y = 2;
+ }
+ }
+ for (i = 18-3; i >= 3; i--)
+ if (legal[18 - 2][i])
+ {
+ value = claim[18 - 2][i];
+ if ((value < 7) &&
+ (value > -5) &&
+ (bord[18 - 2][i + 1] == 0) &&
+ (bord[18 - 2][i - 1] == 0))
+ if (value < lowest)
+ {
+ lowest = value;
+ *x = 18 - 2;
+ *y = i;
+ }
+ }
+ for (i = 3; i <= 18-3; i++)
+ if (legal[i][18 - 2])
+ {
+ value = claim[i][18 - 2];
+ if ((value < 7) &&
+ (value > -5) &&
+ (bord[i + 1][18 - 2] == 0) &&
+ (bord[i - 1][18 - 2] == 0))
+ if (value < lowest)
+ {
+ lowest = value;
+ *x = i;
+ *y = 18 - 2;
+ }
+ }
+ if (lowest == BIGGEST) return FALSE;
+ return TRUE;
+}
+
+ /*
+ check to see if I can save anything in atari
+ */
+short lookForSave(x, y)
+short *x, *y;
+ { /* lookForSave */
+ short i;
+ playReason = "lookForSave";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC == 1) &&
+ (ndbord[gList[i].lx][gList[i].ly] == 1))
+ if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
+ return TRUE;
+ return FALSE;
+ } /* lookForSave */
+
+ /*
+ check to see if I can save anything with n libs
+ */
+short lookForSaveN(x, y)
+short *x, *y;
+ { /* lookForSaveN */
+ short i;
+ if (saveNLibs)
+ {
+ playReason = "lookForSaveN";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC > 1) &&
+ (gList[i].libC <= treeLibLim) &&
+ (ndbord[gList[i].lx][gList[i].ly] == 1))
+ {
+ if (killable(gList[i].lx, gList[i].ly, x, y))
+ if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* lookForSaveN */
+
+
+/*----------------------------------------------------------------
+-- lookForKill() --
+-- check to see if I can kill anything. --
+----------------------------------------------------------------*/
+short
+lookForKill(x, y)
+ short *x, *y;
+{
+ short i;
+ char mv[8];
+
+ playReason = "lookForKill";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC == 1) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ { /* we found a live enemy group with one liberty */
+ /* find the liberty */
+ spanGroup(gList[i].lx, gList[i].ly, &pList);
+ *x = pList.p[1].px;
+ *y = pList.p[1].py;
+ if (legal[*x][*y])
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+short doubleAtari(x, y)
+short *x, *y;
+ { /* doubleAtari */
+ short i, j;
+ playReason = "doubleAtari";
+ for (i = 1; i <= maxGroupID - 1; i++)
+ if ((gList[i].libC == 2) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1)) /* found an atariable group of his */
+ {
+ spanGroup(gList[i].lx, gList[i].ly, &dapList1);
+ for (j = i + 1; j <= maxGroupID; j++)
+ if ((gList[j].libC == 2) &&
+ (ndbord[gList[j].lx][gList[j].ly] == -1))
+ {
+ spanGroup(gList[j].lx, gList[j].ly, &dapList2);
+ intersectPlist(&dapList1, &dapList2, &dapList3);
+ if (dapList3.indx > 0)
+ if (legal[dapList3.p[1].px][dapList3.p[1].py])
+ {
+ tryPlay(dapList3.p[1].px, dapList3.p[1].py, 1);
+ if (gList[groupIDs[dapList3.p[1].px][
+ dapList3.p[1].py]].libC > 1)
+ {
+ *x = dapList3.p[1].px;
+ *y = dapList3.p[1].py;
+ restoreState();
+ return TRUE;
+ }
+ restoreState();
+ }
+ }
+ }
+ return FALSE;
+ } /* doubleAtari */
+
+short lookForAttack(x, y)
+short *x, *y;
+ { /* lookForAttack */
+ short tx, ty, i;
+ playReason = "lookForAttack";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((! gList[i].isLive) &&
+ (gList[i].libC > 1) &&
+ (gList[i].libC <= (treeLibLim + 1)) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ {
+ if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
+ {
+ *x = tx; /* yep - do so */
+ *y = ty;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* lookForAttack */
+
+ /*
+ Plays a move that requires a response on the opponent's part
+ */
+short threaten(x, y)
+short *x, *y;
+ { /* threaten */
+ short i, j, gx, gy, tNum;
+ playReason = "threaten";
+ initArray(threatBord);
+ for (i = 1; i <= maxGroupID; i++)
+ if ((! gList[i].isLive) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ {
+ spanGroup(gList[i].lx, gList[i].ly, &pList);
+ for (j = 1; j <= pList.indx; j++)
+ if (legal[pList.p[j].px][pList.p[j].py])
+ {
+ tryPlay(pList.p[j].px, pList.p[j].py, 1);
+ if (gList[groupIDs[pList.p[j].px][pList.p[j].py]].libC > 1)
+ if (killable(gList[i].lx, gList[i].ly, &gx, &gy))
+ threatBord[pList.p[j].px][pList.p[j].py] += 1;
+ restoreState();
+ }
+ }
+ tNum = 0;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if ((threatBord[i][j] > tNum) &&
+ ((threatBord[i][j] > 1) ||
+ (connectMap[i][j] > 0)))
+ {
+ tNum = threatBord[i][j];
+ *x = i;
+ *y = j;
+ }
+ if (tNum > 0) return TRUE;
+ else return FALSE;
+ } /* threaten */
+
+ /*
+ connects against enemy cuts
+ */
+short connectCut(x, y)
+short *x, *y;
+ { /* connectCut */
+ short i, j, nap, gid, infl;
+ playReason = "connectCut";
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j] &&
+ (protPoints[i][j] == 0)) /* not a protected point */
+ {
+ nap = 0; /* how many of my stones am I adjacent to? */
+ if ((i > 0) && (bord[i - 1][j] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i - 1;
+ pList.p[nap].py = j;
+ }
+ if ((j > 0) && (bord[i][j - 1] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j - 1;
+ }
+ if ((i < maxPoint) && (bord[i + 1][j] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i + 1;
+ pList.p[nap].py = j;
+ }
+ if ((j < maxPoint) && (bord[i][j + 1] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j + 1;
+ }
+ if (nap == 1) /* possible knight's || 2-point extention */
+ {
+ gid = groupIDs[pList.p[1].px][pList.p[1].py];
+ if ((i > 0) && (i < maxPoint) &&
+ (ndbord[i - 1][j] == 1) &&
+ (ndbord[i + 1][j] == 0)) /* contact on left */
+ {
+ if (((j > 0) && (ndbord[i][j - 1] == -1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
+ (i < (maxPoint - 1)) &&
+ (ndbord[i + 2][j] == 1) &&
+ (gid != groupIDs[i + 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((i < maxPoint) && (i > 0) &&
+ (ndbord[i + 1][j] == 1) &&
+ (ndbord[i - 1][j] == 0)) /* r */
+ {
+ if (((j > 0) && (ndbord[i][j - 1] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
+ (i > 1) &&
+ (ndbord[i - 2][j] == 1) &&
+ (gid != groupIDs[i - 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j - 1] == 1) &&
+ (ndbord[i][j + 1] == 0)) /* top */
+ {
+ if (((i > 0) && (ndbord[i - 1][j] == -1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
+ (j < (maxPoint - 1)) &&
+ (ndbord[i][j + 2] == 1) &&
+ (gid != groupIDs[i][j + 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j + 1] == 1) &&
+ (ndbord[i][j - 1] == 0)) /* bottom */
+ {
+ if (((i > 0) && (ndbord[i - 1][j] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
+ (j > 1) &&
+ (ndbord[i][j - 2] == 1) &&
+ (gid != groupIDs[i][j - 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ else if (nap == 2) /* diagonal or 1-point extention */
+ {
+ if (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py])
+ {
+ if ((pList.p[1].px != pList.p[2].px) &&
+ (pList.p[1].py != pList.p[2].py)) /* diag */
+ {
+ spanGroup(pList.p[1].px,
+ pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px,
+ pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ if (plist3.indx == 1)
+ if ((i > 0) && (ndbord[i - 1][j] == -1) ||
+ (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
+ (j > 0) && (ndbord[i][j - 1] == -1) ||
+ (j < maxPoint) && (ndbord[i][j + 1] == -1))
+ { /* must make direct connection */
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ else if (heCanCut(i, j))
+ { /* protect point if possible */
+ infl = 1000;
+ if ((i > 0) && legal[i - 1][j] &&
+ ((i == 1) || (ndbord[i - 2][j] == 0)) &&
+ ((j == 0) || (ndbord[i - 1][j - 1] == 0)) &&
+ ((j == maxPoint) ||
+ (ndbord[i - 1][j + 1] == 0)))
+ if (safeMove(i - 1, j))
+ if (claim[i - 1][j] < infl)
+ {
+ *x = i - 1;
+ *y = j;
+ infl = claim[i - 1][j];
+ }
+ if ((j > 0) && legal[i][j - 1] &&
+ ((j == 1) || (ndbord[i][j - 2] == 0)) &&
+ ((i == 0) || (ndbord[i - 1][j - 1] == 0)) &&
+ ((i == maxPoint) ||
+ (ndbord[i + 1][j - 1] == 0)))
+ if (safeMove(i, j - 1))
+ if (claim[i][j - 1] < infl)
+ {
+ *x = i;
+ *y = j - 1;
+ infl = claim[i][j - 1];
+ }
+ if ((i < maxPoint) && legal[i + 1][j] &&
+ ((i == (maxPoint - 1)) ||
+ (ndbord[i + 2][j] == 0)) &&
+ ((j == 0) || (ndbord[i + 1][j - 1] == 0)) &&
+ ((j == maxPoint) ||
+ (ndbord[i + 1][j + 1] == 0)))
+ if (safeMove(i + 1, j))
+ if (claim[i + 1][j] < infl)
+ {
+ *x = i + 1;
+ *y = j;
+ infl = claim[i + 1][j];
+ }
+ if ((j < maxPoint) && legal[i][j + 1] &&
+ ((j == (maxPoint - 1)) ||
+ (ndbord[i][j + 2] == 0)) &&
+ ((i == 0) || (ndbord[i - 1][j + 1] == 0)) &&
+ ((i == maxPoint) ||
+ (ndbord[i + 1][j + 1] == 0)))
+ if (safeMove(i, j + 1))
+ if (claim[i][j + 1] < infl)
+ {
+ *x = i;
+ *y = j + 1;
+ infl = claim[i][j + 1];
+ }
+ if (infl < 1000)
+ return TRUE;
+ *x = i; /* direct connection */
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else /* 1-point extension, only protect if threatened */
+ {
+ if ((i > 0) && (ndbord[i - 1][j] == -1) ||
+ (j > 0) && (ndbord[i][j - 1] == -1) ||
+ (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
+ (j < maxPoint) && (ndbord[i][j + 1] == -1))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ }
+ else if (nap == 3) /* unprotected, but me on 3 sides */
+ {
+ if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]) ||
+ (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[3].px][pList.p[3].py]) ||
+ (groupIDs[pList.p[3].px][pList.p[3].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]))
+ {
+ spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
+ intersectPlist(&plist2, &plist3, &pList1);
+ if (pList1.indx == 1) /* a common connect point */
+ if (heCanCut(i, j))
+ if (safeMove(i, j))
+ {
+ *x = i;
+ *y = j;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+ } /* connectCut */
+
+short heCanCut(x, y)
+short x, y;
+ { /* heCanCut */
+ short gx, gy, result;
+ if (playLevel > 3)
+ {
+ tryPlay(x, y, -1); /* try his cut */
+ result = ! killable(x, y, &gx, &gy);
+ restoreState();
+ return result;
+ }
+ else
+ return FALSE;
+ } /* heCanCut */
+
+ /*
+ Checks out a move.
+ If my stone is not killable then true.
+ */
+short safeMove(x, y)
+short x, y;
+ { /* safeMove */
+ short gbx, gby, result;
+ tryPlay(x, y, 1); /* try playing at point */
+ if (killFlag) /* I shouldn't kill if lookForKill didn't */
+ result = FALSE;
+ else if (gList[groupIDs[x][y]].libC < 2)
+ { /* if it is in atari or dead */
+ result = FALSE; /* reject it */
+ }
+ else if (gList[groupIDs[x][y]].libC <= treeLibLim) /* see if killable */
+ if (playLevel > 0)
+ result = ! killable(x, y, &gbx, &gby);
+ else
+ result = TRUE;
+ else
+ result = TRUE;
+ restoreState();
+ return result;
+ } /* safeMove */
+
+ /*
+ Extends walls in a connected fashion.
+ Finds the lowest influence (mine) point that is connected to one
+ of my groups.
+ Only looks in the center of the board.
+ */
+short extendWall(x, y)
+short *x, *y;
+ { /* extendWall */
+ short infl, i, j;
+ playReason = "extendWall";
+ *x = iNil;
+ *y = iNil;
+ infl = 11;
+ for (i = 2; i <= maxPoint - 2; i++)
+ for (j = 2; j <= maxPoint - 2; j++)
+ if (legal[i][j])
+ if (connectMap[i][j] > 0)
+ if ((claim[i][j] < infl) &&
+ (ndbord[i - 1][j] < 1) &&
+ (ndbord[i + 1][j] < 1) &&
+ (ndbord[i][j - 1] < 1) &&
+ (ndbord[i][j + 1] < 1) &&
+ ((claim[i - 1][j] < 0) ||
+ (claim[i + 1][j] < 0) ||
+ (claim[i][j - 1] < 0) ||
+ (claim[i][j + 1] < 0)))
+ if (safeMove(i, j))
+ {
+ infl = claim[i][j];
+ *x = i;
+ *y = j;
+ }
+ if (*x != iNil) return TRUE;
+ return FALSE;
+ } /* extendWall */
+
+
+ /*
+ check to see if I can attack one of his groups
+ uses limited depth search so that it can work on larger lib counts
+ */
+short findAttack2(x, y)
+short *x, *y;
+ { /* findAttack2 */
+ short tx, ty, i, otll;
+ if (playLevel < 7)
+ return FALSE;
+ playReason = "findAttack2";
+ depthLimit = 8;
+ otll = treeLibLim;
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((! gList[i].isLive) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1) &&
+ (gList[i].libC > 1))
+ {
+ treeLibLim = 6;
+ if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
+ {
+ *x = tx; /* yep - do so */
+ *y = ty;
+ return TRUE;
+ }
+ treeLibLim = otll;
+ }
+ depthLimit = 100;
+ return FALSE;
+ } /* findAttack2 */
+
+
+ /*
+ blocks enemy cuts thru 1-point extensions
+ */
+short blockCut(x, y)
+short *x, *y;
+ { /* blockCut */
+ short i, j;
+ playReason = "blockCut";
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j])
+ {
+ if ((i > 0) && (j > 0) && (j < maxPoint))
+ {
+ if ((ndbord[i - 1][j] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (groupIDs[i - 1][j - 1] != groupIDs[i - 1][j + 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if ((i < maxPoint) && (j > 0) && (j < maxPoint))
+ {
+ if ((ndbord[i + 1][j] == -1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (groupIDs[i + 1][j - 1] != groupIDs[i + 1][j + 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if ((j > 0) && (i > 0) && (i < maxPoint))
+ {
+ if ((ndbord[i][j - 1] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (groupIDs[i - 1][j - 1] != groupIDs[i + 1][j - 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if ((j < maxPoint) && (i > 0) && (i < maxPoint))
+ {
+ if ((ndbord[i][j + 1] == -1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (groupIDs[i - 1][j + 1] != groupIDs[i + 1][j + 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ } /* blockCut */
+
+
+ /*
+ cuts the enemy
+ */
+short cutHim(x, y)
+short *x, *y;
+ { /* cutHim */
+ short i, j, nap, gid;
+ playReason = "cutHim";
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j])
+ {
+ nap = 0; /* how many of his stones am I adjacent to? */
+ if ((i > 0) && (ndbord[i - 1][j] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i - 1;
+ pList.p[nap].py = j;
+ }
+ if ((j > 0) && (ndbord[i][j - 1] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j - 1;
+ }
+ if ((i < maxPoint) && (ndbord[i + 1][j] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i + 1;
+ pList.p[nap].py = j;
+ }
+ if ((j < maxPoint) && (ndbord[i][j + 1] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j + 1;
+ }
+ if (nap == 1) /* possible knight's or 2-point extention */
+ {
+ gid = groupIDs[pList.p[1].px][pList.p[1].py];
+ if ((i > 0) && (i < maxPoint) &&
+ (ndbord[i - 1][j] == -1) &&
+ (connectMap[i][j] > 0)) /* contact on left */
+ {
+ if (((j > 0) &&
+ (ndbord[i + 1][j - 1] == -1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((j < maxPoint) &&
+ (ndbord[i + 1][j + 1] == -1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((i < (maxPoint - 1)) &&
+ (ndbord[i + 1][j] == 0) &&
+ (ndbord[i + 2][j] == -1) &&
+ (gid != groupIDs[i + 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((i < maxPoint) && (i > 0) &&
+ (ndbord[i + 1][j] == -1) &&
+ (connectMap[i][j] > 0)) /* r */
+ {
+ if (((j > 0) &&
+ (ndbord[i - 1][j - 1] == -1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((j < maxPoint) &&
+ (ndbord[i - 1][j + 1] == -1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((i > 1) &&
+ (ndbord[i - 1][j] == 0) &&
+ (ndbord[i - 2][j] == -1) &&
+ (gid != groupIDs[i - 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j - 1] == -1) &&
+ (connectMap[i][j] > 0)) /* top */
+ {
+ if (((i > 0) &&
+ (ndbord[i - 1][j + 1] == -1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((i < maxPoint) &&
+ (ndbord[i + 1][j + 1] == -1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((j < (maxPoint - 1)) &&
+ (ndbord[i][j + 1] == 0) &&
+ (ndbord[i][j + 2] == -1) &&
+ (gid != groupIDs[i][j + 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j + 1] == -1) &&
+ (connectMap[i][j] > 0)) /* bottom */
+ {
+ if (((i > 0) &&
+ (ndbord[i - 1][j - 1] == -1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((i < maxPoint) &&
+ (ndbord[i + 1][j - 1] == -1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((j > 1) &&
+ (ndbord[i][j - 1] == 0) &&
+ (ndbord[i][j - 2] == -1) &&
+ (gid != groupIDs[i][j - 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ else if (nap == 2) /* diagonal or 1-point extention */
+ {
+ if (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py])
+ {
+ if ((pList.p[1].px != pList.p[2].px) &&
+ (pList.p[1].py != pList.p[2].py)) /* diag */
+ {
+ spanGroup(pList.p[1].px,
+ pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px,
+ pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ if (plist3.indx == 1)
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else /* 1-point extension, only cut if connected */
+ {
+ if (connectMap[i][j] > 0)
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ }
+ else if (nap == 3) /* unprotected, but him on 3 sides */
+ {
+ if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]) ||
+ (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[3].px][pList.p[3].py]) ||
+ (groupIDs[pList.p[3].px][pList.p[3].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]))
+ {
+ spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
+ intersectPlist(&plist2, &plist3, &pList1);
+ if (pList1.indx == 1) /* a common connect point */
+ if (safeMove(i, j))
+ {
+ *x = i;
+ *y = j;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+ } /* cutHim */
+
+
+ /*
+ ataris a group just for the hell of it
+ */
+short atariAnyway(x, y)
+short *x, *y;
+ { /* atariAnyway */
+ short i;
+ playReason = "atariAnyway";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC == 2) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ {
+ spanGroup(gList[i].lx, gList[i].ly, &pList);
+ if (legal[pList.p[1].px][pList.p[1].py] &&
+ ((connectMap[pList.p[1].px][pList.p[1].py] > 0) ||
+ ((pList.p[1].px > 0) &&
+ (connectMap[pList.p[1].px - 1][pList.p[1].py] > 0)) ||
+ ((pList.p[1].px < maxPoint) &&
+ (connectMap[pList.p[1].px + 1][pList.p[1].py] > 0)) ||
+ ((pList.p[1].py > 0) &&
+ (connectMap[pList.p[1].px][pList.p[1].py - 1] > 0)) ||
+ ((pList.p[1].py < maxPoint) &&
+ (connectMap[pList.p[1].px][pList.p[1].py + 1] > 0))))
+ if (safeMove(pList.p[1].px, pList.p[1].py))
+ {
+ *x = pList.p[1].px;
+ *y = pList.p[1].py;
+ return TRUE;
+ }
+ if (legal[pList.p[2].px][pList.p[2].py] &&
+ ((connectMap[pList.p[2].px][pList.p[2].py] > 0) ||
+ ((pList.p[2].px > 0) &&
+ (connectMap[pList.p[2].px - 1][pList.p[2].py] > 0)) ||
+ ((pList.p[2].px < maxPoint) &&
+ (connectMap[pList.p[2].px + 1][pList.p[2].py] > 0)) ||
+ ((pList.p[2].py > 0) &&
+ (connectMap[pList.p[2].px][pList.p[2].py - 1] > 0)) ||
+ ((pList.p[2].py < maxPoint) &&
+ (connectMap[pList.p[2].px][pList.p[2].py + 1] > 0))))
+ if (safeMove(pList.p[2].px, pList.p[2].py))
+ {
+ *x = pList.p[2].px;
+ *y = pList.p[2].py;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* atariAnyway */
+
+
+ /*
+ undercuts his groups
+ */
+short underCut(x, y)
+short *x, *y;
+ { /* underCut */
+ short i, j;
+ playReason = "underCut";
+ for (i = 1; i <= maxPoint - 1; i++)
+ {
+ if (legal[0][i])
+ {
+ if (ndbord[1][i] == -1)
+ if (safeMove(0, i))
+ {
+ *x = 0;
+ *y = i;
+ return TRUE;
+ }
+ }
+ if (legal[maxPoint][i])
+ {
+ if (ndbord[maxPoint - 1][i] == -1)
+ if (safeMove(maxPoint, i))
+ {
+ *x = maxPoint;
+ *y = i;
+ return TRUE;
+ }
+ }
+ if (legal[i][0])
+ {
+ if (ndbord[i][1] == -1)
+ if (safeMove(i, 0))
+ {
+ *x = i;
+ *y = 0;
+ return TRUE;
+ }
+ }
+ if (legal[i][maxPoint])
+ {
+ if (ndbord[i][maxPoint - 1] == -1)
+ if (safeMove(i, maxPoint))
+ {
+ *x = i;
+ *y = maxPoint;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ } /* underCut */
+
+ /*
+ drops to the edge of the board if threatened
+ */
+short dropToEdge(x, y)
+short *x, *y;
+ { /* dropToEdge */
+ short i;
+ playReason = "dropToEdge";
+ for (i = 1; i <= maxPoint - 1; i++)
+ {
+ if (legal[1][i])
+ if ((ndbord[2][i] == 1) &&
+ (ndbord[0][i] == 0) &&
+ (ndbord[1][i - 1] < 1) &&
+ (ndbord[1][i + 1] < 1) &&
+ ((ndbord[2][i - 1] == -1) ||
+ (ndbord[2][i + 1] == -1) ||
+ (ndbord[1][i - 1] == -1) ||
+ (ndbord[1][i + 1] == -1)))
+ {
+ *x = 1;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[maxPoint - 1][i])
+ if ((ndbord[maxPoint - 2][i] == 1) &&
+ (ndbord[maxPoint][i] == 0) &&
+ (ndbord[maxPoint - 1][i - 1] < 1) &&
+ (ndbord[maxPoint - 1][i + 1] < 1) &&
+ ((ndbord[maxPoint - 2][i - 1] == -1) ||
+ (ndbord[maxPoint - 2][i + 1] == -1) ||
+ (ndbord[maxPoint - 1][i - 1] == -1) ||
+ (ndbord[maxPoint - 1][i + 1] == -1)))
+ {
+ *x = maxPoint - 1;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][1])
+ if ((ndbord[i][2] == 1) &&
+ (ndbord[i][0] == 0) &&
+ (ndbord[i - 1][1] < 1) &&
+ (ndbord[i + 1][1] < 1) &&
+ ((ndbord[i - 1][2] == -1) ||
+ (ndbord[i + 1][2] == -1) ||
+ (ndbord[i - 1][1] == -1) ||
+ (ndbord[i + 1][1] == -1)))
+ {
+ *x = i;
+ *y = 1;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][maxPoint - 1])
+ if ((ndbord[i][maxPoint - 2] == 1) &&
+ (ndbord[i][maxPoint] == 0) &&
+ (ndbord[i - 1][maxPoint - 1] < 1) &&
+ (ndbord[i + 1][maxPoint - 1] < 1) &&
+ ((ndbord[i - 1][maxPoint - 2] == -1) ||
+ (ndbord[i + 1][maxPoint - 2] == -1) ||
+ (ndbord[i - 1][maxPoint - 1] == -1) ||
+ (ndbord[i + 1][maxPoint - 1] == -1)))
+ {
+ *x = i;
+ *y = maxPoint - 1;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[0][i])
+ if ((ndbord[1][i] == 1) &&
+ (ndbord[0][i - 1] < 1) &&
+ (ndbord[0][i + 1] < 1) &&
+ (((ndbord[1][i - 1] == -1) &&
+ (ndbord[1][i + 1] == -1)) ||
+ (ndbord[0][i - 1] == -1) ||
+ (ndbord[0][i + 1] == -1)))
+ {
+ *x = 0;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[maxPoint][i])
+ if ((ndbord[maxPoint - 1][i] == 1) &&
+ (ndbord[maxPoint][i - 1] < 1) &&
+ (ndbord[maxPoint][i + 1] < 1) &&
+ (((ndbord[maxPoint - 1][i - 1] == -1) &&
+ (ndbord[maxPoint - 1][i + 1] == -1)) ||
+ (ndbord[maxPoint][i - 1] == -1) ||
+ (ndbord[maxPoint][i + 1] == -1)))
+ {
+ *x = maxPoint;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][0])
+ if ((ndbord[i][1] == 1) &&
+ (ndbord[i - 1][0] < 1) &&
+ (ndbord[i + 1][0] < 1) &&
+ (((ndbord[i - 1][1] == -1) &&
+ (ndbord[i + 1][1] == -1)) ||
+ (ndbord[i - 1][0] == -1) ||
+ (ndbord[i + 1][0] == -1)))
+ {
+ *x = i;
+ *y = 0;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][maxPoint])
+ if ((ndbord[i][maxPoint - 1] == 1) &&
+ (ndbord[i - 1][maxPoint] < 1) &&
+ (ndbord[i + 1][maxPoint] < 1) &&
+ (((ndbord[i - 1][maxPoint - 1] == -1) &&
+ (ndbord[i + 1][maxPoint - 1] == -1)) ||
+ (ndbord[i - 1][maxPoint] == -1) ||
+ (ndbord[i + 1][maxPoint] == -1)))
+ {
+ *x = i;
+ *y = maxPoint;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* dropToEdge */
+
+ /*
+ Pushes walls in a tightly connected fashion.
+ Finds the lowest influence (mine) point that is connected to one
+ of my groups.
+ */
+short pushWall(x, y)
+short *x, *y;
+ { /* pushWall */
+ short infl, i, j, na;
+ playReason = "pushWall";
+ *x = iNil;
+ *y = iNil;
+ infl = 11;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j])
+ if (connectMap[i][j] > 0)
+ if ((claim[i][j] < infl) &&
+ (((i > 0) && (ndbord[i - 1][j] == 1)) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == 1)) ||
+ ((j > 0) && (ndbord[i][j - 1] == 1)) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == 1)) ||
+ ((i > 0) && (j > 0) && (ndbord[i - 1][j - 1] == 1)) ||
+ ((i < maxPoint) && (j > 0) && (ndbord[i + 1][j - 1] == 1)) ||
+ ((i > 0) && (j < maxPoint) && (ndbord[i - 1][j + 1] == 1)) ||
+ ((i < maxPoint) && (j < maxPoint) &&
+ (ndbord[i + 1][j + 1] == 1))) &&
+ (((i > 0) && (claim[i - 1][j] < 0)) ||
+ ((i < maxPoint) && (claim[i + 1][j] < 0)) ||
+ ((j > 0) && (claim[i][j - 1] < 0)) ||
+ ((j < maxPoint) && (claim[i][j + 1] < 0))))
+ {
+ na = 0;
+ if ((i > 0) && (ndbord[i - 1][j] != 0))
+ na = na + 1;
+ if ((i < maxPoint) && (ndbord[i + 1][j] != 0))
+ na = na + 1;
+ if ((j > 0) && (ndbord[i][j - 1] != 0))
+ na = na + 1;
+ if ((j < maxPoint) && (ndbord[i][j + 1] != 0))
+ na = na + 1;
+ if (na < 3)
+ if (safeMove(i, j))
+ {
+ infl = claim[i][j];
+ *x = i;
+ *y = j;
+ }
+ }
+ if (*x != iNil) return TRUE;
+ return FALSE;
+ } /* pushWall */
+
+
+ /*
+ reduces the liberty count of one of his groups
+ */
+short reduceHisLiberties(x, y)
+short *x, *y;
+ { /* reduceHisLiberties */
+ short i, j;
+ playReason = "reduceHisLiberties";
+ sortLibs();
+ for (i = 1; i <= maxGroupID; i++)
+ if ((! gList[sGlist[i]].isLive) &&
+ (gList[sGlist[i]].libC > 2) &&
+ (ndbord[gList[sGlist[i]].lx][gList[sGlist[i]].ly] == -1))
+ {
+ spanGroup(gList[sGlist[i]].lx, gList[sGlist[i]].ly, &pList);
+ for (j = 1; j <= pList.indx; j++)
+ if (legal[pList.p[j].px][pList.p[j].py] &&
+ (connectMap[pList.p[j].px][pList.p[j].py] > 0))
+ if (safeMove(pList.p[j].px, pList.p[j].py))
+ {
+ *x = pList.p[j].px;
+ *y = pList.p[j].py;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* reduceHisLiberties */
+
+
+ /*
+ connects a group to the edge
+ */
+short dropToEdge2(x, y)
+short *x, *y;
+ { /* dropToEdge2 */
+ short i;
+ playReason = "dropToEdge2";
+ for (i = 1; i <= maxPoint - 1; i++)
+ {
+ if (legal[i][0])
+ {
+ if ((ndbord[i][1] == 1) &&
+ ((ndbord[i - 1][0] < 1) ||
+ (groupIDs[i - 1][0] != groupIDs[i][1])) &&
+ ((ndbord[i + 1][0] < 1) ||
+ (groupIDs[i + 1][0] != groupIDs[i][1])) &&
+ ((ndbord[i - 1][1] == -1) ||
+ (ndbord[i + 1][1] == -1)))
+ {
+ *x = i;
+ *y = 0;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if (legal[0][i])
+ {
+ if ((ndbord[1][i] == 1) &&
+ ((ndbord[0][i - 1] < 1) ||
+ (groupIDs[0][i - 1] != groupIDs[1][i])) &&
+ ((ndbord[0][i + 1] < 1) ||
+ (groupIDs[0][i + 1] != groupIDs[1][i])) &&
+ ((ndbord[1][i - 1] == -1) ||
+ (ndbord[1][i + 1] == -1)))
+ {
+ *x = 0;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if (legal[i][maxPoint])
+ {
+ if ((ndbord[i][maxPoint - 1] == 1) &&
+ ((ndbord[i - 1][maxPoint] < 1) ||
+ (groupIDs[i - 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
+ ((ndbord[i + 1][maxPoint] < 1) ||
+ (groupIDs[i + 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
+ ((ndbord[i - 1][maxPoint - 1] == -1) ||
+ (ndbord[i + 1][maxPoint - 1] == -1)))
+ {
+ *x = i;
+ *y = maxPoint;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if (legal[maxPoint][i])
+ {
+ if ((ndbord[maxPoint - 1][i] == 1) &&
+ ((ndbord[maxPoint][i - 1] < 1) ||
+ (groupIDs[maxPoint][i - 1] != groupIDs[maxPoint - 1][i])) &&
+ ((ndbord[maxPoint][i + 1] < 1) ||
+ (groupIDs[maxPoint][i + 1] != groupIDs[maxPoint - 1][i])) &&
+ ((ndbord[maxPoint - 1][i - 1] == -1) ||
+ (ndbord[maxPoint - 1][i + 1] == -1)))
+ {
+ *x = maxPoint;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ } /* dropToEdge2 */
+
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 */
+
diff --git a/noncore/games/go/goplayutils.h b/noncore/games/go/goplayutils.h
new file mode 100644
index 0000000..11ab658
--- a/dev/null
+++ b/noncore/games/go/goplayutils.h
@@ -0,0 +1,85 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef __goplayutils_h
+#define __goplayutils_h
+
+#define iNil 32767 /* a distinguished value like nil */
+#define maxGroup 512
+#define maxSPoint 16
+#define tryLimit 300
+
+typedef short intBoard[19][19]; /* these were -2 to maxPoint + 2 */
+
+typedef short boolBoard[19][19];
+
+typedef struct
+{
+ short px, py;
+} point;
+
+typedef struct
+{
+ point p[401];
+ short indx;
+} pointList;
+
+typedef struct
+{
+ point p[maxSPoint+1];
+ short indx;
+} sPointList;
+
+typedef struct
+{
+ short indx,
+ v[401];
+} intList;
+
+typedef struct { short w, s, sm; } sgRec;
+
+typedef struct
+{
+ short groupMark,
+ atLevel,
+ isLive,
+ isDead,
+ libC,
+ numEyes,
+ size,
+ lx, ly;
+} groupRec;
+
+typedef enum {rem, add, chLib, reMap} playType;
+
+typedef struct { short who, xl, yl, nextGID, sNumber; } remAddRec;
+typedef struct { short oldLC, oldLevel; } chLibRec;
+typedef struct { short oldGID; } reMapRec;
+typedef struct
+{
+ short gID;
+ playType kind;
+ union {
+ remAddRec rem, add;
+ chLibRec chLib;
+ reMapRec reMap;
+ } uval;
+} playRec;
+
+#endif
diff --git a/noncore/games/go/gowidget.cpp b/noncore/games/go/gowidget.cpp
new file mode 100644
index 0000000..fca9797
--- a/dev/null
+++ b/noncore/games/go/gowidget.cpp
@@ -0,0 +1,449 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "gowidget.h"
+
+#include <qpe/config.h>
+#include <qpe/resource.h>
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qpe/qpetoolbar.h>
+#include <qpe/qpemenubar.h>
+#include <qpopupmenu.h>
+#include <qaction.h>
+#include <qapplication.h> //processEvents()
+#include <qlabel.h>
+
+//#include <stdio.h>
+
+#include "amigo.h"
+#include "goplayutils.h"
+
+static const enum bVal computer_color = BLACK;
+
+static int current_handicap = 1;
+
+static QBrush *goBrush;
+//static QImage *newBlackStone;
+//static QImage *blackStone;
+//static QImage *whiteStone;
+static QPixmap *newBlackStone;
+static QPixmap *blackStone;
+static QPixmap *whiteStone;
+
+GoMainWidget::GoMainWidget( QWidget *parent, const char* name) :
+ QMainWindow( parent, name )
+{
+ setToolBarsMovable( FALSE );
+ GoWidget *go = new GoWidget(this);
+
+ setCentralWidget(go);
+ toolbar = new QPEToolBar(this);
+ toolbar->setHorizontalStretchable( TRUE );
+ addToolBar(toolbar);
+
+ QPEMenuBar *mb = new QPEMenuBar( toolbar );
+ mb->setMargin(0);
+ QPopupMenu *file = new QPopupMenu( this );
+
+ QAction *a = new QAction( tr( "New Game" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), go, SLOT( newGame() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Pass" ), Resource::loadPixmap( "pass" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), go, SLOT( pass() ) );
+ a->addTo( file );
+ a->addTo( toolbar );
+
+
+ a = new QAction( tr( "Resign" ), Resource::loadPixmap( "reset" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), go, SLOT( resign() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Two player option" ), QString::null, 0, this, 0 );
+ a->setToggleAction( TRUE );
+ connect( a, SIGNAL( toggled(bool) ), go, SLOT( setTwoplayer(bool) ) );
+ a->addTo( file );
+
+ mb->insertItem( tr( "Game" ), file );
+
+ QLabel *turnLabel = new QLabel( toolbar );
+ turnLabel->setBackgroundMode( PaletteButton );
+ connect( go, SIGNAL(showTurn(const QPixmap&)),
+ turnLabel, SLOT(setPixmap(const QPixmap&)) );
+
+
+ QLabel * scoreLabel = new QLabel( toolbar );
+ scoreLabel->setBackgroundMode( PaletteButton );
+ connect( go, SIGNAL(showScore(const QString&)),
+ scoreLabel, SLOT(setText(const QString&)) );
+
+ toolbar->setStretchableWidget( scoreLabel );
+
+ go->readConfig();
+}
+
+void GoMainWidget::resizeEvent( QResizeEvent * )
+{
+ //### this won't work because of the text label...
+ /*
+ if ( width() > height() )
+ moveToolBar( toolbar, Left );
+ else
+ moveToolBar( toolbar, Top );
+ */
+}
+
+GoWidget *GoWidget::self = 0;
+
+GoWidget::GoWidget( QWidget *parent, const char* name) :
+ QWidget( parent, name )
+{
+ if ( self )
+ fatal( "Only one Go widget allowed" );
+ self = this;
+ twoplayer = FALSE;
+
+
+ d = bx = by = 1;
+
+ QPixmap pix = Resource::loadPixmap( "pine" );
+ goBrush = new QBrush( black, pix );
+ /*
+ QString fn = Resource::findPixmap("Go-black");
+ blackStone = new QImage( fn );
+ fn = Resource::findPixmap("Go-black-highlight");
+ newBlackStone = new QImage( fn );
+ fn = Resource::findPixmap("Go-white");
+ whiteStone = new QImage( fn );
+ */
+ blackStone = new QPixmap(Resource::loadPixmap( "Go-black" ));
+ whiteStone = new QPixmap(Resource::loadPixmap( "Go-white" ));
+ newBlackStone = new QPixmap(Resource::loadPixmap( "Go-black-highlight" ));
+
+ init();
+}
+
+GoWidget::~GoWidget()
+{
+ writeConfig();
+}
+
+void GoWidget::writeConfig()
+{
+ Config cfg("Go");
+ cfg.setGroup("Game");
+ cfg.writeEntry("TwoPlayer", twoplayer);
+ cfg.writeEntry("CurrentPlayer", currentPlayer);
+ cfg.writeEntry("NPassed", nPassed);
+ QString b;
+ for (int i=0; i<19; i++)
+ for (int j=0; j<19; j++)
+ b += board[i][j] == BLACK ? 'B' : board[i][j] == WHITE ? 'W' : '.';
+ cfg.writeEntry("Board", b);
+ cfg.writeEntry("LastX", lastX);
+ cfg.writeEntry("LastY", lastY);
+ extern int blackPrisoners, whitePrisoners;
+ cfg.writeEntry("BlackPrisoners", blackPrisoners);
+ cfg.writeEntry("WhitePrisoners", whitePrisoners);
+}
+
+void GoWidget::readConfig()
+{
+ init();
+ Config cfg("Go");
+ cfg.setGroup("Game");
+ twoplayer = cfg.readBoolEntry("TwoPlayer");
+ currentPlayer = (bVal)cfg.readNumEntry("CurrentPlayer",1);
+ nPassed = cfg.readNumEntry("NPassed",0);
+ QString b = cfg.readEntry("Board");
+ if ( b.length() == 19*19 )
+ for (int i=0; i<19; i++)
+ for (int j=0; j<19; j++) {
+ QChar ch = b[j+19*i];
+ if ( ch != '.' )
+ GoPlaceStone( ch == 'B' ? BLACK : WHITE, i, j );
+ }
+ lastX = cfg.readNumEntry("LastX");
+ lastY = cfg.readNumEntry("LastY");
+ extern int blackPrisoners, whitePrisoners;
+ blackPrisoners = cfg.readNumEntry("BlackPrisoners",0);
+ whitePrisoners = cfg.readNumEntry("WhitePrisoners",0);
+ reportPrisoners(blackPrisoners,whitePrisoners);
+ emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
+}
+
+void GoWidget::resizeEvent( QResizeEvent * )
+{
+ d = QMIN(width(),height())/19;
+ // int r = (d/2-1);
+ bx = (width() - 18*d)/2 ;
+ by = (height() - 18*d)/2 ;
+}
+
+void GoWidget::init()
+{
+ lastX = lastY = newX = newY = -1;
+ nPassed = 0;
+ for ( int i = 0; i < 19; i++ )
+ for ( int j = 0; j < 19; j++ )
+ board[i][j]=-1;
+ gameActive = TRUE;
+ goRestart(current_handicap);
+
+ if ( twoplayer ) {
+ currentPlayer = BLACK;
+ } else {
+ doComputerMove();
+ currentPlayer = WHITE;
+ }
+ emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
+}
+
+void GoWidget::paintEvent( QPaintEvent *e )
+{
+ int i,j;
+
+ int r = whiteStone->width()/2;
+
+ QPainter p(this);
+ p.fillRect( bx - d/2, by - d/2, 19*d, 19*d, *goBrush );
+
+ int xMin = QMAX( x2board(e->rect().left()), 0 );
+ int xMax = QMIN( x2board(e->rect().right()), 18 );
+ int yMin = QMAX( y2board(e->rect().top()), 0 );
+ int yMax = QMIN( y2board(e->rect().bottom()), 18 );
+
+ QColor pine( 255, 186, 89 );
+ p.setPen( pine.dark() );
+
+ for ( i = xMin; i < xMax+1 ; i ++ ) {
+ p.drawLine( bx+i*d, by, bx+i*d, by+18*d );
+ }
+ for ( j = yMin; j < yMax+1 ; j ++ ) {
+ p.drawLine( bx, by+j*d, bx+18*d, by+j*d);
+ }
+
+ // dots are at (3,3), (3,9), (3,15) and so on
+ p.setBrush( black );
+ for ( i = 3; i < xMax+1; i+=6 )
+ for ( j = 3; j < yMax+1; j+=6 )
+ p.drawEllipse( bx+i*d-2, by+j*d-2, 5, 5 );
+
+
+ for ( i = xMin; i < xMax+1; i++ )
+ for ( j = yMin; j < yMax+1; j++ ) {
+ if ( board[i][j] == WHITE ||
+ currentPlayer==WHITE && newX == i && newY == j )
+ p.drawPixmap( bx+i*d - r, by+j*d - r, *whiteStone );
+ else if ( i == lastX && j == lastY )
+ p.drawPixmap( bx+i*d - r, by+j*d - r, *newBlackStone );
+ else if ( board[i][j] == BLACK ||
+ currentPlayer==BLACK && newX == i && newY == j)
+ p.drawPixmap( bx+i*d - r, by+j*d - r, *blackStone );
+ }
+}
+
+void GoWidget::doMove( int x, int y )
+{
+
+ if ( !GoPlaceStone( currentPlayer, x, y ) ) {
+ //printf( "Illegal move (%d,%d)\n", x, y );
+ return;
+ }
+ //printf( "you do (%d,%d)\n", x, y );
+ nPassed = 0;
+ if ( twoplayer )
+ currentPlayer = (currentPlayer==WHITE) ? BLACK : WHITE;
+ else
+ doComputerMove();
+
+ emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
+
+}
+
+void GoWidget::pass()
+{
+ if ( !gameActive )
+ return;
+ nPassed++;
+ if ( nPassed >= 2 )
+ endGame();
+ else if ( !twoplayer )
+ doComputerMove();
+}
+
+void GoWidget::resign()
+{
+ if ( gameActive )
+ endGame();
+}
+
+
+void GoWidget::newGame()
+{
+ init();
+ update();
+}
+
+
+void GoWidget::endGame()
+{
+ gameActive = FALSE;
+
+ int w,b;
+ CountUp( &w, &b);
+ QString s = tr("White %1, Black %2. ").arg(w).arg(b);
+ if ( w > b )
+ s += tr("White wins.");
+ else if ( w < b )
+ s += tr("Black wins.");
+ else
+ s += tr("A draw.");
+ emit showScore( s );
+}
+
+void GoWidget::doComputerMove()
+{
+ int ox = lastX;
+ int oy = lastY;
+ lastX = lastY = -1;
+ emit showTurn( *blackStone );
+ refresh( ox, oy);
+ qApp->processEvents();
+ short int x,y;
+ if ( genMove( computer_color, &x, &y ) ) {
+ lastX = x;
+ lastY = y;
+ //printf( "I do (%d,%d)\n", x, y );
+ GoPlaceStone(computer_color,x,y);
+ nPassed = 0;
+ } else {
+ emit showScore( tr("I pass") );
+ nPassed++;
+ if ( nPassed >= 2 )
+ endGame();
+ }
+}
+
+void GoWidget::mousePressEvent( QMouseEvent *me )
+{
+ if ( !gameActive )
+ return;
+ int x = x2board(me->x());
+ int y = y2board(me->y());
+ showStone(x,y,currentPlayer);
+}
+
+void GoWidget::mouseMoveEvent( QMouseEvent *me )
+{
+ if ( !gameActive )
+ return;
+ int x = x2board(me->x());
+ int y = y2board(me->y());
+ if ( x != newX || y != newY )
+ showStone(x,y,currentPlayer);
+}
+
+void GoWidget::showStone( int x, int y, enum bVal c )
+{
+
+ if ( newX > -1 ) {
+ refresh( newX, newY );
+ newY = newX = -1;
+ }
+ if ( x < 0 || x > 18 || y < 0 || y > 18 ) {
+ newX = newY = -1;
+ return;
+ }
+ if ( board[x][y] == -1 && !Suicide( c, x, y ) ) {
+ newX = x;
+ newY = y;
+ refresh(x,y);
+ }
+
+}
+
+void GoWidget::mouseReleaseEvent( QMouseEvent * )
+{
+ if ( gameActive && newX > -1 )
+ doMove( newX, newY );
+ newX = newY = -1;
+}
+
+void GoWidget::refresh( int x, int y )
+{
+ update( bx+d*x-d/2-1, by+d*y-d/2-1, d+2, d+2 );
+}
+
+void GoWidget::removeStone(short x, short y)
+{
+ board[x][y]=-1;
+ refresh( x, y );
+}
+
+void GoWidget::placeStone (enum bVal c, short x, short y )
+{
+ board[x][y]=c;
+ refresh( x, y );
+}
+
+void GoWidget::reportPrisoners( int blackcnt, int whitecnt )
+{
+ QString s = tr( "Prisoners: black %1, white %2" ).arg(blackcnt).arg(whitecnt);
+ emit showScore( s );
+}
+
+void GoWidget::setTwoplayer( bool b )
+{
+ twoplayer = b;
+}
+
+void GoWidget::setHandicap( int h )
+{
+ current_handicap = h;
+}
+
+
+extern "C" {
+
+void removestone(short x, short y)
+{
+ GoWidget::self->removeStone(x,y);
+}
+
+void placestone (enum bVal c, short x, short y )
+{
+ GoWidget::self->placeStone(c,x,y);
+}
+
+void intrMoveReport(enum bVal c ,char *coord ,char *reason )
+{
+ qDebug( "intrMoveReport colour %d, %s %s", c, coord, reason );
+}
+
+void intrPrisonerReport( short blackcnt, short whitecnt )
+{
+ GoWidget::self->reportPrisoners(blackcnt,whitecnt);
+}
+
+}
+
diff --git a/noncore/games/go/gowidget.h b/noncore/games/go/gowidget.h
new file mode 100644
index 0000000..94de2cc
--- a/dev/null
+++ b/noncore/games/go/gowidget.h
@@ -0,0 +1,111 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef GOWIDGET_H
+#define GOWIDGET_H
+
+#include <qmainwindow.h>
+#include "amigo.h"
+
+
+class QToolBar;
+
+class GoMainWidget : public QMainWindow
+{
+ Q_OBJECT
+public:
+ GoMainWidget( QWidget *parent=0, const char* name=0);
+protected:
+ void resizeEvent( QResizeEvent * );
+private:
+ QToolBar *toolbar;
+
+};
+
+
+class QLabel;
+class GoWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ GoWidget( QWidget *parent=0, const char* name=0);
+ ~GoWidget();
+
+ void doMove( int x, int y );
+ void doComputerMove();
+
+ void readConfig();
+ void writeConfig();
+
+public slots:
+ void pass();
+ void resign();
+ void newGame();
+ void setTwoplayer( bool );
+ void setHandicap( int );
+signals:
+ void showScore( const QString& );
+ void showTurn( const QPixmap& );
+
+protected:
+ void paintEvent( QPaintEvent * );
+ void mousePressEvent( QMouseEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+ void mouseReleaseEvent( QMouseEvent * );
+ void resizeEvent( QResizeEvent * );
+private:
+ void init();
+ void removeStone(short x, short y);
+ void placeStone (enum bVal c, short x, short y );
+
+ void refresh( int x, int y );
+ void showStone( int x, int y, enum bVal );
+ void reportPrisoners(int,int);
+
+ inline int x2board( int x ) { return (x-bx+d/2)/d; }
+ inline int y2board( int y ) { return (y-by+d/2)/d; }
+
+ void endGame();
+
+ bool twoplayer;
+ enum bVal currentPlayer;
+ bool gameActive;
+ int nPassed;
+ signed char board[19][19];
+
+ int d; //distance between lines
+ int bx; //vertical baseline
+ int by; //horizontal baseline
+
+ int lastX,lastY;
+ int newX,newY;
+
+ static GoWidget *self;
+
+ friend void removestone(short x, short y);
+ friend void intrPrisonerReport( short, short );
+ friend void placestone(enum bVal c, short x, short y );
+};
+
+
+
+
+
+#endif
diff --git a/noncore/games/go/killable.c b/noncore/games/go/killable.c
new file mode 100644
index 0000000..3ed2d2e
--- a/dev/null
+++ b/noncore/games/go/killable.c
@@ -0,0 +1,373 @@
+/* By Stoney Ballard */
+/* Ported from Pascal to C by Todd R. Johnson */
+
+#include "go.h"
+#include "goplayutils.h"
+#include "amigo.h"
+
+extern intBoard bord, groupIDs;
+extern boolBoard legal;
+extern groupRec gList[maxGroup];
+extern short gMap[maxGroup], adjInAtari, adj2Libs, playMark, treeLibLim,
+ utilPlayLevel, killFlag, depthLimit, dbStop, showTrees;
+extern pointList plist2;
+
+/*
+ returns true if the group (at x, y) is killable.
+ if so, returns the point to play at in killx, killy.
+*/
+
+ short me, him, depth, i, j, tryCount, tl, topMark, tkMark, mark2;
+ char sChar;
+ sPointList lList, dList;
+ point tp;
+ short libList[maxSPoint+1];
+ short esc;
+
+short mtNbrs(x, y)
+short x, y;
+ { /* mtNbrs */
+ short n = 0;
+ if ((x > 0) && (bord[x - 1][y] == 0))
+ n = n + 1;
+ if ((x < maxPoint) && (bord[x + 1][y] == 0))
+ n = n + 1;
+ if ((y > 0) && (bord[x][y - 1] == 0))
+ n = n + 1;
+ if ((y < maxPoint) && (bord[x][y + 1] == 0))
+ n = n + 1;
+ return n;
+ } /* mtNbrs */
+
+short killTree(tx, ty, gx, gy, escape, tkMark)
+short tx, ty, gx, gy, *escape, tkMark;
+ { /* killTree */
+ short curMark, mark2, mark3, i, j, k, tl, dStart, result;
+ sPointList lList1, lList2;
+ short libList[maxSPoint+1];
+ point tp;
+ short esc = FALSE;
+ tryCount = tryCount + 1;
+ if (tryCount > tryLimit)
+ {
+ undoTo(tkMark);
+/* for (i = 1; i <= depth - 1; i++)
+ {
+ sClearChar(sChar, rXor);
+ } */
+ depth = 1;
+ return FALSE;
+ }
+/* write(sChar); */
+ depth = depth + 1;
+ curMark = playMark;
+ tryPlay(tx, ty, me); /* try my move */
+ pause();
+ if (gList[gMap[groupIDs[tx][ty]]].libC == 0) /* I'm dead */
+ {
+ result = FALSE;
+ goto one;
+ }
+ else if (killFlag) /* I killed something of his */
+ {
+ result = TRUE;
+ goto one;
+ }
+ else if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim) /* safe */
+ {
+ result = FALSE;
+ goto one;
+ }
+ else
+ {
+ sSpanGroup(gx, gy, &lList1); /* find his liberties */
+ if (gList[gMap[groupIDs[tx][ty]]].libC == 1) /* he can kill me */
+ {
+ if (lList1.indx < maxSPoint) /* add that option to his list */
+ {
+ lList1.indx = lList1.indx + 1;
+ spanGroup(tx, ty, &plist2); /* find my liberty */
+ lList1.p[lList1.indx].px = plist2.p[1].px;
+ lList1.p[lList1.indx].py = plist2.p[1].py;
+ }
+ else
+ {
+ result = FALSE;
+ goto one;
+ }
+ }
+ for (i = 1; i <= maxSPoint; i++) /* init liblist so diags can be marked */
+ libList[i] = -1;
+ if ((utilPlayLevel > 4) &&
+ (lList1.indx > 1) &&
+ (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* try diags */
+ {
+ listDiags(gx, gy, &dList);
+ j = 0;
+ i = lList1.indx;
+ while ((j < dList.indx) &&
+ (i < maxSPoint))
+ {
+ j = j + 1;
+ i = i + 1;
+ libList[i] = 0; /* mark this as a diag */
+ lList1.p[i].px = dList.p[j].px;
+ lList1.p[i].py = dList.p[j].py;
+ }
+ lList1.indx = i;
+ }
+ if (lList1.indx > 1) /* sort by decreasing lib count */
+ {
+ for (i = 1; i <= lList1.indx; i++)
+ if (libList[i] != 0) /* diags are tried last */
+ {
+ mark2 = playMark;
+ tryPlay(lList1.p[i].px, lList1.p[i].py, him);
+ libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
+ if ((libList[i] > treeLibLim) ||
+ ((libList[i] > (depthLimit - depth)) &&
+ (libList[i] > 2)))
+ {
+ *escape = TRUE;
+ result = FALSE;
+ goto one;
+ }
+ undoTo(mark2);
+ }
+ for (i = 1; i <= lList1.indx - 1; i++)
+ for (j = i + 1; j <= lList1.indx; j++)
+ if (libList[i] < libList[j])
+ {
+ tl = libList[i];
+ libList[i] = libList[j];
+ libList[j] = tl;
+ tp = lList1.p[i];
+ lList1.p[i] = lList1.p[j];
+ lList1.p[j] = tp;
+ }
+ }
+ for (i = 1; i <= lList1.indx + 1; i++) /* try his responses */
+ {
+ mark2 = playMark;
+ if (i <= lList1.indx) /* try his move */
+ {
+ tryPlay(lList1.p[i].px, lList1.p[i].py, him); /* play his response */
+ pause();
+ if (gList[gMap[groupIDs[lList1.p[i].px]
+ [lList1.p[i].py]]].libC < 2)
+ goto two; /* a bogus move */
+ }
+ else if (gList[gMap[groupIDs[gx][gy]]].libC <= 1)
+ {
+ result = TRUE;
+ goto one;
+ }
+ if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
+ {
+ *escape = TRUE;
+ result = FALSE;
+ goto one;
+ }
+ if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
+ { /* look at my responses */
+ sSpanGroup(gx, gy, &lList2); /* list his liberties */
+ dStart = lList2.indx + 1;
+ if (adjInAtari) /* he wins */
+ {
+ result = FALSE;
+ goto one;
+ }
+ if ((lList2.indx > 2) && adj2Libs) /* he wins */
+ {
+ result = FALSE;
+ goto one;
+ }
+ for (k = 1; k <= maxSPoint; k++)
+ libList[k] = -1;
+ if (utilPlayLevel > 4) /* account for diagonal moves */
+ {
+ listDiags(gx, gy, &dList);
+ j = 0;
+ k = lList2.indx;
+ while ((j < dList.indx) &&
+ (k < maxSPoint))
+ {
+ j = j + 1;
+ k = k + 1;
+ libList[k] = 100;
+ lList2.p[k].px = dList.p[j].px;
+ lList2.p[k].py = dList.p[j].py;
+ }
+ lList2.indx = k;
+ }
+ if (lList2.indx > 1) /* sort by increasing lib count */
+ {
+ for (k = 1; k <= lList2.indx; k++)
+ if (libList[k] != 100) /* diags go last */
+ {
+ mark3 = playMark;
+ tryPlay(lList2.p[k].px, lList2.p[k].py, me);
+ libList[k] = gList[gMap[groupIDs[gx][gy]]].libC;
+ undoTo(mark3);
+ }
+ for (k = 1; k <= lList2.indx - 1; k++)
+ for (j = k + 1; j <= lList2.indx; j++)
+ if (libList[k] > libList[j])
+ {
+ tl = libList[k];
+ libList[k] = libList[j];
+ libList[j] = tl;
+ tp = lList2.p[k];
+ lList2.p[k] = lList2.p[j];
+ lList2.p[j] = tp;
+ }
+ else if ((libList[k] == libList[j]) &&
+ (libList[k] == 1))
+ if (mtNbrs(lList2.p[k].px, lList2.p[k].py) <
+ mtNbrs(lList2.p[j].px, lList2.p[j].py))
+ {
+ tl = libList[k];
+ libList[k] = libList[j];
+ libList[j] = tl;
+ tp = lList2.p[k];
+ lList2.p[k] = lList2.p[j];
+ lList2.p[j] = tp;
+ }
+ }
+ for (j = 1; j <= lList2.indx; j++)
+ {
+ if (killTree(lList2.p[j].px, lList2.p[j].py, gx,
+ gy, &esc, tkMark))
+ goto two; /* this kills him */
+ if (esc && (j >= dStart))
+ {
+ result = FALSE;
+ goto one; /* don't bother with more diags if escapes */
+ }
+ }
+ result = FALSE; /* none of my responses kills him */
+ goto one;
+ }
+ two:
+ undoTo(mark2);
+ }
+ result = TRUE; /* none of his responses saves him */
+ }
+ one:
+ undoTo(curMark);
+/* sClearChar(sChar, rXor); */
+ depth = depth - 1;
+ return result;
+ } /* killTree */
+
+short tKillTree(tx, ty, gx, gy)
+short tx, ty, gx, gy;
+ { /* tKillTree */
+ short tkMark, escape;
+ tryCount = 0;
+ tkMark = playMark;
+ return killTree(tx, ty, gx, gy, &escape, tkMark);
+ } /* tKillTree */
+
+short killable(gx, gy, killx, killy)
+short gx, gy, *killx, *killy;
+{ /* killable */
+#ifdef DEBUG
+ printf( "killable\n" );
+ showTrees = TRUE;
+#endif
+ dbStop = TRUE;
+ him = bord[gx][gy]; /* find out who I am */
+ me = -him;
+/* if (me == 1)
+ sChar = '>';
+ else
+ sChar = '|'; */
+/* write(sChar); */
+ depth = 1;
+ topMark = playMark;
+ sSpanGroup(gx, gy, &lList); /* find his liberties */
+ if (lList.indx == 1)
+ {
+ *killx = lList.p[1].px;
+ *killy = lList.p[1].py;
+ return TRUE;
+ }
+ else if (lList.indx > treeLibLim)
+ return FALSE;
+ else if (adjInAtari)
+ return FALSE;
+ else if ((lList.indx > 2) && adj2Libs)
+ return FALSE;
+ else
+ {
+ for (i = 1; i <= maxSPoint; i++)
+ libList[i] = -1;
+ if (utilPlayLevel > 4) /* account for diagonal moves */
+ {
+ listDiags(gx, gy, &dList);
+ j = 0;
+ i = lList.indx;
+ while ((j < dList.indx) &&
+ (i < maxSPoint))
+ {
+ j = j + 1;
+ i = i + 1;
+ libList[i] = 100;
+ lList.p[i].px = dList.p[j].px;
+ lList.p[i].py = dList.p[j].py;
+ }
+ lList.indx = i;
+ }
+ if (lList.indx > 1) /* sort by increasing lib count */
+ {
+ for (i = 1; i <= lList.indx; i++)
+ if (libList[i] != 100) /* diags go last */
+ {
+ mark2 = playMark;
+ tryPlay(lList.p[i].px, lList.p[i].py, me);
+ libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
+ undoTo(mark2);
+ }
+ for (i = 1; i <= lList.indx - 1; i++)
+ for (j = i + 1; j <= lList.indx; j++)
+ if (libList[i] > libList[j])
+ {
+ tl = libList[i];
+ libList[i] = libList[j];
+ libList[j] = tl;
+ tp = lList.p[i];
+ lList.p[i] = lList.p[j];
+ lList.p[j] = tp;
+ }
+ else if ((libList[i] == libList[j]) &&
+ (libList[i] == 1))
+ if (mtNbrs(lList.p[i].px, lList.p[i].py) <
+ mtNbrs(lList.p[j].px, lList.p[j].py))
+ {
+ tl = libList[i];
+ libList[i] = libList[j];
+ libList[j] = tl;
+ tp = lList.p[i];
+ lList.p[i] = lList.p[j];
+ lList.p[j] = tp;
+ }
+ }
+ for (i = 1; i <= lList.indx; i++)
+ {
+ if (legal[lList.p[i].px][lList.p[i].py])
+ {
+ *killx = lList.p[i].px;
+ *killy = lList.p[i].py;
+ if (tKillTree(*killx, *killy, gx, gy))
+ {
+/* sClearChar(sChar, rXor); */
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ }
+/* sClearChar(sChar, rXor); */
+} /* killable */
+
diff --git a/noncore/games/go/main.cpp b/noncore/games/go/main.cpp
new file mode 100644
index 0000000..c7e2669
--- a/dev/null
+++ b/noncore/games/go/main.cpp
@@ -0,0 +1,35 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "gowidget.h"
+
+#include <qpe/qpeapplication.h>
+
+#include <stdio.h>
+
+int main( int argc, char ** argv)
+{
+ QPEApplication app( argc, argv );
+
+ GoMainWidget m;
+ m.setCaption( GoWidget::tr("Go") );
+ app.showMainWidget( &m );
+ return app.exec();
+}
diff --git a/noncore/games/go/qpe-go.control b/noncore/games/go/qpe-go.control
new file mode 100644
index 0000000..edc106b
--- a/dev/null
+++ b/noncore/games/go/qpe-go.control
@@ -0,0 +1,9 @@
+Files: bin/go apps/Games/go.desktop
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: The game of Go
+ A game for the Qtopia environment.