|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.