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