Changing license to GPL3 (and bumping version to 1.4.0).
[gnushogi.git] / gnushogi / eval.c
blob3f44d9bc676a6ed6dde8f950b8cd1444271ddb61
1 /*
2 * FILE: eval.c
4 * ----------------------------------------------------------------------
6 * Copyright (c) 2012 Free Software Foundation
8 * GNU SHOGI is based on GNU CHESS
10 * This file is part of GNU SHOGI.
12 * GNU Shogi is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 3 of the License,
15 * or (at your option) any later version.
17 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with GNU Shogi; see the file COPYING. If not, see
24 * <http://www.gnu.org/licenses/>.
25 * ----------------------------------------------------------------------
29 #include "gnushogi.h"
30 #include "pattern.h"
32 extern void
33 ShowStage(void);
35 /* Hash table for preventing multiple scoring of the same position */
37 int EADD = 0; /* number of writes to the cache table */
38 int EGET = 0; /* number of hits to the cache table */
39 int PUTVAR = false; /* shall the current scoring be cached? */
42 /* Pieces and colors of initial board setup */
44 const small_short Stboard[NO_SQUARES] =
46 lance, knight, silver, gold, king, gold, silver, knight, lance,
47 0, bishop, 0, 0, 0, 0, 0, rook, 0,
48 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
49 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
53 0, rook, 0, 0, 0, 0, 0, bishop, 0,
54 lance, knight, silver, gold, king, gold, silver, knight, lance
58 const small_short Stcolor[NO_SQUARES] =
60 black, black, black, black,
61 black, black, black, black, black,
62 neutral, black, neutral, neutral,
63 neutral, neutral, neutral, black, neutral,
64 black, black, black, black,
65 black, black, black, black, black,
66 neutral, neutral, neutral, neutral,
67 neutral, neutral, neutral, neutral, neutral,
68 neutral, neutral, neutral, neutral,
69 neutral, neutral, neutral, neutral, neutral,
70 neutral, neutral, neutral, neutral,
71 neutral, neutral, neutral, neutral, neutral,
72 white, white, white, white,
73 white, white, white, white, white,
74 neutral, white, neutral, neutral,
75 neutral, neutral, neutral, white, neutral,
76 white, white, white, white,
77 white, white, white, white, white
81 /* Actual pieces and colors */
83 small_short board[NO_SQUARES], color[NO_SQUARES];
86 /* relative piece values at the beginning of main stages */
88 #define MAIN_STAGES 4
90 static small_short ispvalue[NO_PIECES][MAIN_STAGES] =
92 { 0, 35, 70, 99 }, /* main stage borders */
93 /* ------------------------------------------ */
94 { 7, 7, 8, 10 }, /* Pawn */
95 { 20, 35, 45, 60 }, /* Lance */
96 { 20, 35, 45, 60 }, /* Knight */
97 { 35, 40, 60, 80 }, /* Silver */
98 { 35, 50, 65, 80 }, /* Gold */
99 { 90, 90, 90, 90 }, /* Bishop */
100 { 95, 95, 95, 95 }, /* Rook */
101 { 15, 25, 40, 65 }, /* promoted Pawn */
102 { 25, 45, 55, 65 }, /* promoted Lance */
103 { 25, 45, 55, 65 }, /* promoted Knight */
104 { 35, 55, 75, 75 }, /* promoted Silver */
105 { 99, 99, 99, 99 }, /* promoted Bishop */
106 { 97, 97, 99, 99 }, /* promoted Rook */
107 { 100, 100, 100, 100 }, /* King */
110 /* Features and Weights */
112 #define ATTACKED 0
113 #define HUNGP 1
114 #define HUNGX 2
115 #define CNTRL5TH 3
116 #define HOLES 4
117 #define PCASTLE 5
118 #define PATTACK 6
119 #define CTRLK 7
120 #define PROTECT 8
121 #define HCLSD 9
122 #define PINVAL 10
123 #define XRAY 11
124 #define OPENWRONG 12
125 #define SEED 13
126 #define LOOSE 14
127 #define MOBILITY 15
128 #define TARGET 16
129 #define KSFTY 17
130 #define HOPN 18
131 #define PROMD 19
132 #define KINGOD 20
133 #define PWNDROP 21
134 #define DFFDROP 22
135 #define FCLATTACK 23
136 #define KNGATTACK 24
137 #define KNGPROTECT 25
138 #define DNGLPC 26
139 #define LSATTACK 27
140 #define NIHATTACK 28
141 #define COHESION 29
142 #define OPPDROP 30
145 static small_short weight[NO_FEATURES + 1][MAIN_STAGES + 2] =
147 { 80, 100, 100, 40, 10, 15 }, /* ATTACKED */
148 { 80, 100, 100, 50, 14, 10 }, /* HUNGP */
149 { 80, 100, 100, 50, 18, 12 }, /* HUNGX */
150 { 100, 50, 0, 0, 2, 1 }, /* CNTRL5TH */
151 { 100, 100, 60, 10, 4, 2 }, /* HOLES */
152 { 100, 50, 0, 0, 14, 7 }, /* PCASTLE */
153 { 100, 50, 0, 0, 6, 12 }, /* PATTACK */
154 { 10, 40, 70, 100, 10, 15 }, /* CTRLK */
155 { 100, 80, 50, 40, 2, 1 }, /* PROTECT */
156 { 40, 100, 40, 5, 4, 4 }, /* HCLSD */
157 { 80, 100, 80, 30, 10, 15 }, /* PINVAL */
158 { 80, 100, 60, 15, 6, 10 }, /* XRAY */
159 { 100, 50, 0, 0, 15, 15 }, /* OPENWRONG */
160 { 0, 40, 70, 100, 8, 12 }, /* SEED */
161 { 50, 100, 80, 20, 5, 3 }, /* LOOSE */
162 { 50, 100, 80, 50, 100, 100 }, /* MOBILITY (%) */
163 { 50, 100, 80, 50, 4, 8 }, /* TARGET */
164 { 50, 40, 100, 80, 8, 4 }, /* KSFTY */
165 { 80, 100, 60, 20, 5, 5 }, /* HOPN */
166 { 20, 40, 80, 100, 3, 6 }, /* PROMD */
167 { 20, 40, 80, 100, 4, 1 }, /* KINGOD */
168 { 5, 40, 100, 50, 0, 4 }, /* PWNDROP */
169 { 0, 20, 80, 100, 0, 4 }, /* DFFDROP */
170 { 20, 50, 100, 80, 0, 4 }, /* FCLATTACK */
171 { 0, 20, 80, 100, 0, 8 }, /* KNGATTACK */
172 { 40, 80, 100, 80, 6, 0 }, /* KNGPROTECT */
173 { 50, 100, 60, 10, 0, 8 }, /* DNGPC */
174 { 30, 100, 60, 5, 0, 6 }, /* LSATTACK */
175 { 0, 50, 80, 100, 0, 8 }, /* NIHATTACK */
176 { 50, 100, 80, 60, 8, 0 }, /* COHESION */
177 { 100, 100, 80, 60, 4, 4 }, /* OPPDROP */
181 short ADVNCM[NO_PIECES];
183 /* distance to enemy king */
184 static const short EnemyKingDistanceBonus[10] =
185 { 0, 6, 4, -1, -3, -4, -6, -8, -10, -12 };
187 /* distance to own king */
188 static const short OwnKingDistanceBonus[10] =
189 { 0, 5, 2, 1, 0, -1, -2, -3, -4, -5 };
191 /* distance to promotion zone */
192 static const int PromotionZoneDistanceBonus[NO_ROWS] =
193 { 0, 0, 0, 0, 2, 6, 6, 8, 8 };
195 #define MAX_BMBLTY 20
196 #define MAX_RMBLTY 20
197 #define MAX_LMBLTY 8
199 /* Bishop mobility bonus indexed by # reachable squares */
200 static const short BMBLTY[MAX_BMBLTY] =
201 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
203 /* Rook mobility bonus indexed by # reachable squares */
204 static const short RMBLTY[MAX_RMBLTY] =
205 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
207 /* Lance mobility bonus indexed by # reachable squares */
208 static const short LMBLTY[MAX_LMBLTY] =
209 { 0, 0, 0, 0, 4, 6, 8, 10 };
211 static const short MBLTY[NO_PIECES] =
212 { 0, 2, 1, 10, 5, 5, 1, 1, 5, 5, 5, 5, 1, 1, 4 };
214 static const short KTHRT[36] =
215 { 0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
216 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
217 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80 };
219 static small_short fvalue[2][NO_FEATURES];
221 long attack[2][NO_SQUARES]; /* threats to squares */
222 small_short sseed[NO_SQUARES]; /* square occupied by a seed piece? */
224 struct signature threats_signature[2] = /* statistics valid for position.. */
225 { { -1, -1 }, { -1, -1 } }; /* attack and sseed available */
227 small_short starget[2][NO_SQUARES]; /* significance as a target for a
228 * side of a square */
229 small_short sloose[NO_SQUARES]; /* square occupied by a loose piece? */
230 small_short shole[NO_SQUARES]; /* empty square a hole? */
231 small_short shung[NO_SQUARES]; /* hung piece? */
233 struct signature squares_signature = /* statistics valid for position ... */
234 { 0, 0 }; /* starget, sloose, shole, shung available */
236 short target[2], seed[2], loose[2], hole[2];
238 short captured[2]; /* number of captured pieces */
239 short dcaptured[2]; /* different types of captured pieces */
241 small_short Kdist[2][NO_SQUARES]; /* distance to king */
243 short MAXADIST, MAXCDIST; /* maximum half move distance to pattern */
245 char GameType[2] = { UNKNOWN, UNKNOWN }; /* chosen game type of each side */
248 static short attack_opening_sequence[2]; /* current castle patterns */
249 static short castle_opening_sequence[2]; /* current attack formations */
251 static small_short Mpawn [2][NO_SQUARES];
252 static small_short Msilver[2][NO_SQUARES];
253 static small_short Mgold [2][NO_SQUARES];
254 static small_short Mking [2][NO_SQUARES];
255 static small_short Mlance [2][NO_SQUARES];
256 static small_short Mknight[2][NO_SQUARES];
257 static small_short Mbishop[2][NO_SQUARES];
258 static small_short Mrook [2][NO_SQUARES];
260 static Mpiece_array Mpawn, Mlance, Mknight, Msilver, Mgold,
261 Mbishop, Mrook, Mking;
263 Mpiece_array *Mpiece[NO_PIECES] =
264 { NULL, &Mpawn, &Mlance, &Mknight, &Msilver, &Mgold, &Mbishop, &Mrook,
265 &Mgold, &Mgold, &Mgold, &Mgold, &Mbishop, &Mrook, &Mking };
268 static short c1, c2;
269 static small_short *PC1, *PC2;
270 static small_short *fv1;
271 static long *atk1, *atk2;
272 static long a1, a2;
274 #define csquare(side, sq) ((side == black) ? sq : (NO_SQUARES_1 - sq))
275 #define crow(side, sq) row(csquare(side, sq))
276 #define ccolumn(side, sq) column(csquare(side, sq))
279 inline static short
280 on_csquare(short side, short piece, short square)
282 short sq;
283 /* FIXME: un-obfuscate this! */
284 return ((board[sq = csquare(side, square)] == piece)
285 && (color[sq] == side));
289 inline static short
290 on_column(short side, short piece, short c)
292 short sq;
294 for (sq = c; sq < NO_SQUARES; sq += 9)
296 if (on_csquare(side, piece, sq))
297 return true;
300 return false;
304 #define empty_csquare(side, square) \
305 (board[csquare(side, square)] == no_piece)
307 inline static short
308 on_left_side(short side, short piece)
310 short c;
312 for (c = 0; c < 4; c++)
314 if (on_column(side, piece, c))
315 return true;
318 return false;
322 inline static short
323 on_right_side(short side, short piece)
325 short c;
327 for (c = 5; c < NO_COLS; c++)
329 if (on_column(side, piece, c))
330 return true;
333 return false;
337 short pscore[2]; /* piece score for each side */
343 * Fill array attack[side][] with info about attacks to a square. Bits
344 * 16-31 are set if the piece (king .. pawn) attacks the square. Bits 0-15
345 * contain a count of total attacks to the square. Fill array sseed[] with
346 * info about occupation by a seed piece.
349 void
350 threats(short side)
352 short u, sq;
353 long c;
354 long *a;
355 #ifdef SAVE_NEXTPOS
356 short d;
357 #else
358 unsigned char *ppos, *pdir;
359 #endif
360 short i, kd, piece, xside;
361 small_short *PL;
363 if (MatchSignature(threats_signature[side]))
365 /* data valid for current positional signature */
366 return;
369 a = attack[side];
370 xside = side ^ 1;
372 array_zero(a, NO_SQUARES * sizeof(a[0]));
374 PL = PieceList[side];
376 for (i = PieceCnt[side]; i >= 0; i--)
378 short ptyp;
380 sq = PL[i];
381 piece = board[sq];
382 ptyp = ptype[side][piece];
383 c = control[piece];
384 #ifdef SAVE_NEXTPOS
385 u = first_direction(ptyp, &d, sq);
386 #else
387 ppos = (*nextpos[ptyp])[sq];
388 pdir = (*nextdir[ptyp])[sq];
389 u = ppos[sq];
390 #endif
394 a[u] = ((a[u] + 1) | c);
396 if ((kd = Kdist[xside][u]) < 2)
398 sseed[sq] += 2 - kd;
399 seed[side]++;
402 #ifdef SAVE_NEXTPOS
403 u = ((color[u] == neutral)
404 ? next_position(ptyp, &d, sq, u)
405 : next_direction(ptyp, &d, sq));
406 #else
407 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
408 #endif
410 while (u != sq);
413 /* data valid for current positional signature */
414 CopySignature(threats_signature[side]);
420 * Compute the board square with nunmap offset "id". If side == white,
421 * offset is negated. inunmap[sq] is the corresponding nunmap index isq.
422 * nunmap[isq + id] computes the board square. If negative, it is outside
423 * the board.
426 static void
427 add_target(short sq, short side, short id)
429 short isq, tsq, xside;
430 isq = inunmap[sq];
431 tsq = (side == black) ? nunmap[isq + id] : nunmap[isq - id];
433 if (tsq >= 0)
435 target[xside = side^1]++;
437 if (attack[side][tsq])
438 starget[xside][tsq]++; /* protected target square */
439 else
440 starget[xside][tsq] += 2; /* unprotected target square */
447 * Target squares can be vertically ahead, diagonally ahead
448 * or diagonally behind.
451 static void
452 CheckTargetPiece(short sq, short side)
454 switch (board[sq])
456 case pawn: /* vertically ahead if unprotected */
457 if (!attack[side][sq])
458 add_target(sq, side, 11);
459 break;
461 case king: /* diagonally and vertically ahead */
462 add_target(sq, side, 10);
463 add_target(sq, side, 11);
464 add_target(sq, side, 12);
465 break;
467 case rook: /* diagonally ahead and behind */
468 add_target(sq, side, 10);
469 add_target(sq, side, 12);
470 add_target(sq, side, -10);
471 add_target(sq, side, -12);
472 break;
474 case bishop: /* vertically ahead */
475 add_target(sq, side, 11);
476 break;
478 case knight: /* vertically ahead if advanced */
479 /* FIXME: gotta love them magic numbers... */
480 if ((sq != 1) && (sq != 7) && (sq != 73) && (sq != 79))
481 add_target(sq, side, 11);
482 break;
488 static short
489 ScoreKingOpeningFeatures(void)
491 short s = 0, sq = OwnKing, ds;
493 if (GameType[c1] == STATIC_ROOK)
495 /* Penalty for king on right side or fifth file */
496 short c;
497 c = 4 - ccolumn(c1, sq);
499 if ((c < 0) || ((c == 0) && (sq != kingP[c1])))
500 s += (ds = -c - c - fv1[OPENWRONG]);
502 else if (GameType[c1] == RANGING_ROOK)
504 /* Penalty for king on left side or fifth file */
505 short c;
506 c = 4 - ccolumn(c1, sq);
508 if ((c > 0) || ((c == 0) && (sq != kingP[c1])))
510 s += (ds = -c - c - fv1[OPENWRONG]);
513 /* Penalty for king moved before rook switch */
514 if (sq != kingP[c1])
516 if (on_csquare(c1, rook, 16))
518 s += (ds = -4 * fv1[OPENWRONG]);
521 else
523 /* Penalty for sitting king after rook switch */
524 if (!on_csquare(c1, rook, 16))
526 s += (ds = -2 * fv1[OPENWRONG]);
530 /* Penalty for defending general moved
531 * before king switch to right side */
532 if (ccolumn(c1, sq) < 6)
534 if (Mvboard[csquare(c1, 5)] || Mvboard[csquare(c1, 6)])
536 s += (ds = -2 * fv1[OPENWRONG]);
541 return s;
547 inline static void
548 ExamineSquares(void)
550 short sq, side, piece, n;
552 if (MatchSignature(squares_signature))
554 /* data valid for current positional signature */
555 return;
558 array_zero(shole, sizeof(shole));
559 array_zero(sloose, sizeof(sloose));
560 array_zero(starget, sizeof(starget));
562 hole[0] = hole[1] = loose[0] = loose[1]
563 = target[0] = target[1] = 0;
565 for (sq = 0; sq < NO_SQUARES; sq++)
567 if ((side = color[sq]) == neutral)
569 if (InWhiteCamp(sq))
571 if (!attack[white][sq])
573 shole[sq] = 1;
574 hole[white]++;
577 else if (InBlackCamp(sq))
579 if (!attack[black][sq])
581 shole[sq] = 1;
582 hole[black]++;
586 else
588 /* occupied by "side" piece */
589 if (!attack[side][sq])
591 sloose[sq] = 1;
592 loose[side]++;
595 CheckTargetPiece(sq, side);
599 for (side = black; side <= white; side++)
601 captured[side] = dcaptured[side] = 0;
603 for (piece = pawn; piece <= rook; piece++)
605 if ((n = Captured[side][piece]) != 0)
607 if (piece != pawn)
608 captured[side] += n;
610 dcaptured[side]++;
615 /* Data valid for current positional signature */
616 CopySignature(squares_signature);
621 /* ............ POSITIONAL EVALUATION ROUTINES ............ */
624 * Inputs are:
625 * mtl[side] - value of all material
626 * hung[side] - count of hung pieces
627 * Tscore[ply] - search tree score for ply ply
628 * Pscore[ply] - positional score for ply ply
629 * INCscore - bonus score or penalty for certain moves
630 * Sdepth - search goal depth
631 * xwndw - evaluation window about alpha/beta
632 * EWNDW - second evaluation window about alpha/beta
633 * ChkFlag[ply] - checking piece at level ply or 0 if no check
634 * TesujiFlag[ply] - 1 if tesuji move at level ply or 0 if no tesuji
635 * PC1[column] - # of my pawns in this column
636 * PC2[column] - # of opponents pawns in column
637 * PieceCnt[side] - just what it says
644 * Compute an estimate of the score by adding the positional score from the
645 * previous ply to the material difference. If this score falls inside a
646 * window which is 180 points wider than the alpha-beta window (or within a
647 * 50 point window during quiescence search) call ScorePosition() to
648 * determine a score, otherwise return the estimated score. "side" is the
649 * side which has to move.
653 evaluate(short side,
654 short ply,
655 short alpha,
656 short beta,
657 short INCscore,
658 short *InChk, /* output Check flag */
659 short *blockable) /* king threat blockable */
661 short xside;
662 short s;
664 xside = side ^ 1;
665 s = -Pscore[ply - 1] + mtl[side] - mtl[xside] /* - INCscore */;
666 hung[black] = hung[white] = 0;
668 /* should we use the estimete or score the position */
669 if ((ply == 1)
670 || (ply == Sdepth)
671 || (ply > Sdepth && s >= (alpha - 30) && s <= (beta + 30))
672 #ifdef CACHE
673 || (use_etable && CheckEETable(side))
674 #endif
677 short sq;
679 /* score the position */
680 array_zero(sseed, sizeof(sseed));
682 seed[0] = seed[1] = 0;
683 threats(side);
685 if (Anyattack(side, sq = PieceList[xside][0]) && (board[sq] == king))
687 *InChk = (board[sq = PieceList[side][0]] == king)
688 ? SqAttacked(sq, xside, blockable)
689 : false;
691 return ((SCORE_LIMIT + 1001) - ply);
694 threats(xside);
695 *InChk = (board[sq = PieceList[side][0]] == king)
696 ? Anyattack(xside, sq)
697 : false;
698 *blockable = true;
699 EvalNodes++;
701 if (ply > 4)
702 PUTVAR = true;
704 ExamineSquares();
705 s = ScorePosition(side);
706 PUTVAR = false;
708 else
710 /* use the estimate but look at check */
711 short sq;
713 *InChk = (board[sq = PieceList[side][0]] == king)
714 ? SqAttacked(sq, xside, blockable)
715 : false;
717 if ((board[sq = PieceList[xside][0]] == king)
718 && SqAttacked(sq, side, blockable))
720 return ((SCORE_LIMIT + 1001) - ply);
724 Pscore[ply] = s - mtl[side] + mtl[xside];
725 ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0);
727 return s;
732 static short
733 value_of_weakest_attacker(long a2)
735 short piece;
736 short min_value, v;
737 min_value = SCORE_LIMIT;
739 for (piece = pawn; piece <= king; piece++)
741 if (control[piece] & a2)
743 if (min_value > (v = (*value)[stage][piece]))
744 min_value = v;
748 return min_value;
755 * Find (promoted) Bishop, (promoted) Rook, and Lance mobility, x-ray
756 * attacks, and pins. Let BRL be the bishop, rook, or lance. Let P be the
757 * first piece (not a king or a pawn) in a direction and let Q be the
758 * second piece in the same direction. If Q is an unprotected opponent's
759 * piece with bigger relative value than BRL, there is a pin if P is an
760 * opponent's piece and there is an x-ray attack if P belongs to this side.
761 * Increment the hung[] array if a pin is found.
764 inline int
765 BRLscan(short sq, short *mob)
767 #ifdef SAVE_NEXTPOS
768 short d, dd;
769 #else
770 unsigned char *ppos, *pdir;
771 #endif
773 short s, mobx;
774 short u, xu, pin, ptyp, csq = column(sq);
775 short piece, upiece, xupiece, rvalue, ds;
776 small_short *Kd = Kdist[c2];
778 mobx = s = 0;
779 piece = board[sq];
781 rvalue = (*value)[stage][piece];
782 ptyp = ptype[c1][upiece = unpromoted[piece]];
783 rvalue = (*value)[stage][upiece];
785 #ifdef SAVE_NEXTPOS
786 u = first_direction(ptyp, &d, sq);
787 #else
788 ppos = (*nextpos[ptyp])[sq];
789 pdir = (*nextdir[ptyp])[sq];
790 u = ppos[sq];
791 #endif
793 pin = -1; /* start new direction */
797 if (Kd[u] < 2)
799 s += (ds = fv1[CTRLK] * (2 - Kd[u]));
802 if ((ds = starget[c1][u]) != 0)
804 /* threatening a target square */
805 if ((pin < 0) /* direct threat */
806 || (color[pin] == c2)) /* pin threat */
808 s += (ds *= fv1[TARGET]);
812 if ((ds = shole[u]) != 0)
814 /* attacking or protecting a hole */
815 s += (ds = fv1[HOLES]);
817 else if (InPromotionZone(c1, u))
819 /* attacking a square in promotion zone */
820 s += (ds = fv1[HOLES] / 2);
823 if (color[u] == neutral)
825 #ifdef SAVE_NEXTPOS
826 dd = d;
827 xu = next_position(ptyp, &d, sq, u);
829 if (xu == next_direction(ptyp, &dd, sq))
830 pin = -1; /* oops new direction */
831 #else
833 if ((xu = ppos[u]) == pdir[u])
834 pin = -1; /* oops new direction */
835 #endif
836 u = xu;
837 mobx++;
839 else
841 /* there is a piece in current direction */
842 if (pin < 0)
844 /* it's the first piece in the current direction */
845 if (color[u] == c1)
847 /* own intercepting piece in x-ray attack */
848 if (upiece == lance)
850 /* lance x-ray */
851 if (board[u] == pawn)
853 s += (ds = 2*fv1[PROTECT]);
855 else if (in_opening_stage)
857 s += (ds = -2*fv1[PROTECT]);
860 else
862 /* bishop or rook x-ray */
863 if ((upiece == bishop) && (board[u] == pawn)
864 && (GameType[c1] == STATIC_ROOK))
866 s += (ds = -2*fv1[HCLSD]);
868 else if ((upiece == rook) && (board[u] == lance)
869 && (GameType[c1] == STATIC_ROOK)
870 && (column(u) == csq))
872 s += (ds = fv1[XRAY]);
876 else
878 /* enemy's intercepting piece in pin attack */
879 if (upiece == lance)
881 /* lance pin attack */
882 if (board[u] == pawn)
884 s += (ds = -2*fv1[PROTECT]);
886 else if (in_opening_stage)
888 s += (ds = 2 * fv1[PROTECT]);
891 else
893 /* bishop or rook pin attack */
894 if (board[u] == pawn)
896 s += (ds = -fv1[HCLSD]);
901 #ifdef SAVE_NEXTPOS
902 dd = d;
903 xu = next_position(ptyp, &d, sq, u);
905 if (xu != next_direction(ptyp, &dd, sq))
906 pin = u; /* not on the edge and on to find a pin */
907 #else
908 if ((xu = ppos[u]) != pdir[u])
909 pin = u; /* not on the edge and on to find a pin */
910 #endif
911 u = xu;
913 else
915 /* it's the second piece in the current direction */
917 if (color[u] == c1)
919 /* second piece is an own piece */
920 if ((upiece == bishop) && (board[u] == pawn)
921 && (GameType[c1] == STATIC_ROOK))
923 s += (ds = -fv1[HCLSD]);
926 else
928 /* second piece is an enemy piece */
929 if (upiece == bishop && board[u] == pawn)
931 s += (ds = -fv1[HCLSD]/2);
934 if (((*value)[stage][xupiece = unpromoted[board[u]]]
935 > rvalue)
936 || (atk2[u] == 0))
938 if (color[pin] == c2)
940 if ((xupiece == king) && (in_endgame_stage))
942 s += (ds = 2 * fv1[PINVAL]);
944 else
946 s += (ds = fv1[PINVAL]);
949 if ((atk2[pin] == 0)
950 || (atk1[pin] > control[board[pin]] + 1))
952 hung[c2]++;
953 shung[u]++;
956 else
958 if (upiece == lance)
960 s += (ds = fv1[XRAY] / 2);
962 else
964 s += (ds = fv1[XRAY]);
970 pin = -1; /* new direction */
972 #ifdef SAVE_NEXTPOS
973 u = next_direction(ptyp, &d, sq);
974 #else
975 u = pdir[u];
976 #endif
980 while (u != sq);
982 *mob = mobx;
984 return s;
988 #define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp)
993 * Assign penalties if king can be threatened by checks, if squares near
994 * the king are controlled by the enemy (especially by promoted pieces), or
995 * if there are no own generals near the king.
997 * The following must be true:
998 * board[sq] == king, c1 == color[sq], c2 == otherside[c1]
1001 #define SCORETHREAT \
1003 if (color[u] != c2) \
1005 if ((atk1[u] == 0) || ((atk2[u] & CNT_MASK) > 1)) \
1007 ++cnt; \
1009 else \
1011 s += (ds = -fv1[CTRLK]); \
1019 inline short
1020 KingScan(short sq)
1022 short cnt;
1024 #ifdef SAVE_NEXTPOS
1025 short d;
1026 #else
1027 unsigned char *ppos, *pdir;
1028 #endif
1030 short s;
1031 short u, ptyp;
1032 short ok, ds;
1034 /* Penalties, if a king can be threatened by checks. */
1036 s = 0;
1037 cnt = 0;
1040 short p;
1042 for (p = pawn; p < king; p++)
1044 if (HasPiece[c2][p] || Captured[c2][p])
1046 short ptyp;
1048 /* if a c1 piece can reach u from sq,
1049 * then a c2 piece can reach sq from u.
1050 * That means, each u is a square, from which a
1051 * piece of type p and color c2 threats square sq.
1053 ptyp = ptype[c1][p];
1055 #ifdef SAVE_NEXTPOS
1056 u = first_direction(ptyp, &d, sq);
1057 #else
1058 ppos = (*nextpos[ptyp])[sq];
1059 pdir = (*nextdir[ptyp])[sq];
1060 u = ppos[sq];
1061 #endif
1065 /* If a p piece can reach (controls or can drop to)
1066 * square u, then score threat.
1069 if (atk2[u] & control[p])
1070 SCORETHREAT
1071 else if ((Captured[c2][p] && color[u]) == neutral)
1072 SCORETHREAT
1074 #ifdef SAVE_NEXTPOS
1075 u = ((color[u] == neutral)
1076 ? next_position(ptyp, &d, sq, u)
1077 : next_direction(ptyp, &d, sq));
1078 #else
1079 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1080 #endif
1082 while (u != sq);
1087 s += (ds = fv1[KSFTY] * KTHRT[cnt] / 16);
1089 /* Penalties, if squares near king are controlled by enemy. */
1091 cnt = 0;
1092 ok = false;
1093 ptyp = ptype[c1][king];
1095 #ifdef SAVE_NEXTPOS
1096 u = first_direction(ptyp, &d, sq);
1097 #else
1098 pdir = (*nextpos[ptyp])[sq];
1099 u = pdir[sq];
1100 #endif
1104 if (!ok && color[u] == c1)
1106 short ptype_piece = ptype[black][board[u]];
1108 if ((ptype_piece == ptype_silver) || (ptype_piece == ptype_gold))
1109 ok = true;
1112 if (atk2[u] > atk1[u])
1114 ++cnt;
1116 if (atk2[u] & ctlSG)
1118 s += (ds = -fv1[KSFTY] / 2);
1122 #ifdef SAVE_NEXTPOS
1123 u = next_direction(ptyp, &d, sq);
1124 #else
1125 u = pdir[u];
1126 #endif
1128 while (u != sq);
1130 if (!ok || (cnt > 1))
1132 if (cnt > 1)
1133 s += (ds = -fv1[KSFTY]/2);
1134 else
1135 s += (ds = -fv1[KSFTY]);
1138 return s;
1142 static short checked_trapped;
1146 * See if the attacked piece has unattacked squares to move to. The following
1147 * must be true: c1 == color[sq] c2 == otherside[c1]
1150 inline int
1151 trapped(short sq)
1153 short u, ptyp;
1154 #ifdef SAVE_NEXTPOS
1155 short d;
1156 #else
1157 unsigned char *ppos, *pdir;
1158 #endif
1159 short piece;
1160 short rvalue;
1162 piece = board[sq];
1163 rvalue = (*value)[stage][piece];
1164 ptyp = ptype[c1][piece];
1166 #ifdef SAVE_NEXTPOS
1167 u = first_direction(ptyp, &d, sq);
1168 #else
1169 ppos = (*nextpos[ptyp])[sq];
1170 pdir = (*nextdir[ptyp])[sq];
1171 u = ppos[sq];
1172 #endif
1176 if (color[u] != c1)
1178 if ((atk2[u] == 0) || ((*value)[stage][board[u]] >= rvalue))
1179 return false;
1182 #ifdef SAVE_NEXTPOS
1183 u = ((color[u] == neutral)
1184 ? next_position(ptyp, &d, sq, u)
1185 : next_direction(ptyp, &d, sq));
1186 #else
1187 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1188 #endif
1190 while (u != sq);
1192 checked_trapped = true;
1194 return true;
1199 static int
1200 AttackedPieceValue(short sq, short side)
1202 short s, ds;
1204 s = 0;
1206 ds = -fv1[HUNGP] * 2;
1207 hung[c1]++;
1208 shung[sq]++;
1210 if (trapped(sq))
1212 hung[c1] += 2;
1213 shung[sq] += 2;
1216 return s;
1221 static inline int
1222 OpenFileValue(short sq, short hopn, short hopnx)
1224 short s = 0, fyle;
1226 if (PC1[fyle = column(sq)] == 0)
1228 s += hopn;
1231 if (PC2[fyle] == 0)
1233 s += hopnx;
1236 return s;
1242 /* Distance bonus */
1244 #define PromotionZoneDistanceValue(sq, dd) \
1245 if ((ds = fv1[PROMD])) \
1247 s += (ds = ds * PromotionZoneDistanceBonus[crow(c1, sq)] * dd); \
1250 #define OwnKingDistanceValue(sq, dd, maxd) \
1251 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd)) \
1253 s += (ds = ds * OwnKingDistanceBonus[ad] * dd); \
1256 #define EnemyKingDistanceValue(sq, dd, maxd) \
1257 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd)) \
1259 s += (ds = ds * EnemyKingDistanceBonus[ad] * dd); \
1267 * Calculate the positional value for a pawn on 'sq'.
1270 static inline int
1271 PawnValue(short sq, short side)
1273 short s = 0;
1274 short ds;
1275 short ccol = ccolumn(c1, sq);
1277 PromotionZoneDistanceValue(sq, 3);
1279 /* pawn mobility */
1280 if (color[(c1 == black) ? (sq + 9) : (sq - 9)] == neutral)
1282 s += (ds = MBLTY[pawn]);
1285 if ((a1 & ((ctlR | ctlRp) | ctlL)))
1287 s += (ds = fv1[ATTACKED]);
1290 if (in_opening_stage)
1292 if (crow(c1, sq) == 2) /* pawn on 3d rank */
1294 if (board[(c1 == black) ? (sq + 27) : (sq - 27)] == pawn)
1296 /* opposing pawn has been moved (even column == (sq & 1)) */
1298 short m;
1300 switch (ccol)
1302 case 0:
1303 case 8:
1304 m = (side == c1) ? 3 : 5;
1305 break;
1307 case 4:
1308 m = (side == c1) ? 2 : 3;
1309 break;
1311 default:
1312 m = (side == c1) ? 1 : 2;
1313 break;
1316 s += (ds = -m * MBLTY[pawn]);
1320 if ((GameType[c1] == STATIC_ROOK) && (sq == csquare(c1, 43)))
1322 if ((atk2[csquare(c1, 52)] & CNT_MASK) < 2)
1324 s += (ds = fv1[ATTACKED]);
1328 if ((GameType[c2] == STATIC_ROOK) && (ccol == 1))
1330 if (sq == csquare(c1, 28))
1332 s += (ds = -fv1[ATTACKED]);
1335 if (((atk1[csquare(c1, 19)] & CNT_MASK) < 2)
1336 && ((atk1[csquare(c1, 28)] & CNT_MASK) < 2))
1338 s += (ds = -2 * fv1[ATTACKED]);
1343 return s;
1349 * Calculate the positional value for a lance on 'sq'.
1352 static inline int
1353 LanceValue(short sq, short side)
1355 short s = 0, ds, ad;
1357 OwnKingDistanceValue(sq, 1, 2);
1359 OpenFileValue(sq, -fv1[HOPN], fv1[HOPN]);
1361 if (!checked_trapped && (crow(c1, sq) > 2))
1363 if (in_opening_stage || trapped(sq))
1365 s += (ds = -3 * fv1[ATTACKED]);
1367 else
1369 s += (ds = -2 * fv1[ATTACKED]);
1373 return s;
1379 * Calculate the positional value for a knight on 'sq'.
1382 static inline int
1383 KnightValue(short sq, short side)
1385 short s = 0, ad;
1386 short ds, checked_trapped = false;
1387 short c = column(sq);
1389 PromotionZoneDistanceValue(sq, 1);
1390 OwnKingDistanceValue(sq, 1, 2);
1392 if (!checked_trapped && (crow(c1, sq) > 2))
1394 if (trapped(sq))
1396 s += (ds = -4 * fv1[ATTACKED]);
1398 else
1400 s += (ds = -3 * fv1[ATTACKED]);
1404 if ((c == 0) || (c == 8))
1406 s += (ds = -fv1[ATTACKED]);
1409 return s;
1415 * Calculate the positional value for a silver on 'sq'.
1418 static inline int
1419 SilverValue(short sq, short side)
1421 short s= 0, ds, ad;
1423 OwnKingDistanceValue(sq, 2, 3);
1425 if ((Kdist[c1][sq] < 3)
1426 && (atk1[sq] & (control[gold] | control[silver])))
1428 s += (ds = fv1[COHESION]);
1431 if (in_opening_stage)
1433 if (GameType[c1] == STATIC_ROOK)
1435 if (csquare(c1, sq) == 12)
1437 short csq;
1439 if ((board[csq = csquare(c1, 20)] == bishop)
1440 && (color[csq] == c1))
1442 s += (ds = -2 * fv1[OPENWRONG]);
1447 else
1449 EnemyKingDistanceValue(sq, 2, 3);
1452 return s;
1458 * Calculate the positional value for a gold on 'sq'.
1461 static inline int
1462 GoldValue(short sq, short side)
1464 short s = 0, ds, ad;
1466 OwnKingDistanceValue(sq, 2, 3);
1468 if ((Kdist[c1][sq] < 3)
1469 && (atk1[sq] & (control[gold] | control[silver])))
1471 s += (ds = fv1[COHESION]);
1474 if (in_opening_stage)
1476 if ((GameType[c1] == STATIC_ROOK) && (GameType[c2] != STATIC_ROOK))
1478 if (Mvboard[csquare(c1, 3)])
1480 s += (ds = -2 * fv1[OPENWRONG]);
1484 else
1486 EnemyKingDistanceValue(sq, 2, 3);
1489 return s;
1495 * Calculate the positional value for a bishop on 'sq'.
1498 static inline int
1499 BishopValue(short sq, short side)
1501 short s = 0, ds, ad;
1503 if (in_opening_stage)
1505 if (GameType[c1] == RANGING_ROOK)
1507 /* Bishops diagonal should not be open */
1508 if (!on_csquare(c1, pawn, 30))
1510 s += (ds = -fv1[OPENWRONG]);
1513 else if (GameType[c2] == RANGING_ROOK)
1515 /* Bishops diagonal should be open */
1516 if ((csquare(c1, sq) == 10)
1517 && (!empty_csquare(c1, 20) || !empty_csquare(c1, 30)))
1519 s += (ds = -fv1[OPENWRONG]);
1521 else if ((csquare(c1, sq) == 20) && !empty_csquare(c1, 30))
1523 s += (ds = -fv1[OPENWRONG]);
1527 else
1529 EnemyKingDistanceValue(sq, 1, 3);
1532 return s;
1538 * Calculate the positional value for a rook on 'sq'.
1541 static inline int
1542 RookValue(short sq, short side)
1544 short s = 0, ds, ad;
1546 OpenFileValue(sq, 2 * fv1[HOPN], 4*fv1[HOPN]);
1548 if (in_opening_stage)
1550 short WRONG = fv1[OPENWRONG], OPOK = WRONG / 3;
1552 if (GameType[c1] == STATIC_ROOK)
1554 short c = ccolumn(c1, sq);
1556 /* Bonus for rook on 8th file */
1557 if (c == 7)
1559 s += (ds = OPOK);
1563 * Bonus for rook on right side,
1564 * penalty for rook on left side
1567 c = 4 - c;
1568 ds = 0;
1570 if (c < 0)
1572 s += (ds = c + c + OPOK);
1574 else if (c >= 0)
1576 s += (ds = -c - c - WRONG);
1579 else if (GameType[c1] == RANGING_ROOK)
1581 /* Bonus for rook on left side and
1582 * bishops diagonal closed, penalty otherwise. */
1584 short c;
1585 c = 4 - ccolumn(c1, sq);
1586 ds = 0;
1588 if (c >= 0)
1590 /* Bishops diagonal should not be open. */
1591 if (on_csquare(c1, pawn, 30))
1592 s += (ds = OPOK);
1593 else
1594 s += (ds = -c - c - WRONG);
1596 else if (c < 0)
1598 s += (ds = -c - c - WRONG);
1600 /* Penalty for king not on initial square. */
1601 if (!on_csquare(side, king, 4))
1603 s += -4 * WRONG;
1604 ds += -4 * WRONG;
1609 else
1611 EnemyKingDistanceValue(sq, 1, 3);
1614 return s;
1620 * Calculate the positional value for a promoted pawn on 'sq'.
1623 static inline int
1624 PPawnValue(short sq, short side)
1626 short s = 0, ds, ad;
1628 EnemyKingDistanceValue(sq, 3, 10);
1630 return s;
1636 * Calculate the positional value for a promoted lance on 'sq'.
1639 static inline int
1640 PLanceValue(short sq, short side)
1642 short s = 0, ds, ad;
1644 EnemyKingDistanceValue(sq, 3, 10);
1646 return s;
1652 * Calculate the positional value for a promoted knight on 'sq'.
1655 static inline int
1656 PKnightValue(short sq, short side)
1658 short s = 0, ds, ad;
1660 EnemyKingDistanceValue(sq, 3, 10);
1662 return s;
1668 * Calculate the positional value for a promoted silver on 'sq'.
1671 static inline int
1672 PSilverValue(short sq, short side)
1674 short s = 0, ds, ad;
1676 EnemyKingDistanceValue(sq, 3, 10);
1678 return s;
1684 * Calculate the positional value for a promoted bishop on 'sq'.
1687 static inline int
1688 PBishopValue(short sq, short side)
1690 short s = 0, ds, ad;
1692 EnemyKingDistanceValue(sq, 3, 4);
1694 return s;
1700 * Calculate the positional value for a promoted rook on 'sq'.
1703 static inline int
1704 PRookValue(short sq, short side)
1706 short s = 0, ds, ad;
1708 EnemyKingDistanceValue(sq, 3, 4);
1710 OpenFileValue(sq, 3 * fv1[HOPN], 2 * fv1[HOPN]);
1712 return s;
1718 * Calculate the positional value for a king on 'sq'.
1721 static inline int
1722 KingValue(short sq, short side)
1724 short s = 0, ds;
1726 if (fv1[KSFTY] != 0)
1727 s += KingScan(sq);
1729 if (in_opening_stage)
1731 if ((GameType[c1] != UNKNOWN) && (ccolumn(c1, sq) == 4))
1733 s += (ds = -fv1[OPENWRONG] / 3);
1735 else if ((GameType[c1] == STATIC_ROOK) && on_right_side(c1, sq))
1737 s += (ds = -fv1[OPENWRONG] / 2);
1739 else if ((GameType[c1] == RANGING_ROOK) && on_left_side(c1, sq))
1741 s += (ds = -fv1[OPENWRONG] / 2);
1745 /* CHECKME: is this correct? */
1746 if ((ds = fv1[HOPN]))
1748 s += OpenFileValue(sq, -2 * ds, -4 * ds);
1751 return s;
1757 * Calculate the positional value for a piece on 'sq'.
1760 static inline int
1761 PieceValue(short sq, short side)
1763 short s, piece, ds;
1764 short mob;
1766 piece = board[sq];
1768 if (piece == no_piece)
1769 return 0;
1771 s = (*Mpiece[piece])[c1][sq];
1773 checked_trapped = false;
1775 if (sweep[piece])
1777 /* pin/x-ray attack and mobility for sweeping pieces */
1778 s += (ds = BRLscan(sq, &mob));
1780 if ((piece == bishop) || (piece == pbishop))
1781 s += (ds = BMBLTY[mob] * fv1[MOBILITY] / 100);
1782 else if ((piece == rook) || (piece == prook))
1783 s += (ds = RMBLTY[mob] * fv1[MOBILITY] / 100);
1784 else
1785 s += (ds = LMBLTY[mob] * fv1[MOBILITY] / 100);
1787 else
1789 /* mobility for non-sweeping pieces */
1792 a2 = atk2[sq];
1793 a1 = atk1[sq];
1795 if (a2 > 0)
1797 /* opponent attacks piece */
1798 if (a1 == 0)
1800 /* undefended piece */
1801 s += AttackedPieceValue(sq, side);
1803 else
1805 /* defended piece */
1806 short attack_value = value_of_weakest_attacker(a2);
1807 short piece_value = (*value)[stage][piece];
1809 if (attack_value < piece_value)
1811 /* attacked by a weaker piece */
1812 s += AttackedPieceValue(sq, side) / 2;
1814 else if (abs(attack_value - piece_value) < 10)
1816 /* opponent has the option to exchange equal pieces */
1817 s += (ds = -fv1[ATTACKED]);
1822 if (piece != king)
1825 if (a1 > 0)
1827 /* piece is defended */
1828 s += (ds = (a1 & CNT_MASK) * fv1[PROTECT]);
1831 if (sseed[sq])
1833 s += (ds = fv1[SEED]);
1836 if (sloose[sq])
1838 s += (ds = -fv1[LOOSE]);
1841 if (starget[c1][sq])
1843 if (sweep[piece])
1845 s -= (ds = -fv1[ATTACKED]/2);
1847 else if (piece == pawn)
1849 s += (ds = fv1[ATTACKED]);
1853 if (starget[c2][sq])
1855 if (piece != pawn)
1857 s -= (ds = -fv1[ATTACKED] / 3);
1859 else
1861 s += (ds = fv1[ATTACKED]);
1865 if (Kdist[c1][sq] == 1)
1867 s += (ds = fv1[KSFTY]);
1871 switch (piece)
1873 case pawn:
1874 s += PawnValue(sq, side);
1875 break;
1877 case lance:
1878 s += LanceValue(sq, side);
1879 break;
1881 case knight:
1882 s += KnightValue(sq, side);
1883 break;
1885 case silver:
1886 s += SilverValue(sq, side);
1887 break;
1889 case gold:
1890 s += GoldValue(sq, side);
1891 break;
1893 case bishop:
1894 s += BishopValue(sq, side);
1895 break;
1897 case rook:
1898 s += RookValue(sq, side);
1899 break;
1901 case king:
1902 s += KingValue(sq, side);
1903 break;
1905 case ppawn:
1906 s += PPawnValue(sq, side);
1907 break;
1909 case plance:
1910 s += PLanceValue(sq, side);
1911 break;
1913 case pknight:
1914 s += PKnightValue(sq, side);
1915 break;
1917 case psilver:
1918 s += PSilverValue(sq, side);
1919 break;
1921 case pbishop:
1922 s += PBishopValue(sq, side);
1923 break;
1925 case prook:
1926 s += PRookValue(sq, side);
1927 break;
1930 return s;
1936 * Score distance to pattern regarding the game type which side plays.
1939 short
1940 ScorePatternDistance(short c1)
1942 short ds, s = 0;
1943 small_short *fv1 = fvalue[c1];
1944 short os = 0;
1946 if ((MAXCDIST > 0) && (fv1[PCASTLE] != 0)
1947 && ((os = castle_opening_sequence[c1]) >= 0))
1949 ds = board_to_pattern_distance(c1, os, MAXCDIST, GameCnt);
1951 if (ds != 0)
1953 s += (ds *= fv1[PCASTLE]);
1957 if ((MAXADIST > 0) && (fv1[PATTACK] != 0)
1958 && ((os = attack_opening_sequence[c1]) >= 0))
1960 ds = board_to_pattern_distance(c1, os, MAXADIST, GameCnt);
1962 if (ds != 0)
1964 s += (ds *= fv1[PATTACK]);
1968 return s;
1975 * Determine castle and attack pattern which should be reached next.
1976 * Only patterns are considered, which have not been reached yet.
1979 static void
1980 UpdatePatterns(short side, short GameCnt)
1982 char s[12];
1983 short xside = side ^ 1;
1984 short os;
1985 short j, k, n = 0;
1987 strcpy(s, "CASTLE_?_?");
1988 s[7] = GameType[side];
1989 s[9] = GameType[xside];
1990 castle_opening_sequence[side] = os
1991 = locate_opening_sequence(side, s, GameCnt);
1993 if (flag.post && (os != END_OF_SEQUENCES))
1995 for (j = 0; j < MAX_SEQUENCE; j++)
1997 for (k = OpeningSequence[os].first_pattern[j];
1998 k != END_OF_PATTERNS;
1999 k = Pattern[k].next_pattern)
2001 if (Pattern[k].distance[side] >= 0)
2002 n++;
2007 if (os != END_OF_SEQUENCES)
2008 update_advance_bonus(side, os);
2010 strcpy(s, "ATTACK_?_?");
2011 s[7] = GameType[side];
2012 s[9] = GameType[xside];
2013 attack_opening_sequence[side] = os
2014 = locate_opening_sequence(side, s, GameCnt);
2016 if (flag.post && (os != END_OF_SEQUENCES))
2018 for (j = 0; j < MAX_SEQUENCE; j++)
2020 for (k = OpeningSequence[os].first_pattern[j];
2021 k != END_OF_PATTERNS;
2022 k = Pattern[k].next_pattern)
2024 if (Pattern[k].distance[side] >= 0)
2025 n++;
2030 if (flag.post)
2031 ShowPatternCount(side, n);
2033 if (os != END_OF_SEQUENCES)
2034 update_advance_bonus(side, os);
2039 static void
2040 ScoreCaptures(void)
2042 short ds, col, n, m, piece;
2044 if ((n = Captured[c1][pawn]))
2046 ds = m = 0;
2048 for (col = 0; col < NO_COLS; col++)
2050 if (!PC1[col])
2052 m++;
2053 ds += fv1[PWNDROP];
2057 /* FIXME! another great obfuscated line... */
2058 pscore[c1] += (ds *= ((n > 2) ? 3 : n));
2061 if ((m = seed[c1]))
2063 for (piece = lance, n = 0; piece <= rook; piece++)
2065 if (Captured[c1][piece])
2066 n++;
2069 pscore[c1] += (ds = m * fv1[DFFDROP]);
2072 for (piece = pawn, n = 0; piece <= rook; piece++)
2074 if (Captured[c1][piece])
2076 switch (piece)
2078 case bishop:
2079 ds = BMBLTY[MAX_BMBLTY - 1];
2080 break;
2082 case rook:
2083 ds = RMBLTY[MAX_RMBLTY - 1];
2084 break;
2086 case lance:
2087 ds = LMBLTY[MAX_LMBLTY - 1];
2088 break;
2090 default:
2091 ds = MBLTY[piece];
2094 pscore[c1] += ds;
2096 if (!Captured[c2][piece])
2097 n += relative_value[piece];
2101 if (n)
2103 pscore[c1] += (ds = -n * fv1[OPPDROP] / 2);
2112 * Perform normal static evaluation of board position. A score is generated
2113 * for each piece and these are summed to get a score for each side.
2116 short
2117 ScorePosition(short side)
2119 short score;
2120 short sq, i, xside;
2121 short s;
2122 short ds;
2124 xside = side ^ 1;
2126 UpdateWeights(side);
2128 hung[black] = hung[white] = pscore[black] = pscore[white] = 0;
2130 array_zero(shung, sizeof(shung));
2132 #ifdef CACHE
2133 if (!(use_etable && ProbeEETable(side, &s)))
2135 #endif
2136 for (c1 = black; c1 <= white; c1++)
2138 c2 = c1 ^ 1;
2140 /* atk1 is array of attacks on squares by my side */
2141 atk1 = attack[c1];
2143 /* atk2 is array of attacks on squares by other side */
2144 atk2 = attack[c2];
2146 /* same for PC1 and PC2 */
2147 PC1 = PawnCnt[c1];
2148 PC2 = PawnCnt[c2];
2150 /* same for fv1 and fv2 */
2151 fv1 = fvalue[c1];
2153 for (i = PieceCnt[c1]; i >= 0; i--)
2155 sq = PieceList[c1][i];
2157 #if defined SAVE_SVALUE
2158 pscore[c1] += PieceValue(sq, side);
2159 #else
2160 pscore[c1] += (svalue[sq] = PieceValue(sq, side));
2161 #endif
2164 ScoreCaptures();
2167 for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2169 short n;
2171 fv1 = fvalue[c1];
2173 /* Score fifth rank */
2174 for (sq = 36, n = 0; sq <= 44; sq++)
2176 if ((color[sq] == c1) || (attack[c1][sq] != 0))
2177 n++;
2180 if (n != 0)
2182 pscore[c1] += (ds = n * fv1[CNTRL5TH]);
2185 /* Score holes */
2186 for (sq = ((c1 == black) ? 0 : 54), n = 0;
2187 sq <= ((c1 == black) ? 26 : 80);
2188 sq++)
2190 if (board[sq] == no_piece && attack[c1][sq] == 0)
2191 n++;
2194 if (n != 0)
2196 pscore[c1] += (ds = -n * fv1[HOLES]);
2199 if (hung[c1] > 1)
2201 pscore[c1] += (ds = -fv1[HUNGX]);
2204 /* Score opening features and
2205 * castle/attack pattern distances */
2207 if (in_opening_stage)
2209 pscore[c1] += (ds = ScoreKingOpeningFeatures());
2210 pscore[c1] += (ds = ScorePatternDistance(c1));
2214 score = mtl[side] - mtl[xside]
2215 + pscore[side] - pscore[xside] + 10;
2217 #ifdef CACHE
2218 if (use_etable && PUTVAR)
2219 PutInEETable(side, score);
2220 #endif
2222 return score;
2223 #ifdef CACHE /* CHECKME: this looks bad */
2226 return s;
2227 #endif
2233 * Try to determine the game type of "side".
2236 inline static void
2237 GuessGameType(short side_to_move)
2239 short side, gt;
2240 short StaticRook[2] = { 0, 0 };
2241 short RangingRook[2] = { 0, 0 };
2243 for (side = black; side <= white; side++)
2245 /* computer should not change its mind */
2247 extern int bookflag;
2249 gt = GameType[side];
2251 if (!bookflag && (side == side_to_move))
2253 if (gt == STATIC_ROOK)
2254 StaticRook[side] += 4;
2255 else if (gt == RANGING_ROOK)
2256 RangingRook[side] += 4;
2259 /* static rook conditions */
2261 if (on_column(side, rook, 7))
2262 StaticRook[side] += 3;
2264 if (on_csquare(side, pawn, 34))
2265 StaticRook[side] += 6;
2266 else if (on_csquare(side, pawn, 43))
2267 StaticRook[side] += 4;
2268 else if (!on_column(side, pawn, 7))
2269 StaticRook[side] += 5;
2271 if (empty_csquare(side, 5) || empty_csquare(side, 6))
2272 StaticRook[side] += 2;
2274 if (on_left_side(side, king))
2275 StaticRook[side] += 2;
2277 /* ranging rook conditions */
2279 if (on_left_side(side, rook))
2280 RangingRook[side] += 5;
2281 else if (!on_column(side, rook, 7))
2282 RangingRook[side] += 3;
2284 if (on_csquare(side, pawn, 25))
2285 RangingRook[side] += 1;
2287 if (on_csquare(side, pawn, 30))
2288 RangingRook[side] += 1;
2289 else
2290 RangingRook[side] -= 2;
2292 if (!on_right_side(side, rook))
2293 RangingRook[side] += 4;
2295 if (on_right_side(side, king))
2296 RangingRook[side] += 4;
2298 if (on_csquare(side, bishop, 20))
2300 if (on_csquare(side, silver, 11)
2301 || on_csquare(side, silver, 12)
2302 || on_csquare(side, silver, 21))
2304 RangingRook[side] += 3;
2308 if ((StaticRook[side] > 5) || (RangingRook[side] > 5))
2310 GameType[side] = (StaticRook[side] > RangingRook[side])
2311 ? STATIC_ROOK : RANGING_ROOK;
2313 else
2315 GameType[side] = UNKNOWN;
2319 if ((GameType[black] == UNKNOWN) || (GameType[white] == UNKNOWN))
2321 for (side = black; side <= white; side++)
2323 if ((side == computer) && (GameType[side] == UNKNOWN))
2326 * Game type is UNKNOWN.
2327 * Make a decision what type of game to play.
2328 * To make computer games more interesting, make a
2329 * random decision.
2332 if (!on_csquare(side, pawn, 25))
2334 /* Play static rook if rook pawn has been pushed! */
2335 GameType[side] = STATIC_ROOK;
2337 else
2339 unsigned int random = urand() % 100;
2340 short d = StaticRook[side] - RangingRook[side];
2342 switch (GameType[side ^ 1])
2344 case STATIC_ROOK:
2345 if (random < 35 + d)
2346 GameType[side] = STATIC_ROOK;
2347 else if (random < 95)
2348 GameType[side] = RANGING_ROOK;
2349 break;
2351 case RANGING_ROOK:
2352 if (random < 75 + d)
2353 GameType[side] = STATIC_ROOK;
2354 else if (random < 95)
2355 GameType[side] = RANGING_ROOK;
2356 break;
2358 default:
2359 if (random < 33 + d)
2360 GameType[side] = STATIC_ROOK;
2361 else if (random < 66)
2362 GameType[side] = RANGING_ROOK;
2373 static void
2374 DetermineGameType(short side_to_move)
2376 short side;
2378 GuessGameType(side_to_move);
2380 array_zero(Mpawn, sizeof(Mpawn));
2381 array_zero(Mlance, sizeof(Mlance));
2382 array_zero(Mknight, sizeof(Mknight));
2383 array_zero(Msilver, sizeof(Msilver));
2384 array_zero(Mgold, sizeof(Mgold));
2385 array_zero(Mbishop, sizeof(Mbishop));
2386 array_zero(Mrook, sizeof(Mrook));
2387 array_zero(Mking, sizeof(Mking));
2389 if (in_opening_stage)
2391 for (side = black; side <= white; side++)
2392 UpdatePatterns(side, GameCnt);
2394 else
2396 ShowPatternCount(black, -1);
2397 ShowPatternCount(white, -1);
2404 * This is done one time before the search is started. Set up arrays
2405 * Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue()
2406 * function to determine the positional value of each piece.
2409 void
2410 ExaminePosition(short side)
2412 short c1, piece, sq, i, bsq, wsq;
2414 /* Build enemy king distance tables. */
2416 for (sq = 0, bsq = BlackKing, wsq = WhiteKing; sq < NO_SQUARES; sq++)
2418 Kdist[black][sq] = distance(sq, bsq);
2419 Kdist[white][sq] = distance(sq, wsq);
2422 threats(black);
2423 threats(white);
2425 ExamineSquares();
2427 DetermineGameType(side);
2428 DetermineStage(side);
2430 UpdateWeights(side);
2432 array_zero(HasPiece, sizeof(HasPiece));
2434 for (c1 = black; c1 <= white; c1++)
2436 for (i = PieceCnt[c1]; i >= 0; i--)
2438 ++HasPiece[c1][piece = board[sq = PieceList[c1][i]]];
2445 void
2446 DetermineStage(short side)
2448 short xside = side ^ 1, ds, db1, c1, c2, feature;
2450 /* Determine initial stage */
2452 balance[side] = balance[xside] = 50;
2454 if ((GameType[side] == STATIC_ROOK)
2455 && (GameType[xside] == STATIC_ROOK))
2457 if (GameCnt < 40)
2458 stage = 0;
2459 else if (GameCnt < 60)
2460 stage = 15;
2461 else if (GameCnt < 80)
2462 stage = 25;
2463 else
2464 stage = 30;
2466 else if ((GameType[side] == RANGING_ROOK)
2467 || (GameType[xside] == RANGING_ROOK))
2469 if (GameCnt < 30)
2470 stage = 0;
2471 else if (GameCnt < 50)
2472 stage = 15;
2473 else if (GameCnt < 70)
2474 stage = 25;
2475 else
2476 stage = 30;
2478 else
2480 if (GameCnt < 35)
2481 stage = 0;
2482 else if (GameCnt < 55)
2483 stage = 15;
2484 else if (GameCnt < 75)
2485 stage = 25;
2486 else
2487 stage = 30;
2490 /* Update stage depending on board features and attack balance value */
2492 if (abs(ds = (mtl[side] - mtl[xside]))
2493 > (db1 = (*value)[stage][lance]))
2495 db1 = abs(4 * ds / db1);
2497 if (ds < 0)
2498 balance[side] += db1;
2499 else if (ds > 0)
2500 balance[xside] += db1;
2502 stage += (ds = db1);
2505 for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2507 if ((ds = seed[c1]) > 2)
2509 balance[c1] += (db1 = ds * 2);
2510 balance[c2] -= db1;
2512 if (stage < 30)
2513 stage = 30;
2515 stage += ds;
2518 if ((db1 = hung[c1]) > 2)
2520 balance[c1] -= (db1 *= 2);
2521 balance[c2] += db1;
2524 if ((db1 = loose[c1]) > 4)
2526 balance[c1] -= (db1 /= 2);
2527 balance[c2] += db1;
2528 stage += (ds = 1);
2531 if ((ds = hole[c1]))
2533 balance[c1] -= (db1 = ds);
2534 balance[c2] += db1;
2535 stage += (ds /= 2);
2538 if ((db1 = target[c1]) > 3)
2540 balance[c1] += (db1 /= 3);
2541 balance[c2] -= db1;
2542 stage += (ds = db1 / 4);
2545 stage += (ds = captured[c1] / 2);
2547 if ((db1 = captured[c1]) > 4)
2549 balance[c1] += (db1 /= 2);
2550 stage += (ds = 3);
2553 if ((db1 = dcaptured[c1]) > 3)
2555 balance[c1] += db1;
2556 stage += (ds = 3);
2559 if (balance[c1] > 99)
2560 balance[c1] = 99;
2561 else if (balance[c1] < 0)
2562 balance[c1] = 0;
2565 if (stage > 99)
2566 stage = 99;
2567 else if (stage < 0)
2568 stage = 0;
2570 if (flag.post)
2571 ShowStage();
2573 /* Determine stage dependant weights */
2575 ADVNCM[pawn] = 1; /* advanced pawn bonus increment */
2576 ADVNCM[lance] = 1;
2577 ADVNCM[knight] = 1;
2578 ADVNCM[silver] = 1; /* advanced silver bonus increment */
2579 ADVNCM[gold] = 1; /* advanced gold bonus increment */
2580 ADVNCM[bishop] = 1;
2581 ADVNCM[rook] = 1;
2582 ADVNCM[king] = 1; /* advanced king bonus increment */
2584 MAXCDIST = (stage < 33) ? (33 - stage) / 4 : 0;
2585 MAXADIST = (stage < 30) ? (30 - stage) / 4 : 0;
2587 for (c1 = black; c1 <= white; c1++)
2589 for (feature = 0; feature < NO_FEATURES; feature++)
2591 fvalue[c1][feature] =
2592 ((((*fscore)[stage][feature][0] * (99 - balance[c1])) + 50)
2593 / 100)
2594 + ((((*fscore)[stage][feature][1] * balance[c1]) + 50)
2595 / 100);
2602 void
2603 UpdateWeights(short stage)
2610 * Compute stage dependent relative material values assuming
2611 * linearity between the main stages:
2613 * minstage < stage < maxstage =>
2614 * stage - minstage value - minvalue
2615 * ------------------- = -------------------
2616 * maxstage - minstage maxvalue - minvalue
2620 static short
2621 linear_piece_value(short piece, short stage, short i, short j)
2623 short minvalue, maxvalue, minstage, maxstage;
2625 minstage = ispvalue[0][i];
2626 maxstage = ispvalue[0][j];
2627 minvalue = ispvalue[piece][i];
2628 maxvalue = ispvalue[piece][j];
2630 /* FIXME: set a variable then return it, puh-leeze! */
2631 return ((stage - minstage) * (maxvalue - minvalue)
2632 / (maxstage - minstage)) + minvalue;
2637 static short
2638 linear_feature_value(short feature, short stage, short i, short j)
2640 short minvalue, maxvalue, minstage, maxstage;
2642 minstage = ispvalue[0][i];
2643 maxstage = ispvalue[0][j];
2644 minvalue = weight[feature][i];
2645 maxvalue = weight[feature][j];
2647 /* FIXME: set a variable then return it, puh-leeze! */
2648 return ((stage - minstage) * (maxvalue - minvalue)
2649 / (maxstage - minstage)) + minvalue;
2654 * matweight = percentage_of_max_value * max_value(stage) / 100
2655 * max_value(0) = MAX_VALUE; max_value(100) = MIN_VALUE
2656 * => max_value(stage) = a * stage + b; b = MAX_VALUE,
2657 * a = (MIN_VALUE - MAX_VALUE)/100
2660 #define MIN_VALUE 300
2661 #define MAX_VALUE 1000
2663 #define max_value(stage) \
2664 ((long)(MIN_VALUE - MAX_VALUE) * stage + (long)100 * MAX_VALUE)
2665 #define matweight(value, stage) \
2666 ((long)max_value(stage) * value / 10000)
2670 void
2671 Initialize_eval(void)
2673 short stage, piece, feature, i;
2675 for (stage = 0; stage < NO_STAGES; stage++)
2677 for (i = 0; i < MAIN_STAGES; i++)
2679 if (stage == ispvalue[0][i])
2681 for (piece = 0; piece < NO_PIECES; piece++)
2683 (*value)[stage][piece] =
2684 matweight(ispvalue[piece][i], stage);
2687 for (feature = 0; feature < NO_FEATURES; feature++)
2689 (*fscore)[stage][feature][0] =
2690 (weight[feature][i]
2691 * weight[feature][MAIN_STAGES] + 50) / 100;
2693 (*fscore)[stage][feature][1] =
2694 (weight[feature][i]
2695 * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2698 break;
2701 if (stage < ispvalue[0][i + 1])
2703 for (piece = 0; piece < NO_PIECES; piece++)
2705 (*value)[stage][piece] =
2706 matweight(
2707 linear_piece_value(piece, stage, i, i + 1),
2708 stage);
2711 for (feature = 0; feature < NO_FEATURES; feature++)
2713 (*fscore)[stage][feature][0] =
2714 (linear_feature_value(feature, stage, i, i + 1)
2715 * weight[feature][MAIN_STAGES] + 50) / 100;
2717 (*fscore)[stage][feature][1] =
2718 (linear_feature_value(feature, stage, i, i + 1)
2719 * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2722 break;