2 * eval.c - C source for GNU SHOGI
4 * Copyright (c) 1993 Matthias Mutz
6 * GNU SHOGI is based on GNU CHESS
8 * Copyright (c) 1988,1989,1990 John Stanback
9 * Copyright (c) 1992 Free Software Foundation
11 * This file is part of GNU Shogi.
13 * GNU Shogi is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 1, or (at your option)
18 * GNU Shogi is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with GNU Shogi; see the file COPYING. If not, write to
25 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
35 etable_field
*etab
[2];
39 const small_short Stboard
[NO_SQUARES
] =
40 {lance
,knight
,silver
,gold
,king
,gold
,silver
,knight
,lance
,
41 0, bishop
, 0, 0, 0, 0, 0, rook
, 0,
42 pawn
, pawn
, pawn
, pawn
, pawn
, pawn
, pawn
, pawn
, pawn
,
43 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0, 0,
46 pawn
, pawn
, pawn
, pawn
, pawn
, pawn
, pawn
, pawn
, pawn
,
47 0, rook
, 0, 0, 0, 0, 0, bishop
, 0,
48 lance
,knight
,silver
,gold
,king
,gold
,silver
,knight
,lance
};
50 const small_short Stcolor
[NO_SQUARES
] =
51 {black
, black
, black
, black
, black
, black
, black
, black
, black
,
52 neutral
, black
, neutral
, neutral
, neutral
, neutral
, neutral
, black
, neutral
,
53 black
, black
, black
, black
, black
, black
, black
, black
, black
,
54 neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
,
55 neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
,
56 neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
, neutral
,
57 white
, white
, white
, white
, white
, white
, white
, white
, white
,
58 neutral
, white
, neutral
, neutral
, neutral
, neutral
, neutral
, white
, neutral
,
59 white
, white
, white
, white
, white
, white
, white
, white
, white
};
61 small_short board
[NO_SQUARES
], color
[NO_SQUARES
];
70 extern short debug_eval
;
71 extern FILE *debug_eval_file
;
75 static short in_opening_stage
= true;
76 static short behind_in_material
[2] = {false, false};
79 /* distance to enemy king */
80 static const EnemyKingDistanceBonus
[9] =
81 {0, 20, 15, 8, 5, 3, 1, 0, 0};
83 /* distance to own king */
84 static const OwnKingDistanceBonus
[9] =
85 {0, 10, 4, 1, 0, 0, 0, 0, 0};
87 /* distance to promotion zone */
88 static const PromotionZoneDistanceBonus
[NO_ROWS
] =
89 {0, 0, 0, 0, 4, 8, 10, 10, 10};
91 /* Bishop mobility bonus indexed by # reachable squares */
92 static const short BMBLTY
[20] =
93 {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16};
95 /* Rook mobility bonus indexed by # reachable squares */
96 static const short RMBLTY
[20] =
97 {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16};
99 /* Lance mobility bonus indexed by # reachable squares */
100 static const short LMBLTY
[8] =
101 {0, 0, 0, 0, 1, 2, 4, 8};
104 /* penalty for threats to king, indexed by number of such threats */
105 static const short KTHRT
[36] =
106 {0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
107 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
108 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
111 #if !defined USE_PATTERN
113 /* Pawn positional bonus (STATIC ROOK vs. STATIC ROOK) */
114 static const small_short PawnAdvanceSS
[NO_SQUARES
] =
115 { 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 0, 0, 0, 0, 0, 0, 0, 0,
117 0, 0, 0, 0, 0, 0, 0, 0, 0,
118 3, -2, 15, 4, 6, 1, 6, 8, 3,
119 0, -5, -5, 0, 0, 0, 5, 10, 5,
120 0, 0, 0, 0, 0, 0, 0, 0, 10,
121 0, 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0, 0 };
125 #define PawnAdvanceSR PawnAdvanceSS
127 /* Pawn positional bonus (RANGING ROOK vs. STATIC ROOK) */
128 static const small_short PawnAdvanceRS
[NO_SQUARES
] =
129 { 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 3, -2, 15, 3, 5, 0, -2, -4, 3,
133 1, 0, 8, 3, 5, 2, 2, -2, -2,
134 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0, 0, 0 };
139 #define PawnAdvanceRR PawnAdvanceRS
141 /* Lance positional bonus (STATIC ROOK vs. STATIC ROOK) */
142 static small_short LanceAdvanceSS
[NO_SQUARES
] =
143 { 10, 5, 5, 5, 5, 5, 5, 5, 10,
144 2, 4, 4, 4, 4, 4, 4, 4, 2,
145 4, 1, 1, 1, 1, 1, 1, 1, 4,
146 -2, -2, -2, -2, -2, -2, -2, -2, -2,
147 -4, -4, -4, -4, -4, -4, -4, -4, -4,
148 -6, -6, -6, -6, -6, -6, -6, -6, -6,
149 -8, -8, -8, -8, -8, -8, -8, -8, -8,
150 -9, -9, -9, -9, -9, -9, -9, -9, -9,
151 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* impossible */
153 #define LanceAdvanceSR LanceAdvanceSS
154 #define LanceAdvanceRS LanceAdvanceSS
155 #define LanceAdvanceRR LanceAdvanceRS
157 /* Knight positional bonus (STATIC ROOK vs. STATIC ROOK) */
158 static small_short KnightAdvanceSS
[NO_SQUARES
] =
159 {-9, 4, 4, 4, 4, 4, 4, 4,-9,
160 -9, 2, 2, 2, 2, 2, 2, 2,-9,
161 -9, 1,-10, 1, 1, 1, 1, 1,-9,
162 -9, 0, 0, 0, 0, 0, 0, 0,-9,
163 -9, -5, 0, -5, 0,-5, 0,-5,-9
164 -9, 0, 0, 0, 0, 0, 0, 0,-9,
165 -9, -9, -9, -9,-9,-9,-9,-9,-9,
166 0, 0, 0, 0, 0, 0, 0, 0, 0, /* impossible */
167 0, 0, 0, 0, 0, 0, 0, 0, 0 };/* impossible */
169 #define KnightAdvanceSR KnightAdvanceSS
170 #define KnightAdvanceRS KnightAdvanceSS
171 #define KnightAdvanceRR KnightAdvanceRS
173 /* Silver positional bonus (STATIC ROOK vs. STATIC ROOK) */
174 static small_short SilverAdvanceSS
[NO_SQUARES
] =
175 { 0, 0, 0, 0, -6, 0, 0, 0, 0,
176 0, 8, 3, 4, 0, 3, 2, 0, 0,
177 0, 0, 10, 0, 0, 6, 6, 4, 0,
178 0, 0, 0, 0, 4, 0, 4, 5, 0,
179 0, 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 0, 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0, 0, 0, 0, 0,
182 0, 0, 0, 0, 0, 0, 0, 0, 0,
183 0, 0, 0, 0, 0, 0, 0, 0, 0 };
185 /* Silver positional bonus (STATIC ROOK vs. RANGING ROOK) */
186 static small_short SilverAdvanceSR
[NO_SQUARES
] =
187 { 0, 0, 0, 0, -6, 0, 0, 0, 0,
188 0, -4, -4, 4, 0, 5, 3, 0, 0,
189 0, 0, -4, -4, 2, 8, 6, 0, 0,
190 0, 0, 0, 3, 0, 0, 4, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0, 0, 0, 0, 0,
194 0, 0, 0, 0, 0, 0, 0, 0, 0,
195 0, 0, 0, 0, 0, 0, 0, 0, 0 };
197 /* Silver positional bonus (RANGING ROOK vs. STATIC ROOK) */
198 static small_short SilverAdvanceRS
[NO_SQUARES
] =
199 { -3, 0, 0, 0, 0, 0, 0, 0, -2,
200 -3, -1, 3, 3, -1, -1, 8, -1, -2,
201 -2, -2, 0, 5, -1, 9, -2, 5, -3,
202 0, 0, 5, 2, 5, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 0, 0, 0, 0,
205 0, 0, 0, 0, 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0, 0, 0, 0, 0,
207 0, 0, 0, 0, 0, 0, 0, 0, 0 };
209 #define SilverAdvanceRR SilverAdvanceRS
211 /* Gold positional bonus (STATIC ROOK vs. STATIC ROOK) */
212 static small_short GoldAdvanceSS
[NO_SQUARES
] =
213 { 0, 0, 0, 0, 0, 0, 0, 0, 0,
214 0, 0, 10, 0, 6, 0, 0, 0, 0,
215 0, 0, 0, 8, 0, 0, 0, 0, 0,
216 0, 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0, 0,
220 0, 0, 0, 0, 0, 0, 0, 0, 0,
221 0, 0, 0, 0, 0, 0, 0, 0, 0 };
223 /* Gold positional bonus (STATIC ROOK vs. RANGING ROOK) */
224 static small_short GoldAdvanceSR
[NO_SQUARES
] =
225 { 0, 0, 0, 10, 0, 0, 0, 0, 0,
226 0, 0, 0, 0, 6, 0, 0, 0, 0,
227 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0, 0,
230 0, 0, 0, 0, 0, 0, 0, 0, 0,
231 0, 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0 };
235 /* Gold positional bonus (RANGING ROOK vs. STATIC ROOK) */
236 static small_short GoldAdvanceRS
[NO_SQUARES
] =
237 { -1, 0, -1, 0, -1, 0, -1, -1, -1,
238 -1, 0, 4, -1, 4, -1, 8, 0, -1,
239 -2, -1, 0, -2, 0, 6, 0, -1, -2,
240 0, 0, 0, 0, 0, 0, 0, 0, 0,
241 0, 0, 0, 0, 0, 0, 0, 0, 0,
242 0, 0, 0, 0, 0, 0, 0, 0, 0,
243 0, 0, 0, 0, 0, 0, 0, 0, 0,
244 0, 0, 0, 0, 0, 0, 0, 0, 0,
245 0, 0, 0, 0, 0, 0, 0, 0, 0 };
247 #define GoldAdvanceRR GoldAdvanceRS
249 /* Bishop positional bonus (STATIC ROOK vs. STATIC ROOK) */
250 static small_short BishopAdvanceSS
[NO_SQUARES
] =
251 { 3, 0, 0, 0, 0, 0, 0, 0, 3,
252 0, 4, 0, 8, 0, 0, 0, 3, 0,
253 0, 0, 6, 0, 0, 0, 4, 0, 0,
254 0, 2, 0, 3, 0, 3, 0, 2, 0,
255 0, 0, 2, 0, 3, 0, 0, 0, 0,
256 0, 2, 0, 3, 0, 3, 0, 2, 0,
257 0, 0, 3, 0, 0, 0, 3, 0, 0,
258 0, 3, 0, 0, 0, 0, 0, 3, 0,
259 3, 0, 0, 0, 0, 0, 0, 0, 3 };
261 /* Bishop positional bonus (STATIC ROOK vs. RANGING ROOK) */
262 static small_short BishopAdvanceSR
[NO_SQUARES
] =
263 { 3, 0, 0, 0, 0, 0, 0, 0, 3,
264 0, 10, 0, 2, 0, 0, 0, 3, 0,
265 0, 0, 2, 0, 0, 0, 4, 0, 0,
266 0, 2, 0, 3, 0, 3, 0, 2, 0,
267 0, 0, 2, 0, 3, 0, 0, 0, 0,
268 0, 2, 0, 3, 0, 3, 0, 2, 0,
269 0, 0, 3, 0, 0, 0, 3, 0, 0,
270 0, 3, 0, 0, 0, 0, 0, 3, 0,
271 3, 0, 0, 0, 0, 0, 0, 0, 3 };
273 /* Bishop positional bonus (RANGING ROOK vs. STATIC ROOK) */
274 static small_short BishopAdvanceRS
[NO_SQUARES
] =
275 { 3, 0, 0, 0, 0, 0, 0, 0, 3,
276 0, 4, 0, 2, 0, 0, 0, 3, 0,
277 0, 0, 8, 0, 0, 0, 4, 0, 0,
278 0, 2, 0, 3, 0, 3, 0, 2, 0,
279 0, 0, 2, 0, 3, 0, 0, 0, 0,
280 0, 2, 0, 3, 0, 3, 0, 2, 0,
281 0, 0, 3, 0, 0, 0, 3, 0, 0,
282 0, 3, 0, 0, 0, 0, 0, 3, 0,
283 3, 0, 0, 0, 0, 0, 0, 0, 3 };
285 #define BishopAdvanceRR BishopAdvanceRS
287 /* Rook positional bonus (STATIC ROOK vs. STATIC ROOK) */
288 static small_short RookAdvanceSS
[NO_SQUARES
] =
289 { 2, 0, 0, 0, 0, 0, 0, 4, 2,
290 2, 0, 0, 0, 0, 0, 0, 8, 2,
291 -2, 0, 0, 0, 0, 0, 0, 2, -2,
292 -2, 0, 0, 0, 0, 0, 0, 4, -2,
293 -2, 0, 0, 0, 0, 0, 0, 2, -2,
294 -2, 0, 0, 0, 0, 0, 0, 2, -2,
295 4, 4, 4, 4, 4, 4, 4, 4, 4,
296 6, 6, 6, 6, 6, 6, 6, 6, 6,
297 8, 8, 8, 8, 8, 8, 8, 8, 8 };
299 /* Rook positional bonus (RANING ROOK vs. STATIC ROOK) */
300 static small_short RookAdvanceRS
[NO_SQUARES
] =
301 { 2, 6, 6, 6, 6, 0, 0, 0, 2,
302 2, 4, 4, 4, 4, 0, 0, 0, 2,
303 -2, 2, 3, 3, 3, 0, 0, 0, -2,
304 -2, 4, 1, 1, 1, 0, 0, 0, -2,
305 -2, 0, 2, 2, 2, 0, 0, 0, -2,
306 -2, 0, 0, 0, 0, 0, 0, 0, -2,
307 4, 4, 4, 4, 4, 4, 4, 4, 4,
308 6, 6, 6, 6, 6, 6, 6, 6, 6,
309 8, 8, 8, 8, 8, 8, 8, 8, 8 };
311 #define RookAdvanceSR RookAdvanceSS
312 #define RookAdvanceRR RookAdvanceRS
314 /* King positional bonus inopening stage (STATIC ROOK vs. STATIC ROOK) */
315 static const small_short KingAdvanceSS
[NO_SQUARES
] =
316 { 0, -4, 10, 0, -6, -8,-10,-12,-12,
317 -2, 4, 6, -6, -8, -8,-10,-12,-12,
318 -6, -6, -6, -8, -8,-10,-11,-12,-12,
319 -12,-12,-12,-12,-12,-12,-12,-12,-12,
320 -12,-12,-12,-12,-12,-12,-12,-12,-12,
321 -12,-12,-12,-12,-12,-12,-12,-12,-12,
322 -12,-12,-12,-12,-12,-12,-12,-12,-12,
323 -12,-12,-12,-12,-12,-12,-12,-12,-12,
324 -12,-12,-12,-12,-12,-12,-12,-12,-12 };
326 /* King positional bonus inopening stage (STATIC ROOK vs. RANGING ROOK) */
327 static const small_short KingAdvanceSR
[NO_SQUARES
] =
328 { 5, -4, -4, -4, -6, -8,-10,-12,-12,
329 -2, 4, 10, 6, -8, -8,-10,-12,-12,
330 -6, -6, -6, -8, -8,-10,-11,-12,-12,
331 -12,-12,-12,-12,-12,-12,-12,-12,-12,
332 -12,-12,-12,-12,-12,-12,-12,-12,-12,
333 -12,-12,-12,-12,-12,-12,-12,-12,-12,
334 -12,-12,-12,-12,-12,-12,-12,-12,-12,
335 -12,-12,-12,-12,-12,-12,-12,-12,-12,
336 -12,-12,-12,-12,-12,-12,-12,-12,-12 };
338 /* King positional bonus inopening stage (RANGING ROOK vs. STATIC ROOK) */
339 static const small_short KingAdvanceRS
[NO_SQUARES
] =
340 {-12,-12, -8, -6, -4, -8,-10,-12,-12,
341 -12,-12, -8, -6, -8, 12, 16, 20, -8,
342 -12,-12, -6, -8, -8,-10, 0, 0, -4,
343 -12,-12,-12,-12,-12,-12, 0, 0,-12,
344 -12,-12,-12,-12,-12,-12,-12,-12,-12,
345 -12,-12,-12,-12,-12,-12,-12,-12,-12,
346 -12,-12,-12,-12,-12,-12,-12,-12,-12,
347 -12,-12,-12,-12,-12,-12,-12,-12,-12,
348 -12,-12,-12,-12,-12,-12,-12,-12,-12 };
350 #define KingAdvanceRR KingAdvanceRS
352 #endif /* !USE_PATTERN */
355 static small_short Kfield
[2][NO_SQUARES
];
357 char GameType
[2] = { UNKNOWN
, UNKNOWN
};
360 OpeningPattern
*attack_pattern
[2], *castle_pattern
[2];
363 #if defined USE_PATTERN
366 static small_short Mpawn[2][NO_SQUARES];
367 static small_short Msilver[2][NO_SQUARES];
368 static small_short Mgold[2][NO_SQUARES];
369 static small_short Mking[2][NO_SQUARES];
370 static small_short Mlance[2][NO_SQUARES];
371 static small_short Mknight[2][NO_SQUARES];
372 static small_short Mbishop[2][NO_SQUARES];
373 static small_short Mrook[2][NO_SQUARES];
375 static Mpiece_array Mpawn
, Mlance
, Mknight
, Msilver
, Mgold
,
376 Mbishop
, Mrook
, Mking
;
378 Mpiece_array
*Mpiece
[NO_PIECES
] =
379 { NULL
, &Mpawn
, &Mlance
, &Mknight
, &Msilver
, &Mgold
, &Mbishop
, &Mrook
,
380 &Mgold
, &Mgold
, &Mgold
, &Mgold
, &Mbishop
, &Mrook
, &Mking
};
384 static small_short Mpawn
[2][NO_SQUARES
];
385 static small_short Msilver
[2][NO_SQUARES
];
386 static small_short Mgold
[2][NO_SQUARES
];
387 static small_short Mking
[2][NO_SQUARES
];
389 static small_short
*Mlance
[2];
390 static small_short
*Mknight
[2];
391 static small_short
*Mbishop
[2];
392 static small_short
*Mrook
[2];
397 static small_short
*PC1
, *PC2
;
399 static long *atk1
, *atk2
;
401 static long int atak
[2][NO_SQUARES
];
403 #if defined USE_PATTERN
405 short ADVNCM
[NO_PIECES
];
409 static short PADVNCM
, SADVNCM
, GADVNCM
, KADVNCM
;
413 static short R2NDCOL
, EDRNK2B
, PWEAKH
, PAWNSHIELD
;
415 static short PMBLTY
, BDCLOSED
, PSTRONG
, P2STRONG
;
417 static short PawnBonus
, BishopBonus
, RookBonus
;
418 static short KNIGHTPOST
, KNIGHTSTRONG
, BISHOPSTRONG
, KATAK
;
419 static short RHOPN
, RHOPNX
, BHCLSD
, BHCLSDX
, KHOPN
, KHOPNX
, KSFTY
;
421 static short LHOPN
, LHOPNX
, LPROTECT
, NDNGR
, LDNGR
;
422 static short SBEFOREG
, BXCHG
;
423 static short LXRAY
, BRXRAY
;
424 static short KINGED
, KINGOD
, PROMD
;
426 static short KCASTLD
, KMOVD
, OPENOK
, OPENWRONG
;
427 static short ATAKD
, HUNGP
, HUNGX
, PINVAL
;
430 static short PATTACK
, PCASTLE
;
438 #if defined DEBUG8 || defined DEBUG_EVAL
442 debug_position (FILE *D
)
444 short r
, c
, l
, side
, piece
;
446 fprintf (D
, "\n current board is\n\n");
447 for (piece
= pawn
; piece
<= king
; piece
++)
448 if (c
= Captured
[white
][piece
])
449 fprintf(D
, "%i%c ",c
,pxx
[piece
]);
451 for (c
= 0; c
< NO_COLS
; c
++)
452 fprintf (D
, " %d", PawnCnt
[white
][c
]);
454 for (r
= (NO_ROWS
-1); r
>= 0; r
--)
456 for (c
= 0; c
< NO_COLS
; c
++)
459 if (color
[l
] == neutral
)
461 else if (color
[l
] == black
)
462 fprintf (D
, " %c", qxx
[board
[l
]]);
464 fprintf (D
, " %c", pxx
[board
[l
]]);
469 for (c
= 0; c
< NO_COLS
; c
++)
470 fprintf (D
, " %d", PawnCnt
[black
][c
]);
472 for (piece
= pawn
; piece
<= king
; piece
++)
473 if (c
= Captured
[black
][piece
])
474 fprintf(D
, "%i%c ",c
,pxx
[piece
]);
479 #if !defined SAVE_SVALUE
482 debug_svalue (FILE *D
)
486 for (r
= (NO_ROWS
-1); r
>= 0; r
--)
488 for (c
= 0; c
< NO_COLS
; c
++)
490 short sq
= (r
* NO_COLS
) + c
;
491 fprintf(D
,"%5d",svalue
[sq
]);
501 debug_table (FILE *D
, small_short
*table
)
505 for (r
= (NO_ROWS
-1); r
>= 0; r
--)
507 for (c
= 0; c
< NO_COLS
; c
++)
509 short sq
= (r
* NO_COLS
) + c
;
510 fprintf(D
,"%5d",table
[sq
]);
518 debug_ataks (FILE *D
)
521 for (side
= black
; side
<= white
; side
++)
524 long *atk
= atak
[side
];
526 for (l
= NO_ROWS
-1; l
>= 0; l
--) {
527 for (c
= 0; c
< NO_COLS
; c
++) {
528 short sq
= (l
* NO_COLS
) + c
;
530 short n
= (short)(v
& CNT_MASK
);
534 if ( v
& ctlP
) strcat(s
,"P");
535 if ( v
& ctlPp
) strcat(s
,"+P");
536 if ( v
& ctlL
) strcat(s
,"L");
537 if ( v
& ctlLp
) strcat(s
,"+L");
538 if ( v
& ctlN
) strcat(s
,"N");
539 if ( v
& ctlNp
) strcat(s
,"+N");
540 if ( v
& ctlS
) strcat(s
,"S");
541 if ( v
& ctlSp
) strcat(s
,"+S");
542 if ( v
& ctlG
) strcat(s
,"G");
543 if ( v
& ctlB
) strcat(s
,"B");
544 if ( v
& ctlBp
) strcat(s
,"+B");
545 if ( v
& ctlR
) strcat(s
,"R");
546 if ( v
& ctlRp
) strcat(s
,"+R");
547 if ( v
& ctlK
) strcat(s
,"K");
549 for (i
= strlen(s
); i
< 5; i
++)
563 /* ............ POSITIONAL EVALUATION ROUTINES ............ */
567 * mtl[side] - value of all material
568 * hung[side] - count of hung pieces
569 * Tscore[ply] - search tree score for ply ply
570 * Pscore[ply] - positional score for ply ply
571 * INCscore - bonus score or penalty for certain moves
572 * Sdepth - search goal depth
573 * xwndw - evaluation window about alpha/beta
574 * EWNDW - second evaluation window about alpha/beta
575 * ChkFlag[ply]- checking piece at level ply or 0 if no check
576 * TesujiFlag[ply]- 1 if tesuji move at level ply or 0 if no tesuji
577 * PC1[column] - # of my pawns in this column
578 * PC2[column] - # of opponents pawns in column
579 * PieceCnt[side] - just what it says
585 evaluate (register short int side
,
586 register short int ply
,
587 register short int alpha
,
588 register short int beta
,
590 short int *InChk
) /* output Check flag */
593 * Compute an estimate of the score by adding the positional score from the
594 * previous ply to the material difference. If this score falls inside a
595 * window which is 180 points wider than the alpha-beta window (or within a
596 * 50 point window during quiescence search) call ScorePosition() to
597 * determine a score, otherwise return the estimated score.
598 * "side" has to moved.
602 register short evflag
, xside
;
603 short s
, sq
, blockable
;
606 s
= -Pscore
[ply
- 1] + mtl
[side
] - mtl
[xside
] - INCscore
;
610 fprintf (debug_eval_file
, "estimated score at ply %d:%d, -%d+%d-%d-%d\n",
611 ply
, s
, Pscore
[ply
-1], mtl
[side
], mtl
[xside
], INCscore
);
614 hung
[black
] = hung
[white
] = 0;
616 /* should we use the estimete or score the position */
618 #if !defined OLD_EVALUATE
621 (ply
> Sdepth
&& (s
>= (alpha
- 30) && s
<= (beta
+ 30))) ||
623 if ( ply
<= Sdepth
||
624 ((ply
== Sdepth
+ 1 || ply
== (Sdepth
+ 2)) && (s
> (alpha
- xwndw
) && s
< (beta
+ xwndw
))) ||
625 (ply
> (Sdepth
+ 2) && s
>= (alpha
- EWNDW
) && s
<= (beta
+ EWNDW
)) ||
628 (CheckEETable (side
)) )
632 /* score the position */
635 fprintf (debug_eval_file
, "do NOT use the estimete\n");
637 ataks (side
, atak
[side
]);
638 if (Anyatak (side
, sq
=PieceList
[xside
][0]) && board
[sq
] == king
) {
639 *InChk
= (board
[sq
=PieceList
[side
][0]] == king
) ? SqAtakd (sq
, xside
, &blockable
) : false;
640 return ((SCORE_LIMIT
+1001) - ply
);
642 ataks (xside
, atak
[xside
]);
643 *InChk
= (board
[sq
=PieceList
[side
][0]] == king
) ? Anyatak (xside
, sq
) : false;
647 #if !defined OLD_EVALUATE
651 s
= ScorePosition (side
);
656 /* use the estimate but look at check */
660 fprintf (debug_eval_file
, "use the estimete\n");
662 *InChk
= (board
[sq
=PieceList
[side
][0]] == king
) ? SqAtakd (sq
, xside
, &blockable
) : false;
663 if ( SqAtakd (sq
=PieceList
[xside
][0], side
, &blockable
) && board
[sq
] == king
) {
664 return ((SCORE_LIMIT
+1001) - ply
);
668 Pscore
[ply
] = s
- mtl
[side
] + mtl
[xside
];
669 ChkFlag
[ply
- 1] = ((*InChk
) ? Pindex
[TOsquare
] : 0);
675 BRLscan (register short int sq
, short int *mob
)
678 * Find (promoted) Bishop, (promoted) Rook, and Lance mobility, XRAY attacks, and pins.
679 * Let BRL be the bishop, rook, or lance.
680 * Let P be the first piece (no king and no pawn) in a direction and let Q be the second
681 * piece in the same direction. If Q is an unprotected opponent's piece with
682 * bigger relative value than BRL, there is a pin if P is an opponent's piece and
683 * there is an XRAY attack if P is an own piece.
684 * Increment the hung[] array if a pin is found.
690 register unsigned char *ppos
, *pdir
;
692 register short s
, mobx
;
693 register short u
, pin
, ptyp
;
700 rvalue
= relative_value
[piece
];
701 ptyp
= ptype
[c1
][unpromoted
[piece
]];
703 u
= first_direction(ptyp
,&d
,sq
);
705 ppos
= (*nextpos
[ptyp
])[sq
];
706 pdir
= (*nextdir
[ptyp
])[sq
];
709 pin
= -1; /* start new direction */
714 if ( debug_eval
&& Kf
[u
] != 0 )
715 fprintf(debug_eval_file
,"add %d for controlling square near enemy king\n",Kf
[u
]);
717 if (color
[u
] == neutral
)
721 xu
= next_position(ptyp
,&d
,sq
,u
);
722 if ( xu
== next_direction(ptyp
,&dd
,sq
) )
723 pin
= -1; /* oops new direction */
726 if (ppos
[u
] == pdir
[u
])
727 pin
= -1; /* oops new direction */
733 { /* there is a piece in current direction */
735 { /* it's the first piece in the current direction */
736 if (piece
== lance
&& color
[u
] == c1
)
738 if ( board
[u
] == pawn
)
743 fprintf(debug_eval_file
,"adding %d for lance protection\n",LPROTECT
);
746 else if ( in_opening_stage
)
751 fprintf(debug_eval_file
,"adding %d for lance protection\n",-2*LPROTECT
);
755 else if ( piece
== bishop
&& board
[u
] == pawn
)
757 if ( color
[u
] == c1
)
762 fprintf(debug_eval_file
,"add %d for own pawn in bishops direction\n",2*BHCLSD
);
770 fprintf(debug_eval_file
,"add %d for opponents pawn in bishops direction\n",2*BHCLSDX
);
774 if (board
[u
] == pawn
|| board
[u
] == king
)
776 u
= next_direction(ptyp
,&d
,sq
);
784 xu
= next_position(ptyp
,&d
,sq
,u
);
785 if ( xu
!= next_direction(ptyp
,&dd
,sq
) )
786 pin
= u
; /* not on the edge and on to find a pin */
789 if (ppos
[u
] != pdir
[u
])
790 pin
= u
; /* not on the edge and on to find a pin */
797 /* it's the second piece in the current direction */
798 if ( piece
== bishop
&& board
[u
] == pawn
)
800 if ( color
[u
] == c1
)
805 fprintf(debug_eval_file
,"add %d for own pawn in bishops (2) direction\n",BHCLSD
);
813 fprintf(debug_eval_file
,"add %d for opponents pawn in bishops (2) direction\n",BHCLSDX
);
817 if ((color
[u
] == c2
) &&
818 (relative_value
[board
[u
]] > rvalue
|| atk2
[u
] == 0))
820 if (color
[pin
] == c2
)
825 fprintf(debug_eval_file
,"adding %d for pin\n",PINVAL
);
827 if (atk2
[pin
] == 0 || atk1
[pin
] > control
[board
[pin
]] + 1)
831 if ( piece
== lance
) {
835 fprintf(debug_eval_file
,"lance xray: %d\n",LXRAY
);
841 fprintf(debug_eval_file
,"bishop/rook xray: %d\n",BRXRAY
);
845 pin
= -1; /* new direction */
847 u
= next_direction(ptyp
,&d
,sq
);
861 #define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp)
866 KingScan (register short int sq
)
869 * Assign penalties if king can be threatened by checks, if squares near the
870 * king are controlled by the enemy (especially by promoted pieces),
871 * or if there are no own generals near the king.
872 * The following must be true:
873 * board[sq] == king, c1 == color[sq], c2 == otherside[c1]
877 #define ScoreThreat \
878 { if (color[u] != c2)\
879 if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) {\
891 register unsigned char *ppos
, *pdir
;
893 register short int s
;
894 register short u
, ptyp
;
900 /* Penalties, if a king can be threatened by checks. */
905 for ( p
= pawn
; p
< king
; p
++ )
906 if ( HasPiece
[c2
][p
] || Captured
[c2
][p
] )
908 /* if a c1 piece can reach u from sq,
909 * then a c2 piece can reach sq from u.
910 * That means, each u is a square, from which a
911 * piece of type p and color c2 threats square sq.
915 u
= first_direction(ptyp
,&d
,sq
);
917 ppos
= (*nextpos
[ptyp
])[sq
];
918 pdir
= (*nextdir
[ptyp
])[sq
];
923 /* If a p piece can reach (controls or can drop to)
924 * square u, then score threat.
926 if (atk2
[u
] & control
[p
])
928 else if (Captured
[c2
][p
] && color
[u
] == neutral
)
931 u
= ((color
[u
] == neutral
) ? next_position(ptyp
,&d
,sq
,u
)
932 : next_direction(ptyp
,&d
,sq
));
934 u
= ((color
[u
] == neutral
) ? ppos
[u
] : pdir
[u
]);
940 s
+= (KSFTY
* KTHRT
[cnt
]) / 16;
945 fprintf(debug_eval_file
,"penalty %d for possible king threats\n",
949 /* Penalties, if squares near king are controlled by enemy. */
953 ptyp
= ptype
[black
][king
];
955 u
= first_direction(ptyp
,&d
,sq
);
957 pdir
= (*nextpos
[ptyp
])[sq
];
962 if ( !ok
&& color
[u
] == c1
)
964 short ptype_piece
= ptype
[c1
][board
[u
]];
965 if ( ptype_piece
== ptype_silver
|| ptype_piece
== ptype_gold
)
968 if (atk2
[u
] > atk1
[u
])
975 u
= next_direction(ptyp
,&d
,sq
);
988 fprintf(debug_eval_file
,"penalty %d for squares near king controlled by enemy\n",
997 trapped (register short int sq
)
1000 * See if the attacked piece has unattacked squares to move to. The following
1001 * must be true: c1 == color[sq] c2 == otherside[c1]
1005 register short u
, ptyp
;
1009 register unsigned char *ppos
, *pdir
;
1011 register short int piece
;
1015 rvalue
= relative_value
[piece
];
1016 ptyp
= ptype
[c1
][piece
];
1018 u
= first_direction(ptyp
,&d
,sq
);
1020 ppos
= (*nextpos
[ptyp
])[sq
];
1021 pdir
= (*nextdir
[ptyp
])[sq
];
1026 if (atk2
[u
] == 0 || relative_value
[board
[u
]] >= rvalue
)
1029 u
= ((color
[u
] == neutral
) ? next_position(ptyp
,&d
,sq
,u
)
1030 : next_direction(ptyp
,&d
,sq
));
1032 u
= ((color
[u
] == neutral
) ? ppos
[u
] : pdir
[u
]);
1037 fprintf(debug_eval_file
,"piece is trapped\n");
1044 #define mirrored(sq) (NO_SQUARES-1-sq)
1045 #define csquare(side,sq) ((side==black)?sq:mirrored(sq))
1046 #define crow(side,sq) row(csquare(side,sq))
1047 #define ccolumn(side,sq) column(csquare(side,sq))
1051 static short on_csquare(short side
,short piece
,short square
)
1053 return(board
[sq
=csquare(side
,square
)]==piece
&& color
[sq
]==side
);
1057 static short on_column(short side
,short piece
,short c
)
1059 for (sq
= c
; sq
< NO_SQUARES
; sq
+=9)
1060 if (on_csquare(side
,piece
,sq
))
1065 #define empty_csquare(side,square) (board[csquare(side,square)]==no_piece)
1068 static short on_left_side(short side
,short piece
)
1071 if (on_column(side
,piece
,c
))
1077 static short on_right_side(short side
,short piece
)
1079 for (c
=5; c
<NO_COLS
; c
++)
1080 if (on_column(side
,piece
,c
))
1086 /* Distance bonus */
1090 short AddEnemyKingDistanceBonus (short sq
)
1092 /* near enemy king */
1093 if ( !in_opening_stage
|| behind_in_material
[c1
] )
1094 if ( distance(sq
,OwnKing
) > 2 )
1095 s
= EnemyKingDistanceBonus
[distance(sq
,EnemyKing
)];
1101 short AddOwnKingDistanceBonus (short sq
)
1104 if ( !in_opening_stage
|| behind_in_material
[c1
] )
1105 s
= OwnKingDistanceBonus
[distance(sq
,OwnKing
)];
1111 short AddPromotionZoneDistanceBonus (short sq
)
1113 /* near promotion zone */
1114 if ( !in_opening_stage
)
1115 s
= PromotionZoneDistanceBonus
[crow(c1
,sq
)];
1121 PawnValue (register short int sq
, short int side
)
1123 * Calculate the positional value for a pawn on 'sq'.
1131 #if defined USE_PATTERN
1132 s
= Mpawn
[c1
][sq
] + 2*crow(c1
,sq
);
1134 s
= Mpawn
[c1
][csquare(c1
,sq
)] + 2*crow(c1
,sq
);
1139 fprintf(debug_eval_file
,"inital value [%d] for pawn on %c%c: %d\n",
1140 csquare(c1
,sq
), cxx
[column(sq
)], rxx
[row(sq
)], s
);
1143 s
+= PROMD
* AddPromotionZoneDistanceBonus(sq
);
1147 short u
, ptyp
= ptype
[c1
][pawn
];
1150 u
= first_direction(ptyp
,&d
,sq
);
1152 register unsigned char *pdir
;
1153 pdir
= (*nextdir
[ptyp
])[sq
];
1157 if ( color
[u
] == neutral
) {
1161 fprintf(debug_eval_file
,"adding %d for mobility\n", PMBLTY
);
1171 if (a1
== 0 || a2
> ctlP
+ 1)
1176 fprintf(debug_eval_file
,"adding %d for hung\n", HUNGP
);
1187 fprintf(debug_eval_file
,"adding %d for atacked piece\n",ATAKD
);
1193 s
+= (a1
& CNT_MASK
);
1196 fprintf(debug_eval_file
,"adding %ld for protected piece\n",(a1
& CNT_MASK
));
1200 if ( sq
== csquare(c1
,20) ) {
1204 fprintf(debug_eval_file
,"adding %d for closed bishops diagonal\n",BDCLOSED
);
1208 if ( (a1
& ((ctlR
| ctlRp
) | ctlL
)) ) {
1212 fprintf(debug_eval_file
,"adding %d for rook/lance-supported pawn\n", PSTRONG
);
1216 if ( in_opening_stage
) {
1218 if ( crow(c1
,sq
) == 2 ) /* pawn on 3d rank */
1219 if ( Mvboard
[(c1
==black
)?(sq
+36):(sq
-36)] )
1220 { /* opposing pawn has been moved (even column == (sq & 1)) */
1221 s
-= (sq
& 1) ? (3*PMBLTY
/2) : (2*PMBLTY
);
1224 fprintf(debug_eval_file
,"adding %d for opposing pawn pushed\n",
1225 ((sq
& 1) ? -(3*PMBLTY
/2) : -(2*PMBLTY
)));
1229 if ( GameType
[c1
] == STATIC_ROOK
&& sq
== csquare(c1
,43) )
1230 if ( (atk2
[csquare(c1
,52)] & CNT_MASK
) < 2 )
1235 fprintf(debug_eval_file
,"adding %d for attacking pawn on 2nd col\n",
1240 if ( GameType
[c2
] == STATIC_ROOK
&& ccolumn(c1
,sq
) == 1 )
1242 if ( sq
== csquare(c1
,28) )
1247 fprintf(debug_eval_file
,"adding %d for pushed pawn on 8th file\n",
1251 if ( (atk1
[csquare(c1
,19)] & CNT_MASK
) < 2 && (atk1
[csquare(c1
,28)] & CNT_MASK
) < 2 )
1256 fprintf(debug_eval_file
,"adding %d for weak pawn on 8th col\n",
1268 LanceValue (register short int sq
, short int side
)
1270 * Calculate the positional value for a lance on 'sq'.
1275 register short fyle
, rank
;
1277 short checked_trapped
= false;
1280 #if defined USE_PATTERN
1283 s
= Mlance
[c1
][csquare(c1
,sq
)];
1288 fprintf(debug_eval_file
,"inital value [%d] for lance on %c%c: %d\n",
1289 csquare(c1
,sq
), cxx
[column(sq
)], rxx
[row(sq
)], s
);
1292 s
+= KINGOD
* AddOwnKingDistanceBonus(sq
);
1294 s
+= BRLscan (sq
, &mob
);
1305 fprintf(debug_eval_file
,"adding %d for no own pawn on lance file\n",LHOPN
);
1313 fprintf(debug_eval_file
,"adding %d for no opponents pawn on lance file\n",LHOPNX
);
1322 if (a1
== 0 || a2
> ctlL
+ 1)
1327 fprintf(debug_eval_file
,"adding %d for hung\n", HUNGP
);
1333 else if (a2
>= ctlL
|| a1
< ctlP
)
1338 fprintf(debug_eval_file
,"adding %d for atacked piece\n",ATAKD
);
1343 if ( !checked_trapped
&& rank
> 2 )
1345 if (in_opening_stage
|| trapped (sq
))
1350 fprintf(debug_eval_file
,"adding %d for lance in danger\n",LDNGR
);
1358 fprintf(debug_eval_file
,"adding %d for lance in danger\n",LDNGR
/ 2);
1364 s
+= (a1
& CNT_MASK
);
1367 fprintf(debug_eval_file
,"adding %ld for protected piece\n",(a1
& CNT_MASK
));
1375 KnightValue (register short int sq
, short int side
)
1377 * Calculate the positional value for a knight on 'sq'.
1383 short checked_trapped
= false;
1384 short c
= column(sq
);
1386 #if defined USE_PATTERN
1387 s
= Mknight
[c1
][sq
];
1389 s
= Mknight
[c1
][csquare(c1
,sq
)];
1394 fprintf(debug_eval_file
,"inital value [%d] for knight on %c%c: %d\n",
1395 csquare(c1
,sq
), cxx
[c
], rxx
[row(sq
)], s
);
1398 s
+= PROMD
* AddPromotionZoneDistanceBonus(sq
);
1399 s
+= KINGOD
* AddOwnKingDistanceBonus(sq
);
1406 if (a1
== 0 || a2
> ctlN
+ 1)
1411 fprintf(debug_eval_file
,"adding %d for hung\n", HUNGP
);
1413 checked_trapped
= true;
1418 else if (a2
>= ctlN
|| a1
< ctlP
)
1423 fprintf(debug_eval_file
,"adding %d for atacked piece\n",ATAKD
);
1428 if ( !checked_trapped
&& crow(c1
,sq
) > 2 )
1435 fprintf(debug_eval_file
,"adding %d for knight in danger\n",NDNGR
);
1443 fprintf(debug_eval_file
,"adding %d for knight in danger\n",NDNGR
/ 4);
1448 if ( c
== 0 || c
== 8 ) {
1452 fprintf(debug_eval_file
,"adding %d for knight on edge file\n",NEDGE
);
1457 s
+= (a1
& CNT_MASK
);
1460 fprintf(debug_eval_file
,"adding %ld for protected piece\n",(a1
& CNT_MASK
));
1468 SilverValue (register short int sq
, short int side
)
1470 * Calculate the positional value for a silver on 'sq'.
1477 #if defined USE_PATTERN
1478 s
= Msilver
[c1
][sq
];
1480 s
= Msilver
[c1
][csquare(c1
,sq
)];
1483 s
+= KINGED
* AddEnemyKingDistanceBonus(sq
);
1484 s
+= KINGOD
* AddOwnKingDistanceBonus(sq
);
1490 if (a1
== 0 || a2
> ctlS
+ 1)
1497 else if (a2
>= ctlS
|| a1
< ctlP
)
1501 s
+= (a1
& CNT_MASK
);
1503 if ( in_opening_stage
&& GameType
[c1
] == STATIC_ROOK
)
1504 if ( csquare(c1
,sq
) == 12 )
1507 if ( board
[csq
= csquare(c1
,20)] == bishop
&& color
[csq
] == c1
)
1513 /* proverb: silver before gold */
1515 short u
, ptyp
= ptype
[c2
][pawn
];
1518 u
= first_direction(ptyp
,&d
,sq
);
1520 register unsigned char *pdir
;
1521 pdir
= (*nextdir
[ptyp
])[sq
];
1525 if ( color
[u
] == c1
&& board
[u
] == gold
)
1532 GoldValue (register short int sq
, short int side
)
1534 * Calculate the positional value for a gold on 'sq'.
1541 #if defined USE_PATTERN
1544 s
= Mgold
[c1
][csquare(c1
,sq
)];
1547 s
+= KINGED
* AddEnemyKingDistanceBonus(sq
);
1548 s
+= KINGOD
* AddOwnKingDistanceBonus(sq
);
1554 if (a1
== 0 || a2
> ctlG
+ 1)
1561 else if (a2
>= ctlG
|| a1
< ctlP
)
1565 s
+= (a1
& CNT_MASK
);
1567 if ( in_opening_stage
&&
1568 GameType
[c1
] == STATIC_ROOK
&& GameType
[c2
] != STATIC_ROOK
)
1569 if ( Mvboard
[csquare(c1
,3)] )
1579 BishopValue (register short int sq
, short int side
)
1581 * Calculate the positional value for a bishop on 'sq'.
1589 #if defined USE_PATTERN
1590 s
= Mbishop
[c1
][sq
];
1592 s
= Mbishop
[c1
][csquare(c1
,sq
)];
1597 fprintf(debug_eval_file
,"inital value [%d] for bishop on %c%c: %d\n",
1598 csquare(c1
,sq
), cxx
[column(sq
)], rxx
[row(sq
)], s
);
1601 s
+= BRLscan (sq
, &mob
);
1608 if (a1
== 0 || a2
> ctlB
+ 1)
1613 fprintf(debug_eval_file
,"adding %d for hung\n", HUNGP
);
1619 else if (a2
>= ctlB
|| a1
< ctlP
)
1624 fprintf(debug_eval_file
,"adding %d for atacked piece\n",ATAKD
);
1629 if ( in_opening_stage
)
1631 if ( GameType
[c1
] == RANGING_ROOK
)
1633 /* Bishops diagonal should not be open */
1634 if ( !on_csquare(c1
,pawn
,30) )
1637 else if ( GameType
[c2
] == RANGING_ROOK
)
1639 /* Bishops diagonal should be open */
1640 if ( csquare(c1
,sq
) == 10 &&
1641 (!empty_csquare(c1
,20) || !empty_csquare(c1
,30)) )
1643 else if ( csquare(c1
,sq
) == 20 && !empty_csquare(c1
,30) )
1652 RookValue (register short int sq
, short int side
)
1654 * Calculate the positional value for a rook on 'sq'.
1659 register short fyle
;
1663 #if defined USE_PATTERN
1666 s
= Mrook
[c1
][csquare(c1
,sq
)];
1671 fprintf(debug_eval_file
,"inital value [%d] for rook on %c%c: %d\n",
1672 csquare(c1
,sq
), cxx
[column(sq
)], rxx
[row(sq
)], s
);
1675 s
+= BRLscan (sq
, &mob
);
1679 if ( debug_eval
&& (c
= RMBLTY
[mob
]) != 0 ) {
1681 fprintf(debug_eval_file
,"adding rook for mobility %d value %d\n",mob
,c
);
1687 if (PC1
[fyle
] == 0) {
1688 s
+= RHOPN
; /* no own pawn on rook file */
1691 fprintf(debug_eval_file
,"adding %d for no own pawn on rook file\n",RHOPN
);
1694 if (PC2
[fyle
] == 0) {
1695 s
+= RHOPNX
; /* no enemy pawn on rook file */
1698 fprintf(debug_eval_file
,"adding %d for no enemy pawn on rook file\n",RHOPNX
);
1706 if (a1
== 0 || a2
> ctlR
+ 1)
1711 fprintf(debug_eval_file
,"adding %d for hung\n", HUNGP
);
1718 else if (a2
>= ctlR
|| a1
< ctlP
)
1723 fprintf(debug_eval_file
,"adding %d for atacked piece\n",ATAKD
);
1728 if ( in_opening_stage
) {
1732 if ( GameType
[c1
] == STATIC_ROOK
)
1734 short c
= ccolumn(c1
,sq
);
1735 /* Bonus for rook on 8th file */
1739 /* Bonus for rook on right side, malus for rook on left side */
1742 s
+= c
+ c
+ OPENOK
;
1743 } else if ( c
>= 0 ) {
1744 s
+= c
+ c
+ OPENWRONG
;
1747 else if ( GameType
[c1
] == RANGING_ROOK
)
1749 /* Bonus for rook on left side and bishops diagonal closed, malus otherwise. */
1751 c
= 4 - ccolumn(c1
,sq
);
1753 /* Bishops diagonal should not be open */
1754 if ( on_csquare(c1
,pawn
,30) )
1757 s
+= c
+ c
+ OPENWRONG
;
1758 } else if ( c
< 0 ) {
1759 s
+= c
+ c
+ OPENWRONG
;
1760 /* Malus for king not on initial square */
1761 if ( !on_csquare(side
,king
,4) ) {
1767 if ( debug_eval
&& (s0
!= s
) )
1768 fprintf(debug_eval_file
,"adding %d for opening\n",(s
-s0
));
1776 PPawnValue (register short int sq
, short int side
)
1778 * Calculate the positional value for a promoted pawn on 'sq'.
1787 s
+= (KINGED
+ 2) * AddEnemyKingDistanceBonus(sq
);
1793 if (a1
== 0 || a2
> ctlPp
+ 1)
1800 else if (a2
>= ctlPp
|| a1
< ctlP
)
1808 PLanceValue (register short int sq
, short int side
)
1810 * Calculate the positional value for a promoted lance on 'sq'.
1819 s
+= (KINGED
+ 1) * AddEnemyKingDistanceBonus(sq
);
1825 if (a1
== 0 || a2
> ctlLp
+ 1)
1832 else if (a2
>= ctlLp
|| a1
< ctlP
)
1840 PKnightValue (register short int sq
, short int side
)
1842 * Calculate the positional value for a promoted knight on 'sq'.
1851 s
+= (KINGED
+ 1 ) * AddEnemyKingDistanceBonus(sq
);
1857 if (a1
== 0 || a2
> ctlNp
+ 1)
1864 else if (a2
>= ctlNp
|| a1
< ctlP
)
1872 PSilverValue (register short int sq
, short int side
)
1874 * Calculate the positional value for a promoted silver on 'sq'.
1883 s
+= (KINGED
+ 1) * AddEnemyKingDistanceBonus(sq
);
1889 if (a1
== 0 || a2
> ctlSp
+ 1)
1896 else if (a2
>= ctlSp
|| a1
< ctlP
)
1904 PBishopValue (register short int sq
, short int side
)
1906 * Calculate the positional value for a promoted bishop on 'sq'.
1914 #if defined USE_PATTERN
1915 s
= Mbishop
[c1
][sq
];
1917 s
= Mbishop
[c1
][csquare(c1
,sq
)];
1920 if ( InPromotionZone(c1
,sq
) )
1921 s
+= KINGED
* AddEnemyKingDistanceBonus(sq
);
1923 s
+= BRLscan (sq
, &mob
);
1929 if (a1
== 0 || a2
> ctlBp
+ 1)
1936 else if (a2
>= ctlBp
|| a1
< ctlP
)
1944 PRookValue (register short int sq
, short int side
)
1946 * Calculate the positional value for a promoted rook on 'sq'.
1951 register short fyle
;
1955 #if defined USE_PATTERN
1958 s
= Mrook
[c1
][csquare(c1
,sq
)];
1961 if ( InPromotionZone(c1
,sq
) )
1962 s
+= KINGED
* AddEnemyKingDistanceBonus(sq
);
1964 s
+= BRLscan (sq
, &mob
);
1975 if (a1
== 0 || a2
> ctlRp
+ 1)
1982 else if (a2
>= ctlRp
|| a1
< ctlP
)
1990 KingValue (register short int sq
, short int side
)
1992 * Calculate the positional value for a king on 'sq'.
1996 register short fyle
;
1999 #if defined USE_PATTERN
2002 s
= Mking
[c1
][csquare(c1
,sq
)];
2007 fprintf(debug_eval_file
,"inital value [%d] for king on %c%c: %d\n",
2008 csquare(c1
,sq
), cxx
[column(sq
)], rxx
[row(sq
)], s
);
2014 if (Mvboard
[kingP
[c1
]])
2023 fprintf(debug_eval_file
,"adding %d for now own pawn on file\n",
2032 fprintf(debug_eval_file
,"adding %d for now opponents pawn on file\n",
2041 if (a1
== 0 || a2
> ctlK
+ 1)
2046 fprintf(debug_eval_file
,"adding %d for hung\n", HUNGP
);
2055 fprintf(debug_eval_file
,"adding %d for attacked piece\n",
2061 if ( in_opening_stage
) {
2062 if ( GameType
[c1
] == STATIC_ROOK
)
2064 /* Malus for king on right side or fifth file */
2066 c
= 4 - ccolumn(c1
,sq
);
2067 if ( c
< 0 || (c
== 0 && sq
!= kingP
[c1
]) ) {
2068 s
+= c
+ c
+ OPENWRONG
;
2071 fprintf(debug_eval_file
,"add %d for king on right side (Static)\n",
2076 else if ( GameType
[c1
] == RANGING_ROOK
)
2078 /* Malus for king on left side or fifth file */
2080 c
= 4 - ccolumn(c1
,sq
);
2081 if ( c
> 0 || (c
== 0 && sq
!= kingP
[c1
]) ) {
2082 s
+= c
+ c
+ OPENWRONG
;
2085 fprintf(debug_eval_file
,"add %d for king on left side (Ranging)\n",
2089 /* Malus for king moved before rook switch */
2090 if ( sq
!= kingP
[c1
] )
2092 if ( on_csquare(c1
,rook
,16) ) {
2096 fprintf(debug_eval_file
,"add %d for king moved before rook switch (Ranging)\n",
2102 /* Malus for sitting king after rook switch */
2104 if ( !on_csquare(c1
,rook
,16) ) {
2108 fprintf(debug_eval_file
,"add %d for sitting king after rook switch (Ranging)\n",
2113 /* Malus for defending general moved before king switch to right side */
2114 if ( ccolumn(c1
,sq
) < 6 )
2115 if ( Mvboard
[csquare(c1
,5)] || Mvboard
[csquare(c1
,6)] ) {
2119 fprintf(debug_eval_file
,
2120 "add %d for defending general moved before king switch (Ranging)\n",
2136 ScorePatternDistance (register short int side
)
2139 * Score distance to pattern regarding the game type which side plays.
2144 OpeningPattern
*p
= NULL
;
2148 fprintf(debug_eval_file
,"scoring castle pattern distance for PCASTLE=%d\n",
2152 if ( PCASTLE
!= 0 && ((p
= castle_pattern
[side
]) != NULL
) )
2154 ds
= board_to_pattern_distance(side
,p
,PCASTLE
,GameCnt
);
2158 if ( debug_eval
&& ds
!= 0 )
2159 fprintf(debug_eval_file
,
2160 "add %d for max gain of %s to reachable castle patterns %s\n",
2161 ds
, ColorStr
[side
], p
->name
);
2166 else if ( debug_eval
&& p
== NULL
)
2167 fprintf(debug_eval_file
,"no castle pattern for %s\n",ColorStr
[side
]);
2172 fprintf(debug_eval_file
,"scoring attack pattern distance for PATTACK=%d\n",
2176 if ( PATTACK
!= 0 && ((p
= attack_pattern
[side
]) != NULL
) )
2178 ds
= board_to_pattern_distance(side
,p
,PATTACK
,GameCnt
);
2182 if ( debug_eval
&& ds
!= 0 )
2183 fprintf(debug_eval_file
,
2184 "add %d for max gain of %s to reachable attack patterns %s\n",
2185 ds
, ColorStr
[side
], p
->name
);
2190 else if ( debug_eval
&& p
== NULL
)
2191 fprintf(debug_eval_file
,"no attack pattern for %s\n",ColorStr
[side
]);
2200 UpdatePatterns (short int side
, short int GameCnt
)
2203 * Determine castle and attack pattern which should be reached next.
2204 * Only patterns are considered, which have not been reached yet.
2209 short xside
= side
^ 1;
2212 PatternSequence
*sequence
;
2214 strcpy(s
,"CASTLE_?_?");
2215 s
[7] = GameType
[side
];
2216 s
[9] = GameType
[xside
];
2217 castle_pattern
[side
] = p
= locate_opening_pattern(side
,s
,GameCnt
);
2219 if ( flag
.post
&& p
)
2221 for (i
=0,sequence
=p
->sequence
; i
<p
->n
; i
++,sequence
=sequence
->next_pattern
)
2222 if ( sequence
->distance
[side
] != CANNOT_REACH
) n
++;
2225 #if defined USE_PATTERN
2226 if ( p
) update_advance_bonus (side
,p
);
2233 fprintf(debug_eval_file
,"castle pattern of %s is %s\n",
2234 ColorStr
[side
], p
->name
);
2235 fprintf(debug_eval_file
,"reachable patterns: ");
2236 for (i
=0,sequence
=p
->sequence
; i
<p
->n
; i
++,sequence
=sequence
->next_pattern
)
2237 if ( sequence
->distance
[side
] != CANNOT_REACH
)
2238 fprintf(debug_eval_file
,"%d ",i
);
2239 fprintf(debug_eval_file
,"\n");
2243 fprintf(debug_eval_file
,"no castle pattern %s for %s\n",
2248 strcpy(s
,"ATTACK_?_?");
2249 s
[7] = GameType
[side
];
2250 s
[9] = GameType
[xside
];
2251 attack_pattern
[side
] = p
= locate_opening_pattern(side
,s
,GameCnt
);
2253 if ( flag
.post
&& p
)
2255 for (i
=0,sequence
=p
->sequence
; i
<p
->n
; i
++,sequence
=sequence
->next_pattern
)
2256 if ( sequence
->distance
[side
] != CANNOT_REACH
) n
++;
2262 ShowPatternCount(side
,n
);
2263 if ( p
) update_advance_bonus (side
,p
);
2270 fprintf(debug_eval_file
,"attak pattern of %s is %s\n",
2271 ColorStr
[side
], p
->name
);
2272 fprintf(debug_eval_file
,"reachable patterns: ");
2273 for (i
=0,sequence
=p
->sequence
; i
<p
->n
; i
++,sequence
=sequence
->next_pattern
)
2274 if ( sequence
->distance
[side
] != CANNOT_REACH
)
2275 fprintf(debug_eval_file
,"%d ",i
);
2276 fprintf(debug_eval_file
,"\n");
2280 fprintf(debug_eval_file
,"no attak pattern %s for %s\n",
2293 ScorePosition (register short int side
)
2296 * Perform normal static evaluation of board position. A score is generated
2297 * for each piece and these are summed to get a score for each side.
2301 register short int score
;
2302 register short sq
, i
, xside
;
2313 fprintf (debug_eval_file
, "side = %d, stage = %d, in_opening = %d\n",
2314 side
, stage
, in_opening_stage
);
2318 hung
[black
] = hung
[white
] = pscore
[black
] = pscore
[white
] = 0;
2322 if (debug_eval
|| !ProbeEETable (side
, &s
))
2324 if (!ProbeEETable (side
, &s
))
2328 for (c1
= black
; c1
<= white
; c1
++)
2331 /* atk1 is array of atacks on squares by my side */
2333 /* atk2 is array of atacks on squares by other side */
2335 /* same for PC1 and PC2 */
2338 for (i
= PieceCnt
[c1
]; i
>= 0; i
--)
2340 sq
= PieceList
[c1
][i
];
2344 s
= PawnValue (sq
, side
);
2347 s
= KnightValue (sq
, side
);
2350 s
= BishopValue (sq
, side
);
2353 s
= RookValue (sq
, side
);
2356 s
= LanceValue (sq
, side
);
2359 s
= SilverValue (sq
, side
);
2362 s
= GoldValue (sq
, side
);
2365 s
= PPawnValue (sq
, side
);
2368 s
= PLanceValue (sq
, side
);
2371 s
= PKnightValue (sq
, side
);
2374 s
= PSilverValue (sq
, side
);
2377 s
= PBishopValue (sq
, side
);
2380 s
= PRookValue (sq
, side
);
2383 s
= KingValue (sq
, side
);
2390 #if !defined SAVE_SVALUE
2397 fprintf(debug_eval_file
,"pscore[black] = %d, pscore[white] = %d\n",
2398 pscore
[black
], pscore
[white
]);
2399 #if !defined SAVE_SVALUE
2400 debug_svalue(debug_eval_file
);
2404 if (hung
[side
] > 1) {
2407 fprintf(debug_eval_file
,"adding %d to pscore for %d hung %d pieces.\n",
2408 HUNGX
, hung
[side
], side
);
2411 pscore
[side
] += HUNGX
;
2413 if (hung
[xside
] > 1) {
2416 fprintf(debug_eval_file
,"adding %d to pscore for %d hung %d pieces.\n",
2417 HUNGX
, hung
[xside
], xside
);
2420 pscore
[xside
] += HUNGX
;
2423 for (c1
=black
,c2
=white
; c1
<=white
; c1
++,c2
--)
2426 short ps0
= pscore
[c1
];
2428 /* Score fifth rank */
2429 for ( sq
= 36; sq
<= 44; sq
++ )
2430 if ( color
[sq
] == c1
|| atak
[c1
][sq
] != 0 )
2434 if ( debug_eval
&& ps0
!= pscore
[c1
] )
2435 fprintf(debug_eval_file
,"adding %d for %s's control of 5th rank\n",
2436 pscore
[c1
]-ps0
, ColorStr
[c1
]);
2441 for ( sq
= ((c1
==black
)?0:54); sq
<=((c1
==black
)?26:80); sq
++ )
2442 if ( board
[sq
] == no_piece
&& atak
[c1
][sq
] == 0 )
2446 if ( debug_eval
&& ps0
!= pscore
[c1
] )
2447 fprintf(debug_eval_file
,"adding %d for holes in %s's camp\n",
2448 pscore
[c1
]-ps0
, ColorStr
[c1
]);
2451 /* Scoring depending whether in opening stage or not */
2453 if ( in_opening_stage
)
2455 /* do not exchange bishops in ranging rook openings */
2456 if ( GameType
[c1
] == RANGING_ROOK
)
2457 if ( Captured
[c2
][bishop
] ) {
2458 pscore
[c1
] += BXCHG
;
2461 fprintf(debug_eval_file
,"adding %d for %s's bishop catched by opponent\n",
2462 BXCHG
, ColorStr
[c1
]);
2468 short d1
= HasPiece
[c1
][silver
] + HasPiece
[c1
][gold
];
2469 short d2
= Captured
[c1
][silver
] + Captured
[c1
][gold
];
2470 pscore
[c1
] += (d1
*2 + d2
*3) * stage
/ 2;
2473 fprintf(debug_eval_file
,"adding %d for more valuable %s generals\n",
2474 (d1
*2 + d2
*3) * stage
/ 2, ColorStr
[c1
]);
2483 if ( in_opening_stage
) {
2484 pscore
[side
] += ScorePatternDistance (side
);
2485 pscore
[xside
] += ScorePatternDistance (xside
);
2489 score
= mtl
[side
] - mtl
[xside
] + pscore
[side
] - pscore
[xside
] + 10;
2493 gsrand (starttime
+ (unsigned int) hashbd
);
2494 score
+= urand () % dither
;
2499 PutInEETable(side
,score
);
2503 fprintf (debug_eval_file
, "score = %d\n", score
);
2512 fprintf (debug_eval_file
, "Score cached!\n" );
2518 fprintf (debug_eval_file
, "s = %d\n", s
);
2526 #if !defined USE_PATTERN
2536 short int *PawnAdvance
[2],*LanceAdvance
[2],*KnightAdvance
[2],
2537 *SilverAdvance
[2],*GoldAdvance
[2],*BishopAdvance
[2],*RookAdvance
[2],
2544 SetOpeningStrategy(short c
, short s
)
2548 fprintf(debug_eval_file
,"strategy for %s is ",ColorStr
[c
]);
2551 PawnAdvance
[c
] = PawnAdvanceRS
;
2552 LanceAdvance
[c
] = LanceAdvanceRS
;
2553 KnightAdvance
[c
] = KnightAdvanceRS
;
2554 SilverAdvance
[c
] = SilverAdvanceRS
;
2555 GoldAdvance
[c
] = GoldAdvanceRS
;
2556 BishopAdvance
[c
] = BishopAdvanceRS
;
2557 RookAdvance
[c
] = RookAdvanceRS
;
2558 KingAdvance
[c
] = KingAdvanceRS
;
2561 fprintf(debug_eval_file
,"Ranging vs. Static\n");
2563 } else if ( s
== SR
) {
2564 PawnAdvance
[c
] = PawnAdvanceSR
;
2565 LanceAdvance
[c
] = LanceAdvanceSR
;
2566 KnightAdvance
[c
] = KnightAdvanceSR
;
2567 SilverAdvance
[c
] = SilverAdvanceSR
;
2568 GoldAdvance
[c
] = GoldAdvanceSR
;
2569 BishopAdvance
[c
] = BishopAdvanceSR
;
2570 RookAdvance
[c
] = RookAdvanceSR
;
2571 KingAdvance
[c
] = KingAdvanceSR
;
2574 fprintf(debug_eval_file
,"Static vs. Ranging\n");
2576 } else if ( s
== RR
) {
2577 PawnAdvance
[c
] = PawnAdvanceRR
;
2578 LanceAdvance
[c
] = LanceAdvanceRR
;
2579 KnightAdvance
[c
] = KnightAdvanceRR
;
2580 SilverAdvance
[c
] = SilverAdvanceRR
;
2581 GoldAdvance
[c
] = GoldAdvanceRR
;
2582 BishopAdvance
[c
] = BishopAdvanceRR
;
2583 RookAdvance
[c
] = RookAdvanceRR
;
2584 KingAdvance
[c
] = KingAdvanceRR
;
2587 fprintf(debug_eval_file
,"Ranging vs. Ranging\n");
2590 PawnAdvance
[c
] = PawnAdvanceSS
;
2591 LanceAdvance
[c
] = LanceAdvanceSS
;
2592 KnightAdvance
[c
] = KnightAdvanceSS
;
2593 SilverAdvance
[c
] = SilverAdvanceSS
;
2594 GoldAdvance
[c
] = GoldAdvanceSS
;
2595 BishopAdvance
[c
] = BishopAdvanceSS
;
2596 RookAdvance
[c
] = RookAdvanceSS
;
2597 KingAdvance
[c
] = KingAdvanceSS
;
2600 fprintf(debug_eval_file
,"Static vs. Static\n");
2608 #define AssignAdvance(b,w)\
2610 SetOpeningStrategy(black,b);\
2611 SetOpeningStrategy(white,w);\
2617 CopyBoard (small_short
*a
, small_short
*b
, short n
, short d
)
2619 register small_short
*sqa
, *sqb
;
2623 bcopy(a
,b
,NO_SQUARES
*sizeof(short));
2625 for (sqa
= a
,sqb
= b
,i
=0; i
<NO_SQUARES
; sqa
++,sqb
++,i
++)
2632 *sqb
= (n
* (*sqa
)) / d
;
2636 #endif /* USE_PATTERN */
2640 GuessGameType (void)
2643 * Try to determine the game type of "side".
2646 short side
, sq
, StaticRook
[2] = {0,0}, RangingRook
[2] = {0,0};
2648 for ( side
=black
; side
<=white
; side
++ ) {
2650 /* static rook conditions */
2652 if ( on_column(side
,rook
,7) )
2653 StaticRook
[side
] += 3;
2654 if ( on_csquare(side
,pawn
,34) )
2655 StaticRook
[side
] += 6;
2656 else if ( on_csquare(side
,pawn
,43) )
2657 StaticRook
[side
] += 8;
2658 else if ( !on_column(side
,pawn
,7) )
2659 StaticRook
[side
] += 5;
2660 if ( empty_csquare(side
,5) || empty_csquare(side
,6) )
2661 StaticRook
[side
] += 2;
2662 if ( on_left_side(side
,king
) )
2663 StaticRook
[side
] += 2;
2665 /* ranging rook conditions */
2667 if ( on_left_side(side
,rook
) )
2668 RangingRook
[side
] += 5;
2669 else if ( !on_column(side
,rook
,7) )
2670 RangingRook
[side
] += 3;
2671 if ( on_csquare(side
,pawn
,25) )
2672 RangingRook
[side
] += 1;
2673 if ( on_csquare(side
,pawn
,30) )
2674 RangingRook
[side
] += 1;
2676 RangingRook
[side
] -= 2;
2677 if ( !on_right_side(side
,rook
) )
2678 RangingRook
[side
] += 2;
2679 if ( on_right_side(side
,king
) )
2680 RangingRook
[side
] += 2;
2681 if ( on_csquare(side
,bishop
,20) )
2682 if ( on_csquare(side
,silver
,11) || on_csquare(side
,silver
,12) ||
2683 on_csquare(side
,silver
,21) )
2684 RangingRook
[side
] += 3;
2686 if ( StaticRook
[side
] > 5 || RangingRook
[side
] > 5 )
2687 GameType
[side
] = (StaticRook
[side
] > RangingRook
[side
])
2688 ? STATIC_ROOK
: RANGING_ROOK
;
2690 GameType
[side
] = UNKNOWN
;
2695 #define StringOfGameType(side)\
2696 (GameType[side] == STATIC_ROOK ? "Static Rook" :\
2697 (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
2700 fprintf(debug_eval_file
,"guessing game type: %s vs. %s\n",
2701 StringOfGameType(black
), StringOfGameType(white
));
2704 if ( GameType
[black
] == UNKNOWN
|| GameType
[white
] == UNKNOWN
)
2706 for (side
= black
; side
<= white
; side
++)
2707 if ( side
== computer
&& GameType
[side
] == UNKNOWN
) {
2709 * Game type is UNKNOWN.
2710 * Make a decision what type of game to play.
2711 * To make computer games more interesting, make a
2714 if ( !on_csquare(side
,pawn
,25) ) {
2715 /* Play static rook if rook pawn has been pushed! */
2716 GameType
[side
] = STATIC_ROOK
;
2718 unsigned int random
= urand () % 100;
2719 short d
= StaticRook
[side
] - RangingRook
[side
];
2720 switch ( GameType
[side
^ 1] ) {
2722 if ( random
< 35 + d
) GameType
[side
] = STATIC_ROOK
;
2723 else if ( random
< 95 ) GameType
[side
] = RANGING_ROOK
;
2726 if ( random
< 75 + d
) GameType
[side
] = STATIC_ROOK
;
2727 else if ( random
< 95 ) GameType
[side
] = RANGING_ROOK
;
2730 if ( random
< 33 + d
) GameType
[side
] = STATIC_ROOK
;
2731 else if ( random
< 66 ) GameType
[side
] = RANGING_ROOK
;
2736 fprintf(debug_eval_file
,"decide game type: %s vs. %s\n",
2737 StringOfGameType(black
), StringOfGameType(white
));
2747 #define StringOfGameType(side)\
2748 (GameType[side] == STATIC_ROOK ? "Static Rook" :\
2749 (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
2756 DetermineGameType (void)
2767 #if defined USE_PATTERN
2769 memset ((char *)Mpawn
, 0, sizeof(Mpawn
));
2770 memset ((char *)Mlance
, 0, sizeof(Mlance
));
2771 memset ((char *)Mknight
, 0, sizeof(Mknight
));
2772 memset ((char *)Msilver
, 0, sizeof(Msilver
));
2773 memset ((char *)Mgold
, 0, sizeof(Mgold
));
2774 memset ((char *)Mbishop
, 0, sizeof(Mbishop
));
2775 memset ((char *)Mrook
, 0, sizeof(Mrook
));
2776 memset ((char *)Mking
, 0, sizeof(Mking
));
2780 if ( GameType
[black
] == STATIC_ROOK
) {
2781 if ( GameType
[white
] == STATIC_ROOK
) {
2782 /* STATIC vs. STATIC */
2783 AssignAdvance(SS
,SS
);
2784 } else if ( GameType
[white
] == RANGING_ROOK
) {
2785 /* STATIC vs. RANGING */
2786 AssignAdvance(SR
,RS
);
2788 /* STATIC vs. ??? */
2789 AssignAdvance(SS
,SS
);
2791 } else if ( GameType
[black
] == RANGING_ROOK
) {
2792 if ( GameType
[white
] == STATIC_ROOK
) {
2793 /* RANGING vs. STATIC */
2794 AssignAdvance(RS
,SR
);
2795 } else if ( GameType
[white
] == RANGING_ROOK
) {
2796 /* RANGING vs. RANGING */
2797 AssignAdvance(RR
,RR
);
2799 /* RANGING vs. ???? */
2800 AssignAdvance(RS
,SR
);
2803 if ( GameType
[white
] == STATIC_ROOK
) {
2804 /* ???? vs. STATIC */
2805 AssignAdvance(SS
,SS
);
2806 } else if ( GameType
[white
] == RANGING_ROOK
) {
2807 /* ???? vs. RANGING */
2808 AssignAdvance(SR
,RS
);
2811 AssignAdvance(SS
,SS
);
2815 /* Weighted advance tables. Can be updated. */
2817 CopyBoard (PawnAdvance
[black
], Mpawn
[black
], PADVNCM
, 10);
2818 CopyBoard (PawnAdvance
[white
], Mpawn
[white
], PADVNCM
, 10);
2819 CopyBoard (SilverAdvance
[black
], Msilver
[black
], SADVNCM
, 10);
2820 CopyBoard (SilverAdvance
[white
], Msilver
[white
], SADVNCM
, 10);
2821 CopyBoard (GoldAdvance
[black
], Mgold
[black
], GADVNCM
, 10);
2822 CopyBoard (GoldAdvance
[white
], Mgold
[white
], GADVNCM
, 10);
2823 CopyBoard (KingAdvance
[black
], Mking
[black
], KADVNCM
, 1);
2824 CopyBoard (KingAdvance
[white
], Mking
[white
], KADVNCM
, 1);
2826 /* Tables without weighted advances. Must not be updated! */
2828 for ( side
= black
; side
<= white
; side
++ ) {
2829 Mlance
[side
] = LanceAdvance
[side
];
2830 Mknight
[side
] = KnightAdvance
[side
];
2831 Mbishop
[side
] = BishopAdvance
[side
];
2832 Mrook
[side
] = RookAdvance
[side
];
2837 fprintf(debug_eval_file
,"relative pawn table weigth: %d\n",PADVNCM
);
2838 fprintf(debug_eval_file
,"relative silver table weigth: %d\n",SADVNCM
);
2839 fprintf(debug_eval_file
,"relative gold table weigth: %d\n",GADVNCM
);
2840 fprintf(debug_eval_file
,"relative king table weigth: %d\n",KADVNCM
);
2844 #endif /* USE_PATTERN */
2846 #if defined USE_PATTERN
2847 if ( in_opening_stage
) {
2848 for (side
= black
; side
<= white
; side
++)
2849 UpdatePatterns (side
, GameCnt
);
2851 ShowPatternCount(black
,-1);
2852 ShowPatternCount(white
,-1);
2861 ExaminePosition (void)
2864 * This is done one time before the search is started. Set up arrays Mwpawn,
2865 * Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue() function
2866 * to determine the positional value of each piece.
2870 register short i
, sq
, msq
;
2871 register short fyle
;
2872 short wpadv
, bpadv
, z
, side
, pp
, j
, k
, val
, Pd
, rank
;
2875 ShowMessage("begin of ExaminePosition");
2878 ataks (black
, atak
[black
]);
2879 ataks (white
, atak
[white
]);
2882 ShowMessage("after ataks");
2887 debug_position (debug_eval_file
);
2888 /* debug_ataks (debug_eval_file); */
2895 ShowMessage("after UpdateWeights");
2900 for ( c
= black
; c
<= white
; c
++ )
2901 for ( p
= pawn
; p
<= king
; p
++ )
2905 memset ((char *)HasPiece
, 0,(unsigned long)sizeof(HasPiece
));
2908 for (side
= black
; side
<= white
; side
++)
2909 for (i
= PieceCnt
[side
]; i
>= 0; i
--)
2910 ++HasPiece
[side
][board
[PieceList
[side
][i
]]];
2912 DetermineGameType();
2914 /* Build up weighted enemy-king distance tables. */
2918 #if defined(NOMEMSET)
2920 ShowMessage("just before 0 distance assignment");
2922 for (sq
= 0; sq
< NO_SQUARES
; sq
++)
2923 Kfield
[black
][sq
] = Kfield
[white
][sq
] = 0;
2926 ShowMessage("just before memset");
2928 memset ((char *) Kfield
, 0, (unsigned long)sizeof (Kfield
));
2929 #endif /* NOMEMSET */
2934 ShowMessage("just before distance assignments");
2936 for (sq
= 0; sq
< NO_SQUARES
; sq
++)
2938 Kfield
[black
][sq
] = (distance(sq
,WhiteKing
)==1) ? KATAK
: 0;
2939 Kfield
[white
][sq
] = (distance(sq
,BlackKing
)==1) ? KATAK
: 0;
2945 for (side
=black
; side
<=white
; side
++)
2947 fprintf(debug_eval_file
,"%s's pawn table\n\n",ColorStr
[side
]);
2948 debug_table(debug_eval_file
,Mpawn
[side
]);
2949 fprintf(debug_eval_file
,"%s's silver table\n\n",ColorStr
[side
]);
2950 debug_table(debug_eval_file
,Msilver
[side
]);
2951 fprintf(debug_eval_file
,"%s's gold table\n\n",ColorStr
[side
]);
2952 debug_table(debug_eval_file
,Mgold
[side
]);
2953 fprintf(debug_eval_file
,"%s's king table\n\n",ColorStr
[side
]);
2954 debug_table(debug_eval_file
,Mking
[side
]);
2955 fprintf(debug_eval_file
,"%s's distance to enemy king table\n\n",ColorStr
[side
]);
2956 debug_table(debug_eval_file
,Kfield
[side
]);
2961 ShowMessage("end of ExaminePosition");
2968 UpdateWeights (void)
2971 * If material balance has changed, determine the values for the positional
2976 register short s1
, dio
, io
, os
;
2978 behind_in_material
[black
] = ((mtl
[white
] - mtl
[black
]) > valueB
);
2979 behind_in_material
[white
] = ((mtl
[black
] - mtl
[white
]) > valueB
);
2981 /* GameCnt = number of half moves */
2984 s1
= 0; /* 0 <= GameCnt <= 20: stage = 0 */
2985 else if (GameCnt
< 41)
2986 s1
= 1 + (GameCnt
-20)/3; /* 21 <= GameCnt <= 40: stage = 1..7 */
2987 else if (GameCnt
< 61)
2988 s1
= 8 + (GameCnt
-40)/5; /* 41 <= GameCnt <= 60: stage = 8..11 */
2990 s1
= 12 + (GameCnt
-60)/7;
2994 stage
= stage2
= s1
;
2996 os
= (GameType
[black
] == STATIC_ROOK
&& GameType
[white
] == STATIC_ROOK
) ? 10 : 8;
2997 dio
= (in_opening_stage
= io
= (s1
< os
)) ? (os
- s1
) : 0;
2999 #if defined USE_PATTERN
3000 ADVNCM
[pawn
] = io
?2+s1
:1; /* advanced pawn bonus increment*/
3003 ADVNCM
[silver
] = io
?1+s1
:1; /* advanced silver bonus increment */
3004 ADVNCM
[gold
] = io
?1+s1
:1; /* advanced gold bonus increment */
3007 ADVNCM
[king
] = io
?1+s1
:1; /* advanced king bonus increment */
3009 PADVNCM
= io
?12+s1
:1; /* advanced pawn multiplier */
3010 SADVNCM
= io
?15+s1
:1; /* advanced silver multiplier */
3011 GADVNCM
= io
?14+s1
:1; /* advanced gold multiplier */
3012 KADVNCM
= io
?1+s1
:0; /* advanced king multiplier */
3014 PMBLTY
= 5; /* pawn mobility */
3015 PSTRONG
= 3; /* pawn supported by rook/lance */
3016 BDCLOSED
= -(dio
*2); /* bishops diagonal closed by pawn */
3017 P2STRONG
= 20; /* attacking pawn on 2nd col is strong */
3019 LHOPN
= -4; /* no own pawn on lance file ahead */
3020 LHOPNX
= 4; /* no enemy pawn on lance file ahead */
3021 LPROTECT
= 6; /* protect own piece with lance */
3022 LDNGR
= -6; /* lance is in danger */
3023 LXRAY
= 8; /* lance Xray attack on piece */
3025 NDNGR
= -4; /* knight is in danger */
3026 KNIGHTPOST
= 2; /* knight near enemy pieces */
3027 KNIGHTSTRONG
= 2; /* occupies pawn hole */
3028 NEDGE
= io
?-16:-8; /* knight is on edge file */
3030 SBEFOREG
= 2; /* proverb: silver before gold */
3032 BISHOPSTRONG
= 4; /* occupies pawn hole */
3033 BHCLSD
= -3; /* first or second piece in a bishop's direction is an own pawn */
3034 BHCLSDX
= -2; /* first or second piece in a bishop's direction is an opponents pawn */
3035 BRXRAY
= 10; /* bishop or rook Xray attack on piece */
3036 BXCHG
= -10; /* bishop exchange in ranging rook opening */
3038 RHOPN
= 10; /* no own pawn on rook file ahead */
3039 RHOPNX
= 8; /* no enemy pawn on rook file ahead */
3040 R2NDCOL
= dio
*2; /* rook is on 2nd column */
3042 PINVAL
= 15; /* Pin */
3044 KHOPN
= -8; /* no own pawn in kings file */
3045 KHOPNX
= KHOPN
* 2; /* no opponents pawn in kings file */
3046 KCASTLD
= 20; /* king protected by castle */
3047 KMOVD
= 4; /* proverb: a sitting king is a sitting duck */
3048 KATAK
= io
? 1 : 8; /* B,R,L attacks near enemy king */
3049 KSFTY
= /* king safety */
3050 io
? 0 : KINGSAFETY
+ s1
- 20;
3052 OPENOK
= dio
*3/2; /* corresponding to opening pattern */
3053 OPENWRONG
= -dio
*2; /* not correpsonding */
3055 KINGOD
= 2+s1
/4; /* distance to own king multiplier */
3056 KINGED
= 3+s1
/4; /* distance to enemy king multiplier */
3057 PROMD
= 2+s1
/4; /* distance to promotion zone multiplier */
3059 ATAKD
= -15; /* defender > attacker */
3060 HUNGP
= -14; /* each hung piece */
3061 HUNGX
= -18; /* extra for >1 hung piece */
3064 PATTACK
= dio
; /* attack pattern distance multiplier */
3065 PCASTLE
= dio
; /* castle pattern distance multiplier */