Merge from vendor branch NTPD:
[dragonfly.git] / games / backgammon / backgammon / extra.c
1 /*
2  * Copyright (c) 1980, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)extra.c  8.1 (Berkeley) 5/31/93
34  * $FreeBSD: src/games/backgammon/backgammon/extra.c,v 1.4 1999/11/30 03:48:22 billf Exp $
35  * $DragonFly: src/games/backgammon/backgammon/extra.c,v 1.2 2003/06/17 04:25:22 dillon Exp $
36  */
37
38 #include "back.h"
39
40 #ifdef DEBUG
41 #include <stdio.h>
42 FILE    *trace;
43 #endif
44
45 /*
46  * dble()
47  *      Have the current player double and ask opponent to accept.
48  */
49
50 dble ()  {
51         int     resp;                   /* response to y/n */
52
53         for (;;)  {
54                 writel (" doubles.");           /* indicate double */
55
56                 if (cturn == -pnum)  {          /* see if computer accepts */
57                         if (dblgood())  {           /* guess not */
58                                 writel ("  Declined.\n");
59                                 nexturn();
60                                 cturn *= -2;        /* indicate loss */
61                                 return;
62                         } else  {                   /* computer accepts */
63                                 writel ("  Accepted.\n");
64                                 gvalue *= 2;        /* double game value */
65                                 dlast = cturn;
66                                 if (tflag)
67                                         gwrite();
68                                 return;
69                         }
70                 }
71
72                                                 /* ask if player accepts */
73                 writel ("  Does ");
74                 writel (cturn == 1? color[2]: color[3]);
75                 writel (" accept?");
76
77                                                 /* get response from yorn,
78                                                  * a "2" means he said "p"
79                                                  * for print board. */
80                 if ((resp = yorn ('R')) == 2)  {
81                         writel ("  Reprint.\n");
82                         buflush();
83                         wrboard();
84                         writel (*Colorptr);
85                         continue;
86                 }
87
88                                                 /* check response */
89                 if (resp)  {
90                                                     /* accepted */
91                         gvalue *= 2;
92                         dlast = cturn;
93                         if (tflag)
94                                 gwrite();
95                         return;
96                 }
97
98                 nexturn ();                     /* declined */
99                 cturn *= -2;
100                 return;
101         }
102 }
103 \f
104 /*
105  * dblgood ()
106  *      Returns 1 if the computer would double in this position.  This
107  * is not an exact science.  The computer will decline a double that he
108  * would have made.  Accumulated judgments are kept in the variable n,
109  * which is in "pips", i.e., the position of each man summed over all
110  * men, with opponent's totals negative.  Thus, n should have a positive
111  * value of 7 for each move ahead, or a negative value of 7 for each one
112  * behind.
113  */
114
115 dblgood ()  {
116         int     n;                      /* accumulated judgment */
117         int     OFFC = *offptr;         /* no. of computer's men off */
118         int     OFFO = *offopp;         /* no. of player's men off */
119
120 #ifdef DEBUG
121         int     i;
122         if (trace == NULL)
123                 trace = fopen ("bgtrace","w");
124 #endif
125
126                                                 /* get real pip value */
127         n = eval()*cturn;
128 #ifdef DEBUG
129         fputs ("\nDoubles:\nBoard: ",trace);
130         for (i = 0; i < 26; i++)
131                 fprintf (trace," %d",board[i]);
132         fprintf (trace,"\n\tpip = %d, ",n);
133 #endif
134
135                                                 /* below adjusts pip value
136                                                  * according to position
137                                                  * judgments */
138
139                                                 /* check men moving off
140                                                  * board */
141         if (OFFC > -15 || OFFO > -15)  {
142                 if (OFFC < 0 && OFFO < 0)  {
143                         OFFC += 15;
144                         OFFO += 15;
145                         n +=((OFFC-OFFO)*7)/2;
146                 } else if (OFFC < 0)  {
147                         OFFC += 15;
148                         n -= OFFO*7/2;
149                 } else if (OFFO < 0)  {
150                         OFFO += 15;
151                         n += OFFC*7/2;
152                 }
153                 if (OFFC < 8 && OFFO > 8)
154                         n -= 7;
155                 if (OFFC < 10 && OFFO > 10)
156                         n -= 7;
157                 if (OFFC < 12 && OFFO > 12)
158                         n -= 7;
159                 if (OFFO < 8 && OFFC > 8)
160                         n += 7;
161                 if (OFFO < 10 && OFFC > 10)
162                         n += 7;
163                 if (OFFO < 12 && OFFC > 12)
164                         n += 7;
165                 n += ((OFFC-OFFO)*7)/2;
166         }
167
168 #ifdef DEBUG
169         fprintf (trace,"off = %d, ",n);
170 #endif
171
172                                                 /* see if men are trapped */
173         n -= freemen(bar);
174         n += freemen(home);
175         n += trapped(home,-cturn);
176         n -= trapped(bar,cturn);
177
178 #ifdef DEBUG
179         fprintf (trace,"free = %d\n",n);
180         fprintf (trace,"\tOFFC = %d, OFFO = %d\n",OFFC,OFFO);
181         fflush (trace);
182 #endif
183
184                                                 /* double if 2-3 moves ahead */
185         if (n > 10+rnum(7))
186                 return(1);
187         return (0);
188 }
189 \f
190 freemen (b)
191 int     b;
192
193 {
194         int             i, inc, lim;
195
196         odds(0,0,0);
197         if (board[b] == 0)
198                 return (0);
199         inc = (b == 0? 1: -1);
200         lim = (b == 0? 7: 18);
201         for (i = b+inc; i != lim; i += inc)
202                 if (board[i]*inc < -1)
203                         odds(abs(b-i),0,abs(board[b]));
204         if (abs(board[b]) == 1)
205                 return ((36-count())/5);
206         return (count()/5);
207 }
208 \f
209 trapped (n,inc)
210 int     n, inc;
211
212 {
213         int             i, j, k;
214         int             c, l, ct;
215
216         ct = 0;
217         l = n+7*inc;
218         for (i = n+inc; i != l; i += inc)  {
219                 odds (0,0,0);
220                 c = abs(i-l);
221                 if (board[i]*inc > 0)  {
222                         for (j = c; j < 13; j++)
223                                 if (board[i+inc*j]*inc < -1)  {
224                                         if (j < 7)
225                                                 odds (j,0,1);
226                                         for (k = 1; k < 7 && k < j; k++)
227                                                 if (j-k < 7)
228                                                         odds (k,j-k,1);
229                                 }
230                         ct += abs(board[i])*(36-count());
231                 }
232         }
233         return (ct/5);
234 }
235 \f
236 eval ()  {
237
238         int             i, j;
239
240         for (j = i = 0; i < 26; i++)
241                 j += (board[i] >= 0 ? i*board[i] : (25-i)*board[i]);
242
243         if (off[1] >= 0)
244                 j += 25*off[1];
245         else
246                 j += 25*(off[1]+15);
247
248         if (off[0] >= 0)
249                 j -= 25*off[0];
250         else
251                 j -= 25*(off[0]+15);
252         return (j);
253 }