diff options
Diffstat (limited to 'backgammon/backgammon/move.c')
-rw-r--r-- | backgammon/backgammon/move.c | 551 |
1 files changed, 551 insertions, 0 deletions
diff --git a/backgammon/backgammon/move.c b/backgammon/backgammon/move.c new file mode 100644 index 00000000..17a5dfde --- /dev/null +++ b/backgammon/backgammon/move.c @@ -0,0 +1,551 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)move.c 5.6 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include "back.h" + +#ifdef DEBUG +#include <stdio.h> +FILE *trace; +static char tests[20]; +#endif + +struct BOARD { /* structure of game position */ + int b_board[26]; /* board position */ + int b_in[2]; /* men in */ + int b_off[2]; /* men off */ + int b_st[4], b_fn[4]; /* moves */ + + struct BOARD *b_next; /* forward queue pointer */ +}; + +struct BOARD *freeq = 0; +struct BOARD *checkq = 0; +struct BOARD *bsave(); +struct BOARD *nextfree(); + + /* these variables are values for the + * candidate move */ +static int ch; /* chance of being hit */ +static int op; /* computer's open men */ +static int pt; /* comp's protected points */ +static int em; /* farthest man back */ +static int frc; /* chance to free comp's men */ +static int frp; /* chance to free pl's men */ + + /* these values are the values for the + * move chosen (so far) */ +static int chance; /* chance of being hit */ +static int openmen; /* computer's open men */ +static int points; /* comp's protected points */ +static int endman; /* farthest man back */ +static int barmen; /* men on bar */ +static int menin; /* men in inner table */ +static int menoff; /* men off board */ +static int oldfrc; /* chance to free comp's men */ +static int oldfrp; /* chance to free pl's men */ + +static int cp[5]; /* candidate start position */ +static int cg[5]; /* candidate finish position */ + +static int race; /* game reduced to a race */ + +move (okay) +int okay; /* zero if first move */ +{ + register int i; /* index */ + register int l; /* last man */ + + if (okay) { + /* see if comp should double */ + if (gvalue < 64 && dlast != cturn && dblgood()) { + writel (*Colorptr); + dble(); /* double */ + /* return if declined */ + if (cturn != 1 && cturn != -1) + return; + } + roll(); + } + + race = 0; + for (i = 0; i < 26; i++) { + if (board[i] < 0) + l = i; + } + for (i = 0; i < l; i++) { + if (board[i] > 0) + break; + } + if (i == l) + race = 1; + + /* print roll */ + if (tflag) + curmove (cturn == -1? 18: 19,0); + writel (*Colorptr); + writel (" rolls "); + writec (D0+'0'); + writec (' '); + writec (D1+'0'); + /* make tty interruptable + * while thinking */ + if (tflag) + cline(); + fixtty (noech); + + /* find out how many moves */ + mvlim = movallow(); + if (mvlim == 0) { + writel (" but cannot use it.\n"); + nexturn(); + fixtty (raw); + return; + } + + /* initialize */ + for (i = 0; i < 4; i++) + cp[i] = cg[i] = 0; + + /* strategize */ + trymove (0,0); + pickmove(); + + /* print move */ + writel (" and moves "); + for (i = 0; i < mvlim; i++) { + if (i > 0) + writec (','); + wrint (p[i] = cp[i]); + writec ('-'); + wrint (g[i] = cg[i]); + makmove (i); + } + writec ('.'); + + /* print blots hit */ + if (tflag) + curmove (20,0); + else + writec ('\n'); + for (i = 0; i < mvlim; i++) + if (h[i]) + wrhit(g[i]); + /* get ready for next move */ + nexturn(); + if (!okay) { + buflush(); + sleep (3); + } + fixtty (raw); /* no more tty interrupt */ +} + +trymove (mvnum,swapped) +register int mvnum; /* number of move (rel zero) */ +int swapped; /* see if swapped also tested */ + +{ + register int pos; /* position on board */ + register int rval; /* value of roll */ + + /* if recursed through all dice + * values, compare move */ + if (mvnum == mvlim) { + binsert (bsave()); + return; + } + + /* make sure dice in always + * same order */ + if (d0 == swapped) + swap; + /* choose value for this move */ + rval = dice[mvnum != 0]; + + /* find all legitimate moves */ + for (pos = bar; pos != home; pos += cturn) { + /* fix order of dice */ + if (d0 == swapped) + swap; + /* break if stuck on bar */ + if (board[bar] != 0 && pos != bar) + break; + /* on to next if not occupied */ + if (board[pos]*cturn <= 0) + continue; + /* set up arrays for move */ + p[mvnum] = pos; + g[mvnum] = pos+rval*cturn; + if (g[mvnum]*cturn >= home) { + if (*offptr < 0) + break; + g[mvnum] = home; + } + /* try to move */ + if (makmove (mvnum)) + continue; + else + trymove (mvnum+1,2); + /* undo move to try another */ + backone (mvnum); + } + + /* swap dice and try again */ + if ((!swapped) && D0 != D1) + trymove (0,1); +} + +struct BOARD * +bsave () { + register int i; /* index */ + struct BOARD *now; /* current position */ + + now = nextfree (); /* get free BOARD */ + + /* store position */ + for (i = 0; i < 26; i++) + now->b_board[i] = board[i]; + now->b_in[0] = in[0]; + now->b_in[1] = in[1]; + now->b_off[0] = off[0]; + now->b_off[1] = off[1]; + for (i = 0; i < mvlim; i++) { + now->b_st[i] = p[i]; + now->b_fn[i] = g[i]; + } + return (now); +} + +binsert (new) +struct BOARD *new; /* item to insert */ +{ + register struct BOARD *p = checkq; /* queue pointer */ + register int result; /* comparison result */ + + if (p == 0) { /* check if queue empty */ + checkq = p = new; + p->b_next = 0; + return; + } + + result = bcomp (new,p); /* compare to first element */ + if (result < 0) { /* insert in front */ + new->b_next = p; + checkq = new; + return; + } + if (result == 0) { /* duplicate entry */ + mvcheck (p,new); + makefree (new); + return; + } + + while (p->b_next != 0) { /* traverse queue */ + result = bcomp (new,p->b_next); + if (result < 0) { /* found place */ + new->b_next = p->b_next; + p->b_next = new; + return; + } + if (result == 0) { /* duplicate entry */ + mvcheck (p->b_next,new); + makefree (new); + return; + } + p = p->b_next; + } + /* place at end of queue */ + p->b_next = new; + new->b_next = 0; +} + +bcomp (a,b) +struct BOARD *a; +struct BOARD *b; +{ + register int *aloc = a->b_board; /* pointer to board a */ + register int *bloc = b->b_board; /* pointer to board b */ + register int i; /* index */ + int result; /* comparison result */ + + for (i = 0; i < 26; i++) { /* compare boards */ + result = cturn*(aloc[i]-bloc[i]); + if (result) + return (result); /* found inequality */ + } + return (0); /* same position */ +} + +mvcheck (incumbent,candidate) +register struct BOARD *incumbent; +register struct BOARD *candidate; +{ + register int i; + register int result; + + for (i = 0; i < mvlim; i++) { + result = cturn*(candidate->b_st[i]-incumbent->b_st[i]); + if (result > 0) + return; + if (result < 0) + break; + } + if (i == mvlim) + return; + for (i = 0; i < mvlim; i++) { + incumbent->b_st[i] = candidate->b_st[i]; + incumbent->b_fn[i] = candidate->b_fn[i]; + } +} + +makefree (dead) +struct BOARD *dead; /* dead position */ +{ + dead->b_next = freeq; /* add to freeq */ + freeq = dead; +} + +struct BOARD * +nextfree () { + struct BOARD *new; + + if (freeq == 0) { + new = (struct BOARD *)calloc (1,sizeof (struct BOARD)); + if (new == 0) { + writel ("\nOut of memory\n"); + getout(); + } + new->b_next = 0; + return (new); + } + + new = freeq; + freeq = freeq->b_next; +} + +pickmove () { + /* current game position */ + register struct BOARD *now = bsave(); + register struct BOARD *next; /* next move */ + +#ifdef DEBUG + if (trace == NULL) + trace = fopen ("bgtrace","w"); + fprintf (trace,"\nRoll: %d %d%s\n",D0,D1,race? " (race)": ""); + fflush (trace); +#endif + do { /* compare moves */ + boardcopy (checkq); + next = checkq->b_next; + makefree (checkq); + checkq = next; + movcmp(); + } while (checkq != 0); + + boardcopy (now); +} + +boardcopy (s) +register struct BOARD *s; /* game situation */ +{ + register int i; /* index */ + + for (i = 0; i < 26; i++) + board[i] = s->b_board[i]; + for (i = 0; i < 2; i++) { + in[i] = s->b_in[i]; + off[i] = s->b_off[i]; + } + for (i = 0; i < mvlim; i++) { + p[i] = s->b_st[i]; + g[i] = s->b_fn[i]; + } +} + +movcmp () { + register int i; + register int c; + +#ifdef DEBUG + if (trace == NULL) + trace = fopen ("bgtrace","w"); +#endif + + odds (0,0,0); + if (!race) { + ch = op = pt = 0; + for (i = 1; i < 25; i++) { + if (board[i] == cturn) + ch = canhit (i,1); + op += abs (bar-i); + } + for (i = bar+cturn; i != home; i += cturn) + if (board[i]*cturn > 1) + pt += abs(bar-i); + frc = freemen (bar)+trapped (bar,cturn); + frp = freemen (home)+trapped (home,-cturn); + } + for (em = bar; em != home; em += cturn) + if (board[em]*cturn > 0) + break; + em = abs(home-em); +#ifdef DEBUG + fputs ("Board: ",trace); + for (i = 0; i < 26; i++) + fprintf (trace, " %d",board[i]); + if (race) + fprintf (trace,"\n\tem = %d\n",em); + else + fprintf (trace, + "\n\tch = %d, pt = %d, em = %d, frc = %d, frp = %d\n", + ch,pt,em,frc,frp); + fputs ("\tMove: ",trace); + for (i = 0; i < mvlim; i++) + fprintf (trace," %d-%d",p[i],g[i]); + fputs ("\n",trace); + fflush (trace); + strcpy (tests,""); +#endif + if ((cp[0] == 0 && cg[0] == 0) || movegood()) { +#ifdef DEBUG + fprintf (trace,"\t[%s] ... wins.\n",tests); + fflush (trace); +#endif + for (i = 0; i < mvlim; i++) { + cp[i] = p[i]; + cg[i] = g[i]; + } + if (!race) { + chance = ch; + openmen = op; + points = pt; + endman = em; + barmen = abs(board[home]); + oldfrc = frc; + oldfrp = frp; + } + menin = *inptr; + menoff = *offptr; + } +#ifdef DEBUG + else { + fprintf (trace,"\t[%s] ... loses.\n",tests); + fflush (trace); + } +#endif +} + +movegood () { + register int n; + + if (*offptr == 15) + return (1); + if (menoff == 15) + return (0); + if (race) { +#ifdef DEBUG + strcat (tests,"o"); +#endif + if (*offptr-menoff) + return (*offptr > menoff); +#ifdef DEBUG + strcat (tests,"e"); +#endif + if (endman-em) + return (endman > em); +#ifdef DEBUG + strcat (tests,"i"); +#endif + if (menin == 15) + return (0); + if (*inptr == 15) + return (1); +#ifdef DEBUG + strcat (tests,"i"); +#endif + if (*inptr-menin) + return (*inptr > menin); + return (rnum(2)); + } else { + n = barmen-abs(board[home]); +#ifdef DEBUG + strcat (tests,"c"); +#endif + if (abs(chance-ch)+25*n > rnum(150)) + return (n? (n < 0): (ch < chance)); +#ifdef DEBUG + strcat (tests,"o"); +#endif + if (*offptr-menoff) + return (*offptr > menoff); +#ifdef DEBUG + strcat (tests,"o"); +#endif + if (abs(openmen-op) > 7+rnum(12)) + return (openmen > op); +#ifdef DEBUG + strcat (tests,"b"); +#endif + if (n) + return (n < 0); +#ifdef DEBUG + strcat (tests,"e"); +#endif + if (abs(endman-em) > rnum(2)) + return (endman > em); +#ifdef DEBUG + strcat (tests,"f"); +#endif + if (abs(frc-oldfrc) > rnum(2)) + return (frc < oldfrc); +#ifdef DEBUG + strcat (tests,"p"); +#endif + if (abs(n = pt-points) > rnum(4)) + return (n > 0); +#ifdef DEBUG + strcat (tests,"i"); +#endif + if (*inptr-menin) + return (*inptr > menin); +#ifdef DEBUG + strcat (tests,"f"); +#endif + if (abs(frp-oldfrp) > rnum(2)) + return (frp > oldfrp); + return (rnum(2)); + } +} |