[net.sources.games] yao yet another othello program

keith@motel6.UUCP (Keith Packard) (07/09/85)

This is the source to an othello program I wrote completely from
scratch.  Do what you will to the source but, if you mangle it
don't expect me to fix it...

As usual, bug fixes will be most gratefully accepted.  If you
care to figure out how the edgescore array is generated you can
probably improve the play considerably by mucking about with the
generating yacc program makeedge.y. 

This was developed on my pdp 11/73 running 2.9BSD unix.
I do nothing weird to either the screen or to signals; it
*should* run without major modifications on sys5, sys3 and,
gasp, even version 7.  It ran at one time on 4.2BSD and I
haven't made substantial changes since then so, who knows, it
may run there with no modifications!

	Keith Packard

...!tektronix!reed!motel6!keith
...!tektronix!azure!keithp

*** Writing silly programs so you don't have to. ***
[ With cat like tread upon our prey we steal... ]

: shell archive - extract with /bin/sh
: corners.c
: count.c
: display.c
: edges.c
: fini.c
: gencor.c
: genedge.c
: hasmove.c
: legal.c
: makeedge.y
: makefile
: minmax.c
: move.c
: reversi.h
: score.c
: ulex.l
: user.y
sed 's/^X//' << \EOF_OF_corners.c >corners.c
X/*
X *	cornerscores.c
X */
X
Xshort cornerscores[81] = {
X		-20,	/* O O O O */
X		  0,	/* O O O - */
X		 10,	/* O O O * */
X		-20,	/* O O - O */
X		  0,	/* O O - - */
X		-10,	/* O O - * */
X		-20,	/* O O * O */
X		  0,	/* O O * - */
X		 20,	/* O O * * */
X		-20,	/* O - O O */
X		  0,	/* O - O - */
X		-10,	/* O - O * */
X		-20,	/* O - - O */
X		  0,	/* O - - - */
X		-10,	/* O - - * */
X		-20,	/* O - * O */
X		  0,	/* O - * - */
X		 20,	/* O - * * */
X		-20,	/* O * O O */
X		  0,	/* O * O - */
X		 20,	/* O * O * */
X		-20,	/* O * - O */
X		  0,	/* O * - - */
X		 10,	/* O * - * */
X		-20,	/* O * * O */
X		  0,	/* O * * - */
X		 10,	/* O * * * */
X		 40,	/* - O O O */
X		  0,	/* - O O - */
X		-40,	/* - O O * */
X		 40,	/* - O - O */
X		  0,	/* - O - - */
X		-40,	/* - O - * */
X		 40,	/* - O * O */
X		  0,	/* - O * - */
X		-40,	/* - O * * */
X		 40,	/* - - O O */
X		  0,	/* - - O - */
X		-40,	/* - - O * */
X		 40,	/* - - - O */
X		  0,	/* - - - - */
X		-40,	/* - - - * */
X		 40,	/* - - * O */
X		  0,	/* - - * - */
X		-40,	/* - - * * */
X		 40,	/* - * O O */
X		  0,	/* - * O - */
X		-40,	/* - * O * */
X		 40,	/* - * - O */
X		  0,	/* - * - - */
X		-40,	/* - * - * */
X		 40,	/* - * * O */
X		  0,	/* - * * - */
X		-40,	/* - * * * */
X		-20,	/* * O O O */
X		  0,	/* * O O - */
X		 20,	/* * O O * */
X		-10,	/* * O - O */
X		  0,	/* * O - - */
X		 20,	/* * O - * */
X		-10,	/* * O * O */
X		  0,	/* * O * - */
X		 20,	/* * O * * */
X		-10,	/* * - O O */
X		  0,	/* * - O - */
X		 20,	/* * - O * */
X		-10,	/* * - - O */
X		  0,	/* * - - - */
X		 20,	/* * - - * */
X		-10,	/* * - * O */
X		  0,	/* * - * - */
X		 20,	/* * - * * */
X		-10,	/* * * O O */
X		  0,	/* * * O - */
X		 20,	/* * * O * */
X		-10,	/* * * - O */
X		  0,	/* * * - - */
X		 20,	/* * * - * */
X		-10,	/* * * * O */
X		  0,	/* * * * - */
X		 20,	/* * * * * */
X	};
EOF_OF_corners.c
echo extracting 'count.c'
sed 's/^X//' << \EOF_OF_count.c >count.c
X/*
X *	count.c
X *
X *	count up the board
X */
X
X# include	"reversi.h"
X
Xcount (player, board)
XboardT	board;
X{
X	register int	x, y, count;
X
X	count = 0;
X	for (x = 1; x <= SIZE; x++)
X		for (y = 1; y <= SIZE; y++)
X			count += board[x][y];
X	return count * player;
X}
EOF_OF_count.c
echo extracting 'display.c'
sed 's/^X//' << \EOF_OF_display.c >display.c
X/*
X *	display.c
X */
X
X# include	"reversi.h"
X# include	<curses.h>
X# include	<ctype.h>
X
X# define	toscrx(x)	((x) * 5 - 1)
X# define	toscry(y)	((y) * 3 - 2)
X
X# define	LINEX	(toscrx(10)-2)
X# define	LINEY	(toscry(5)+1)
X
Xstatic	helpShown;
X
XdispInit ()
X{
X	register int	i, j;
X	int				dispEnd();
X
X	initscr ();
X	savetty();
X	noecho ();
X	crmode ();
X	helpShown = 0;
X	for (i = 1; i <= SIZE; i++) {
X		move (toscry(i), 0);
X		printw ("%1d", i);
X		move (0, toscrx(i));
X		printw ("%1d", i);
X	}
X	refresh ();
X}
X
XdispGrid ()
X{
X	register int	i, j;
X
X	for (i = 1; i <= SIZE; i++) {
X		for (j = 1; j <= SIZE + 1; j++) {
X			if (i <= SIZE) {
X				move (toscry(i)+1, toscrx(j)-2);
X				addch ('|');
X				move (toscry(i), toscrx(j)-2);
X				addch ('|');
X				move (toscry(i)-1, toscrx(j)-2);
X			}
X			if (j <= SIZE) {
X				if (i == 1)
X					printw ("+-%1d--", j);
X				else
X					addstr ("+----");
X			} else
X				addstr ("+");
X		}
X	}
X	refresh ();
X}
X
XdispNoGrid ()
X{
X	register int	i, j;
X
X	for (i = 1; i <= SIZE; i++) {
X		for (j = 1; j <= SIZE + 1; j++) {
X			move (toscry(i)+1, toscrx(j)-2);
X			addch (' ');
X			move (toscry(i), toscrx(j)-2);
X			addch (' ');
X			move (toscry(i)-1, toscrx(j)-2);
X			if (j <= SIZE) {
X				if (i == 1)
X					printw ("  %1d  ", j);
X				else
X					addstr ("     ");
X			} else
X				addstr (" ");
X		}
X	}
X	refresh ();
X}
X
XdispEnd ()
X{
X	clearok(stdscr, 1);
X	erase ();
X	refresh ();
X	resetty();
X	endwin ();
X	exit (0);
X}
X
XboardT	old;
X
Xdisplay (board)
XboardT	board;
X{
X	register int	i,j;
X	extern int	showScore;
X
X	for (i = 1; i <= SIZE; i++)
X		for (j = 1; j <= SIZE; j++)
X			if (board[i][j] != old[i][j]) {
X				dispOne (i, j, board[i][j]);
X				old[i][j] = board[i][j];
X			}
X	refresh ();
X	if (showScore)
X		dispScore (board);
X}
X
XdispOne (y, x, who)
X{
X	move (toscry (y), toscrx (x));
X	switch (who) {
X	case BLACK:
X		addstr ("/\\");
X		break;
X	case WHITE:
X		addstr ("**");
X		break;
X	case EMPTY:
X		addstr ("  ");
X		break;
X	}
X	move (toscry(y) + 1, toscrx (x));
X	switch (who) {
X	case BLACK:
X		addstr ("\\/");
X		break;
X	case WHITE:
X		addstr ("**");
X		break;
X	case EMPTY:
X		addstr ("  ");
X		break;
X	}
X}
X
XdispScore (board)
Xregister boardT	board;
X{
X	register int	i,j;
X	register int	ws, bs;
X
X	ws = bs = 0;
X	for (i = 1; i <= SIZE; i++)
X		for (j = 1; j <= SIZE; j++)
X			switch (board[i][j]) {
X			case WHITE:
X				ws++; break;
X			case BLACK:
X				bs++; break;
X			}
X	move (LINEY - 3, LINEX);
X	printw ("white: %-2d  black: %-2d", ws, bs);
X	refresh ();
X}
X
XdispNoScore ()
X{
X	move (LINEY - 3, LINEX);
X	clrtoeol ();
X	refresh ();
X}
X
Xstatic char *helpText[] = {
X	"y, x              [no] grid",
X	"[no] help         hint",
X	"play              quit",
X	"restart           record",
X	"replay            save",
X	"[no] score        undo",
X	"level",
X	"white|black first",
X	"white|black second",
X	0,
X};
X
XdispTurn (player)
X{
X	static displayed = EMPTY;
X
X	if (displayed == player)
X		return;
X	move (LINEY-1, LINEX);
X	switch (player) {
X	case WHITE:
X		addstr ("white's turn");
X		break;
X	case BLACK:
X		addstr ("black's turn");
X		break;
X	case EMPTY:
X		clrtoeol ();
X	}
X	displayed = player;
X	refresh ();
X}
X
XdispHelp ()
X{
X	register int	i;
X	register char	**h;
X
X	if (helpShown)
X		return;
X	i = 0;
X	for (h = helpText; *h; ++h) {
X		move (i, LINEX);
X		addstr (*h);
X		++i;
X	}
X	move (LINEY+4, LINEX);
X	printw ("white pieces are  **");
X	move (LINEY+5, LINEX+18);
X	printw ("**");
X	move (LINEY+7, LINEX);
X	printw ("black pieces are  /\\");
X	move (LINEY+8, LINEX+18);
X	printw ("\\/");
X	refresh ();
X	++helpShown;
X}
X
XdispNoHelp ()
X{
X	register int	i;
X	register char	**h;
X
X	if (!helpShown)
X		return;
X	i = 0;
X	for (h = helpText; *h; ++h) {
X		move (i, LINEX);
X		clrtoeol ();
X		++i;
X	}
X	move (LINEY+4, LINEX);
X	clrtoeol ();
X	move (LINEY+5, LINEX+18);
X	clrtoeol ();
X	move (LINEY+7, LINEX);
X	clrtoeol ();
X	move (LINEY+8, LINEX+18);
X	clrtoeol ();
X	refresh ();
X	helpShown = 0;
X}
X
Xstatic char	lexbuf[256];
Xstatic char	*lexpnt;
X
XreadLine ()
X{
X	int	ch, x, y;
X
X	move (LINEY, LINEX);
X	addstr ("-> ");
Xloop:
X	x = LINEX+3;
X	y = LINEY;
X	move (y, x);
X	clrtoeol ();
X	refresh ();
X	lexpnt = lexbuf;
X	for (;;) {
X		ch = getch ();
X		if (ch == -1)
X			ch = '\004';
X		*lexpnt++ = ch;
X		if (isprint (ch)) {
X			addch (ch);
X			++x;
X			refresh ();
X		} else
X			switch (ch) {
X			case '\f':
X				clearok (stdscr, 1);
X			case '\030':
X			case '\025':
X				goto loop;
X			case '\004':
X				*lexpnt++ = -1;
X			case '\r':
X			case '\n':
X				move (LINEY+1, LINEX);
X				refresh ();
X				*lexpnt++ = '\0';
X				goto done;
X			case '\b':
X				if (lexpnt >= lexbuf + 2) {
X					lexpnt -= 2;
X					--x;
X					move (y,x);
X					delch ();
X					refresh ();
X				} else
X					--lexpnt;
X				break;
X			default:
X				--lexpnt;
X				write (1, "\007", 1);
X				break;
X			}
X	}
Xdone:	lexpnt = lexbuf;
X	dispError ("");
X}
X
Xlexgetc ()
X{
X	int	c;
X	extern int yylineno;
X
X	c = *lexpnt++;
X	if (c == -1)
X		c = 4;
X	c &= 0177;
X	if (c == '\r')
X		c = '\n';
X	if (c == '\n')
X		++yylineno;
X	return c;
X}
X
Xlexungetc (c)
X{
X	--lexpnt;
X}
X
XdispError (s)
Xchar *s;
X{
X	move (LINEY+1, LINEX);
X	clrtoeol ();
X	addstr (s);
X	refresh ();
X}
EOF_OF_display.c
echo extracting 'edges.c'
sed 's/^X//' << \EOF_OF_edges.c >edges.c
X/*
X *	edgescores.c
X */
X
Xshort edgescores [6561] = {
X# include "edges.out"
X};
EOF_OF_edges.c
echo extracting 'fini.c'
sed 's/^X//' << \EOF_OF_fini.c >fini.c
X/*
X *	fini.c
X *
X *	count up score and display winner
X */
X
X# include	"reversi.h"
X
Xfini (board)
XboardT	board;
X{
X	register int	x,y;
X	register int	wscore, bscore;
X	char			sbuf[80];
X
X	wscore = bscore = 0;
X
X	for (x = 1; x <= SIZE; x++)
X		for (y = 1; y <= SIZE; y++)
X			if (board[x][y] == WHITE)
X				++wscore;
X			else if (board[x][y] == BLACK)
X				++bscore;
X	if (wscore > bscore)
X		sprintf (sbuf, "white wins %d to %d.", wscore, bscore);
X	else if (bscore > wscore)
X		sprintf (sbuf, "black wins %d to %d.", bscore, wscore);
X	else
X		sprintf (sbuf, "tie game %d to %d.", wscore, bscore);
X	dispError (sbuf);
X}
EOF_OF_fini.c
echo extracting 'gencor.c'
sed 's/^X//' << \EOF_OF_gencor.c >gencor.c
X/*
X *	generate preliminary corner score array
X */
X
Xchar	board[9];
X
Xmain ()
X{
X	register int	i;
X	for (board[1] = -1; board[1] <= 1; board[1]++)
X	for (board[2] = -1; board[2] <= 1; board[2]++)
X	for (board[3] = -1; board[3] <= 1; board[3]++)
X	for (board[4] = -1; board[4] <= 1; board[4]++) {
X		for (i = 1; i <= 4; i++)
X			switch (board[i]) {
X			case 0:
X				printf (" -");
X				break;
X			case -1:
X				printf (" O");
X				break;
X			case 1:
X				printf (" *");
X				break;
X			}
X		printf ("\n");
X	}
X}
EOF_OF_gencor.c
echo extracting 'genedge.c'
sed 's/^X//' << \EOF_OF_genedge.c >genedge.c
X/*
X *	generate preliminary edge score array
X */
X
Xchar	board[9];
X
Xmain ()
X{
X	register int	i;
X	for (board[1] = -1; board[1] <= 1; board[1]++)
X	for (board[2] = -1; board[2] <= 1; board[2]++)
X	for (board[3] = -1; board[3] <= 1; board[3]++)
X	for (board[4] = -1; board[4] <= 1; board[4]++)
X	for (board[5] = -1; board[5] <= 1; board[5]++)
X	for (board[6] = -1; board[6] <= 1; board[6]++)
X	for (board[7] = -1; board[7] <= 1; board[7]++)
X	for (board[8] = -1; board[8] <= 1; board[8]++) {
X		for (i = 1; i <= 8; i++)
X			switch (board[i]) {
X			case 0:
X				printf (" -");
X				break;
X			case -1:
X				printf (" O");
X				break;
X			case 1:
X				printf (" *");
X				break;
X			}
X		printf ("\n");
X	}
X}
EOF_OF_genedge.c
echo extracting 'hasmove.c'
sed 's/^X//' << \EOF_OF_hasmove.c >hasmove.c
X/*
X *	hasmove.c
X *
X *	figure out if player has move in board
X */
X
X# include	"reversi.h"
X
Xhasmove (player, board)
XboardT	board;
X{
X	register int	x,y;
X
X	for (x = 1; x <= SIZE; x++)
X		for (y = 1; y <= SIZE; y++)
X			if (legal (player, x, y, board))
X				return 1;
X	return 0;
X}
EOF_OF_hasmove.c
echo extracting 'legal.c'
sed 's/^X//' << \EOF_OF_legal.c >legal.c
X# include	"reversi.h"
Xextern int offsets[];
X
Xlegal (player, x, y, board)
Xregister int	player;
Xint				x, y;
XboardT			board;
X{
X	register char	*b, *m;
X	register int	*o, i;
X
X	b = & board[x][y];
X	player = -player;
X	if (*b == EMPTY) {
X		for (o = offsets; i = *o++;) {
X			if (b[i] == player) {
X				m = b+i;
X				while (*m == player)
X					m += i;
X				if (*m == -player)
X					return 1;
X			}
X		}
X	}
X	return 0;
X}
EOF_OF_legal.c
echo extracting 'makeedge.y'
sed 's/^X//' << \EOF_OF_makeedge.y >makeedge.y
X%{
X/*
X *	ex:set ts=8 sw=8:
X */
Xint	score;
Xextern int	position;
X%}
X%union {
X	struct {
X		int	width;
X		int	position;
X		int	base;
X	} field;
X	int	ival;
X}
X%type  <field>	line whites blacks empties oempties
X%type  <field>	type1 type2 otype3e type3e type3 otype4 type4 type4.w type4.b
X%token <field>	WHITE BLACK EMPTY
X%token <ival>	NL
X%%
Xlines	:	lines line
X			{ printf ("\t%5d,\t/*%s */\n", $2.base, line); }
X	|
X	;
Xline	:	whites type1 NL
X			{ $$.base = 20 * $1.width + $2.base; }
X	|	blacks type2 NL
X			{ $$.base = -20 * $1.width + $2.base; }
X	|	EMPTY type3 NL
X			{ $$.base = $2.base; }
X	|	EMPTY empties otype4 NL
X			{ $$.base = $3.base; }
X	;
Xtype1	:	blacks whites empties otype4
X			{
X				$$.base = $4.base;
X				switch ($2.position) {
X				case 7:
X					$$.base -= ($2.width + $1.width+1) * 15;
X					break;
X				default:
X					if ($3.width == 1)
X						$$.base -=
X						($1.width + $2.width+1) * 15;
X					else
X						$$.base +=
X						($2.width - $1.width) * 20;
X					break;
X				}
X				$$.position = $4.position;
X				$$.width = $1.width + $2.width + $3.width;
X			}
X	|	blacks whites type1
X			{
X				$$.base = $3.base;
X				$$.base -= ($1.width - $2.width) * 20;
X				$$.position = $3.position;
X				$$.width = $1.width + $2.width + $3.width;
X			}
X	|	blacks empties otype4
X			{
X				$$.base = ($1.width + 1) * 15 + $3.base;
X				$$.width = $1.width + $2.width + $3.width;
X				$$.position = $3.position;
X			}
X	|	blacks
X			{
X				$$ = $1;
X				$$.base = - $1.width * 20;
X			}
X	|	empties otype4
X			{
X				$$.position = $2.position;
X				$$.width = $1.width+$2.width;
X				$$.base = $2.base;
X			}
X	|
X			{ $$.position = position; $$.width = 0; $$.base = 0; }
X	;
Xtype2	:	whites blacks empties otype4
X			{
X				$$.base = $4.base;
X				switch ($2.position) {
X				case 7:
X					$$.base += ($2.width + $1.width+1) * 15;
X					break;
X				default:
X					if ($3.width == 1)
X						$$.base +=
X						($1.width + $2.width+1) * 15;
X					else
X						$$.base -=
X						($2.width - $1.width) * 20;
X					break;
X				}
X				$$.position = $4.position;
X				$$.width = $1.width + $2.width + $3.width
X					 + $4.width;
X			}
X	|	whites blacks type2
X			{
X				$$.base = $3.base;
X				$$.base += ($1.width - $2.width) * 20;
X				$$.position = $3.position;
X				$$.width = $1.width + $2.width + $3.width;
X			}
X	|	whites empties otype4
X			{
X				$$.base = - ($1.width + 1) * 15 + $3.base;
X				$$.width = $1.width + $2.width + $3.width;
X				$$.position = $3.position;
X			}
X	|	whites
X			{
X				$$ = $1;
X				$$.base = $1.width * 20;
X			}
X	|	empties otype4
X			{
X				$$.position = $2.position;
X				$$.width = $1.width+$2.width;
X				$$.base = $2.base;
X			}
X	|
X		{ $$.position = 0; $$.width = 0; $$.base = 0; }
X	;
Xotype4	:	type4
X			{ $$ = $1; }
X	|
X			{ $$.position = position; $$.width = 0; $$.base = 0; }
X	;
Xwhites	:	whites WHITE
X			{
X				$$.position = $2.position;
X				$$.width = $1.width + $2.width;
X				$$.base = $1.base + $2.base;
X			}
X	|	WHITE
X			{ $$ = $1; }
X	;
Xblacks	:	blacks BLACK
X			{
X				$$.position = $2.position;
X				$$.width = $1.width + $2.width;
X				$$.base = $1.base + $2.base;
X			}
X	|	BLACK
X			{ $$ = $1; }
X	;
Xempties	:	empties EMPTY
X			{
X				$$.position = $2.position;
X				$$.width = $1.width + $2.width;
X				$$.base = $1.base + $2.base;
X			}
X	|	EMPTY
X			{ $$ = $1; }
X	;
Xotype3e	:	type3e
X			{ $$ = $1; }
X	|
X			{ $$.position = position; $$.width = 0; $$.base = 0; }
X	;
Xtype3	:	whites EMPTY whites oempties otype3e
X			{
X				$$.base = -($1.width + $3.width + 2) * 15 +
X					$5.base;
X				$$.width = $1.width + $2.width + $3.width 
X					 + $4.width + $5.width;
X				$$.position = $5.position;
X			}
X	|	blacks EMPTY blacks oempties otype3e
X			{
X				$$.base = ($1.width + $3.width + 2) * 15 +
X					$5.base;
X				$$.width = $1.width + $2.width + $3.width 
X					 + $4.width + $5.width;
X				$$.position = $5.position;
X			}
X	|	type3e
X	;
Xtype3e	:	whites blacks type2
X			{
X				$$.base = -15 * ($1.width + $2.width + 1);
X				$$.width = $1.width + $2.width + $3.width;
X				$$.position = $3.position;
X			}
X	|	blacks whites type1
X			{
X				$$.base = 15 * ($1.width + $2.width + 1);
X				$$.width = $1.width + $2.width + $3.width;
X				$$.position = $3.position;
X			}
X	|	whites empties otype3e
X			{
X				if ($1.position - $1.width == 1) {
X					switch ($1.width) {
X					case 1:
X						$$.base = -30;
X						break;
X					case 6:
X						$$.base = -20;
X						break;
X					case 2:
X						$$.base = -15;
X						break;
X					case 3:
X						$$.base = -10;
X						break;
X					case 4:
X						$$.base = -5;
X						break;
X					case 5:
X						$$.base = 10;
X						break;
X					default:
X						yyerror ("weirdo");
X						break;
X					}
X				} else {
X					$$.base = $1.base;
X				}
X				$$.base += $3.base;
X				$$.position = $3.position;
X				$$.width = $1.width + $2.width + $3.width;
X			}
X	|	blacks empties otype3e
X			{
X				if ($1.position - $1.width == 1) {
X					switch ($1.width) {
X					case 1:
X						$$.base = 30;
X						break;
X					case 6:
X						$$.base = 20;
X					break;
X					case 2:
X						$$.base = 15;
X						break;
X					case 3:
X						$$.base = 10;
X						break;
X					case 4:
X						$$.base = 5;
X						break;
X					case 5:
X						$$.base = -10;
X						break;
X					default:
X						yyerror ("weirdo");
X						break;
X					}
X				} else {
X					$$.base = $1.base;
X				}
X				$$.base += $3.base;
X				$$.position = $3.position;
X				$$.width = $1.width + $2.width + $3.width;
X			}
X	|	whites
X			{
X				$$.base = 20 * $1.width;
X				$$.position = $1.position;
X				$$.width = $1.width;
X			}
X	|	blacks
X			{
X				$$.base = -20 * $1.width;
X				$$.position = $1.position;
X				$$.width = $1.width;
X			}
X	;
Xtype4	:	whites EMPTY whites oempties otype4
X		{
X			if ($4.position == 8) {
X				$$.base = -($1.width + $3.width + 2) * 15;
X			} else {
X				$$.base = 0;
X				if ($1.position - $1.width + 1 == 3)
X					$$.base = $1.width * 15;
X				else
X					$$.base = $1.base;
X				if ($3.position == 6)
X					$$.base += $3.width * 15;
X				else
X					$$.base += $3.base;
X				$$.base += $5.base;
X			}
X			$$.width = $1.width + $2.width + $3.width
X				 + $4.width + $5.width;
X			$$.position = $5.position;
X		}
X	|	whites empties otype4
X			{
X				if ($1.position - $1.width + 1 == 3)
X					$$.base = $1.width * 15 + $3.base;
X				else if ($1.position == 6)
X					$$.base = $1.width * 15 + $3.base;
X				else
X					$$.base = $1.base + $3.base;
X				$$.position = $3.position;
X				$$.width = $1.width + $2.width + $3.width;
X			}
X	|	blacks EMPTY blacks oempties otype4
X		{
X			if ($4.position == 8) {
X				$$.base = ($1.width + $3.width + 2) * 15;
X			} else {
X				$$.base = 0;
X				if ($1.position - $1.width + 1 == 3)
X					$$.base = -$1.width * 15;
X				else
X					$$.base = $1.base;
X				if ($3.position == 6)
X					$$.base +=  -$3.width * 15;
X				else
X					$$.base += $3.base;
X				$$.base += $5.base;
X			}
X			$$.width = $1.width + $2.width + $3.width
X				 + $4.width + $5.width;
X			$$.position = $5.position;
X		}
X	|	blacks empties otype4
X			{
X				if ($1.position - $1.width + 1 == 3)
X					$$.base = -$1.width * 15 + $3.base;
X				else if ($1.position == 6)
X					$$.base = -$1.width * 15 + $3.base;
X				else
X					$$.base = $1.base + $3.base;
X				$$.position = $3.position;
X				$$.width = $1.width + $2.width + $3.width;
X			}
X	|	whites
X			{
X				$$.base = 20 * $1.width;
X				$$.position = $1.position;
X				$$.width = $1.width;
X			}
X	|	blacks
X			{
X				$$.base = -20 * $1.width;
X				$$.position = $1.position;
X				$$.width = $1.width;
X			}
X	|	type4.w
X			{ $$ = $1; }
X	|	type4.b
X			{ $$ = $1; }
X	;
Xtype4.w	:	whites blacks oempties otype4
X		{
X			if ($2.position == 8)
X				$$.base = - ($1.width + $2.width + 1) * 15;
X			else if ($3.position == 8 && $3.width == 1)
X				$$.base = ($1.width + $2.width + 1) * 10;
X			else
X				$$.base = $1.base + $2.base + $4.base;
X			$$.position = $4.position;
X			$$.width = $1.width + $2.width + $3.width + $4.width;
X		}
X	;
Xtype4.b	:	blacks whites oempties otype4
X		{
X			if ($2.position == 8)
X				$$.base = ($1.width + $2.width + 1) * 15;
X			else if ($3.position == 8 && $3.width == 1)
X				$$.base = - ($1.width + $2.width + 1) * 10;
X			else
X				$$.base = $1.base + $2.base + $4.base;
X			$$.position = $4.position;
X			$$.width = $1.width + $2.width + $3.width + $4.width;
X		}
X	;
Xoempties:	empties
X			{ $$ = $1; }
X	|
X			{ $$.position = position; $$.width = 0; $$.base = 0; }
X	;
X%%
X
X# include	<stdio.h>
X
Xmain ()
X{
X	return yyparse ();
X}
X
Xchar	line[80];
Xchar	*lp = line;
X
Xyyerror (s)
Xchar *s;
X{
X	fprintf (stderr, "%s in %s\n", s, line);
X}
X
Xyywrap ()
X{
X	return 1;
X}
X
Xint position = 1;
X
Xint base[] = { 0, 20, -30, 15, -5, -5, 15, -30, 20, 0 };
X
Xyylex ()
X{
X	char *gets();
X
X	if (*lp == '\0')
X		if (fgets (line, 80, stdin) == 0)
X			return -1;
X		else
X			lp = line;
X	for (;;) {
X		switch (*lp++) {
X		case ' ':
X		case '\t':
X			break;
X		case '\n':
X			lp[-1] = '\0';
X			position = 1;
X			return NL;
X		case 'O':
X			yylval.field.base = -
X				base[yylval.field.position = position++];
X			yylval.field.width = 1;
X			return BLACK;
X		case '*':
X			yylval.field.base =
X				base[yylval.field.position = position++];
X			yylval.field.width = 1;
X			return WHITE;
X		case '-':
X			yylval.field.base = 0;
X			yylval.field.position = position++;
X			yylval.field.width = 1;
X			return EMPTY;
X		}
X	}
X}
EOF_OF_makeedge.y
echo extracting 'makefile'
sed 's/^X//' << \EOF_OF_makefile >makefile
XCFLAGS=-O -i
XOFILES=user.o ulex.o move.o display.o hasmove.o fini.o \
X	minmax.o score.o edges.o corners.o count.o
XSOURCE= makefile corners.c count.c display.c edges.c fini.c genedge.c \
X	hasmove.c makeedge.y minmax.c move.c reversi.h score.c ulex.l user.y
X
Xreversi: $(OFILES)
X	cc $(CFLAGS) -o reversi $(OFILES) -lcurses -ltermlib
X
Xreversi.shar: $(SOURCE)
X	shar -c $(SOURCE) > reversi.shar
X
X$(OFILES): reversi.h
Xuser.o: user.c
Xuser.c: user.y
X	yacc -dv user.y
X	mv y.tab.c user.c
Xulex.o: ulex.c
Xulex.c: ulex.l
X	lex ulex.l
X	mv lex.yy.c ulex.c
Xcorners.o: corners.c
X	$(CC) $(CFLAGS) -R -c corners.c
X
Xedges.o: edges.c edges.out
X	$(CC) $(CFLAGS) -R -c edges.c
Xedges.out: makeedge genedge
X	genedge | makeedge > edges.out
Xmakeedge: makeedge.o
X	$(CC) $(CFLAGS) -o makeedge makeedge.o
Xmakeedge.o: makeedge.c
Xmakeedge.c: makeedge.y
X	yacc makeedge.y
X	mv y.tab.c makeedge.c
Xgenedge: genedge.o
X	$(CC) $(CFLAGS) -o genedge genedge.o
Xgenedge.o: genedge.c
EOF_OF_makefile
echo extracting 'minmax.c'
sed 's/^X//' << \EOF_OF_minmax.c >minmax.c
X/*
X *	minmax.c
X */
X
X# include	"reversi.h"
X
Xint	maxlev, movex, movey;
X
X/*
X *	this defines the order in which the board
X *	is searched for the best move.  It is
X *	here to shorten the time to best move,
X *	this increasing the chance of hitting
X *	a good trimming point as well as
X *	increasing the possibility of making
X *	a reasonable move when an interrupt is
X *	caught.
X */
Xshort	morder[64][2] = {
X	1,1, 1,8, 8,1, 8,8,
X	1,3, 1,6, 3,1, 3,8, 6,1, 6,8, 8,3, 8,6,
X	3,3, 3,6, 6,3, 6,6,
X	1,4, 1,5, 4,1, 4,8, 5,1, 5,8, 8,4, 8,5,
X	3,4, 3,5, 4,3, 4,6, 5,3, 5,6, 6,4, 6,5,
X	2,3, 2,6, 3,2, 3,7, 6,2, 6,7, 7,3, 7,6,
X	2,4, 2,5, 4,2, 4,7, 5,2, 5,7, 7,4, 7,5,
X	1,2, 1,7, 2,1, 2,8, 7,1, 7,8, 8,2, 8,7,
X	2,2, 2,7, 7,2, 7,7, 4,4, 4,5, 5,4, 5,5,
X};
X
X# define	NOMOVE	(-32760)
X
X
X# define	USECOPY
X# ifdef	USECOPY
Xstruct copyB {
X	boardT	data;
X};
X# define	copyb(next,board)	(*((struct copyB *)next) = *((struct copyB *) board))
X# else
X# define	copyb(next,board)	copy(next,board)
X# endif
X
Xcopy(next, board)
Xregister int	*next, *board;
X{
X	register int	count;
X
X	count = sizeof (boardT) / sizeof (int);
X	do {
X		*next++ = *board++;
X	} while (--count);
X}
X
Xcomputer (player, board, level)
XboardT	board;
X{
X	int	i;
X	extern int	com, defcom;
X
X	maxlev = level;
X	movex = movey = -1;
X	i = seek (player, board, 0, 1, -NOMOVE);
X	if (movex == -1 || movey == -1)
X		return 0;
X	move (player, movex, movey, board);
X	return 1;
X}
X
Xhint (player, board, level)
XboardT board;
X{
X	int	i;
X
X	maxlev = level;
X	i = seek (player, board, 0, 1, -NOMOVE);
X	if (movex == -1 || movey == -1)
X		return 0;
X	return 1;
X}
X
Xseek (player, board, level, moved, best)
Xregister player;
Xregister boardT	board;
X{
X	boardT		next;
X	register int	x, y;
X	register int	s;
X	int		max, i;
X	int		bestx, besty;
X	int		m, j;
X	extern int	gotsignal;
X
X	max = NOMOVE;
X	m = 0;
X	for (j = 0; j < 60; j++) {
X		x = morder[j][0];
X		y = morder[j][1];
X		if (gotsignal)
X			return 0;
X		if (legal (player, x, y, board)) {
X			copyb (next, board);
X			if (level == 0 && movex == -1) {
X				movex = x;
X				movey = y;
X			}
X			move (player, x, y, next);
X			++m;
X			if (level >= maxlev)
X				s = score (next, player);
X			else
X				s = seek (-player, next, level+1, 1, -max);
X			if (s >= max) {
X				/*
X				 *	try to make the game appear random
X				 *	by choosing among equal moves
X				 *	randomly
X				 */
X				if (s == max && rand()&01)
X					goto skip;
X				if (s > best)
X					return -s;
X				bestx = x;
X				besty = y;
X				if (level == 0) {
X					movex = bestx;
X					movey = besty;
X				}
X				max = s;
X			}
Xskip:			;
X		}
X	}
X	if (m == 0)
X		if (moved && level)
X			return seek (-player, board, level + 1, 0, -best);
X		else
X			return - count (player, board) * 500;
X	return -max;
X}
EOF_OF_minmax.c
echo extracting 'move.c'
sed 's/^X//' << \EOF_OF_move.c >move.c
X/*
X *	move.c
X *
X *	move player to x,y in board
X */
X
X# include	"reversi.h"
X
Xint		offsets[] = { -11, -10, -9, -1, 1, 9, 10, 11, 0 };
X
Xmove (player, x, y, board)
Xregister int	player;
Xint				x, y;
XboardT			board;
X{
X	register char	*b, *m;
X	register int	*o, i;
X
X	b = & board[x][y];
X	*b = player;
X	player = -player;
X	for (o = offsets; i = *o++;) {
X		if (b[i] == player) {
X			m = b+i;
X			while (*m == player)
X				m += i;
X			if (*m == -player) {
X				while (m != b) {
X					*m = -player;
X					m -= i;
X				}
X			}
X		}
X	}
X}
X
Xlegal (player, x, y, board)
Xregister int	player;
Xint				x, y;
XboardT			board;
X{
X	register char	*b, *m;
X	register int	*o, i;
X
X	b = & board[x][y];
X	player = -player;
X	if (*b == EMPTY) {
X		for (o = offsets; i = *o++;) {
X			if (b[i] == player) {
X				m = b+i;
X				while (*m == player)
X					m += i;
X				if (*m == -player)
X					return 1;
X			}
X		}
X	}
X	return 0;
X}
EOF_OF_move.c
echo extracting 'reversi.h'
sed 's/^X//' << \EOF_OF_reversi.h >reversi.h
X/*
X *	reversi.h
X *
X *	include file for game program
X */
X
X# define	SIZE	8
X
Xtypedef char	boardT[SIZE+2][SIZE+2];
X
Xtypedef boardT	*boardP;
X
X# define	EMPTY	0
X# define	WHITE	1
X# define	BLACK	-1
EOF_OF_reversi.h
echo extracting 'score.c'
sed 's/^X//' << \EOF_OF_score.c >score.c
X/*
X *	score.c
X *
X *	score a board position
X */
X
X# include	"reversi.h"
X#ifdef SDEBUG
Xextern int sdebug;
X#endif
X
XboardT	base = {
X	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
X	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
X	  0,   0, -40, -10,  -5,  -5, -10, -40,   0,   0,
X	  0,   0, -10,   3,   1,   1,   3, -10,   0,   0,
X	  0,   0,  -5,   1,   0,   0,   1,  -5,   0,   0,
X	  0,   0,  -5,   1,   0,   0,   1,  -5,   0,   0,
X	  0,   0, -10,   3,   1,   1,   3, -10,   0,   0,
X	  0,   0, -40, -10,  -5,  -5, -10, -40,   0,   0,
X	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
X	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
X};
X
Xshort edgemod[10][3] = {
X	0,	0,	0,
X	0,	0,	0,
X	0,	0,	0,
X	5,	-10,	5,
X	5,	-5,	5,
X	5,	-5,	5,
X	5,	-10,	5,
X	0,	0,	0,
X	0,	0,	0,
X	0,	0,	0,
X};
X
Xextern short	cornerscores[3][3][3][3];
X
Xextern short	edgescores[6561];
X
X# define edgesc(a,b,c,d,e,f,g,h)	edgescores[a*2187 + b*729 + c*243 + \
X					d*81 + e*27 + f*9 + g*3 + h + 3280]
X
Xscore (board, player)
Xregister boardT	board;
Xint	player;
X{
X	register char	*j, *b;
X	char	*l;
X	register int	score;
X	int	i;
X	int	n, m;
X
X#ifdef SDEBUG
X	if (sdebug) {
X		display (board);
X	}
X#endif
X	score = 0;
X	for (i = 3; i < SIZE - 1; i++) {
X		j = & board[i][3];
X		b = & base [i][3];
X		l = & board[i][SIZE-1];
X		while (j != l) {
X			n = *j++;
X			score += n * *b++;
X		}
X		score += board[2][i]      * edgemod[i][board[1][i]+1];
X		score += board[SIZE-1][i] * edgemod[i][board[SIZE][i]+1];
X		score += board[i][2]      * edgemod[i][board[i][1]+1];
X		score += board[i][SIZE-1] * edgemod[i][board[i][SIZE]+1];
X	}
X	score +=
X		cornerscores[board[1][1] + 1]
X			[board[1][2] + 1]
X			[board[2][1] + 1]
X			[board[2][2] + 1] +
X		cornerscores[board[1][8] + 1]
X			[board[1][7] + 1]
X			[board[2][8] + 1]
X			[board[2][7] + 1] +
X		cornerscores[board[8][1] + 1]
X			[board[8][2] + 1]
X			[board[7][1] + 1]
X			[board[7][2] + 1] +
X		cornerscores[board[8][8] + 1]
X			[board[8][7] + 1]
X			[board[7][8] + 1]
X			[board[7][7] + 1];
X	score += edgesc (board[1][1], board[1][2], board[1][3], board[1][4],
X			 board[1][5], board[1][6], board[1][7], board[1][8]) +
X		 edgesc (board[8][1], board[8][2], board[8][3], board[8][4],
X			 board[8][5], board[8][6], board[8][7], board[8][8]);
X	score += edgesc (board[1][1], board[2][1], board[3][1], board[4][1],
X			 board[5][1], board[6][1], board[7][1], board[8][1]) +
X		 edgesc (board[1][8], board[2][8], board[3][8], board[4][8],
X			 board[5][8], board[6][8], board[7][8], board[8][8]);
X#ifdef SDEBUG
X	if (sdebug)
X		printf ("score: %d\n", score);
X#endif
X	return score * player;
X}
EOF_OF_score.c
echo extracting 'ulex.l'
sed 's/^X//' << \EOF_OF_ulex.l >ulex.l
X%{
X/*
X *	ex:set ts=8 sw=8:
X */
X# include	"y.tab.h"
Xextern int	yylval;
Xextern char	sbuf[];
X#undef input
X#define input()	lexgetc()
X#undef unput
X#define unput(c)	lexungetc(c)
X%}
X%%
X[ \t]		;
X\004		return EOG;
Xblack		{ yylval = -1; return BL; }
Xboth		return BOTH;
Xcomputer	return COMPUTER;
Xdebug		return DEBUG;
Xeval		return EVAL;
Xfile		return FILEe;
Xfirst		return FIRST;
Xfrom		return FROM;
Xgame		return GAME;
Xgrid		return GRID;
Xhelp		return HELP;
Xhint		return HINT;
Xhuman		return HUMAN;
Xinto		return INTO;
Xlevel		return LEVEL;
Xme		return HUMAN;
Xmove		return MOVE;
Xnew		return NEW;
Xneither		return NEITHER;
Xno		return NO;
Xnogrid		return NOGRID;
Xnohelp		return NOHELP;
Xnoscore		return NOSCORE;
Xnone		return NONE;
Xplay		return PLAY;
Xquit		return QUIT;
Xrecord		return RECORD;
Xreplay		return REPLAY;
Xrestart		return RESTART;
Xsave		return SAVE;
Xscore		return SCORE;
Xsecond		return SECOND;
Xto		return TO;
Xundo		return UNDO;
Xwhite		{ yylval =  1; return WH; }
Xyou		return COMPUTER;
X\n		return NL;
X[0-9]+		{ yylval = atoi (yytext); return NUMBER; }
X","		return COMMA;
X";"		return SEMI;
X\"[^"]*\"	{ strcpy (sbuf, yytext+1); sbuf[yyleng-2]='\0'; return STRING; }
X.		return ERR;
EOF_OF_ulex.l
echo extracting 'user.y'
sed 's/^X//' << \EOF_OF_user.y >user.y
X%{
X/*
X *	ex:set ts=8 sw=8:
X *	user interface
X */
X
X# include	"reversi.h"
X# include	<stdio.h>
X# include	<signal.h>
X
XboardT	board, saveBoard;
Xint	saved;
Xint	savePlayer;
Xint	atend;
Xint	atbegin;
Xint	level;
Xint	player;
Xextern int	maxlev, movex, movey;
Xint	com;
Xint	gotsignal;
Xchar	sbuf[80];
Xchar	ebuf[80];
Xint	sdebug = 0, mdebug = 0;
Xint	record = 0;
XFILE	*rfile;
Xint	first = WHITE;
Xint	defcom = BLACK;
Xint	showScore = 1;
X
Xstruct move {
X	int	p, x, y;
X};
X
Xstruct move	saveGame[64];
Xstruct move	*saveP;
X
X%}
X%token	MOVE LEVEL COMPUTER UNDO HINT PLAY
X%token	RECORD REPLAY SAVE
X%token	RESTART NEW GAME QUIT
X%token	GRID NOGRID HELP NOHELP SCORE NOSCORE
X%token	DEBUG EVAL
X%token	FROM INTO TO FILEe NO
X%token	NUMBER COMMA NL STRING SEMI EOG ERR
X%token	WH BL HUMAN BOTH NEITHER NONE FIRST SECOND
X%%
Xgame	:	game commands NL prompt
X	|	prompt
X	;
Xprompt	:
X	{
X		if (!atend) {
X			loop:	;
X			dispTurn (player);
X			if (!hasmove (player, board)) {
X				if (!hasmove (-player, board)) {
X					fini (board);
X					if (com == 0)
X						com = BLACK;
X					++atend;
X					dispTurn (EMPTY);
X					goto nomove;
X				} else {
X					if (player == WHITE)
X						dispError ("white has no move");
X					else
X						dispError ("black has no move");
X					player = -player;
X				}
X			}
X			if (com == 0 || com == player) {
X				dispError ("thinking...");
X				if (computer (player, board, level)) {
X					atbegin = 0;
X					sprintf (ebuf, "I move to %d, %d\n",
X						movex, movey);
X					dispError (ebuf);
X					saveP->x = movex;
X					saveP->y = movey;
X					saveP->p = player;
X					++saveP;
X					if (record)
X						fprintf (rfile, "%d: %d,%d\n",
X						    player, movex, movey);
X					player = -player;
X					display (board);
X					if (gotsignal && com != 0)
X						gotsignal = 0;
X				}
X				if (gotsignal && com == 0) {
X					com = -player;
X					gotsignal = 0;
X				}
X				goto loop;
X			}
X		}
X	nomove:	;
X		readLine ();
X	}
X	;
Xcommands:	commands SEMI command
X	|	command
X	|	error oerror
X		{
X			dispHelp ();
X		}
X	;
Xcommand	:	
X	|	EOG
X		{
X			YYACCEPT;
X		}
X	|	omove NUMBER ocomma NUMBER
X		{
X			if (1 <= $2 && $2 <= SIZE &&
X			    1 <= $4 && $4 <= SIZE &&
X			    legal (player, $2, $4, board)) {
X				copy (saveBoard, board);
X				savePlayer = player;
X				++saved;
X				move (player, $2, $4, board);
X				atbegin = 0;
X				if (record)
X					fprintf (rfile, "%d: %d,%d\n",
X					    player, $2, $4);
X				saveP->x = $2;
X				saveP->y = $4;
X				saveP->p = player;
X				++saveP;
X				player = -player;
X				display (board);
X			} else {
X				sprintf (ebuf, "illegal move: %d, %d", $2, $4);
X				dispError (ebuf);
X			}
X		}
X	|	DEBUG STRING
X		{
X			register char	*s;
X			register int	v;
X
X			v = 1;
X			for (s = sbuf; *s; ++s)
X				switch (*s) {
X				case 'm':
X					mdebug = v;
X					break;
X				case 's':
X					sdebug = v;
X					break;
X				case '!':
X					v = !v;
X					break;
X				}
X		}
X	|	GRID
X		{
X			dispGrid ();
X		}
X	|	NO GRID
X		{
X			dispNoGrid ();
X		}
X	|	NOGRID
X		{
X			dispNoGrid ();
X		}
X	|	SCORE
X		{
X			showScore = 1;
X			dispScore (board);
X		}
X	|	NOSCORE
X		{
X			showScore = 0;
X			dispNoScore ();
X		}
X	|	NO SCORE
X		{
X			showScore = 0;
X			dispNoScore ();
X		}
X	|	LEVEL NUMBER
X		{
X			level = $2;
X		}
X	|	LEVEL oerror
X		{
X			sprintf (ebuf, "current level is %d", level);
X			dispError (ebuf);
X		}
X	|	PLAY whichp
X		{
X			if ($2 == WHITE || $2 == BLACK) 
X				defcom = $2;
X			com = $2;
X		}
X	|	PLAY oerror
X		{
X			dispError ("play (white black both none)");
X		}
X	|	whichp FIRST
X		{
X			if ($1 == WHITE || $1 == BLACK)
X				first = $1;
X			if (atbegin)
X				player = first;
X		}
X	|	FIRST oerror
X		{
X			dispError ("(white black you me) first");
X		}
X	|	whichp SECOND
X		{
X			if ($1 == WHITE || $1 == BLACK)
X				first = - $1;
X			if (atbegin)
X				player = first;
X		}
X	|	SECOND oerror
X		{
X			dispError ("(white black you me) second");
X		}
X	|	HELP
X		{
X			dispHelp ();
X		}
X	|	NOHELP
X		{
X			dispNoHelp ();
X		}
X	|	NO HELP
X		{
X			dispNoHelp ();
X		}
X	|	QUIT
X		{
X			YYACCEPT;
X		}
X	|	UNDO
X		{
X			if (saved) {
X				copy (board, saveBoard);
X				player = savePlayer;
X				saved = 0;
X				display (board);
X			}
X		}
X	|	NEW ogame eoc
X		{
X			YYABORT;
X		}
X	|	RESTART eoc
X		{
X			YYABORT;
X		}
X	|	EVAL
X		{
X			sprintf (ebuf, "score: %d\n", score (board, WHITE));
X			dispError (ebuf);
X		}
X	|	RECORD ointo ofile STRING
X		{
X			if ((rfile = fopen (sbuf, "w")) == NULL) {
X				sprintf (ebuf, "could not open %s", sbuf);
X				dispError (ebuf);
X				record = 0;
X			} else
X				++record;
X		}
X	|	RECORD oerror
X		{
X			dispError ("record \"file\"");
X		}
X	|	REPLAY whichp ofrom ofile STRING
X		{
X			replay ($2, sbuf);
X		}
X	|	REPLAY oerror
X		{
X			dispError ("replay (both white black) \"file\"");
X		}
X	|	SAVE ointo ofile STRING
X		{
X			struct move	*m;
X
X			if ((rfile = fopen (sbuf, "w")) == NULL) {
X				sprintf (ebuf, "could not open %s", sbuf);
X				dispError (ebuf);
X			} else {
X				m = saveGame;
X				fprintf (rfile, "%d: -1,-1\n", m->p);
X				for (; m != saveP; m++)
X					fprintf (rfile, "%d: %d,%d\n",
X					    m->p, m->x, m->y);
X				fclose (rfile);
X				rfile = 0;
X			}
X		}
X	|	SAVE oerror
X		{
X			dispError ("save \"file\"");
X		}
X	|	HINT
X		{
X			if (hasmove (player, board)) {
X				char	buf[80];
X				hint (player, board, level);
X				sprintf (buf, "I suggest %d, %d", movex, movey);
X				dispError (buf);
X			}
X		}
X	;
Xeoc	:	SEMI
X	|	NL
X	;
Xomove	:	MOVE
X	|
X	;
Xogame	:	GAME
X	|
X	;
Xocomma	:	COMMA
X	|
X	;
Xoerror	:	oerror error
X		{
X			yyerrok;
X		}
X	|	oerror ERR
X	|
X	;
Xointo	:	TO
X	|	INTO
X	|
X	;
Xofrom	:	FROM
X	|
X	;
Xofile	:	FILEe
X	|
X	;
Xwhichp	:	WH
X		{ $$ = WHITE; }
X	|	BL
X		{ $$ = BLACK; }
X	|	COMPUTER
X		{ $$ = com==WHITE?WHITE:BLACK; }
X	|	HUMAN
X		{ $$ = com==WHITE?BLACK:WHITE; }
X	|	BOTH
X		{ $$ = 0; }
X	|	none
X		{ $$ = 2; }
X	;
Xnone	:	NONE
X	|	NEITHER
X	;
X%%
Xyyerror (s)
Xchar	*s;
X{
X	dispError (s);
X}
X
Xcaught ()
X{
X	gotsignal++;
X	signal (SIGINT, caught);
X}
X
Xmain (argc, argv)
Xchar **argv;
X{
X	signal (SIGINT, caught);
X	level = 2;
X	dispInit ();
X	srand (getpid());
X	while (**++argv == '-') {
X		while (*++*argv) {
X			switch (**argv) {
X			case 'b':
X				defcom = BLACK;
X				break;
X			case 'w':
X				defcom = WHITE;
X				break;
X			case '1':
X				if (!*++*argv)
X					continue;
X				if (**argv == WHITE)
X					first = WHITE;
X				else
X					first = BLACK;
X				break;
X			case 'g':
X				dispGrid ();
X				break;
X			case 's':
X				showScore = 1;
X			}
X		}
X	}
X	do {
X		if (rfile)
X			fclose (rfile);
X		rfile = 0;
X		player = first;
X		com = defcom;
X		atend = 0;
X		atbegin = 1;
X		setup ();
X		saved = 0;
X		saveP = saveGame;
X		display (board);
X		if (*argv) {
X			replay (0, *argv);
X			++argv;
X		}
X	} while (yyparse ());
X	dispEnd ();
X}
X
Xyywrap ()
X{
X	return 1;
X}
X
Xsetup ()
X{
X	register int	i,j;
X
X	for (i = 1; i <= SIZE; i++)
X		for (j = 1; j <= SIZE; j++)
X			board[i][j] = 0;
X	board[4][4] = WHITE;
X	board[4][5] = BLACK;
X	board[5][4] = BLACK;
X	board[5][5] = WHITE;
X}
X
Xreplay (who, file)
Xchar *file;
X{
X	int	x, y, p;
X	if (rfile)
X		fclose (rfile);
X	if ((rfile = fopen (file, "r")) == NULL) {
X		sprintf (ebuf, "could not open %s", file);
X		dispError (ebuf);
X		return;
X	}
X	while (fscanf (rfile, "%d: %d, %d\n", &p, &x, &y) == 3) {
X		if (x == -1 && y == -1) {
X			player = p;
X			continue;
X		}
X		if (!hasmove (player, board)) {
X			player = -player;
X			if (!hasmove (player, board))
X				return;
X		}
X		if (p != player) {
X			sprintf (ebuf, "not %s's turn\n",
X			    player == WHITE? "white":"black");
X			dispError (ebuf);
X			return;
X		}
X		if (who == 0 || p == who) {
X			if (!legal (p, x, y, board)) {
X				sprintf(ebuf, "illegal move: %d, %d\n", x, y);
X				dispError (ebuf);
X				return;
X			}
X			move (p, x, y, board);
X			atbegin = 0;
X			player = -player;
X			display (board);
X		}
X		else if (player == com) {
X			if (hasmove (player, board)) {
X				dispError ("thinking...");
X				dispTurn (EMPTY);
X				if (computer (player, board, level)) {
X					dispError ("");
X					atbegin = 0;
X					player = -player;
X					display (board);
X				}
X			}
X		}
X	}
X	fclose (rfile);
X	rfile = 0;
X}
EOF_OF_user.y

deg@mtgzz.UUCP (d.e.gillespie) (07/24/85)

There are some assumptions your code makes about the target machine,
in particular in the use of 'char' variables.  On many targets, a
char is never negative!  In your program, the board is stored as a
char array, and so far this is the only problem i noticed.  

The easiest solution was to add this line to reversi.h:
	typdef short int	boardE;
The diff listings of the affected files follows:

***** diff between gencor.c.BAK and gencor.c
5c5
< char	board[9];
---
> boardE	board[9];
***** diff between genedge.c.BAK and genedge.c
5c5
< char	board[9];
---
> boardE	board[9];
***** diff between legal.c.BAK and legal.c
9c9
< 	register char	*b, *m;
---
> 	register boardE	*b, *m;
***** diff between move.c.BAK and move.c
16c16
< 	register char	*b, *m;
---
> 	register boardE	*b, *m;
42c42
< 	register char	*b, *m;
---
> 	register boardE	*b, *m;
***** diff between reversi.h.BAK and reversi.h
8,9c8,9
< 
< typedef short int	boardT[SIZE+2][SIZE+2];
---
> typedef short int	boardE;
> typedef boardE		boardT[SIZE+2][SIZE+2];
***** diff between score.c.BAK and score.c
49,50c49,50
< 	register char	*j, *b;
< 	char	*l;
---
> 	register boardE	*j, *b;
> 	boardE	*l;