xref: /original-bsd/games/gomoku/pickmove.c (revision 8af5b582)
1*8af5b582Smckusick /*
2*8af5b582Smckusick  * Copyright (c) 1994
3*8af5b582Smckusick  *	The Regents of the University of California.  All rights reserved.
4*8af5b582Smckusick  *
5*8af5b582Smckusick  * This code is derived from software contributed to Berkeley by
6*8af5b582Smckusick  * Ralph Campbell.
7*8af5b582Smckusick  *
8*8af5b582Smckusick  * %sccs.include.redist.c%
9*8af5b582Smckusick  */
10*8af5b582Smckusick 
11*8af5b582Smckusick #ifndef lint
12*8af5b582Smckusick static char sccsid[] = "@(#)pickmove.c	8.1 (Berkeley) 07/24/94";
13*8af5b582Smckusick #endif /* not lint */
14*8af5b582Smckusick 
15*8af5b582Smckusick #include <stdio.h>
16*8af5b582Smckusick #include <curses.h>
17*8af5b582Smckusick 
18*8af5b582Smckusick #include "gomoku.h"
19*8af5b582Smckusick 
20*8af5b582Smckusick struct	combostr *sortcombos[2];	/* combos at higher levels */
21*8af5b582Smckusick int	combolen[2];			/* number of combos in sortcombos */
22*8af5b582Smckusick int	nextcolor;			/* color of next move */
23*8af5b582Smckusick 
24*8af5b582Smckusick extern char pdir[];
25*8af5b582Smckusick 
26*8af5b582Smckusick pickmove(us)
27*8af5b582Smckusick 	int us;
28*8af5b582Smckusick {
29*8af5b582Smckusick 	register struct spotstr *sp, *sp1, *sp2;
30*8af5b582Smckusick 	register union combo *Ocp, *Tcp;
31*8af5b582Smckusick 
32*8af5b582Smckusick 	/* first move is easy */
33*8af5b582Smckusick 	if (movenum == 1)
34*8af5b582Smckusick 		return (PT(K,10));
35*8af5b582Smckusick 
36*8af5b582Smckusick 	/* initialize all the board values */
37*8af5b582Smckusick 	for (sp = &board[PT(T,20)]; --sp >= &board[PT(A,1)]; ) {
38*8af5b582Smckusick 		sp->s_combo[BLACK].s = MAXCOMBO;
39*8af5b582Smckusick 		sp->s_combo[WHITE].s = MAXCOMBO;
40*8af5b582Smckusick 		sp->s_level[BLACK] = 255;
41*8af5b582Smckusick 		sp->s_level[WHITE] = 255;
42*8af5b582Smckusick 		sp->s_nforce[BLACK] = 0;
43*8af5b582Smckusick 		sp->s_nforce[WHITE] = 0;
44*8af5b582Smckusick 		sp->s_flg &= ~(FFLAGALL | MFLAGALL);
45*8af5b582Smckusick 	}
46*8af5b582Smckusick 
47*8af5b582Smckusick 	/* remove old combos */
48*8af5b582Smckusick 	removecombos(BLACK);
49*8af5b582Smckusick 	removecombos(WHITE);
50*8af5b582Smckusick 	removeemptyspots();
51*8af5b582Smckusick 
52*8af5b582Smckusick 	/* compute new values */
53*8af5b582Smckusick 	nextcolor = us;
54*8af5b582Smckusick 	scanframes(BLACK);
55*8af5b582Smckusick 	scanframes(WHITE);
56*8af5b582Smckusick 
57*8af5b582Smckusick 	/* find the spot with the highest value */
58*8af5b582Smckusick 	for (sp = sp1 = sp2 = &board[PT(T,19)]; --sp >= &board[PT(A,1)]; ) {
59*8af5b582Smckusick 		if (sp->s_occ != EMPTY)
60*8af5b582Smckusick 			continue;
61*8af5b582Smckusick 		if (debug && (sp->s_combo[BLACK].s < 0x200 ||
62*8af5b582Smckusick 		    sp->s_combo[WHITE].s < 0x200)) {
63*8af5b582Smckusick 			sprintf(fmtbuf, "- %s %x/%d %d %x/%d %d %d", stoc(sp - board),
64*8af5b582Smckusick 				sp->s_combo[BLACK].s, sp->s_level[BLACK],
65*8af5b582Smckusick 				sp->s_nforce[BLACK],
66*8af5b582Smckusick 				sp->s_combo[WHITE].s, sp->s_level[WHITE],
67*8af5b582Smckusick 				sp->s_nforce[WHITE],
68*8af5b582Smckusick 				sp->s_wval);
69*8af5b582Smckusick 			dlog(fmtbuf);
70*8af5b582Smckusick 		}
71*8af5b582Smckusick 		/* pick the best black move */
72*8af5b582Smckusick 		if (better(sp, sp1, BLACK))
73*8af5b582Smckusick 			sp1 = sp;
74*8af5b582Smckusick 		/* pick the best white move */
75*8af5b582Smckusick 		if (better(sp, sp2, WHITE))
76*8af5b582Smckusick 			sp2 = sp;
77*8af5b582Smckusick 	}
78*8af5b582Smckusick 	if (debug) {
79*8af5b582Smckusick 		sprintf(fmtbuf, "B %s %x/%d %d %x/%d %d %d %d",
80*8af5b582Smckusick 			stoc(sp1 - board),
81*8af5b582Smckusick 			sp1->s_combo[BLACK].s, sp1->s_level[BLACK],
82*8af5b582Smckusick 			sp1->s_nforce[BLACK],
83*8af5b582Smckusick 			sp1->s_combo[WHITE].s, sp1->s_level[WHITE],
84*8af5b582Smckusick 			sp1->s_nforce[WHITE], sp1->s_wval, combolen[BLACK]);
85*8af5b582Smckusick 		dlog(fmtbuf);
86*8af5b582Smckusick 		sprintf(fmtbuf, "W %s %x/%d %d %x/%d %d %d %d",
87*8af5b582Smckusick 			stoc(sp2 - board),
88*8af5b582Smckusick 			sp2->s_combo[WHITE].s, sp2->s_level[WHITE],
89*8af5b582Smckusick 			sp2->s_nforce[WHITE],
90*8af5b582Smckusick 			sp2->s_combo[BLACK].s, sp2->s_level[BLACK],
91*8af5b582Smckusick 			sp2->s_nforce[BLACK], sp2->s_wval, combolen[WHITE]);
92*8af5b582Smckusick 		dlog(fmtbuf);
93*8af5b582Smckusick 	}
94*8af5b582Smckusick 	if (us == BLACK) {
95*8af5b582Smckusick 		Ocp = &sp1->s_combo[BLACK];
96*8af5b582Smckusick 		Tcp = &sp2->s_combo[WHITE];
97*8af5b582Smckusick 	} else {
98*8af5b582Smckusick 		Tcp = &sp1->s_combo[BLACK];
99*8af5b582Smckusick 		Ocp = &sp2->s_combo[WHITE];
100*8af5b582Smckusick 		sp = sp1;
101*8af5b582Smckusick 		sp1 = sp2;
102*8af5b582Smckusick 		sp2 = sp;
103*8af5b582Smckusick 	}
104*8af5b582Smckusick 	/*
105*8af5b582Smckusick 	 * Block their combo only if we have to (i.e., if they are one move
106*8af5b582Smckusick 	 * away from completing a force and we don't have a force that
107*8af5b582Smckusick 	 * we can complete which takes fewer moves to win).
108*8af5b582Smckusick 	 */
109*8af5b582Smckusick 	if (Tcp->c.a <= 1 && (Ocp->c.a > 1 ||
110*8af5b582Smckusick 	    Tcp->c.a + Tcp->c.b < Ocp->c.a + Ocp->c.b))
111*8af5b582Smckusick 		return (sp2 - board);
112*8af5b582Smckusick 	return (sp1 - board);
113*8af5b582Smckusick }
114*8af5b582Smckusick 
115*8af5b582Smckusick /*
116*8af5b582Smckusick  * Return true if spot 'sp' is better than spot 'sp1' for color 'us'.
117*8af5b582Smckusick  */
118*8af5b582Smckusick better(sp, sp1, us)
119*8af5b582Smckusick 	struct spotstr *sp;
120*8af5b582Smckusick 	struct spotstr *sp1;
121*8af5b582Smckusick 	int us;
122*8af5b582Smckusick {
123*8af5b582Smckusick 	int them;
124*8af5b582Smckusick 
125*8af5b582Smckusick 	if (sp->s_combo[us].s < sp1->s_combo[us].s)
126*8af5b582Smckusick 		return (1);
127*8af5b582Smckusick 	if (sp->s_combo[us].s != sp1->s_combo[us].s)
128*8af5b582Smckusick 		return (0);
129*8af5b582Smckusick 	if (sp->s_level[us] < sp1->s_level[us])
130*8af5b582Smckusick 		return (1);
131*8af5b582Smckusick 	if (sp->s_level[us] != sp1->s_level[us])
132*8af5b582Smckusick 		return (0);
133*8af5b582Smckusick 	if (sp->s_nforce[us] > sp1->s_nforce[us])
134*8af5b582Smckusick 		return (1);
135*8af5b582Smckusick 	if (sp->s_nforce[us] != sp1->s_nforce[us])
136*8af5b582Smckusick 		return (0);
137*8af5b582Smckusick 
138*8af5b582Smckusick 	them = !us;
139*8af5b582Smckusick 	if (sp->s_combo[them].s < sp1->s_combo[them].s)
140*8af5b582Smckusick 		return (1);
141*8af5b582Smckusick 	if (sp->s_combo[them].s != sp1->s_combo[them].s)
142*8af5b582Smckusick 		return (0);
143*8af5b582Smckusick 	if (sp->s_level[them] < sp1->s_level[them])
144*8af5b582Smckusick 		return (1);
145*8af5b582Smckusick 	if (sp->s_level[them] != sp1->s_level[them])
146*8af5b582Smckusick 		return (0);
147*8af5b582Smckusick 	if (sp->s_nforce[them] > sp1->s_nforce[them])
148*8af5b582Smckusick 		return (1);
149*8af5b582Smckusick 	if (sp->s_nforce[them] != sp1->s_nforce[them])
150*8af5b582Smckusick 		return (0);
151*8af5b582Smckusick 
152*8af5b582Smckusick 	if (sp->s_wval > sp1->s_wval)
153*8af5b582Smckusick 		return (1);
154*8af5b582Smckusick 	if (sp->s_wval != sp1->s_wval)
155*8af5b582Smckusick 		return (0);
156*8af5b582Smckusick 
157*8af5b582Smckusick #ifdef SVR4
158*8af5b582Smckusick 	return (rand() & 1);
159*8af5b582Smckusick #else
160*8af5b582Smckusick 	return (random() & 1);
161*8af5b582Smckusick #endif
162*8af5b582Smckusick }
163*8af5b582Smckusick 
164*8af5b582Smckusick int		curcolor;	/* implicit parameter to makecombo() */
165*8af5b582Smckusick int		curlevel;	/* implicit parameter to makecombo() */
166*8af5b582Smckusick 
167*8af5b582Smckusick /*
168*8af5b582Smckusick  * Scan the sorted list of frames and update the minimum combo values.
169*8af5b582Smckusick  */
170*8af5b582Smckusick scanframes(color)
171*8af5b582Smckusick 	int color;
172*8af5b582Smckusick {
173*8af5b582Smckusick 	register struct combostr *cbp, *ecbp;
174*8af5b582Smckusick 	register struct spotstr *sp;
175*8af5b582Smckusick 	register union combo *cp;
176*8af5b582Smckusick 	register struct elist *ep;
177*8af5b582Smckusick 	register int i, r, d, n;
178*8af5b582Smckusick 	union combo cb;
179*8af5b582Smckusick 
180*8af5b582Smckusick 	curcolor = color;
181*8af5b582Smckusick 
182*8af5b582Smckusick 	/* check for empty list of frames */
183*8af5b582Smckusick 	cbp = sortframes[color];
184*8af5b582Smckusick 	if (cbp == (struct combostr *)0)
185*8af5b582Smckusick 		return;
186*8af5b582Smckusick 
187*8af5b582Smckusick 	/* quick check for four in a row */
188*8af5b582Smckusick 	sp = &board[cbp->c_vertex];
189*8af5b582Smckusick 	cb.s = sp->s_fval[color][d = cbp->c_dir].s;
190*8af5b582Smckusick 	if (cb.s < 0x101) {
191*8af5b582Smckusick 		d = dd[d];
192*8af5b582Smckusick 		for (i = 5 + cb.c.b; --i >= 0; sp += d) {
193*8af5b582Smckusick 			if (sp->s_occ != EMPTY)
194*8af5b582Smckusick 				continue;
195*8af5b582Smckusick 			sp->s_combo[color].s = cb.s;
196*8af5b582Smckusick 			sp->s_level[color] = 1;
197*8af5b582Smckusick 		}
198*8af5b582Smckusick 		return;
199*8af5b582Smckusick 	}
200*8af5b582Smckusick 
201*8af5b582Smckusick 	/* update the minimum combo value for each spot in the frame */
202*8af5b582Smckusick 	n = combolen[color];
203*8af5b582Smckusick 	ecbp = cbp;
204*8af5b582Smckusick 	do {
205*8af5b582Smckusick 		sp = &board[cbp->c_vertex];
206*8af5b582Smckusick 		cp = &sp->s_fval[color][r = cbp->c_dir];
207*8af5b582Smckusick 		d = dd[r];
208*8af5b582Smckusick 		if (cp->c.b) {
209*8af5b582Smckusick 			cb.c.a = cp->c.a + 1;
210*8af5b582Smckusick 			cb.c.b = 0;
211*8af5b582Smckusick 			if (cb.s < sp->s_combo[color].s) {
212*8af5b582Smckusick 				sp->s_combo[color].s = cb.s;
213*8af5b582Smckusick 				sp->s_level[color] = 1;
214*8af5b582Smckusick 			}
215*8af5b582Smckusick 			makecombo2(cbp, sp, cb.s);
216*8af5b582Smckusick 			if (cp->s != 0x101)
217*8af5b582Smckusick 				cb.s = cp->s;
218*8af5b582Smckusick 			sp += d;
219*8af5b582Smckusick 			i = 4;
220*8af5b582Smckusick 		} else {
221*8af5b582Smckusick 			cb.s = cp->s;
222*8af5b582Smckusick 			i = 5;
223*8af5b582Smckusick 		}
224*8af5b582Smckusick 		for (; --i >= 0; sp += d) {	/* for each spot */
225*8af5b582Smckusick 			if (sp->s_occ != EMPTY)
226*8af5b582Smckusick 				continue;
227*8af5b582Smckusick 			if (cp->s < sp->s_combo[color].s) {
228*8af5b582Smckusick 				sp->s_combo[color].s = cp->s;
229*8af5b582Smckusick 				sp->s_level[color] = 1;
230*8af5b582Smckusick 			}
231*8af5b582Smckusick 			if (cp->s == 0x101)
232*8af5b582Smckusick 				sp->s_nforce[color]++;
233*8af5b582Smckusick 			makecombo2(cbp, sp, cb.s);
234*8af5b582Smckusick 		}
235*8af5b582Smckusick 		/* mark frame as having been processed */
236*8af5b582Smckusick 		board[cbp->c_vertex].s_flg |= MFLAG << r;
237*8af5b582Smckusick 	} while ((cbp = cbp->c_next) != ecbp);
238*8af5b582Smckusick 
239*8af5b582Smckusick 	/* try to make new 3rd level combos, 4th level, etc. */
240*8af5b582Smckusick 	d = 2;
241*8af5b582Smckusick 	while (combolen[color] > n) {
242*8af5b582Smckusick 		if (debug) {
243*8af5b582Smckusick 			sprintf(fmtbuf, "%cL%d %d", "BW"[color], d,
244*8af5b582Smckusick 				combolen[color] - n);
245*8af5b582Smckusick 			dlog(fmtbuf);
246*8af5b582Smckusick 			refresh();
247*8af5b582Smckusick 		}
248*8af5b582Smckusick 		n = combolen[color];
249*8af5b582Smckusick 		addframes(d);
250*8af5b582Smckusick 		d++;
251*8af5b582Smckusick 	}
252*8af5b582Smckusick 
253*8af5b582Smckusick 	/* scan for combos at empty spots */
254*8af5b582Smckusick 	for (sp = &board[PT(T,20)]; --sp >= &board[PT(A,1)]; ) {
255*8af5b582Smckusick 		for (ep = sp->s_empty[color]; ep; ep = ep->e_next) {
256*8af5b582Smckusick 			cbp = ep->e_combo;
257*8af5b582Smckusick 			if (cbp->c_combo.s < sp->s_combo[color].s) {
258*8af5b582Smckusick 				sp->s_combo[color].s = cbp->c_combo.s;
259*8af5b582Smckusick 				sp->s_level[color] = cbp->c_nframes;
260*8af5b582Smckusick 			} else if (cbp->c_combo.s == sp->s_combo[color].s &&
261*8af5b582Smckusick 			    cbp->c_nframes < sp->s_level[color])
262*8af5b582Smckusick 				sp->s_level[color] = cbp->c_nframes;
263*8af5b582Smckusick 		}
264*8af5b582Smckusick 	}
265*8af5b582Smckusick }
266*8af5b582Smckusick 
267*8af5b582Smckusick /*
268*8af5b582Smckusick  * Compute all level 2 combos of frames intersecting spot 'osp'
269*8af5b582Smckusick  * within the frame 'ocbp' and combo value 's'.
270*8af5b582Smckusick  */
271*8af5b582Smckusick makecombo2(ocbp, osp, s)
272*8af5b582Smckusick 	struct combostr *ocbp;
273*8af5b582Smckusick 	struct spotstr *osp;
274*8af5b582Smckusick 	int s;
275*8af5b582Smckusick {
276*8af5b582Smckusick 	register struct spotstr *sp, *fsp;
277*8af5b582Smckusick 	register struct combostr *cbp;
278*8af5b582Smckusick 	register int f, r, d, c;
279*8af5b582Smckusick 	int baseB, bmask, n;
280*8af5b582Smckusick 	union combo ocb, fcb;
281*8af5b582Smckusick 
282*8af5b582Smckusick 	/* try to combine a new frame with those found so far */
283*8af5b582Smckusick 	ocb.s = s;
284*8af5b582Smckusick 	baseB = ocb.c.a + ocb.c.b - 1;
285*8af5b582Smckusick 	for (r = 4; --r >= 0; ) {			/* for each direction */
286*8af5b582Smckusick 	    /* don't include frames that overlap ones already included */
287*8af5b582Smckusick 	    if (r == ocbp->c_dir)
288*8af5b582Smckusick 		continue;
289*8af5b582Smckusick 	    d = dd[r];
290*8af5b582Smckusick 	    bmask = (BFLAG | FFLAG | MFLAG) << r;
291*8af5b582Smckusick 	    fsp = osp;
292*8af5b582Smckusick 	    for (f = 5; --f >= 0; fsp -= d) {		/* for each frame */
293*8af5b582Smckusick 		/*
294*8af5b582Smckusick 		 * Don't include frames that are blocked or
295*8af5b582Smckusick 		 * part of a <1,x> combo.
296*8af5b582Smckusick 		 */
297*8af5b582Smckusick 		if (fsp->s_occ == BORDER)
298*8af5b582Smckusick 		    break;
299*8af5b582Smckusick 		if (fsp->s_flg & bmask)
300*8af5b582Smckusick 		    continue;
301*8af5b582Smckusick 
302*8af5b582Smckusick 		/* don't include frames of the wrong color */
303*8af5b582Smckusick 		fcb.s = fsp->s_fval[curcolor][r].s;
304*8af5b582Smckusick 		if (fcb.c.a >= MAXA)
305*8af5b582Smckusick 		    continue;
306*8af5b582Smckusick 
307*8af5b582Smckusick 		/*
308*8af5b582Smckusick 		 * Get the combo value for this frame.
309*8af5b582Smckusick 		 * If this is the end point of the frame,
310*8af5b582Smckusick 		 * use the closed ended value for the frame.
311*8af5b582Smckusick 		 */
312*8af5b582Smckusick 		if (f == 4 && fcb.c.b || fcb.s == 0x101) {
313*8af5b582Smckusick 		    fcb.c.a++;
314*8af5b582Smckusick 		    fcb.c.b = 0;
315*8af5b582Smckusick 		}
316*8af5b582Smckusick 
317*8af5b582Smckusick 		/* compute combo value */
318*8af5b582Smckusick 		c = fcb.c.a + ocb.c.a - 3;
319*8af5b582Smckusick 		if (c > 3)
320*8af5b582Smckusick 		    continue;
321*8af5b582Smckusick 		n = fcb.c.a + fcb.c.b - 1;
322*8af5b582Smckusick 		if (baseB < n)
323*8af5b582Smckusick 		    n = baseB;
324*8af5b582Smckusick 
325*8af5b582Smckusick 		/* make a new combo! */
326*8af5b582Smckusick 		cbp = (struct combostr *)malloc(sizeof(struct combostr));
327*8af5b582Smckusick 		cbp->c_combo.c.a = c;
328*8af5b582Smckusick 		cbp->c_combo.c.b = n;
329*8af5b582Smckusick 		cbp->c_link[0] = ocbp;
330*8af5b582Smckusick 		cbp->c_link[1] = fsp->s_frame[r];
331*8af5b582Smckusick 		cbp->c_vertex = osp - board;
332*8af5b582Smckusick 		cbp->c_nframes = 2;
333*8af5b582Smckusick 		cbp->c_dir = 0;
334*8af5b582Smckusick 		cbp->c_flg = 0;
335*8af5b582Smckusick 		cbp->c_refcnt = 0;
336*8af5b582Smckusick 
337*8af5b582Smckusick 		if (c == 1 && debug > 1 || debug > 3) {
338*8af5b582Smckusick 		    sprintf(fmtbuf, "%c %s %x/2 r%d f%d %x",
339*8af5b582Smckusick 			curcolor == BLACK ? 'b' : 'w',
340*8af5b582Smckusick 			stoc(osp - board), cbp->c_combo.s, r, f, ocb.s);
341*8af5b582Smckusick 		    dlog(fmtbuf);
342*8af5b582Smckusick #ifdef DEBUG
343*8af5b582Smckusick 		    markcombo(cbp, curcolor, 0);
344*8af5b582Smckusick 		    bdisp();
345*8af5b582Smckusick 		    whatsup(0);
346*8af5b582Smckusick 		    clearcombo(cbp, curcolor, 0);
347*8af5b582Smckusick #endif
348*8af5b582Smckusick 		}
349*8af5b582Smckusick 		if (c > 1) {
350*8af5b582Smckusick 		    if (ocb.c.a > 2)
351*8af5b582Smckusick 			makeempty(cbp, ocbp, ocb.c.b);
352*8af5b582Smckusick 		    if (fcb.c.a > 2)
353*8af5b582Smckusick 			makeempty(cbp, cbp->c_link[1], fcb.c.b);
354*8af5b582Smckusick 
355*8af5b582Smckusick 		    /* add the new combo to the end of the list */
356*8af5b582Smckusick 		    appendcombo(cbp, curcolor);
357*8af5b582Smckusick 		} else {
358*8af5b582Smckusick 		    updatecombo(cbp, curcolor);
359*8af5b582Smckusick 		    free(cbp);
360*8af5b582Smckusick 		}
361*8af5b582Smckusick 	    }
362*8af5b582Smckusick 	}
363*8af5b582Smckusick }
364*8af5b582Smckusick 
365*8af5b582Smckusick /*
366*8af5b582Smckusick  * Scan the sorted list of frames and try to combine into combos.
367*8af5b582Smckusick  */
368*8af5b582Smckusick addframes(level)
369*8af5b582Smckusick 	int level;
370*8af5b582Smckusick {
371*8af5b582Smckusick 	register struct combostr *cbp, *ecbp;
372*8af5b582Smckusick 	register struct spotstr *sp, *fsp;
373*8af5b582Smckusick 	register int i, r, d;
374*8af5b582Smckusick 	union combo fcb, cb;
375*8af5b582Smckusick 
376*8af5b582Smckusick 	curlevel = level;
377*8af5b582Smckusick 
378*8af5b582Smckusick 	/* clear MFLAG for this level */
379*8af5b582Smckusick 	cbp = ecbp = sortframes[curcolor];
380*8af5b582Smckusick 	do {
381*8af5b582Smckusick 		board[cbp->c_vertex].s_flg &= ~MFLAGALL;
382*8af5b582Smckusick 	} while ((cbp = cbp->c_next) != ecbp);
383*8af5b582Smckusick 
384*8af5b582Smckusick 	cbp = ecbp;
385*8af5b582Smckusick 	do {
386*8af5b582Smckusick 		fsp = &board[cbp->c_vertex];
387*8af5b582Smckusick 		r = cbp->c_dir;
388*8af5b582Smckusick 		/* skip frames that are part of a <1,x> combo */
389*8af5b582Smckusick 		if (fsp->s_flg & (FFLAG << r))
390*8af5b582Smckusick 			continue;
391*8af5b582Smckusick 
392*8af5b582Smckusick 		/*
393*8af5b582Smckusick 		 * Don't include <1,x> combo frames,
394*8af5b582Smckusick 		 * treat it as a blocked three in a row instead.
395*8af5b582Smckusick 		 */
396*8af5b582Smckusick 		fcb.s = fsp->s_fval[curcolor][r].s;
397*8af5b582Smckusick 		if (fcb.s == 0x101)
398*8af5b582Smckusick 			fcb.s = 0x200;
399*8af5b582Smckusick 
400*8af5b582Smckusick 		/*
401*8af5b582Smckusick 		 * If this is an open ended frame, use
402*8af5b582Smckusick 		 * the combo value with the end closed.
403*8af5b582Smckusick 		 */
404*8af5b582Smckusick 		if (fsp->s_occ == EMPTY) {
405*8af5b582Smckusick 			if (fcb.c.b) {
406*8af5b582Smckusick 				cb.c.a = fcb.c.a + 1;
407*8af5b582Smckusick 				cb.c.b = 0;
408*8af5b582Smckusick 			} else
409*8af5b582Smckusick 				cb.s = fcb.s;
410*8af5b582Smckusick 			makecombo(cbp, fsp, cb.s);
411*8af5b582Smckusick 		}
412*8af5b582Smckusick 
413*8af5b582Smckusick 		/*
414*8af5b582Smckusick 		 * The next four spots are handled the same for both
415*8af5b582Smckusick 		 * open and closed ended frames.
416*8af5b582Smckusick 		 */
417*8af5b582Smckusick 		d = dd[r];
418*8af5b582Smckusick 		sp = fsp + d;
419*8af5b582Smckusick 		for (i = 4; --i >= 0; sp += d) {
420*8af5b582Smckusick 			if (sp->s_occ != EMPTY)
421*8af5b582Smckusick 				continue;
422*8af5b582Smckusick 			makecombo(cbp, sp, fcb.s);
423*8af5b582Smckusick 		}
424*8af5b582Smckusick 
425*8af5b582Smckusick 		/* mark frame as having been processed */
426*8af5b582Smckusick 		fsp->s_flg |= MFLAG << r;
427*8af5b582Smckusick 	} while ((cbp = cbp->c_next) != ecbp);
428*8af5b582Smckusick }
429*8af5b582Smckusick 
430*8af5b582Smckusick /*
431*8af5b582Smckusick  * Compute all level N combos of frames intersecting spot 'osp'
432*8af5b582Smckusick  * within the frame 'ocbp' and combo value 's'.
433*8af5b582Smckusick  */
434*8af5b582Smckusick makecombo(ocbp, osp, s)
435*8af5b582Smckusick 	struct combostr *ocbp;
436*8af5b582Smckusick 	struct spotstr *osp;
437*8af5b582Smckusick 	int s;
438*8af5b582Smckusick {
439*8af5b582Smckusick 	register struct combostr *cbp, *ncbp;
440*8af5b582Smckusick 	register struct spotstr *sp;
441*8af5b582Smckusick 	register struct elist *ep;
442*8af5b582Smckusick 	register int n, c;
443*8af5b582Smckusick 	struct elist *nep, **epp;
444*8af5b582Smckusick 	struct combostr *fcbp;
445*8af5b582Smckusick 	int baseB, verts, d;
446*8af5b582Smckusick 	union combo ocb, cb;
447*8af5b582Smckusick 
448*8af5b582Smckusick 	ocb.s = s;
449*8af5b582Smckusick 	baseB = ocb.c.a + ocb.c.b - 1;
450*8af5b582Smckusick 	for (ep = osp->s_empty[curcolor]; ep; ep = ep->e_next) {
451*8af5b582Smckusick 	    /* don't try to combine this combo if it is the wrong level */
452*8af5b582Smckusick 	    cbp = ep->e_combo;
453*8af5b582Smckusick 	    if (cbp->c_nframes > curlevel)
454*8af5b582Smckusick 		continue;
455*8af5b582Smckusick 	    if (cbp->c_nframes != curlevel)
456*8af5b582Smckusick 		break;
457*8af5b582Smckusick 
458*8af5b582Smckusick 	    /* don't include frames that overlap ones already included */
459*8af5b582Smckusick 	    ncbp = ep->e_frame;
460*8af5b582Smckusick 	    if (ncbp->c_dir == ocbp->c_dir ||
461*8af5b582Smckusick 		(cbp->c_flg & C_LOOP) && cbp->c_dir == ocbp->c_dir ||
462*8af5b582Smckusick 		(n = checkframes(cbp, ocbp, osp - board, ncbp)) < 0)
463*8af5b582Smckusick 		    continue;
464*8af5b582Smckusick 
465*8af5b582Smckusick 	    /* compute first half of combo value */
466*8af5b582Smckusick 	    c = cbp->c_combo.c.a + ocb.c.a - 3;
467*8af5b582Smckusick 	    if (c > 3)
468*8af5b582Smckusick 		continue;
469*8af5b582Smckusick 
470*8af5b582Smckusick 	    /* check to see if this frame forms a valid loop */
471*8af5b582Smckusick 	    verts = 0;
472*8af5b582Smckusick 	    if (n) {
473*8af5b582Smckusick 		sp = &board[ocbp->c_vertex];
474*8af5b582Smckusick 		d = dd[ocbp->c_dir];
475*8af5b582Smckusick 		if (n = ocb.c.b)
476*8af5b582Smckusick 			sp += d;
477*8af5b582Smckusick 		for (; n < 5; n++, sp += d) {
478*8af5b582Smckusick 		    if (sp->s_occ != EMPTY || sp == osp)
479*8af5b582Smckusick 			continue;
480*8af5b582Smckusick 		    for (nep = sp->s_empty[curcolor]; nep; nep = nep->e_next) {
481*8af5b582Smckusick 			if (nep->e_combo == cbp) {
482*8af5b582Smckusick 			    verts++;
483*8af5b582Smckusick 			    fcbp = nep->e_frame;
484*8af5b582Smckusick 			    continue;
485*8af5b582Smckusick 			}
486*8af5b582Smckusick 			if (nep->e_combo->c_nframes < cbp->c_nframes)
487*8af5b582Smckusick 			    break;
488*8af5b582Smckusick 		    }
489*8af5b582Smckusick 		}
490*8af5b582Smckusick #if 0
491*8af5b582Smckusick 		{
492*8af5b582Smckusick 		char *str;
493*8af5b582Smckusick 		sprintf(fmtbuf, "%c v%d %s%c",
494*8af5b582Smckusick 		    curcolor == BLACK ? 'b' : 'w', verts,
495*8af5b582Smckusick 		    stoc(ocbp->c_vertex), pdir[ocbp->c_dir]);
496*8af5b582Smckusick 		str = fmtbuf + strlen(fmtbuf);
497*8af5b582Smckusick 		for (; cbp->c_link[1]; cbp = cbp->c_link[0]) {
498*8af5b582Smckusick 		    sprintf(str, " %s%c", stoc(cbp->c_link[1]->c_vertex),
499*8af5b582Smckusick 			pdir[cbp->c_link[1]->c_dir]);
500*8af5b582Smckusick 		    str += strlen(str);
501*8af5b582Smckusick 		}
502*8af5b582Smckusick 		sprintf(str, " %s%c", stoc(cbp->c_vertex), pdir[cbp->c_dir]);
503*8af5b582Smckusick 		dlog(fmtbuf);
504*8af5b582Smckusick 		cbp = ep->e_combo;
505*8af5b582Smckusick 		}
506*8af5b582Smckusick #endif
507*8af5b582Smckusick 		/* frame overlaps but not at a valid spot */
508*8af5b582Smckusick 		if (verts == 0 || ocb.c.a < 3)
509*8af5b582Smckusick 		    continue;
510*8af5b582Smckusick 	    }
511*8af5b582Smckusick 
512*8af5b582Smckusick 	    /* compute second half of combo value */
513*8af5b582Smckusick 	    cb.s = board[ncbp->c_vertex].s_fval[curcolor][ncbp->c_dir].s;
514*8af5b582Smckusick 	    n = cb.c.a + cb.c.b - 1;
515*8af5b582Smckusick 	    if (baseB < n)
516*8af5b582Smckusick 		n = baseB;
517*8af5b582Smckusick 
518*8af5b582Smckusick 	    /* make a new combo! */
519*8af5b582Smckusick 	    ncbp = (struct combostr *)malloc(sizeof(struct combostr));
520*8af5b582Smckusick 	    c -= verts;
521*8af5b582Smckusick 	    ncbp->c_combo.c.a = c;
522*8af5b582Smckusick 	    ncbp->c_combo.c.b = n;
523*8af5b582Smckusick 	    ncbp->c_link[0] = cbp;
524*8af5b582Smckusick 	    ncbp->c_link[1] = ocbp;
525*8af5b582Smckusick 	    ncbp->c_vertex = osp - board;
526*8af5b582Smckusick 	    ncbp->c_nframes = cbp->c_nframes + 1;
527*8af5b582Smckusick 	    ncbp->c_refcnt = 0;
528*8af5b582Smckusick 	    if (verts) {
529*8af5b582Smckusick 		ncbp->c_flg = C_LOOP;
530*8af5b582Smckusick 		ncbp->c_dir = fcbp->c_dir;
531*8af5b582Smckusick 
532*8af5b582Smckusick 		/* add the combo to the list of empty spots */
533*8af5b582Smckusick 		nep = (struct elist *)malloc(sizeof(struct elist));
534*8af5b582Smckusick 		nep->e_combo = ncbp;
535*8af5b582Smckusick 		nep->e_frame = ocbp;
536*8af5b582Smckusick 		if (debug > 2) {
537*8af5b582Smckusick 		    sprintf(fmtbuf, "e %s", stoc(ncbp->c_vertex));
538*8af5b582Smckusick 		    dlog(fmtbuf);
539*8af5b582Smckusick 		}
540*8af5b582Smckusick 
541*8af5b582Smckusick 		/* sort by the number of frames in the combo */
542*8af5b582Smckusick 		epp = &board[ncbp->c_vertex].s_empty[curcolor];
543*8af5b582Smckusick 		while (*epp) {
544*8af5b582Smckusick 		    if (cbp->c_nframes >= (*epp)->e_combo->c_nframes)
545*8af5b582Smckusick 			break;
546*8af5b582Smckusick 		    epp = &(*epp)->e_next;
547*8af5b582Smckusick 		}
548*8af5b582Smckusick 		nep->e_next = *epp;
549*8af5b582Smckusick 		*epp = nep;
550*8af5b582Smckusick 	    } else {
551*8af5b582Smckusick 		ncbp->c_flg = 0;
552*8af5b582Smckusick 		ncbp->c_dir = 0;
553*8af5b582Smckusick 		if (ocb.c.a > 2)
554*8af5b582Smckusick 		    makeempty(ncbp, ocbp, ocb.c.b);
555*8af5b582Smckusick 	    }
556*8af5b582Smckusick 	    if (verts > 1 && debug || c == 1 && debug > 1 || debug > 2) {
557*8af5b582Smckusick 		char *str;
558*8af5b582Smckusick 
559*8af5b582Smckusick 		sprintf(fmtbuf, "%c %s%c %x v%d %x/%d",
560*8af5b582Smckusick 		    curcolor == BLACK ? 'b' : 'w',
561*8af5b582Smckusick 		    stoc(osp - board), pdir[ocbp->c_dir], ocb.s,
562*8af5b582Smckusick 		    verts, ncbp->c_combo.s, ncbp->c_nframes);
563*8af5b582Smckusick 		dlog(fmtbuf);
564*8af5b582Smckusick 		str = fmtbuf;
565*8af5b582Smckusick 		for (cbp = ncbp; cbp->c_link[1]; cbp = cbp->c_link[0]) {
566*8af5b582Smckusick 		    sprintf(str, " %s%c", stoc(cbp->c_link[1]->c_vertex),
567*8af5b582Smckusick 			pdir[cbp->c_link[1]->c_dir]);
568*8af5b582Smckusick 		    str += strlen(str);
569*8af5b582Smckusick 		}
570*8af5b582Smckusick 		sprintf(str, " %s%c", stoc(cbp->c_vertex), pdir[cbp->c_dir]);
571*8af5b582Smckusick 		dlog(fmtbuf);
572*8af5b582Smckusick #ifdef DEBUG
573*8af5b582Smckusick 		markcombo(ncbp, curcolor, 0);
574*8af5b582Smckusick 		bdisp();
575*8af5b582Smckusick 		whatsup(0);
576*8af5b582Smckusick 		clearcombo(ncbp, curcolor, 0);
577*8af5b582Smckusick #endif
578*8af5b582Smckusick 	    }
579*8af5b582Smckusick 	    if (c > 1) {
580*8af5b582Smckusick 		/* add the new combo to the end of the list */
581*8af5b582Smckusick 		appendcombo(ncbp, curcolor);
582*8af5b582Smckusick 	    } else {
583*8af5b582Smckusick 		updatecombo(ncbp, curcolor);
584*8af5b582Smckusick 		free(ncbp);
585*8af5b582Smckusick 	    }
586*8af5b582Smckusick 	}
587*8af5b582Smckusick }
588*8af5b582Smckusick 
589*8af5b582Smckusick /*
590*8af5b582Smckusick  * Add the combostr 'cbp' to the empty spots list for each empty spot
591*8af5b582Smckusick  * in the frame 'fcbp' except for the intersection.
592*8af5b582Smckusick  * 's' is zero if 'fcbp' is a closed ended frame, else it is one.
593*8af5b582Smckusick  * Return the number of valid intersections with ocbp for detecting loops.
594*8af5b582Smckusick  */
595*8af5b582Smckusick makeempty(cbp, fcbp, s)
596*8af5b582Smckusick 	struct combostr *cbp;
597*8af5b582Smckusick 	struct combostr *fcbp;
598*8af5b582Smckusick 	int s;
599*8af5b582Smckusick {
600*8af5b582Smckusick 	struct spotstr *sp, *vsp;
601*8af5b582Smckusick 	struct elist *ep, **epp;
602*8af5b582Smckusick 	int d;
603*8af5b582Smckusick 
604*8af5b582Smckusick 	if (debug > 2) {
605*8af5b582Smckusick 		sprintf(fmtbuf, "E %s%c s%d", stoc(fcbp->c_vertex),
606*8af5b582Smckusick 			pdir[fcbp->c_dir], s);
607*8af5b582Smckusick 		sprintf(fmtbuf + strlen(fmtbuf), " %s", stoc(cbp->c_vertex));
608*8af5b582Smckusick 		dlog(fmtbuf);
609*8af5b582Smckusick 	}
610*8af5b582Smckusick 	vsp = &board[cbp->c_vertex];
611*8af5b582Smckusick 	sp = &board[fcbp->c_vertex];
612*8af5b582Smckusick 	d = dd[fcbp->c_dir];
613*8af5b582Smckusick 	if (s)
614*8af5b582Smckusick 		sp += d;
615*8af5b582Smckusick 	for (; s < 5; s++, sp += d) {
616*8af5b582Smckusick 		if (sp->s_occ != EMPTY || sp == vsp)
617*8af5b582Smckusick 			continue;
618*8af5b582Smckusick 
619*8af5b582Smckusick 		/* add the combo to the list of empty spots */
620*8af5b582Smckusick 		ep = (struct elist *)malloc(sizeof(struct elist));
621*8af5b582Smckusick 		ep->e_combo = cbp;
622*8af5b582Smckusick 		ep->e_frame = fcbp;
623*8af5b582Smckusick 		if (debug > 2) {
624*8af5b582Smckusick 			sprintf(fmtbuf, "e %s", stoc(sp - board));
625*8af5b582Smckusick 			dlog(fmtbuf);
626*8af5b582Smckusick 		}
627*8af5b582Smckusick 
628*8af5b582Smckusick 		/* sort by the number of frames in the combo */
629*8af5b582Smckusick 		epp = &sp->s_empty[curcolor];
630*8af5b582Smckusick 		while (*epp) {
631*8af5b582Smckusick 			if (cbp->c_nframes >= (*epp)->e_combo->c_nframes)
632*8af5b582Smckusick 				break;
633*8af5b582Smckusick 			epp = &(*epp)->e_next;
634*8af5b582Smckusick 		}
635*8af5b582Smckusick 		ep->e_next = *epp;
636*8af5b582Smckusick 		*epp = ep;
637*8af5b582Smckusick 	}
638*8af5b582Smckusick }
639*8af5b582Smckusick 
640*8af5b582Smckusick /*
641*8af5b582Smckusick  * Update the board value based on the combostr.
642*8af5b582Smckusick  * This is called only if 'cbp' is a <1,x> combo.
643*8af5b582Smckusick  * We handle things differently depending on whether the next move
644*8af5b582Smckusick  * would be trying to "complete" the combo or trying to block it.
645*8af5b582Smckusick  */
646*8af5b582Smckusick updatecombo(cbp, color)
647*8af5b582Smckusick 	struct combostr *cbp;
648*8af5b582Smckusick 	int color;
649*8af5b582Smckusick {
650*8af5b582Smckusick 	register struct framestr *fp;
651*8af5b582Smckusick 	register struct spotstr *sp;
652*8af5b582Smckusick 	register struct combostr *tcbp;
653*8af5b582Smckusick 	register int i, d;
654*8af5b582Smckusick 	int nframes, vertex;
655*8af5b582Smckusick 	union combo cb;
656*8af5b582Smckusick 
657*8af5b582Smckusick 	for (; tcbp = cbp->c_link[1]; cbp = cbp->c_link[0]) {
658*8af5b582Smckusick 		if (color == nextcolor) {
659*8af5b582Smckusick 			/* update the board value for the vertex */
660*8af5b582Smckusick 			sp = &board[cbp->c_vertex];
661*8af5b582Smckusick 			sp->s_nforce[color]++;
662*8af5b582Smckusick 			if (cbp->c_combo.s < sp->s_combo[color].s) {
663*8af5b582Smckusick 				sp->s_combo[color].s = cbp->c_combo.s;
664*8af5b582Smckusick 				sp->s_level[color] = cbp->c_nframes;
665*8af5b582Smckusick 			} else if (cbp->c_combo.s == sp->s_combo[color].s &&
666*8af5b582Smckusick 			    cbp->c_nframes < sp->s_level[color])
667*8af5b582Smckusick 				sp->s_level[color] = cbp->c_nframes;
668*8af5b582Smckusick 		} else {
669*8af5b582Smckusick 			/* update the board values for each spot in frame */
670*8af5b582Smckusick 			vertex = cbp->c_vertex;
671*8af5b582Smckusick 			sp = &board[tcbp->c_vertex];
672*8af5b582Smckusick 			if (sp->s_fval[color][tcbp->c_dir].c.b &&
673*8af5b582Smckusick 			    tcbp->c_vertex != vertex)
674*8af5b582Smckusick 				i = 6;
675*8af5b582Smckusick 			else
676*8af5b582Smckusick 				i = 5;
677*8af5b582Smckusick 			d = dd[tcbp->c_dir];
678*8af5b582Smckusick 			cb.s = cbp->c_combo.s;
679*8af5b582Smckusick 			nframes = cbp->c_nframes;
680*8af5b582Smckusick 			for (; --i >= 0; sp += d) {
681*8af5b582Smckusick 				sp->s_nforce[color]++;
682*8af5b582Smckusick 				if (cb.s < sp->s_combo[color].s) {
683*8af5b582Smckusick 					sp->s_combo[color].s = cb.s;
684*8af5b582Smckusick 					sp->s_level[color] = nframes;
685*8af5b582Smckusick 				} else if (cb.s == sp->s_combo[color].s &&
686*8af5b582Smckusick 				    cbp->c_nframes < sp->s_level[color])
687*8af5b582Smckusick 					sp->s_level[color] = nframes;
688*8af5b582Smckusick 			}
689*8af5b582Smckusick 		}
690*8af5b582Smckusick 
691*8af5b582Smckusick 		/* mark the frame as being part of a <1,x> combo */
692*8af5b582Smckusick 		board[tcbp->c_vertex].s_flg |= FFLAG << tcbp->c_dir;
693*8af5b582Smckusick 	}
694*8af5b582Smckusick 
695*8af5b582Smckusick 	if (color != nextcolor) {
696*8af5b582Smckusick 		/* update the board values for each spot in frame */
697*8af5b582Smckusick 		sp = &board[cbp->c_vertex];
698*8af5b582Smckusick 		if (sp->s_fval[color][cbp->c_dir].c.b &&
699*8af5b582Smckusick 		    cbp->c_vertex != vertex)
700*8af5b582Smckusick 			i = 6;
701*8af5b582Smckusick 		else
702*8af5b582Smckusick 			i = 5;
703*8af5b582Smckusick 		d = dd[cbp->c_dir];
704*8af5b582Smckusick 		for (; --i >= 0; sp += d) {
705*8af5b582Smckusick 			sp->s_nforce[color]++;
706*8af5b582Smckusick 			if (cb.s < sp->s_combo[color].s) {
707*8af5b582Smckusick 				sp->s_combo[color].s = cb.s;
708*8af5b582Smckusick 				sp->s_level[color] = nframes;
709*8af5b582Smckusick 			} else if (cb.s == sp->s_combo[color].s &&
710*8af5b582Smckusick 			    cbp->c_nframes < sp->s_level[color])
711*8af5b582Smckusick 				sp->s_level[color] = nframes;
712*8af5b582Smckusick 		}
713*8af5b582Smckusick 	}
714*8af5b582Smckusick 
715*8af5b582Smckusick 	/* mark the frame as being part of a <1,x> combo */
716*8af5b582Smckusick 	board[cbp->c_vertex].s_flg |= FFLAG << cbp->c_dir;
717*8af5b582Smckusick }
718*8af5b582Smckusick 
719*8af5b582Smckusick /*
720*8af5b582Smckusick  * Free all elist structures.
721*8af5b582Smckusick  */
722*8af5b582Smckusick removeemptyspots()
723*8af5b582Smckusick {
724*8af5b582Smckusick 	register struct elist *ep, *nep;
725*8af5b582Smckusick 	register struct spotstr *sp;
726*8af5b582Smckusick 	int i;
727*8af5b582Smckusick 
728*8af5b582Smckusick 	for (sp = &board[PT(T,20)]; --sp >= &board[PT(A,1)]; ) {
729*8af5b582Smckusick 		for (i = BLACK; i <= WHITE; i++) {
730*8af5b582Smckusick 			for (ep = sp->s_empty[i]; ep; ep = nep) {
731*8af5b582Smckusick 				nep = ep->e_next;
732*8af5b582Smckusick 				free(ep);
733*8af5b582Smckusick 			}
734*8af5b582Smckusick 			sp->s_empty[i] = (struct elist *)0;
735*8af5b582Smckusick 		}
736*8af5b582Smckusick 	}
737*8af5b582Smckusick }
738*8af5b582Smckusick 
739*8af5b582Smckusick /*
740*8af5b582Smckusick  * Remove all combo structures.
741*8af5b582Smckusick  */
742*8af5b582Smckusick removecombos(color)
743*8af5b582Smckusick 	int color;
744*8af5b582Smckusick {
745*8af5b582Smckusick 	register struct combostr *cbp, *ncbp, *endcbp;
746*8af5b582Smckusick 
747*8af5b582Smckusick 	/* check the list */
748*8af5b582Smckusick 	if ((cbp = sortcombos[color]) == (struct combostr *)0)
749*8af5b582Smckusick 		return;
750*8af5b582Smckusick 
751*8af5b582Smckusick 	/* scan the list */
752*8af5b582Smckusick 	endcbp = cbp;
753*8af5b582Smckusick 	do {
754*8af5b582Smckusick 		ncbp = cbp->c_next;
755*8af5b582Smckusick 		cbp->c_next = (struct combostr *)0;
756*8af5b582Smckusick 		cbp->c_prev = (struct combostr *)0;
757*8af5b582Smckusick 		free(cbp);
758*8af5b582Smckusick 		cbp = ncbp;
759*8af5b582Smckusick 	} while (cbp != endcbp);
760*8af5b582Smckusick 
761*8af5b582Smckusick 	sortcombos[color] = (struct combostr *)0;
762*8af5b582Smckusick 	combolen[color] = 0;
763*8af5b582Smckusick }
764*8af5b582Smckusick 
765*8af5b582Smckusick /*
766*8af5b582Smckusick  * Add combo to the end of the list.
767*8af5b582Smckusick  */
768*8af5b582Smckusick appendcombo(cbp, color)
769*8af5b582Smckusick 	struct combostr *cbp;
770*8af5b582Smckusick 	int color;
771*8af5b582Smckusick {
772*8af5b582Smckusick 	struct combostr *pcbp, *ncbp;
773*8af5b582Smckusick 
774*8af5b582Smckusick 	combolen[color]++;
775*8af5b582Smckusick 	ncbp = sortcombos[color];
776*8af5b582Smckusick 	if (ncbp == (struct combostr *)0) {
777*8af5b582Smckusick 		sortcombos[color] = cbp;
778*8af5b582Smckusick 		cbp->c_next = cbp;
779*8af5b582Smckusick 		cbp->c_prev = cbp;
780*8af5b582Smckusick 		return;
781*8af5b582Smckusick 	}
782*8af5b582Smckusick 	pcbp = ncbp->c_prev;
783*8af5b582Smckusick 	cbp->c_next = ncbp;
784*8af5b582Smckusick 	cbp->c_prev = pcbp;
785*8af5b582Smckusick 	ncbp->c_prev = cbp;
786*8af5b582Smckusick 	pcbp->c_next = cbp;
787*8af5b582Smckusick }
788*8af5b582Smckusick 
789*8af5b582Smckusick /*
790*8af5b582Smckusick  * Return positive if frame 'fcbp' overlaps any of the frames in 'cbp'
791*8af5b582Smckusick  * other than the frame 'ecbp'.
792*8af5b582Smckusick  * Return -1 if any of the frames in 'cbp' are marked or part of a <1,x> combo.
793*8af5b582Smckusick  * Else, return zero.
794*8af5b582Smckusick  */
795*8af5b582Smckusick checkframes(cbp, fcbp, vertex, ecbp)
796*8af5b582Smckusick 	struct combostr *cbp;
797*8af5b582Smckusick 	struct combostr *fcbp;
798*8af5b582Smckusick 	int vertex;
799*8af5b582Smckusick 	struct combostr *ecbp;
800*8af5b582Smckusick {
801*8af5b582Smckusick 	struct combostr *tcbp;
802*8af5b582Smckusick 	char *str;
803*8af5b582Smckusick 	int i, n, mask;
804*8af5b582Smckusick 	short *ip;
805*8af5b582Smckusick 
806*8af5b582Smckusick 	n = (fcbp - frames) * FAREA;
807*8af5b582Smckusick 	str = &overlap[n];
808*8af5b582Smckusick 	ip = &intersect[n];
809*8af5b582Smckusick 	i = vertex == fcbp->c_vertex ? 2 : 0;
810*8af5b582Smckusick 	for (; tcbp = cbp->c_link[1]; cbp = cbp->c_link[0]) {
811*8af5b582Smckusick #if 0
812*8af5b582Smckusick 		if (board[tcbp->c_vertex].s_flg & (FFLAG << tcbp->c_dir))
813*8af5b582Smckusick 			return (-1);
814*8af5b582Smckusick #endif
815*8af5b582Smckusick 		vertex = cbp->c_vertex;
816*8af5b582Smckusick 		if (tcbp == ecbp)
817*8af5b582Smckusick 			continue;
818*8af5b582Smckusick 		n = tcbp - frames;
819*8af5b582Smckusick 		if (board[ip[n]].s_occ != EMPTY)
820*8af5b582Smckusick 			continue;
821*8af5b582Smckusick 		mask = str[n];
822*8af5b582Smckusick 		if (mask & (1 << (i + (tcbp->c_vertex == vertex))))
823*8af5b582Smckusick 			return (1);
824*8af5b582Smckusick 	}
825*8af5b582Smckusick #if 0
826*8af5b582Smckusick 	if (board[cbp->c_vertex].s_flg & (FFLAG << cbp->c_dir))
827*8af5b582Smckusick 		return (-1);
828*8af5b582Smckusick #endif
829*8af5b582Smckusick 	if (cbp == ecbp)
830*8af5b582Smckusick 		return (0);
831*8af5b582Smckusick 	n = cbp - frames;
832*8af5b582Smckusick 	if (board[ip[n]].s_occ != EMPTY)
833*8af5b582Smckusick 		return (0);
834*8af5b582Smckusick 	mask = str[n];
835*8af5b582Smckusick 	return (mask & (1 << (i + (cbp->c_vertex == vertex))));
836*8af5b582Smckusick }
837*8af5b582Smckusick 
838*8af5b582Smckusick #ifdef DEBUG
839*8af5b582Smckusick markcombo(cbp, color, vertex)
840*8af5b582Smckusick 	struct combostr *cbp;
841*8af5b582Smckusick 	int color;
842*8af5b582Smckusick 	int vertex;
843*8af5b582Smckusick {
844*8af5b582Smckusick 	register struct spotstr *sp;
845*8af5b582Smckusick 	struct combostr *tcbp;
846*8af5b582Smckusick 	int i, d, r, n, mask;
847*8af5b582Smckusick 
848*8af5b582Smckusick 	for (; tcbp = cbp->c_link[1]; cbp = cbp->c_link[0])
849*8af5b582Smckusick 		markcombo(tcbp, color, vertex = cbp->c_vertex);
850*8af5b582Smckusick 	sp = &board[cbp->c_vertex];
851*8af5b582Smckusick 	d = dd[r = cbp->c_dir];
852*8af5b582Smckusick 	mask = (IFLAG | CFLAG) << r;
853*8af5b582Smckusick 	n = sp->s_fval[color][r].c.b && cbp->c_vertex != vertex ? 6 : 5;
854*8af5b582Smckusick 	for (i = 0; i < n; i++, sp += d) {
855*8af5b582Smckusick 		if (n == 6 && (i == 0 || i == 5))
856*8af5b582Smckusick 			sp->s_flg |= CFLAG << r;
857*8af5b582Smckusick 		else
858*8af5b582Smckusick 			sp->s_flg |= mask;
859*8af5b582Smckusick 	}
860*8af5b582Smckusick }
861*8af5b582Smckusick 
862*8af5b582Smckusick clearcombo(cbp, color, vertex)
863*8af5b582Smckusick 	struct combostr *cbp;
864*8af5b582Smckusick 	int color;
865*8af5b582Smckusick 	int vertex;
866*8af5b582Smckusick {
867*8af5b582Smckusick 	register struct spotstr *sp;
868*8af5b582Smckusick 	struct combostr *tcbp;
869*8af5b582Smckusick 	int i, d, r, n, mask;
870*8af5b582Smckusick 
871*8af5b582Smckusick 	for (; tcbp = cbp->c_link[1]; cbp = cbp->c_link[0])
872*8af5b582Smckusick 		clearcombo(tcbp, color, vertex = cbp->c_vertex);
873*8af5b582Smckusick 	sp = &board[cbp->c_vertex];
874*8af5b582Smckusick 	d = dd[r = cbp->c_dir];
875*8af5b582Smckusick 	mask = ~((IFLAG | CFLAG) << r);
876*8af5b582Smckusick 	n = sp->s_fval[color][r].c.b && cbp->c_vertex != vertex ? 6 : 5;
877*8af5b582Smckusick 	for (i = 0; i < n; i++, sp += d)
878*8af5b582Smckusick 		sp->s_flg &= mask;
879*8af5b582Smckusick }
880*8af5b582Smckusick #endif /* DEBUG */
881