Import of 4.4BSD-Lite2 source

This commit is contained in:
tls 1996-12-28 18:44:55 +00:00
parent e16e1de8fd
commit 193cec78aa
9 changed files with 3307 additions and 0 deletions

10
games/gomoku/Makefile Normal file
View File

@ -0,0 +1,10 @@
# @(#)Makefile 8.1 (Berkeley) 7/24/94
PROG= gomoku
SRCS= bdinit.c bdisp.c main.c makemove.c pickmove.c stoc.c
MAN6= gomoku.0
DPADD= ${LIBCURSES} ${LIBTERM}
LDADD= -lcurses -ltermlib
HIDEGAME=hidegame
.include <bsd.prog.mk>

246
games/gomoku/bdinit.c Normal file
View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)bdinit.c 8.2 (Berkeley) 5/3/95";
#endif /* not lint */
#include <string.h>
#include "gomoku.h"
bdinit(bp)
struct spotstr *bp;
{
register int i, j, r;
register struct spotstr *sp;
register struct combostr *cbp;
movenum = 1;
/* mark the borders as such */
sp = bp;
for (i = BSZ2; --i >= 0; sp++) {
sp->s_occ = BORDER; /* top border */
sp->s_flg = BFLAGALL;
}
/* fill entire board with EMPTY spots */
memset(frames, 0, sizeof(frames));
cbp = frames;
for (j = 0; ++j < BSZ1; sp++) { /* for each row */
for (i = 0; ++i < BSZ1; sp++) { /* for each column */
sp->s_occ = EMPTY;
sp->s_flg = 0;
sp->s_wval = 0;
if (j < 5) {
/* directions 1, 2, 3 are blocked */
sp->s_flg |= (BFLAG << 1) | (BFLAG << 2) |
(BFLAG << 3);
sp->s_fval[BLACK][1].s = MAXCOMBO;
sp->s_fval[BLACK][2].s = MAXCOMBO;
sp->s_fval[BLACK][3].s = MAXCOMBO;
sp->s_fval[WHITE][1].s = MAXCOMBO;
sp->s_fval[WHITE][2].s = MAXCOMBO;
sp->s_fval[WHITE][3].s = MAXCOMBO;
} else if (j == 5) {
/* five spaces, blocked on one side */
sp->s_fval[BLACK][1].s = 0x500;
sp->s_fval[BLACK][2].s = 0x500;
sp->s_fval[BLACK][3].s = 0x500;
sp->s_fval[WHITE][1].s = 0x500;
sp->s_fval[WHITE][2].s = 0x500;
sp->s_fval[WHITE][3].s = 0x500;
} else {
/* six spaces, not blocked */
sp->s_fval[BLACK][1].s = 0x401;
sp->s_fval[BLACK][2].s = 0x401;
sp->s_fval[BLACK][3].s = 0x401;
sp->s_fval[WHITE][1].s = 0x401;
sp->s_fval[WHITE][2].s = 0x401;
sp->s_fval[WHITE][3].s = 0x401;
}
if (i > (BSZ - 4)) {
/* directions 0, 1 are blocked */
sp->s_flg |= BFLAG | (BFLAG << 1);
sp->s_fval[BLACK][0].s = MAXCOMBO;
sp->s_fval[BLACK][1].s = MAXCOMBO;
sp->s_fval[WHITE][0].s = MAXCOMBO;
sp->s_fval[WHITE][1].s = MAXCOMBO;
} else if (i == (BSZ - 4)) {
sp->s_fval[BLACK][0].s = 0x500;
sp->s_fval[WHITE][0].s = 0x500;
/* if direction 1 is not blocked */
if (!(sp->s_flg & (BFLAG << 1))) {
sp->s_fval[BLACK][1].s = 0x500;
sp->s_fval[WHITE][1].s = 0x500;
}
} else {
sp->s_fval[BLACK][0].s = 0x401;
sp->s_fval[WHITE][0].s = 0x401;
if (i < 5) {
/* direction 3 is blocked */
sp->s_flg |= (BFLAG << 3);
sp->s_fval[BLACK][3].s = MAXCOMBO;
sp->s_fval[WHITE][3].s = MAXCOMBO;
} else if (i == 5 &&
!(sp->s_flg & (BFLAG << 3))) {
sp->s_fval[BLACK][3].s = 0x500;
sp->s_fval[WHITE][3].s = 0x500;
}
}
/*
* Allocate a frame structure for non blocked frames.
*/
for (r = 4; --r >= 0; ) {
if (sp->s_flg & (BFLAG << r))
continue;
cbp->c_combo.s = sp->s_fval[BLACK][r].s;
cbp->c_vertex = sp - board;
cbp->c_nframes = 1;
cbp->c_dir = r;
sp->s_frame[r] = cbp;
cbp++;
}
}
sp->s_occ = BORDER; /* left & right border */
sp->s_flg = BFLAGALL;
}
/* mark the borders as such */
for (i = BSZ1; --i >= 0; sp++) {
sp->s_occ = BORDER; /* bottom border */
sp->s_flg = BFLAGALL;
}
sortframes[BLACK] = (struct combostr *)0;
sortframes[WHITE] = (struct combostr *)0;
init_overlap();
}
/*
* Initialize the overlap array.
* Each entry in the array is a bit mask with eight bits corresponding
* to whether frame B overlaps frame A (as indexed by overlap[A * FAREA + B]).
* The eight bits coorespond to whether A and B are open ended (length 6) or
* closed (length 5).
* 0 A closed and B closed
* 1 A closed and B open
* 2 A open and B closed
* 3 A open and B open
* 4 A closed and B closed and overlaps in more than one spot
* 5 A closed and B open and overlaps in more than one spot
* 6 A open and B closed and overlaps in more than one spot
* 7 A open and B open and overlaps in more than one spot
* As pieces are played, it can make frames not overlap if there are no
* common open spaces shared between the two frames.
*/
init_overlap()
{
register struct spotstr *sp1, *sp2;
register struct combostr *cbp;
register int i, f, r, n, d1, d2;
int mask, bmask, vertex, s;
u_char *str;
short *ip;
memset(overlap, 0, sizeof(overlap));
memset(intersect, 0, sizeof(intersect));
str = &overlap[FAREA * FAREA];
ip = &intersect[FAREA * FAREA];
for (cbp = frames + FAREA; --cbp >= frames; ) { /* each frame */
str -= FAREA;
ip -= FAREA;
sp1 = &board[vertex = cbp->c_vertex];
d1 = dd[r = cbp->c_dir];
/*
* s = 5 if closed, 6 if open.
* At this point black & white are the same.
*/
s = 5 + sp1->s_fval[BLACK][r].c.b;
/* for each spot in frame A */
for (i = 0; i < s; i++, sp1 += d1, vertex += d1) {
/* the sixth spot in frame A only overlaps if it is open */
mask = (i == 5) ? 0xC : 0xF;
/* for each direction */
for (r = 4; --r >= 0; ) {
bmask = BFLAG << r;
sp2 = sp1;
d2 = dd[r];
/* for each frame that intersects at spot sp1 */
for (f = 0; f < 6; f++, sp2 -= d2) {
if (sp2->s_occ == BORDER)
break;
if (sp2->s_flg & bmask)
continue;
n = sp2->s_frame[r] - frames;
ip[n] = vertex;
str[n] |= (f == 5) ? mask & 0xA : mask;
if (r == cbp->c_dir) {
/* compute the multiple spot overlap values */
switch (i) {
case 0: /* sp1 is the first spot in A */
if (f == 4)
str[n] |= 0xA0;
else if (f != 5)
str[n] |= 0xF0;
break;
case 1: /* sp1 is the second spot in A */
if (f == 5)
str[n] |= 0xA0;
else
str[n] |= 0xF0;
break;
case 4: /* sp1 is the penultimate spot in A */
if (f == 0)
str[n] |= 0xC0;
else
str[n] |= 0xF0;
break;
case 5: /* sp1 is the last spot in A */
if (f == 1)
str[n] |= 0xC0;
else if (f != 0)
str[n] |= 0xF0;
break;
default:
str[n] |= 0xF0;
}
}
}
}
}
}
}

275
games/gomoku/bdisp.c Normal file
View File

@ -0,0 +1,275 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)bdisp.c 8.2 (Berkeley) 5/3/95";
#endif /* not lint */
#include "gomoku.h"
#include <stdio.h>
#include <curses.h>
#define SCRNH 24 /* assume 24 lines for the moment */
#define SCRNW 80 /* assume 80 chars for the moment */
static int lastline;
static char pcolor[] = "*O.?";
/*
* Initialize screen display.
*/
cursinit()
{
initscr();
noecho();
cbreak();
leaveok(stdscr, TRUE);
}
/*
* Restore screen display.
*/
cursfini()
{
leaveok(stdscr, FALSE);
move(23, 0);
clrtoeol();
refresh();
endwin();
}
/*
* Initialize board display.
*/
bdisp_init()
{
register int i, j;
/* top border */
for (i = 1; i < BSZ1; i++) {
move(0, 2 * i + 1);
addch(letters[i]);
}
/* left and right edges */
for (j = BSZ1; --j > 0; ) {
move(20 - j, 0);
printw("%2d ", j);
move(20 - j, 2 * BSZ1 + 1);
printw("%d ", j);
}
/* bottom border */
for (i = 1; i < BSZ1; i++) {
move(20, 2 * i + 1);
addch(letters[i]);
}
bdwho(0);
move(0, 47);
addstr("# black white");
lastline = 0;
bdisp();
}
/*
* Update who is playing whom.
*/
bdwho(update)
int update;
{
int i;
extern char *plyr[];
move(21, 0);
clrtoeol();
i = 6 - strlen(plyr[BLACK]) / 2;
move(21, i > 0 ? i : 0);
printw("BLACK/%s", plyr[BLACK]);
i = 30 - strlen(plyr[WHITE]) / 2;
move(21, i);
printw("WHITE/%s", plyr[WHITE]);
move(21, 19);
addstr(" vs. ");
if (update)
refresh();
}
/*
* Update the board display after a move.
*/
bdisp()
{
register int i, j, c;
register struct spotstr *sp;
for (j = BSZ1; --j > 0; ) {
for (i = 1; i < BSZ1; i++) {
move(BSZ1 - j, 2 * i + 1);
sp = &board[i + j * BSZ1];
if (debug > 1 && sp->s_occ == EMPTY) {
if (sp->s_flg & IFLAGALL)
c = '+';
else if (sp->s_flg & CFLAGALL)
c = '-';
else
c = '.';
} else
c = pcolor[sp->s_occ];
addch(c);
}
}
refresh();
}
#ifdef DEBUG
/*
* Dump board display to a file.
*/
bdump(fp)
FILE *fp;
{
register int i, j, c;
register struct spotstr *sp;
/* top border */
fprintf(fp, " A B C D E F G H J K L M N O P Q R S T\n");
for (j = BSZ1; --j > 0; ) {
/* left edge */
fprintf(fp, "%2d ", j);
for (i = 1; i < BSZ1; i++) {
sp = &board[i + j * BSZ1];
if (debug > 1 && sp->s_occ == EMPTY) {
if (sp->s_flg & IFLAGALL)
c = '+';
else if (sp->s_flg & CFLAGALL)
c = '-';
else
c = '.';
} else
c = pcolor[sp->s_occ];
putc(c, fp);
putc(' ', fp);
}
/* right edge */
fprintf(fp, "%d\n", j);
}
/* bottom border */
fprintf(fp, " A B C D E F G H J K L M N O P Q R S T\n");
}
#endif /* DEBUG */
/*
* Display a transcript entry
*/
dislog(str)
char *str;
{
if (++lastline >= SCRNH - 1) {
/* move 'em up */
lastline = 1;
}
if (strlen(str) >= SCRNW - 46)
str[SCRNW - 46 - 1] = '\0';
move(lastline, 46);
addstr(str);
clrtoeol();
move(lastline + 1, 46);
clrtoeol();
}
/*
* Display a question.
*/
ask(str)
char *str;
{
int len = strlen(str);
move(23, 0);
addstr(str);
clrtoeol();
move(23, len);
refresh();
}
getline(buf, size)
char *buf;
int size;
{
register char *cp, *end;
register int c;
extern int interactive;
cp = buf;
end = buf + size - 1; /* save room for the '\0' */
while (cp < end && (c = getchar()) != EOF && c != '\n' && c != '\r') {
*cp++ = c;
if (interactive) {
switch (c) {
case 0x0c: /* ^L */
wrefresh(curscr);
cp--;
continue;
case 0x15: /* ^U */
case 0x18: /* ^X */
while (cp > buf) {
cp--;
addch('\b');
}
clrtoeol();
break;
case '\b':
case 0x7f: /* DEL */
if (cp == buf + 1) {
cp--;
continue;
}
cp -= 2;
addch('\b');
c = ' ';
/* FALLTHROUGH */
default:
addch(c);
}
refresh();
}
}
*cp = '\0';
return(c != EOF);
}

92
games/gomoku/gomoku.6 Normal file
View File

@ -0,0 +1,92 @@
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Ralph Campbell.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)gomoku.6 8.2 (Berkeley) 8/4/94
.\"
.Dd August 4, 1994
.Dt GOMOKU 6
.Os BSD 4.4
.Sh NAME
.Nm gomoku
.Nd game of 5 in a row
.Sh SYNOPSIS
.Nm gomoku
.Op Fl bcdu
.Op Fl D Ar debugfile
.Op Ar inputfile
.Sh DESCRIPTION
.Nm Gomoku
is a two player game were the object is to get 5 in a row horizontally,
vertically or diagonally on a 19 by 19 grid. By convention, black always
moves first.
With no arguments,
.Nm gomoku
will display a playing board and prompt for moves from the user.
Valid moves are a letter for the column and a number for the row of an empty
board location. Entering ``quit" or ``resign" will end the game.
You can save the current state of the game by entering ``save" and
supplying a file name when prompted.
The optional file
.Ar inputfile
can be used to restore a saved game.
.Pp
The options are:
.Bl -tag -width Ds
.It Fl b
This option sets background mode. Input moves are read from standard input,
the computer picks a move, and prints it to standard output. The first
input line should be either ``black" or ``white" to specify whether
.Nm gomoku
has the first move or not respectively. This
option was intended for game tournaments where a referee program handles
the board display and pits one program against another.
.It Fl c
Computer verses computer.
.Nm Gomoku
will play a game against itself. This is mostly used for testing.
.It Fl d
Print debugging information. Repeating this option more than
once yields more detailed information.
.It Fl D Ar debugfile
Print the debug information to
.Ar debugfile
instead of to the standard output.
.It Fl u
User verses user. This is mostly used for testing.
.Sh AUTHOR
Ralph Campbell
.Sh ACKNOWLEDGEMENTS
The board display routines were based on the
.Nm goref
program written by Peter Langston.

266
games/gomoku/gomoku.h Normal file
View File

@ -0,0 +1,266 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)gomoku.h 8.2 (Berkeley) 5/3/95
*/
#include <sys/types.h>
/* board dimensions */
#define BSZ 19
#define BSZ1 (BSZ+1)
#define BSZ2 (BSZ+2)
#define BAREA (BSZ2*BSZ1+1)
/* frame dimentions (based on 5 in a row) */
#define FSZ1 BSZ
#define FSZ2 (BSZ-4)
#define FAREA (FSZ1*FSZ2 + FSZ2*FSZ2 + FSZ1*FSZ2 + FSZ2*FSZ2)
#define MUP (BSZ1)
#define MDOWN (-BSZ1)
#define MLEFT (-1)
#define MRIGHT (1)
/* values for s_occ */
#define BLACK 0
#define WHITE 1
#define EMPTY 2
#define BORDER 3
/* return values for makemove() */
#define MOVEOK 0
#define RESIGN 1
#define ILLEGAL 2
#define WIN 3
#define TIE 4
#define SAVE 5
#define A 1
#define B 2
#define C 3
#define D 4
#define E 5
#define F 6
#define G 7
#define H 8
#define J 9
#define K 10
#define L 11
#define M 12
#define N 13
#define O 14
#define P 15
#define Q 16
#define R 17
#define S 18
#define T 19
#define PT(x,y) ((x) + BSZ1 * (y))
/*
* A 'frame' is a group of five or six contiguous board locations.
* An open ended frame is one with spaces on both ends; otherwise, its closed.
* A 'combo' is a group of intersecting frames and consists of two numbers:
* 'A' is the number of moves to make the combo non-blockable.
* 'B' is the minimum number of moves needed to win once it can't be blocked.
* A 'force' is a combo that is one move away from being non-blockable
*
* Single frame combo values:
* <A,B> board values
* 5,0 . . . . . O
* 4,1 . . . . . .
* 4,0 . . . . X O
* 3,1 . . . . X .
* 3,0 . . . X X O
* 2,1 . . . X X .
* 2,0 . . X X X O
* 1,1 . . X X X .
* 1,0 . X X X X O
* 0,1 . X X X X .
* 0,0 X X X X X O
*
* The rule for combining two combos (<A1,B1> <A2,B2>)
* with V valid intersection points, is:
* A' = A1 + A2 - 2 - V
* B' = MIN(A1 + B1 - 1, A2 + B2 - 1)
* Each time a frame is added to the combo, the number of moves to complete
* the force is the number of moves needed to 'fill' the frame plus one at
* the intersection point. The number of moves to win is the number of moves
* to complete the best frame minus the last move to complete the force.
* Note that it doesn't make sense to combine a <1,x> with anything since
* it is already a force. Also, the frames have to be independent so a
* single move doesn't affect more than one frame making up the combo.
*
* Rules for comparing which of two combos (<A1,B1> <A2,B2>) is better:
* Both the same color:
* <A',B'> = (A1 < A2 || A1 == A2 && B1 <= B2) ? <A1,B1> : <A2,B2>
* We want to complete the force first, then the combo with the
* fewest moves to win.
* Different colors, <A1,B1> is the combo for the player with the next move:
* <A',B'> = A2 <= 1 && (A1 > 1 || A2 + B2 < A1 + B1) ? <A2,B2> : <A1,B1>
* We want to block only if we have to (i.e., if they are one move away
* from completing a force and we don't have a force that we can
* complete which takes fewer or the same number of moves to win).
*/
#define MAXA 6
#define MAXB 2
#define MAXCOMBO 0x600
union comboval {
struct {
#if BYTE_ORDER == BIG_ENDIAN
u_char a; /* # moves to complete force */
u_char b; /* # moves to win */
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
u_char b; /* # moves to win */
u_char a; /* # moves to complete force */
#endif
} c;
u_short s;
};
/*
* This structure is used to record information about single frames (F) and
* combinations of two more frames (C).
* For combinations of two or more frames, there is an additional
* array of pointers to the frames of the combination which is sorted
* by the index into the frames[] array. This is used to prevent duplication
* since frame A combined with B is the same as B with A.
* struct combostr *c_sort[size c_nframes];
* The leaves of the tree (frames) are numbered 0 (bottom, leftmost)
* to c_nframes - 1 (top, right). This is stored in c_frameindex and
* c_dir if C_LOOP is set.
*/
struct combostr {
struct combostr *c_next; /* list of combos at the same level */
struct combostr *c_prev; /* list of combos at the same level */
struct combostr *c_link[2]; /* C:previous level or F:NULL */
union comboval c_linkv[2]; /* C:combo value for link[0,1] */
union comboval c_combo; /* C:combo value for this level */
u_short c_vertex; /* C:intersection or F:frame head */
u_char c_nframes; /* number of frames in the combo */
u_char c_dir; /* C:loop frame or F:frame direction */
u_char c_flg; /* C:combo flags */
u_char c_frameindex; /* C:intersection frame index */
u_char c_framecnt[2]; /* number of frames left to attach */
u_char c_emask[2]; /* C:bit mask of completion spots for
* link[0] and link[1] */
u_char c_voff[2]; /* C:vertex offset within frame */
};
/* flag values for c_flg */
#define C_OPEN_0 0x01 /* link[0] is an open ended frame */
#define C_OPEN_1 0x02 /* link[1] is an open ended frame */
#define C_LOOP 0x04 /* link[1] intersects previous frame */
#define C_MARK 0x08 /* indicates combo processed */
/*
* This structure is used for recording the completion points of
* multi frame combos.
*/
struct elist {
struct elist *e_next; /* list of completion points */
struct combostr *e_combo; /* the whole combo */
u_char e_off; /* offset in frame of this empty spot */
u_char e_frameindex; /* intersection frame index */
u_char e_framecnt; /* number of frames left to attach */
u_char e_emask; /* real value of the frame's emask */
union comboval e_fval; /* frame combo value */
};
/*
* One spot structure for each location on the board.
* A frame consists of the combination for the current spot plus the five spots
* 0: right, 1: right & down, 2: down, 3: down & left.
*/
struct spotstr {
short s_occ; /* color of occupant */
short s_wval; /* weighted value */
int s_flg; /* flags for graph walks */
struct combostr *s_frame[4]; /* level 1 combo for frame[dir] */
union comboval s_fval[2][4]; /* combo value for [color][frame] */
union comboval s_combo[2]; /* minimum combo value for BLK & WHT */
u_char s_level[2]; /* number of frames in the min combo */
u_char s_nforce[2]; /* number of <1,x> combos */
struct elist *s_empty; /* level n combo completion spots */
struct elist *s_nempty; /* level n+1 combo completion spots */
int dummy[2]; /* XXX */
};
/* flag values for s_flg */
#define CFLAG 0x000001 /* frame is part of a combo */
#define CFLAGALL 0x00000F /* all frame directions marked */
#define IFLAG 0x000010 /* legal intersection point */
#define IFLAGALL 0x0000F0 /* any intersection points? */
#define FFLAG 0x000100 /* frame is part of a <1,x> combo */
#define FFLAGALL 0x000F00 /* all force frames */
#define MFLAG 0x001000 /* frame has already been seen */
#define MFLAGALL 0x00F000 /* all frames seen */
#define BFLAG 0x010000 /* frame intersects border or dead */
#define BFLAGALL 0x0F0000 /* all frames dead */
/*
* This structure is used to store overlap information between frames.
*/
struct ovlp_info {
int o_intersect; /* intersection spot */
struct combostr *o_fcombo; /* the connecting combo */
u_char o_link; /* which link to update (0 or 1) */
u_char o_off; /* offset in frame of intersection */
u_char o_frameindex; /* intersection frame index */
};
extern char *letters;
extern char fmtbuf[];
extern char pdir[];
extern int dd[4];
extern struct spotstr board[BAREA]; /* info for board */
extern struct combostr frames[FAREA]; /* storage for single frames */
extern struct combostr *sortframes[2]; /* sorted, non-empty frames */
extern u_char overlap[FAREA * FAREA]; /* frame [a][b] overlap */
extern short intersect[FAREA * FAREA]; /* frame [a][b] intersection */
extern int movelog[BSZ * BSZ]; /* history of moves */
extern int movenum;
extern int debug;
extern char *copy();
extern char *stoc();
extern char *tail();
#define ASSERT(x)

532
games/gomoku/main.c Normal file
View File

@ -0,0 +1,532 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95";
#endif /* not lint */
#include <curses.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "gomoku.h"
#define USER 0 /* get input from standard input */
#define PROGRAM 1 /* get input from program */
#define INPUTF 2 /* get input from a file */
int interactive = 1; /* true if interactive */
int debug; /* true if debugging */
int test; /* both moves come from 1: input, 2: computer */
char *prog; /* name of program */
FILE *debugfp; /* file for debug output */
FILE *inputfp; /* file for debug input */
char pdir[4] = "-\\|/";
char fmtbuf[128];
struct spotstr board[BAREA]; /* info for board */
struct combostr frames[FAREA]; /* storage for all frames */
struct combostr *sortframes[2]; /* sorted list of non-empty frames */
u_char overlap[FAREA * FAREA]; /* true if frame [a][b] overlap */
short intersect[FAREA * FAREA]; /* frame [a][b] intersection */
int movelog[BSZ * BSZ]; /* log of all the moves */
int movenum; /* current move number */
char *plyr[2]; /* who's who */
extern void quit();
#ifdef DEBUG
extern void whatsup();
#endif
main(argc, argv)
int argc;
char **argv;
{
char buf[128];
int color, curmove, i, ch;
int input[2];
static char *fmt[2] = {
"%3d %-6s",
"%3d %-6s"
};
prog = strrchr(argv[0], '/');
if (prog)
prog++;
else
prog = argv[0];
while ((ch = getopt(argc, argv, "bcdD:u")) != EOF) {
switch (ch) {
case 'b': /* background */
interactive = 0;
break;
case 'd': /* debugging */
debug++;
break;
case 'D': /* log debug output to file */
if ((debugfp = fopen(optarg, "w")) == NULL)
err(1, "%s", optarg);
break;
case 'u': /* testing: user verses user */
test = 1;
break;
case 'c': /* testing: computer verses computer */
test = 2;
break;
}
}
argc -= optind;
argv += optind;
if (argc) {
if ((inputfp = fopen(*argv, "r")) == NULL)
err(1, "%s", *argv);
}
if (!debug)
#ifdef SVR4
srand(time(0));
#else
srandom(time(0));
#endif
if (interactive)
cursinit(); /* initialize curses */
again:
bdinit(board); /* initialize board contents */
if (interactive) {
plyr[BLACK] = plyr[WHITE] = "???";
bdisp_init(); /* initialize display of board */
#ifdef DEBUG
signal(SIGINT, whatsup);
#else
signal(SIGINT, quit);
#endif
if (inputfp == NULL && test == 0) {
for (;;) {
ask("black or white? ");
getline(buf, sizeof(buf));
if (buf[0] == 'b' || buf[0] == 'B') {
color = BLACK;
break;
}
if (buf[0] == 'w' || buf[0] == 'W') {
color = WHITE;
break;
}
move(22, 0);
printw("Black moves first. Please enter `black' or `white'\n");
}
move(22, 0);
clrtoeol();
}
} else {
setbuf(stdout, 0);
getline(buf, sizeof(buf));
if (strcmp(buf, "black") == 0)
color = BLACK;
else if (strcmp(buf, "white") == 0)
color = WHITE;
else {
sprintf(fmtbuf,
"Huh? Expected `black' or `white', got `%s'\n",
buf);
panic(fmtbuf);
}
}
if (inputfp) {
input[BLACK] = INPUTF;
input[WHITE] = INPUTF;
} else {
switch (test) {
case 0: /* user verses program */
input[color] = USER;
input[!color] = PROGRAM;
break;
case 1: /* user verses user */
input[BLACK] = USER;
input[WHITE] = USER;
break;
case 2: /* program verses program */
input[BLACK] = PROGRAM;
input[WHITE] = PROGRAM;
break;
}
}
if (interactive) {
plyr[BLACK] = input[BLACK] == USER ? "you" : prog;
plyr[WHITE] = input[WHITE] == USER ? "you" : prog;
bdwho(1);
}
for (color = BLACK; ; color = !color) {
top:
switch (input[color]) {
case INPUTF: /* input comes from a file */
curmove = readinput(inputfp);
if (curmove != ILLEGAL)
break;
switch (test) {
case 0: /* user verses program */
input[color] = USER;
input[!color] = PROGRAM;
break;
case 1: /* user verses user */
input[BLACK] = USER;
input[WHITE] = USER;
break;
case 2: /* program verses program */
input[BLACK] = PROGRAM;
input[WHITE] = PROGRAM;
break;
}
plyr[BLACK] = input[BLACK] == USER ? "you" : prog;
plyr[WHITE] = input[WHITE] == USER ? "you" : prog;
bdwho(1);
goto top;
case USER: /* input comes from standard input */
getinput:
if (interactive)
ask("move? ");
if (!getline(buf, sizeof(buf))) {
curmove = RESIGN;
break;
}
if (buf[0] == '\0')
goto getinput;
curmove = ctos(buf);
if (interactive) {
if (curmove == SAVE) {
FILE *fp;
ask("save file name? ");
(void)getline(buf, sizeof(buf));
if ((fp = fopen(buf, "w")) == NULL) {
log("cannot create save file");
goto getinput;
}
for (i = 0; i < movenum - 1; i++)
fprintf(fp, "%s\n",
stoc(movelog[i]));
fclose(fp);
goto getinput;
}
if (curmove != RESIGN &&
board[curmove].s_occ != EMPTY) {
log("Illegal move");
goto getinput;
}
}
break;
case PROGRAM: /* input comes from the program */
curmove = pickmove(color);
break;
}
if (interactive) {
sprintf(fmtbuf, fmt[color], movenum, stoc(curmove));
log(fmtbuf);
}
if ((i = makemove(color, curmove)) != MOVEOK)
break;
if (interactive)
bdisp();
}
if (interactive) {
move(22, 0);
switch (i) {
case WIN:
if (input[color] == PROGRAM)
addstr("Ha ha, I won");
else
addstr("Rats! you won");
break;
case TIE:
addstr("Wow! its a tie");
break;
case ILLEGAL:
addstr("Illegal move");
break;
}
clrtoeol();
bdisp();
if (i != RESIGN) {
replay:
ask("replay? ");
if (getline(buf, sizeof(buf)) &&
buf[0] == 'y' || buf[0] == 'Y')
goto again;
if (strcmp(buf, "save") == 0) {
FILE *fp;
ask("save file name? ");
(void)getline(buf, sizeof(buf));
if ((fp = fopen(buf, "w")) == NULL) {
log("cannot create save file");
goto replay;
}
for (i = 0; i < movenum - 1; i++)
fprintf(fp, "%s\n",
stoc(movelog[i]));
fclose(fp);
goto replay;
}
}
}
quit();
}
readinput(fp)
FILE *fp;
{
char *cp;
int c;
cp = fmtbuf;
while ((c = getc(fp)) != EOF && c != '\n')
*cp++ = c;
*cp = '\0';
return (ctos(fmtbuf));
}
#ifdef DEBUG
/*
* Handle strange situations.
*/
void
whatsup(signum)
int signum;
{
int i, pnum, n, s1, s2, d1, d2;
struct spotstr *sp;
FILE *fp;
char *str;
struct elist *ep;
struct combostr *cbp;
if (!interactive)
quit();
top:
ask("cmd? ");
if (!getline(fmtbuf, sizeof(fmtbuf)))
quit();
switch (*fmtbuf) {
case '\0':
goto top;
case 'q': /* conservative quit */
quit();
case 'd': /* set debug level */
debug = fmtbuf[1] - '0';
sprintf(fmtbuf, "Debug set to %d", debug);
dlog(fmtbuf);
sleep(1);
case 'c':
break;
case 'b': /* back up a move */
if (movenum > 1) {
movenum--;
board[movelog[movenum - 1]].s_occ = EMPTY;
bdisp();
}
goto top;
case 's': /* suggest a move */
i = fmtbuf[1] == 'b' ? BLACK : WHITE;
sprintf(fmtbuf, "suggest %c %s", i == BLACK ? 'B' : 'W',
stoc(pickmove(i)));
dlog(fmtbuf);
goto top;
case 'f': /* go forward a move */
board[movelog[movenum - 1]].s_occ = movenum & 1 ? BLACK : WHITE;
movenum++;
bdisp();
goto top;
case 'l': /* print move history */
if (fmtbuf[1] == '\0') {
for (i = 0; i < movenum - 1; i++)
dlog(stoc(movelog[i]));
goto top;
}
if ((fp = fopen(fmtbuf + 1, "w")) == NULL)
goto top;
for (i = 0; i < movenum - 1; i++) {
fprintf(fp, "%s", stoc(movelog[i]));
if (++i < movenum - 1)
fprintf(fp, " %s\n", stoc(movelog[i]));
else
fputc('\n', fp);
}
bdump(fp);
fclose(fp);
goto top;
case 'o':
n = 0;
for (str = fmtbuf + 1; *str; str++)
if (*str == ',') {
for (d1 = 0; d1 < 4; d1++)
if (str[-1] == pdir[d1])
break;
str[-1] = '\0';
sp = &board[s1 = ctos(fmtbuf + 1)];
n = (sp->s_frame[d1] - frames) * FAREA;
*str++ = '\0';
break;
}
sp = &board[s2 = ctos(str)];
while (*str)
str++;
for (d2 = 0; d2 < 4; d2++)
if (str[-1] == pdir[d2])
break;
n += sp->s_frame[d2] - frames;
str = fmtbuf;
sprintf(str, "overlap %s%c,", stoc(s1), pdir[d1]);
str += strlen(str);
sprintf(str, "%s%c = %x", stoc(s2), pdir[d2], overlap[n]);
dlog(fmtbuf);
goto top;
case 'p':
sp = &board[i = ctos(fmtbuf + 1)];
sprintf(fmtbuf, "V %s %x/%d %d %x/%d %d %d %x", stoc(i),
sp->s_combo[BLACK].s, sp->s_level[BLACK],
sp->s_nforce[BLACK],
sp->s_combo[WHITE].s, sp->s_level[WHITE],
sp->s_nforce[WHITE], sp->s_wval, sp->s_flg);
dlog(fmtbuf);
sprintf(fmtbuf, "FB %s %x %x %x %x", stoc(i),
sp->s_fval[BLACK][0].s, sp->s_fval[BLACK][1].s,
sp->s_fval[BLACK][2].s, sp->s_fval[BLACK][3].s);
dlog(fmtbuf);
sprintf(fmtbuf, "FW %s %x %x %x %x", stoc(i),
sp->s_fval[WHITE][0].s, sp->s_fval[WHITE][1].s,
sp->s_fval[WHITE][2].s, sp->s_fval[WHITE][3].s);
dlog(fmtbuf);
goto top;
case 'e': /* e {b|w} [0-9] spot */
str = fmtbuf + 1;
if (*str >= '0' && *str <= '9')
n = *str++ - '0';
else
n = 0;
sp = &board[i = ctos(str)];
for (ep = sp->s_empty; ep; ep = ep->e_next) {
cbp = ep->e_combo;
if (n) {
if (cbp->c_nframes > n)
continue;
if (cbp->c_nframes != n)
break;
}
printcombo(cbp, fmtbuf);
dlog(fmtbuf);
}
goto top;
default:
syntax:
dlog("Options are:");
dlog("q - quit");
dlog("c - continue");
dlog("d# - set debug level to #");
dlog("p# - print values at #");
goto top;
}
}
#endif /* DEBUG */
/*
* Display debug info.
*/
dlog(str)
char *str;
{
if (debugfp)
fprintf(debugfp, "%s\n", str);
if (interactive)
dislog(str);
else
fprintf(stderr, "%s\n", str);
}
log(str)
char *str;
{
if (debugfp)
fprintf(debugfp, "%s\n", str);
if (interactive)
dislog(str);
else
printf("%s\n", str);
}
void
quit()
{
if (interactive) {
bdisp(); /* show final board */
cursfini();
}
exit(0);
}
/*
* Die gracefully.
*/
panic(str)
char *str;
{
fprintf(stderr, "%s: %s\n", prog, str);
fputs("resign\n", stdout);
quit();
}

301
games/gomoku/makemove.c Normal file
View File

@ -0,0 +1,301 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)makemove.c 8.2 (Berkeley) 5/3/95";
#endif /* not lint */
#include "gomoku.h"
/* direction deltas */
int dd[4] = {
MRIGHT, MRIGHT+MDOWN, MDOWN, MDOWN+MLEFT
};
int weight[5] = { 0, 1, 7, 22, 100 };
/*
* Return values:
* MOVEOK everything is OK.
* RESIGN Player resigned.
* ILLEGAL Illegal move.
* WIN The the winning move was just played.
* TIE The game is a tie.
*/
makemove(us, mv)
int us, mv;
{
register struct spotstr *sp, *fsp;
register union comboval *cp;
struct spotstr *osp;
struct combostr *cbp, *cbp1;
union comboval *cp1;
register int i, f, r, d, n;
int space, val, bmask;
/* check for end of game */
if (mv == RESIGN)
return(RESIGN);
/* check for illegal move */
sp = &board[mv];
if (sp->s_occ != EMPTY)
return(ILLEGAL);
/* make move */
sp->s_occ = us;
movelog[movenum - 1] = mv;
if (++movenum == BSZ * BSZ)
return(TIE);
/* compute new frame values */
sp->s_wval = 0;
osp = sp;
for (r = 4; --r >= 0; ) { /* for each direction */
d = dd[r];
fsp = osp;
bmask = BFLAG << r;
for (f = 5; --f >= 0; fsp -= d) { /* for each frame */
if (fsp->s_occ == BORDER)
goto nextr;
if (fsp->s_flg & bmask)
continue;
/* remove this frame from the sorted list of frames */
cbp = fsp->s_frame[r];
if (cbp->c_next) {
if (sortframes[BLACK] == cbp)
sortframes[BLACK] = cbp->c_next;
if (sortframes[WHITE] == cbp)
sortframes[WHITE] = cbp->c_next;
cbp->c_next->c_prev = cbp->c_prev;
cbp->c_prev->c_next = cbp->c_next;
}
/* compute old weight value for this frame */
cp = &fsp->s_fval[BLACK][r];
if (cp->s <= 0x500)
val = weight[5 - cp->c.a - cp->c.b];
else
val = 0;
cp = &fsp->s_fval[WHITE][r];
if (cp->s <= 0x500)
val += weight[5 - cp->c.a - cp->c.b];
/* compute new combo value for this frame */
sp = fsp;
space = sp->s_occ == EMPTY;
n = 0;
for (i = 5; --i >= 0; sp += d) { /* for each spot */
if (sp->s_occ == us)
n++;
else if (sp->s_occ == EMPTY)
sp->s_wval -= val;
else {
/* this frame is now blocked, adjust values */
fsp->s_flg |= bmask;
fsp->s_fval[BLACK][r].s = MAXCOMBO;
fsp->s_fval[WHITE][r].s = MAXCOMBO;
while (--i >= 0) {
sp += d;
if (sp->s_occ == EMPTY)
sp->s_wval -= val;
}
goto nextf;
}
}
/* check for game over */
if (n == 5)
return(WIN);
/* compute new value & combo number for this frame & color */
fsp->s_fval[!us][r].s = MAXCOMBO;
cp = &fsp->s_fval[us][r];
/* both ends open? */
if (space && sp->s_occ == EMPTY) {
cp->c.a = 4 - n;
cp->c.b = 1;
} else {
cp->c.a = 5 - n;
cp->c.b = 0;
}
val = weight[n];
sp = fsp;
for (i = 5; --i >= 0; sp += d) /* for each spot */
if (sp->s_occ == EMPTY)
sp->s_wval += val;
/* add this frame to the sorted list of frames by combo value */
cbp1 = sortframes[us];
if (!cbp1)
sortframes[us] = cbp->c_next = cbp->c_prev = cbp;
else {
cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
if (cp->s <= cp1->s) {
/* insert at the head of the list */
sortframes[us] = cbp;
} else {
do {
cbp1 = cbp1->c_next;
cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
if (cp->s <= cp1->s)
break;
} while (cbp1 != sortframes[us]);
}
cbp->c_next = cbp1;
cbp->c_prev = cbp1->c_prev;
cbp1->c_prev->c_next = cbp;
cbp1->c_prev = cbp;
}
nextf:
;
}
/* both ends open? */
if (fsp->s_occ == EMPTY) {
cp = &fsp->s_fval[BLACK][r];
if (cp->c.b) {
cp->c.a += 1;
cp->c.b = 0;
}
cp = &fsp->s_fval[WHITE][r];
if (cp->c.b) {
cp->c.a += 1;
cp->c.b = 0;
}
}
nextr:
;
}
update_overlap(osp);
return(MOVEOK);
}
/*
* fix up the overlap array due to updating spot osp.
*/
update_overlap(osp)
struct spotstr *osp;
{
register struct spotstr *sp, *sp1, *sp2;
register int i, f, r, r1, d, d1, n;
int a, b, bmask, bmask1;
struct spotstr *esp;
char *str;
for (r = 4; --r >= 0; ) { /* for each direction */
d = dd[r];
sp1 = osp;
bmask = BFLAG << r;
for (f = 0; f < 6; f++, sp1 -= d) { /* for each frame */
if (sp1->s_occ == BORDER)
break;
if (sp1->s_flg & bmask)
continue;
/*
* Update all other frames that intersect the current one
* to indicate whether they still overlap or not.
* Since F1 overlap F2 == F2 overlap F1, we only need to
* do the rows 0 <= r1 <= r. The r1 == r case is special
* since the two frames can overlap at more than one point.
*/
str = &overlap[(a = sp1->s_frame[r] - frames) * FAREA];
sp2 = sp1 - d;
for (i = f + 1; i < 6; i++, sp2 -= d) {
if (sp2->s_occ == BORDER)
break;
if (sp2->s_flg & bmask)
continue;
/*
* count the number of empty spots to see if there is
* still an overlap.
*/
n = 0;
sp = sp1;
for (b = i - f; b < 5; b++, sp += d) {
if (sp->s_occ == EMPTY) {
esp = sp; /* save the intersection point */
n++;
}
}
b = sp2->s_frame[r] - frames;
if (n == 0) {
if (sp->s_occ == EMPTY) {
str[b] &= 0xA;
overlap[b * FAREA + a] &= 0xC;
intersect[a * FAREA + b] = n = sp - board;
intersect[b * FAREA + a] = n;
} else {
str[b] = 0;
overlap[b * FAREA + a] = 0;
}
} else if (n == 1) {
if (sp->s_occ == EMPTY) {
str[b] &= 0xAF;
overlap[b * FAREA + a] &= 0xCF;
} else {
str[b] &= 0xF;
overlap[b * FAREA + a] &= 0xF;
}
intersect[a * FAREA + b] = n = esp - board;
intersect[b * FAREA + a] = n;
}
/* else no change, still multiple overlap */
}
/* the other directions can only intersect at spot osp */
for (r1 = r; --r1 >= 0; ) {
d1 = dd[r1];
bmask1 = BFLAG << r1;
sp = osp;
for (i = 6; --i >= 0; sp -= d1) { /* for each spot */
if (sp->s_occ == BORDER)
break;
if (sp->s_flg & bmask1)
continue;
b = sp->s_frame[r1] - frames;
str[b] = 0;
overlap[b * FAREA + a] = 0;
}
}
}
}
}

1479
games/gomoku/pickmove.c Normal file

File diff suppressed because it is too large Load Diff

106
games/gomoku/stoc.c Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)stoc.c 8.1 (Berkeley) 7/24/94";
#endif /* not lint */
#include "gomoku.h"
#include <ctype.h>
char *letters = "<ABCDEFGHJKLMNOPQRST>";
struct mvstr {
int m_code;
char *m_text;
};
static struct mvstr mv[] = {
RESIGN, "resign",
RESIGN, "quit",
SAVE, "save",
-1, 0
};
/*
* Turn the spot number form of a move into the character form.
*/
char *
stoc(s)
int s;
{
static char buf[32];
register int i;
for (i = 0; mv[i].m_code >= 0; i++)
if (s == mv[i].m_code)
return(mv[i].m_text);
sprintf(buf, "%c%d", letters[s % BSZ1], s / BSZ1);
return(buf);
}
/*
* Turn the character form of a move into the spot number form.
*/
ctos(mp)
char *mp;
{
register int i;
for (i = 0; mv[i].m_code >= 0; i++)
if (strcmp(mp, mv[i].m_text) == 0)
return(mv[i].m_code);
if (!isalpha(mp[0]))
return(ILLEGAL);
i = atoi(&mp[1]);
if (i < 1 || i > 19)
return(ILLEGAL);
return(PT(lton(mp[0]), i));
}
/*
* Turn a letter into a number.
*/
lton(c)
int c;
{
register int i;
if (islower(c))
c = toupper(c);
for (i = 1; i <= BSZ && letters[i] != c; i++)
;
return(i);
}