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