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