xref: /original-bsd/games/gomoku/makemove.c (revision deff14a8)
1 /*
2  * Copyright (c) 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)makemove.c	8.1 (Berkeley) 07/24/94";
13 #endif /* not lint */
14 
15 #include "gomoku.h"
16 
17 		/* direction deltas */
18 int     dd[4] = {
19 	MRIGHT, MRIGHT+MDOWN, MDOWN, MDOWN+MLEFT
20 };
21 
22 int	weight[5] = { 0, 1, 7, 22, 100 };
23 
24 /*
25  * Return values:
26  *	MOVEOK	everything is OK.
27  *	RESIGN	Player resigned.
28  *	ILLEGAL	Illegal move.
29  *	WIN	The the winning move was just played.
30  *	TIE	The game is a tie.
31  */
32 makemove(us, mv)
33 	int us, mv;
34 {
35 	register struct spotstr *sp, *fsp;
36 	register union combo *cp;
37 	struct spotstr *osp;
38 	struct combostr *cbp, *cbp1;
39 	union combo *cp1;
40 	register int i, f, r, d, n;
41 	int space, val, bmask;
42 
43 	/* check for end of game */
44 	if (mv == RESIGN)
45 		return(RESIGN);
46 
47 	/* check for illegal move */
48 	sp = &board[mv];
49 	if (sp->s_occ != EMPTY)
50 		return(ILLEGAL);
51 
52 	/* make move */
53 	sp->s_occ = us;
54 	movelog[movenum - 1] = mv;
55 	if (++movenum == BSZ * BSZ)
56 		return(TIE);
57 
58 	/* compute new frame values */
59 	sp->s_wval = 0;
60 	osp = sp;
61 	for (r = 4; --r >= 0; ) {			/* for each direction */
62 	    d = dd[r];
63 	    fsp = osp;
64 	    bmask = BFLAG << r;
65 	    for (f = 5; --f >= 0; fsp -= d) {		/* for each frame */
66 		if (fsp->s_occ == BORDER)
67 		    goto nextr;
68 		if (fsp->s_flg & bmask)
69 		    continue;
70 
71 		/* remove this frame from the sorted list of frames */
72 		cbp = fsp->s_frame[r];
73 		if (cbp->c_next) {
74 			if (sortframes[BLACK] == cbp)
75 			    sortframes[BLACK] = cbp->c_next;
76 			if (sortframes[WHITE] == cbp)
77 			    sortframes[WHITE] = cbp->c_next;
78 			cbp->c_next->c_prev = cbp->c_prev;
79 			cbp->c_prev->c_next = cbp->c_next;
80 		}
81 
82 		/* compute old weight value for this frame */
83 		cp = &fsp->s_fval[BLACK][r];
84 		if (cp->s <= 0x500)
85 		    val = weight[5 - cp->c.a - cp->c.b];
86 		else
87 		    val = 0;
88 		cp = &fsp->s_fval[WHITE][r];
89 		if (cp->s <= 0x500)
90 		    val += weight[5 - cp->c.a - cp->c.b];
91 
92 		/* compute new combo value for this frame */
93 		sp = fsp;
94 		space = sp->s_occ == EMPTY;
95 		n = 0;
96 		for (i = 5; --i >= 0; sp += d) {	/* for each spot */
97 		    if (sp->s_occ == us)
98 			n++;
99 		    else if (sp->s_occ == EMPTY)
100 			sp->s_wval -= val;
101 		    else {
102 			/* this frame is now blocked, adjust values */
103 			fsp->s_flg |= bmask;
104 			fsp->s_fval[BLACK][r].s = MAXCOMBO;
105 			fsp->s_fval[WHITE][r].s = MAXCOMBO;
106 			while (--i >= 0) {
107 			    sp += d;
108 			    if (sp->s_occ == EMPTY)
109 				sp->s_wval -= val;
110 			}
111 			goto nextf;
112 		    }
113 		}
114 
115 		/* check for game over */
116 		if (n == 5)
117 		    return(WIN);
118 
119 		/* compute new value & combo number for this frame & color */
120 		fsp->s_fval[!us][r].s = MAXCOMBO;
121 		cp = &fsp->s_fval[us][r];
122 		/* both ends open? */
123 		if (space && sp->s_occ == EMPTY) {
124 		    cp->c.a = 4 - n;
125 		    cp->c.b = 1;
126 		} else {
127 		    cp->c.a = 5 - n;
128 		    cp->c.b = 0;
129 		}
130 		val = weight[n];
131 		sp = fsp;
132 		for (i = 5; --i >= 0; sp += d)		/* for each spot */
133 		    if (sp->s_occ == EMPTY)
134 			sp->s_wval += val;
135 
136 		/* add this frame to the sorted list of frames by combo value */
137 		cbp1 = sortframes[us];
138 		if (!cbp1)
139 		    sortframes[us] = cbp->c_next = cbp->c_prev = cbp;
140 		else {
141 		    cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
142 		    if (cp->s <= cp1->s) {
143 			/* insert at the head of the list */
144 			sortframes[us] = cbp;
145 		    } else {
146 			do {
147 			    cbp1 = cbp1->c_next;
148 			    cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
149 			    if (cp->s <= cp1->s)
150 				break;
151 			} while (cbp1 != sortframes[us]);
152 		    }
153 		    cbp->c_next = cbp1;
154 		    cbp->c_prev = cbp1->c_prev;
155 		    cbp1->c_prev->c_next = cbp;
156 		    cbp1->c_prev = cbp;
157 		}
158 
159 	    nextf:
160 		;
161 	    }
162 
163 	    /* both ends open? */
164 	    if (fsp->s_occ == EMPTY) {
165 		cp = &fsp->s_fval[BLACK][r];
166 		if (cp->c.b) {
167 		    cp->c.a += 1;
168 		    cp->c.b = 0;
169 		}
170 		cp = &fsp->s_fval[WHITE][r];
171 		if (cp->c.b) {
172 		    cp->c.a += 1;
173 		    cp->c.b = 0;
174 		}
175 	    }
176 
177 	nextr:
178 	    ;
179 	}
180 
181 	return(MOVEOK);
182 }
183