1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: static char sccsid[] = "@(#)move.c 5.1 (Berkeley) 5/29/85"; 9: #endif not lint 10: 11: #include "back.h" 12: 13: #ifdef DEBUG 14: #include <stdio.h> 15: FILE *trace; 16: static char tests[20]; 17: #endif 18: 19: struct BOARD { /* structure of game position */ 20: int b_board[26]; /* board position */ 21: int b_in[2]; /* men in */ 22: int b_off[2]; /* men off */ 23: int b_st[4], b_fn[4]; /* moves */ 24: 25: struct BOARD *b_next; /* forward queue pointer */ 26: }; 27: 28: struct BOARD *freeq = -1; 29: struct BOARD *checkq = -1; 30: struct BOARD *bsave(); 31: struct BOARD *nextfree(); 32: 33: /* these variables are values for the 34: * candidate move */ 35: static int ch; /* chance of being hit */ 36: static int op; /* computer's open men */ 37: static int pt; /* comp's protected points */ 38: static int em; /* farthest man back */ 39: static int frc; /* chance to free comp's men */ 40: static int frp; /* chance to free pl's men */ 41: 42: /* these values are the values for the 43: * move chosen (so far) */ 44: static int chance; /* chance of being hit */ 45: static int openmen; /* computer's open men */ 46: static int points; /* comp's protected points */ 47: static int endman; /* farthest man back */ 48: static int barmen; /* men on bar */ 49: static int menin; /* men in inner table */ 50: static int menoff; /* men off board */ 51: static int oldfrc; /* chance to free comp's men */ 52: static int oldfrp; /* chance to free pl's men */ 53: 54: static int cp[5]; /* candidate start position */ 55: static int cg[5]; /* candidate finish position */ 56: 57: static int race; /* game reduced to a race */ 58: 59: move (okay) 60: int okay; /* zero if first move */ 61: { 62: register int i; /* index */ 63: register int l; /* last man */ 64: 65: if (okay) { 66: /* see if comp should double */ 67: if (gvalue < 64 && dlast != cturn && dblgood()) { 68: writel (*Colorptr); 69: dble(); /* double */ 70: /* return if declined */ 71: if (cturn != 1 && cturn != -1) 72: return; 73: } 74: roll(); 75: } 76: 77: race = 0; 78: for (i = 0; i < 26; i++) { 79: if (board[i] < 0) 80: l = i; 81: } 82: for (i = 0; i < l; i++) { 83: if (board[i] > 0) 84: break; 85: } 86: if (i == l) 87: race = 1; 88: 89: /* print roll */ 90: if (tflag) 91: curmove (cturn == -1? 18: 19,0); 92: writel (*Colorptr); 93: writel (" rolls "); 94: writec (D0+'0'); 95: writec (' '); 96: writec (D1+'0'); 97: /* make tty interruptable 98: * while thinking */ 99: if (tflag) 100: cline(); 101: fixtty (noech); 102: 103: /* find out how many moves */ 104: mvlim = movallow(); 105: if (mvlim == 0) { 106: writel (" but cannot use it.\n"); 107: nexturn(); 108: fixtty (raw); 109: return; 110: } 111: 112: /* initialize */ 113: for (i = 0; i < 4; i++) 114: cp[i] = cg[i] = 0; 115: 116: /* strategize */ 117: trymove (0,0); 118: pickmove(); 119: 120: /* print move */ 121: writel (" and moves "); 122: for (i = 0; i < mvlim; i++) { 123: if (i > 0) 124: writec (','); 125: wrint (p[i] = cp[i]); 126: writec ('-'); 127: wrint (g[i] = cg[i]); 128: makmove (i); 129: } 130: writec ('.'); 131: 132: /* print blots hit */ 133: if (tflag) 134: curmove (20,0); 135: else 136: writec ('\n'); 137: for (i = 0; i < mvlim; i++) 138: if (h[i]) 139: wrhit(g[i]); 140: /* get ready for next move */ 141: nexturn(); 142: if (!okay) { 143: buflush(); 144: sleep (3); 145: } 146: fixtty (raw); /* no more tty interrupt */ 147: } 148: 149: trymove (mvnum,swapped) 150: register int mvnum; /* number of move (rel zero) */ 151: int swapped; /* see if swapped also tested */ 152: 153: { 154: register int pos; /* position on board */ 155: register int rval; /* value of roll */ 156: 157: /* if recursed through all dice 158: * values, compare move */ 159: if (mvnum == mvlim) { 160: binsert (bsave()); 161: return; 162: } 163: 164: /* make sure dice in always 165: * same order */ 166: if (d0 == swapped) 167: swap; 168: /* choose value for this move */ 169: rval = dice[mvnum != 0]; 170: 171: /* find all legitimate moves */ 172: for (pos = bar; pos != home; pos += cturn) { 173: /* fix order of dice */ 174: if (d0 == swapped) 175: swap; 176: /* break if stuck on bar */ 177: if (board[bar] != 0 && pos != bar) 178: break; 179: /* on to next if not occupied */ 180: if (board[pos]*cturn <= 0) 181: continue; 182: /* set up arrays for move */ 183: p[mvnum] = pos; 184: g[mvnum] = pos+rval*cturn; 185: if (g[mvnum]*cturn >= home) { 186: if (*offptr < 0) 187: break; 188: g[mvnum] = home; 189: } 190: /* try to move */ 191: if (makmove (mvnum)) 192: continue; 193: else 194: trymove (mvnum+1,2); 195: /* undo move to try another */ 196: backone (mvnum); 197: } 198: 199: /* swap dice and try again */ 200: if ((!swapped) && D0 != D1) 201: trymove (0,1); 202: } 203: 204: struct BOARD * 205: bsave () { 206: register int i; /* index */ 207: struct BOARD *now; /* current position */ 208: 209: now = nextfree (); /* get free BOARD */ 210: 211: /* store position */ 212: for (i = 0; i < 26; i++) 213: now->b_board[i] = board[i]; 214: now->b_in[0] = in[0]; 215: now->b_in[1] = in[1]; 216: now->b_off[0] = off[0]; 217: now->b_off[1] = off[1]; 218: for (i = 0; i < mvlim; i++) { 219: now->b_st[i] = p[i]; 220: now->b_fn[i] = g[i]; 221: } 222: return (now); 223: } 224: 225: binsert (new) 226: struct BOARD *new; /* item to insert */ 227: { 228: register struct BOARD *p = checkq; /* queue pointer */ 229: register int result; /* comparison result */ 230: 231: if (p == -1) { /* check if queue empty */ 232: checkq = p = new; 233: p->b_next = -1; 234: return; 235: } 236: 237: result = bcomp (new,p); /* compare to first element */ 238: if (result < 0) { /* insert in front */ 239: new->b_next = p; 240: checkq = new; 241: return; 242: } 243: if (result == 0) { /* duplicate entry */ 244: mvcheck (p,new); 245: makefree (new); 246: return; 247: } 248: 249: while (p->b_next != -1) { /* traverse queue */ 250: result = bcomp (new,p->b_next); 251: if (result < 0) { /* found place */ 252: new->b_next = p->b_next; 253: p->b_next = new; 254: return; 255: } 256: if (result == 0) { /* duplicate entry */ 257: mvcheck (p->b_next,new); 258: makefree (new); 259: return; 260: } 261: p = p->b_next; 262: } 263: /* place at end of queue */ 264: p->b_next = new; 265: new->b_next = -1; 266: } 267: 268: bcomp (a,b) 269: struct BOARD *a; 270: struct BOARD *b; 271: { 272: register int *aloc = a->b_board; /* pointer to board a */ 273: register int *bloc = b->b_board; /* pointer to board b */ 274: register int i; /* index */ 275: int result; /* comparison result */ 276: 277: for (i = 0; i < 26; i++) { /* compare boards */ 278: result = cturn*(aloc[i]-bloc[i]); 279: if (result) 280: return (result); /* found inequality */ 281: } 282: return (0); /* same position */ 283: } 284: 285: mvcheck (incumbent,candidate) 286: register struct BOARD *incumbent; 287: register struct BOARD *candidate; 288: { 289: register int i; 290: register int result; 291: 292: for (i = 0; i < mvlim; i++) { 293: result = cturn*(candidate->b_st[i]-incumbent->b_st[i]); 294: if (result > 0) 295: return; 296: if (result < 0) 297: break; 298: } 299: if (i == mvlim) 300: return; 301: for (i = 0; i < mvlim; i++) { 302: incumbent->b_st[i] = candidate->b_st[i]; 303: incumbent->b_fn[i] = candidate->b_fn[i]; 304: } 305: } 306: 307: makefree (dead) 308: struct BOARD *dead; /* dead position */ 309: { 310: dead->b_next = freeq; /* add to freeq */ 311: freeq = dead; 312: } 313: 314: struct BOARD * 315: nextfree () { 316: struct BOARD *new; 317: 318: if (freeq == -1) { 319: new = calloc (1,sizeof (struct BOARD)); 320: if (new == 0) { 321: writel ("\nOut of memory\n"); 322: getout(); 323: } 324: new->b_next = -1; 325: return (new); 326: } 327: 328: new = freeq; 329: freeq = freeq->b_next; 330: } 331: 332: pickmove () { 333: /* current game position */ 334: register struct BOARD *now = bsave(); 335: register struct BOARD *next; /* next move */ 336: 337: #ifdef DEBUG 338: if (trace == NULL) 339: trace = fopen ("bgtrace","w"); 340: fprintf (trace,"\nRoll: %d %d%s\n",D0,D1,race? " (race)": ""); 341: fflush (trace); 342: #endif 343: do { /* compare moves */ 344: bcopy (checkq); 345: next = checkq->b_next; 346: makefree (checkq); 347: checkq = next; 348: movcmp(); 349: } while (checkq != -1); 350: 351: bcopy (now); 352: } 353: 354: bcopy (s) 355: register struct BOARD *s; /* game situation */ 356: { 357: register int i; /* index */ 358: 359: for (i = 0; i < 26; i++) 360: board[i] = s->b_board[i]; 361: for (i = 0; i < 2; i++) { 362: in[i] = s->b_in[i]; 363: off[i] = s->b_off[i]; 364: } 365: for (i = 0; i < mvlim; i++) { 366: p[i] = s->b_st[i]; 367: g[i] = s->b_fn[i]; 368: } 369: } 370: 371: movcmp () { 372: register int i; 373: register int c; 374: 375: #ifdef DEBUG 376: if (trace == NULL) 377: trace = fopen ("bgtrace","w"); 378: #endif 379: 380: odds (0,0,0); 381: if (!race) { 382: ch = op = pt = 0; 383: for (i = 1; i < 25; i++) { 384: if (board[i] == cturn) 385: ch = canhit (i,1); 386: op += abs (bar-i); 387: } 388: for (i = bar+cturn; i != home; i += cturn) 389: if (board[i]*cturn > 1) 390: pt += abs(bar-i); 391: frc = freemen (bar)+trapped (bar,cturn); 392: frp = freemen (home)+trapped (home,-cturn); 393: } 394: for (em = bar; em != home; em += cturn) 395: if (board[em]*cturn > 0) 396: break; 397: em = abs(home-em); 398: #ifdef DEBUG 399: fputs ("Board: ",trace); 400: for (i = 0; i < 26; i++) 401: fprintf (trace, " %d",board[i]); 402: if (race) 403: fprintf (trace,"\n\tem = %d\n",em); 404: else 405: fprintf (trace, 406: "\n\tch = %d, pt = %d, em = %d, frc = %d, frp = %d\n", 407: ch,pt,em,frc,frp); 408: fputs ("\tMove: ",trace); 409: for (i = 0; i < mvlim; i++) 410: fprintf (trace," %d-%d",p[i],g[i]); 411: fputs ("\n",trace); 412: fflush (trace); 413: strcpy (tests,""); 414: #endif 415: if ((cp[0] == 0 && cg[0] == 0) || movegood()) { 416: #ifdef DEBUG 417: fprintf (trace,"\t[%s] ... wins.\n",tests); 418: fflush (trace); 419: #endif 420: for (i = 0; i < mvlim; i++) { 421: cp[i] = p[i]; 422: cg[i] = g[i]; 423: } 424: if (!race) { 425: chance = ch; 426: openmen = op; 427: points = pt; 428: endman = em; 429: barmen = abs(board[home]); 430: oldfrc = frc; 431: oldfrp = frp; 432: } 433: menin = *inptr; 434: menoff = *offptr; 435: } 436: #ifdef DEBUG 437: else { 438: fprintf (trace,"\t[%s] ... loses.\n",tests); 439: fflush (trace); 440: } 441: #endif 442: } 443: 444: movegood () { 445: register int n; 446: 447: if (*offptr == 15) 448: return (1); 449: if (menoff == 15) 450: return (0); 451: if (race) { 452: #ifdef DEBUG 453: strcat (tests,"o"); 454: #endif 455: if (*offptr-menoff) 456: return (*offptr > menoff); 457: #ifdef DEBUG 458: strcat (tests,"e"); 459: #endif 460: if (endman-em) 461: return (endman > em); 462: #ifdef DEBUG 463: strcat (tests,"i"); 464: #endif 465: if (menin == 15) 466: return (0); 467: if (*inptr == 15) 468: return (1); 469: #ifdef DEBUG 470: strcat (tests,"i"); 471: #endif 472: if (*inptr-menin) 473: return (*inptr > menin); 474: return (rnum(2)); 475: } else { 476: n = barmen-abs(board[home]); 477: #ifdef DEBUG 478: strcat (tests,"c"); 479: #endif 480: if (abs(chance-ch)+25*n > rnum(150)) 481: return (n? (n < 0): (ch < chance)); 482: #ifdef DEBUG 483: strcat (tests,"o"); 484: #endif 485: if (*offptr-menoff) 486: return (*offptr > menoff); 487: #ifdef DEBUG 488: strcat (tests,"o"); 489: #endif 490: if (abs(openmen-op) > 7+rnum(12)) 491: return (openmen > op); 492: #ifdef DEBUG 493: strcat (tests,"b"); 494: #endif 495: if (n) 496: return (n < 0); 497: #ifdef DEBUG 498: strcat (tests,"e"); 499: #endif 500: if (abs(endman-em) > rnum(2)) 501: return (endman > em); 502: #ifdef DEBUG 503: strcat (tests,"f"); 504: #endif 505: if (abs(frc-oldfrc) > rnum(2)) 506: return (frc < oldfrc); 507: #ifdef DEBUG 508: strcat (tests,"p"); 509: #endif 510: if (abs(n = pt-points) > rnum(4)) 511: return (n > 0); 512: #ifdef DEBUG 513: strcat (tests,"i"); 514: #endif 515: if (*inptr-menin) 516: return (*inptr > menin); 517: #ifdef DEBUG 518: strcat (tests,"f"); 519: #endif 520: if (abs(frp-oldfrp) > rnum(2)) 521: return (frp > oldfrp); 522: return (rnum(2)); 523: } 524: }