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