/* Go game AI for LCARS 24, adapted from Wally, by Bill Newman
*/
/* This program is free software. You may redistribute and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License or
 * (at your option) any later version.
 *
 * Refer to the file C:\LCARS24\DATA\COPYING.TXT for details.
 */


#ifndef GOAI_H
#define GOAI_H

#include <stdio.h>
#include <strings.h>
#include <assert.h>

# define  PATCHLEVEL	2
# define  WALLY_OUTPUT  0
# define  MGT_OUTPUT    1
# define  CAT_OUTPUT    2

/*
# define  M_LETTER(x)	\
	((x < 8) ? lettercol(x) : ((x == 8) ? 'i' : lettercol(x - 1)))

int outputmode = WALLY_OUTPUT;
#endif
*/

/*#define ASSERT 1*/	/* flag for whether assert() macros should be */
			/* expanded*/

#define BIGU 10000	/* a number higher than any meaningful "urgency" */
			/* or move importance */

#define RESIGN   -2	/* codes for resigning */
#define PASS     -1	/* passing moves */
#define BOTHPASS -3	/* code for both sides passed, game is over */

#define EDGE 23		/* max # intersections on the edge of a go board */
int edge;		/* the number of intersections which we are using (a */
			/* command line parameter) */

#define NPLAYERS 2	/* # players (hence # copies to keep of score &c.) */

int debugattack;	/* flag for printing debugging messages in GoAiAttack() */

/* Return the absolute value of i. */
#define abs(i) (i>=0?i:-i)

/* Return TRUE if (x,y) corresponds to a point on the board. */
#define on1board(x) (0<=x&&x<edge)
#define onboard(x,y) (on1board(x)&&on1board(y))

/* Return TRUE if (x,y) is on the edge of the board. */
#define onedge1(x) (0==x||edge-1==x)
#define onedge(x,y) (onedge1(x)||onedge1(y))

/* codes for players; and a code for something (e.g. a point on the board) */
/* which belongs to neither*/
#define BLACKSIDE 0
#define WHITESIDE 1
#define EMPTY 2
/* flags in shape table entries for types of points    */
#define F_BLACK 1	/* the point has a black stone */
#define F_WHITE 2	/* the point has a white stone */
#define F_EMPTY 4	/* the point is empty */
#define F_OFF   8	/* the point is off the board */

int evenmode;	/* Are we (against our better judgment) to play */
			/* an even game? */

/* Return TRUE if a move violates ko. */
#define ko(x,y) (thegame.kox==x &&thegame.koy==y)

/* Return the code for the other player, who is the next to play. */
#define nextp(p) (BLACKSIDE==p ? WHITESIDE : WHITESIDE== p? BLACKSIDE:\
	GoAiPanic("illegal input to nextp()"))

/*Return a letter corresponding to column x; 'i' is omitted from letter */
/* sequence by tradition.*/
#define lettercol(x) (							\
	  (0<=(x)&&(x)<=7) ? 'a'+(x) : (7<(x)&&(x)<edge) ? 'a'+(x)+1 :	\
	  GoAiPanic("illegal lettercol()") )

/*Convert any uppercase letter to lowercase.*/
#define lowercase(c) ('A'<=(c)&&(c)<='Z'?(c)-'A'+'a':(c))


/* Return TRUE if a move would leave the group it creates or attaches to */
/* in atari or dead. */
#define intoatari(x,y) (GoAiSubjLib(x,y)<=1)

/* a macro to abort the program if a test is not successful */

/*
#if ASSERT
#define assert(q) ((q)?1:(fprintf(stderr, \
"\n?!panic--failed assert() @ %s %d.\n", \
 __FILE__, __LINE__), fflush(stderr),exit(1)))
#else
#define	assert(q)
#endif
*/

/* ASCII character codes */
/* #define TAB 8 */


/* name of and pointer to output file */
char *ofname;
FILE *ofile;

/* name program uses for itself */
/*
char *progname= "Wally";
char version[]= "2.1";
*/

/* a struct for holding information on every square of the board */
typedef int goboard[EDGE][EDGE];

/* current position of stones on the board */
goboard wallyboard;


/* other information about the game */
struct thegame
{ int kox, koy;		/* coords of current ko, or negative for none */
  int pla;		/* code for next player to play */
  int tur;		/* the number of this move */
  int qpa;		/* flag for the last move was a pass, so that if this */
			/* move is a pass, that's all folx */
} thegame;

typedef struct group
{ int	color,		/*the color of stones in this group*/
	nliberties,	/*the number of liberties that this group has*/
	nstones,	/*the number of stones in this group*/
	x, y;		/*one point in this group*/
} group;
group groups[EDGE*EDGE]; /*(EDGE*EDGE is a lazy bound; the number of groups */
			/* of groups must be less than number of points)*/
int ngroups;

/*handicap stones for the 3 common board sizes*/
/*
int handi9[]= { 2, 2,	6, 2,	2, 6,	6, 6 } ;
int handi13[]= { 2, 2,	2, 6,	2, 10,
		 6, 2,	6, 6,	6, 10,
		10, 2,	10, 6, 	10, 10 } ;
#if 0

int handi19[]= { 15, 3, 15, 6,	15, 9,	15, 12,	15, 15,
		 12, 3,				12, 15,
		 9,  3,		9, 9,		9, 15,
		 6, 3, 				6, 15,
		 3, 3,	3, 6,	3, 9,	3, 12,	3, 15 } ;
#else
int handi19[]= { 15, 3, 	15, 9,		15, 15,
		 9,  3,		9, 9,		9, 15,
		 3, 3,		3, 9,		3, 15 } ;
#endif

int nhandicap[]=
{ 0, 0, 0, 0, 0,
  0, 0, 0, 0, sizeof(handi9)/(2*sizeof(int)),
  0, 0, 0, sizeof(handi13)/(2*sizeof(int)), 0,
  0, 0, 0, 0, sizeof(handi19)/(2*sizeof(int))
} ;
int *handicap[]=
{ 0, 0, 0, 0, 0,
  0, 0, 0, 0, handi9,
  0, 0, 0, handi13, 0,
  0, 0, 0, 0, handi19
} ;
*/


/*a variable for debugging -- records the number of the pattern the */
/* program thinks it has matched, so when the program makes a bizarre */
/* move and claims that this helps it make shape, I can see what pattern */
/* has gone wrong*/

int patnum;

/*Where did the enemy last move?  This is used to help decide which patterns */
/* are most important (try to leech off enemy's greater expertise).*/

int lex, ley;

/*
a table of moves the heuristics are ambivalent about, for
random selection
*/

int goodmoves[2*EDGE*EDGE];
int *pgoodmoves;	/* &next free space in goodmoves[] */


/* for the LCARS interface */

int ComputerMoveX;
int ComputerMoveY;
int MessageY;
int BlackScore;
int WhiteScore;
int Opponent;
char AtariWarning;

/* Functions in GoAi.c */

int GoAiFatal(char *message);
int GoAiPanic(char *message);
int GoAiRng(int n); /* Return a (slightly) random number from 0 to n-1.*/
void GoAiInitGame(int handicap);
void GoAiRemoveStone(int x, int y); /* all stones of the group */
int GoAiCapture(int p, int *capx, int *capy); /* all of p's dead stones */
void GoAiMoveDone();
void GoAiCount(int x, int y, group *thisgroup, goboard scratch, int mark);
int GoAiMakeGroups();
int GoAiPlaceStone(int x, int y, int p);
void GoAiSortV(group **p, int n);

int GoAiSubjLib(int x, int y);
int GoAiPattern1(int *u, goboard masks, goboard movehere);
int GoAiPattern(int *chosenx, int *choseny, int *urgency, goboard movehere);
int GoAiAttack(group *g, int *rx, int *ry, int ml);

int GoAiEscape(group *g, int *rx, int *ry);
int GoAiComputerMove();
int GoAiHumanMove(int x, int y, int pass);
void GoAiFileScore(FILE *file,  int territory[NPLAYERS]);
int GoAiIsT(int x, int y, int n, goboard scratch);
int GoAiIsTerritory(int x, int y, int p);
void GoAiScore();

#endif

