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.3 2006/08/08 16:36:11 pavalos Exp $
36  */
37 
38 #include "back.h"
39 
40 #ifdef DEBUG
41 #include <stdio.h>
42 FILE	*trace;
43 #endif
44 
45 static int	eval(void);
46 
47 /*
48  * dble()
49  *	Have the current player double and ask opponent to accept.
50  */
51 
52 void
53 dble(void)
54 {
55 	int	resp;			/* response to y/n */
56 
57 	for (;;)  {
58 		writel (" doubles.");		/* indicate double */
59 
60 		if (cturn == -pnum)  {		/* see if computer accepts */
61 			if (dblgood())  {	    /* guess not */
62 				writel ("  Declined.\n");
63 				nexturn();
64 				cturn *= -2;	    /* indicate loss */
65 				return;
66 			} else  {		    /* computer accepts */
67 				writel ("  Accepted.\n");
68 				gvalue *= 2;	    /* double game value */
69 				dlast = cturn;
70 				if (tflag)
71 					gwrite();
72 				return;
73 			}
74 		}
75 
76 						/* ask if player accepts */
77 		writel ("  Does ");
78 		writel (cturn == 1? color[2]: color[3]);
79 		writel (" accept?");
80 
81 						/* get response from yorn,
82 						 * a "2" means he said "p"
83 						 * for print board. */
84 		if ((resp = yorn ('R')) == 2)  {
85 			writel ("  Reprint.\n");
86 			buflush();
87 			wrboard();
88 			writel (*Colorptr);
89 			continue;
90 		}
91 
92 						/* check response */
93 		if (resp)  {
94 						    /* accepted */
95 			gvalue *= 2;
96 			dlast = cturn;
97 			if (tflag)
98 				gwrite();
99 			return;
100 		}
101 
102 		nexturn ();			/* declined */
103 		cturn *= -2;
104 		return;
105 	}
106 }
107 
108 /*
109  * dblgood ()
110  *	Returns 1 if the computer would double in this position.  This
111  * is not an exact science.  The computer will decline a double that he
112  * would have made.  Accumulated judgments are kept in the variable n,
113  * which is in "pips", i.e., the position of each man summed over all
114  * men, with opponent's totals negative.  Thus, n should have a positive
115  * value of 7 for each move ahead, or a negative value of 7 for each one
116  * behind.
117  */
118 
119 int
120 dblgood(void)
121 {
122 	int	n;			/* accumulated judgment */
123 	int	OFFC = *offptr;		/* no. of computer's men off */
124 	int	OFFO = *offopp;		/* no. of player's men off */
125 
126 #ifdef DEBUG
127 	int	i;
128 	if (trace == NULL)
129 		trace = fopen ("bgtrace","w");
130 #endif
131 
132 						/* get real pip value */
133 	n = eval()*cturn;
134 #ifdef DEBUG
135 	fputs ("\nDoubles:\nBoard: ",trace);
136 	for (i = 0; i < 26; i++)
137 		fprintf (trace," %d",board[i]);
138 	fprintf (trace,"\n\tpip = %d, ",n);
139 #endif
140 
141 						/* below adjusts pip value
142 						 * according to position
143 						 * judgments */
144 
145 						/* check men moving off
146 						 * board */
147 	if (OFFC > -15 || OFFO > -15)  {
148 		if (OFFC < 0 && OFFO < 0)  {
149 			OFFC += 15;
150 			OFFO += 15;
151 			n +=((OFFC-OFFO)*7)/2;
152 		} else if (OFFC < 0)  {
153 			OFFC += 15;
154 			n -= OFFO*7/2;
155 		} else if (OFFO < 0)  {
156 			OFFO += 15;
157 			n += OFFC*7/2;
158 		}
159 		if (OFFC < 8 && OFFO > 8)
160 			n -= 7;
161 		if (OFFC < 10 && OFFO > 10)
162 			n -= 7;
163 		if (OFFC < 12 && OFFO > 12)
164 			n -= 7;
165 		if (OFFO < 8 && OFFC > 8)
166 			n += 7;
167 		if (OFFO < 10 && OFFC > 10)
168 			n += 7;
169 		if (OFFO < 12 && OFFC > 12)
170 			n += 7;
171 		n += ((OFFC-OFFO)*7)/2;
172 	}
173 
174 #ifdef DEBUG
175 	fprintf (trace,"off = %d, ",n);
176 #endif
177 
178 						/* see if men are trapped */
179 	n -= freemen(bar);
180 	n += freemen(home);
181 	n += trapped(home,-cturn);
182 	n -= trapped(bar,cturn);
183 
184 #ifdef DEBUG
185 	fprintf (trace,"free = %d\n",n);
186 	fprintf (trace,"\tOFFC = %d, OFFO = %d\n",OFFC,OFFO);
187 	fflush (trace);
188 #endif
189 
190 						/* double if 2-3 moves ahead */
191 	if (n > 10+rnum(7))
192 		return(1);
193 	return (0);
194 }
195 
196 int
197 freemen(int b)
198 {
199 	int		i, inc, lim;
200 
201 	odds(0,0,0);
202 	if (board[b] == 0)
203 		return (0);
204 	inc = (b == 0? 1: -1);
205 	lim = (b == 0? 7: 18);
206 	for (i = b+inc; i != lim; i += inc)
207 		if (board[i]*inc < -1)
208 			odds(abs(b-i),0,abs(board[b]));
209 	if (abs(board[b]) == 1)
210 		return ((36-count())/5);
211 	return (count()/5);
212 }
213 
214 int
215 trapped(int n, int inc)
216 {
217 	int		i, j, k;
218 	int		c, l, ct;
219 
220 	ct = 0;
221 	l = n+7*inc;
222 	for (i = n+inc; i != l; i += inc)  {
223 		odds (0,0,0);
224 		c = abs(i-l);
225 		if (board[i]*inc > 0)  {
226 			for (j = c; j < 13; j++)
227 				if (board[i+inc*j]*inc < -1)  {
228 					if (j < 7)
229 						odds (j,0,1);
230 					for (k = 1; k < 7 && k < j; k++)
231 						if (j-k < 7)
232 							odds (k,j-k,1);
233 				}
234 			ct += abs(board[i])*(36-count());
235 		}
236 	}
237 	return (ct/5);
238 }
239 
240 static int
241 eval(void)
242 {
243 	int		i, j;
244 
245 	for (j = i = 0; i < 26; i++)
246 		j += (board[i] >= 0 ? i*board[i] : (25-i)*board[i]);
247 
248 	if (off[1] >= 0)
249 		j += 25*off[1];
250 	else
251 		j += 25*(off[1]+15);
252 
253 	if (off[0] >= 0)
254 		j -= 25*off[0];
255 	else
256 		j -= 25*(off[0]+15);
257 	return (j);
258 }
259