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