Long-dead code removal: unused macro
[gnushogi.git] / gnushogi / eval.c
blobb4f69fa2866511ecb96563690430c2047d912035
1 /*
2 * FILE: eval.c
4 * ----------------------------------------------------------------------
5 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
7 * Copyright (c) 2008, 2013, 2014 Yann Dirson and the Free Software Foundation
9 * GNU SHOGI is based on GNU CHESS
11 * Copyright (c) 1988, 1989, 1990 John Stanback
12 * Copyright (c) 1992 Free Software Foundation
14 * This file is part of GNU SHOGI.
16 * GNU Shogi is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 3 of the License,
19 * or (at your option) any later version.
21 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with GNU Shogi; see the file COPYING. If not, see
28 * <http://www.gnu.org/licenses/>.
29 * ----------------------------------------------------------------------
33 #include "gnushogi.h"
34 #include "pattern.h"
36 /* Hash table for preventing multiple scoring of the same position */
38 int EADD = 0; /* number of writes to the cache table */
39 int EGET = 0; /* number of hits to the cache table */
40 static bool PUTVAR = false; /* shall the current scoring be cached? */
43 /* Pieces and colors of initial board setup */
45 #ifndef MINISHOGI
46 const small_short Stboard[NO_SQUARES] =
48 lance, knight, silver, gold, king, gold, silver, knight, lance,
49 0, bishop, 0, 0, 0, 0, 0, rook, 0,
50 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
51 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
55 0, rook, 0, 0, 0, 0, 0, bishop, 0,
56 lance, knight, silver, gold, king, gold, silver, knight, lance
60 const small_short Stcolor[NO_SQUARES] =
62 black, black, black, black,
63 black, black, black, black, black,
64 neutral, black, neutral, neutral,
65 neutral, neutral, neutral, black, neutral,
66 black, black, black, black,
67 black, black, black, black, black,
68 neutral, neutral, neutral, neutral,
69 neutral, neutral, neutral, neutral, neutral,
70 neutral, neutral, neutral, neutral,
71 neutral, neutral, neutral, neutral, neutral,
72 neutral, neutral, neutral, neutral,
73 neutral, neutral, neutral, neutral, neutral,
74 white, white, white, white,
75 white, white, white, white, white,
76 neutral, white, neutral, neutral,
77 neutral, neutral, neutral, white, neutral,
78 white, white, white, white,
79 white, white, white, white, white
81 #else
82 const small_short Stboard[NO_SQUARES] =
84 king, gold, silver, bishop, rook,
85 pawn, 0, 0, 0, 0,
86 0, 0, 0, 0, 0,
87 0, 0, 0, 0, pawn,
88 rook, bishop, silver, gold, king,
92 const small_short Stcolor[NO_SQUARES] =
94 black, black, black, black, black,
95 black, neutral, neutral, neutral, neutral,
96 neutral, neutral, neutral, neutral, neutral,
97 neutral, neutral, neutral, neutral, white,
98 white, white, white, white, white
100 #endif
102 /* Actual pieces and colors */
104 small_short board[NO_SQUARES], color[NO_SQUARES];
107 /* relative piece values at the beginning of main stages */
109 #define MAIN_STAGES 4
111 static small_short ispvalue[NO_PIECES][MAIN_STAGES] =
113 { 0, 35, 70, 99 }, /* main stage borders */
114 /* ------------------------------------------ */
115 { 7, 7, 8, 10 }, /* Pawn */
116 #ifndef MINISHOGI
117 { 20, 35, 45, 60 }, /* Lance */
118 { 20, 35, 45, 60 }, /* Knight */
119 #endif
120 { 35, 40, 60, 80 }, /* Silver */
121 { 35, 50, 65, 80 }, /* Gold */
122 { 90, 90, 90, 90 }, /* Bishop */
123 { 95, 95, 95, 95 }, /* Rook */
124 { 15, 25, 40, 65 }, /* promoted Pawn */
125 #ifndef MINISHOGI
126 { 25, 45, 55, 65 }, /* promoted Lance */
127 { 25, 45, 55, 65 }, /* promoted Knight */
128 #endif
129 { 35, 55, 75, 75 }, /* promoted Silver */
130 { 99, 99, 99, 99 }, /* promoted Bishop */
131 { 97, 97, 99, 99 }, /* promoted Rook */
132 { 100, 100, 100, 100 }, /* King */
135 /* Features and Weights */
137 #define ATTACKED 0
138 #define HUNGP 1
139 #define HUNGX 2
140 #define CNTRL5TH 3
141 #define HOLES 4
142 #define PCASTLE 5
143 #define PATTACK 6
144 #define CTRLK 7
145 #define PROTECT 8
146 #define HCLSD 9
147 #define PINVAL 10
148 #define XRAY 11
149 #define OPENWRONG 12
150 #define SEED 13
151 #define LOOSE 14
152 #define MOBILITY 15
153 #define TARGET 16
154 #define KSFTY 17
155 #define HOPN 18
156 #define PROMD 19
157 #define KINGOD 20
158 #define PWNDROP 21
159 #define DFFDROP 22
160 #define FCLATTACK 23
161 #define KNGATTACK 24
162 #define KNGPROTECT 25
163 #define DNGLPC 26
164 #define LSATTACK 27
165 #define NIHATTACK 28
166 #define COHESION 29
167 #define OPPDROP 30
170 static small_short weight[NO_FEATURES + 1][MAIN_STAGES + 2] =
172 { 80, 100, 100, 40, 10, 15 }, /* ATTACKED */
173 { 80, 100, 100, 50, 14, 10 }, /* HUNGP */
174 { 80, 100, 100, 50, 18, 12 }, /* HUNGX */
175 { 100, 50, 0, 0, 2, 1 }, /* CNTRL5TH */
176 { 100, 100, 60, 10, 4, 2 }, /* HOLES */
177 { 100, 50, 0, 0, 14, 7 }, /* PCASTLE */
178 { 100, 50, 0, 0, 6, 12 }, /* PATTACK */
179 { 10, 40, 70, 100, 10, 15 }, /* CTRLK */
180 { 100, 80, 50, 40, 2, 1 }, /* PROTECT */
181 { 40, 100, 40, 5, 4, 4 }, /* HCLSD */
182 { 80, 100, 80, 30, 10, 15 }, /* PINVAL */
183 { 80, 100, 60, 15, 6, 10 }, /* XRAY */
184 { 100, 50, 0, 0, 15, 15 }, /* OPENWRONG */
185 { 0, 40, 70, 100, 8, 12 }, /* SEED */
186 { 50, 100, 80, 20, 5, 3 }, /* LOOSE */
187 { 50, 100, 80, 50, 100, 100 }, /* MOBILITY (%) */
188 { 50, 100, 80, 50, 4, 8 }, /* TARGET */
189 { 50, 40, 100, 80, 8, 4 }, /* KSFTY */
190 { 80, 100, 60, 20, 5, 5 }, /* HOPN */
191 { 20, 40, 80, 100, 3, 6 }, /* PROMD */
192 { 20, 40, 80, 100, 4, 1 }, /* KINGOD */
193 { 5, 40, 100, 50, 0, 4 }, /* PWNDROP */
194 { 0, 20, 80, 100, 0, 4 }, /* DFFDROP */
195 { 20, 50, 100, 80, 0, 4 }, /* FCLATTACK */
196 { 0, 20, 80, 100, 0, 8 }, /* KNGATTACK */
197 { 40, 80, 100, 80, 6, 0 }, /* KNGPROTECT */
198 { 50, 100, 60, 10, 0, 8 }, /* DNGPC */
199 { 30, 100, 60, 5, 0, 6 }, /* LSATTACK */
200 { 0, 50, 80, 100, 0, 8 }, /* NIHATTACK */
201 { 50, 100, 80, 60, 8, 0 }, /* COHESION */
202 { 100, 100, 80, 60, 4, 4 }, /* OPPDROP */
206 short ADVNCM[NO_PIECES];
208 /* distance to enemy king */
209 static const short EnemyKingDistanceBonus[10] =
210 { 0, 6, 4, -1, -3, -4, -6, -8, -10, -12 };
212 /* distance to own king */
213 static const short OwnKingDistanceBonus[10] =
214 { 0, 5, 2, 1, 0, -1, -2, -3, -4, -5 };
216 /* distance to promotion zone */
217 #ifndef MINISHOGI
218 static const int PromotionZoneDistanceBonus[NO_ROWS] =
219 { 0, 0, 0, 0, 2, 6, 6, 8, 8 };
220 #else
221 static const int PromotionZoneDistanceBonus[NO_ROWS] =
222 { 0, 0, 2, 6, 8 }; /* FIXME ? */
223 #endif
225 #define MAX_BMBLTY 20
226 #define MAX_RMBLTY 20
227 #define MAX_LMBLTY 8
229 /* Bishop mobility bonus indexed by # reachable squares */
230 static const short BMBLTY[MAX_BMBLTY] =
231 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
233 /* Rook mobility bonus indexed by # reachable squares */
234 static const short RMBLTY[MAX_RMBLTY] =
235 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
237 #ifndef MINISHOGI
238 /* Lance mobility bonus indexed by # reachable squares */
239 static const short LMBLTY[MAX_LMBLTY] =
240 { 0, 0, 0, 0, 4, 6, 8, 10 };
241 #endif
243 static const short MBLTY[NO_PIECES] =
244 { 0, 2,
245 #ifndef MINISHOGI
246 1, 10,
247 #endif
248 5, 5, 1, 1, 5,
249 #ifndef MINISHOGI
250 5, 5,
251 #endif
252 5, 1, 1, 4 };
254 static const short KTHRT[36] =
255 { 0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
256 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
257 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80 };
259 static small_short fvalue[2][NO_FEATURES];
261 long attack[2][NO_SQUARES]; /* threats to squares */
262 small_short sseed[NO_SQUARES]; /* square occupied by a seed piece? */
264 struct signature threats_signature[2] = /* statistics valid for position.. */
265 { { -1, -1 }, { -1, -1 } }; /* attack and sseed available */
267 small_short starget[2][NO_SQUARES]; /* significance as a target for a
268 * side of a square */
269 small_short sloose[NO_SQUARES]; /* square occupied by a loose piece? */
270 small_short shole[NO_SQUARES]; /* empty square a hole? */
271 small_short shung[NO_SQUARES]; /* hung piece? */
273 struct signature squares_signature = /* statistics valid for position ... */
274 { 0, 0 }; /* starget, sloose, shole, shung available */
276 short target[2], seed[2], loose[2], hole[2];
278 short captured[2]; /* number of captured pieces */
279 short dcaptured[2]; /* different types of captured pieces */
281 small_short Kdist[2][NO_SQUARES]; /* distance to king */
283 short MAXADIST, MAXCDIST; /* maximum half move distance to pattern */
285 char GameType[2] = { UNKNOWN, UNKNOWN }; /* chosen game type of each side */
288 static short attack_opening_sequence[2]; /* current castle patterns */
289 static short castle_opening_sequence[2]; /* current attack formations */
291 static small_short Mpawn [2][NO_SQUARES];
292 static small_short Msilver[2][NO_SQUARES];
293 static small_short Mgold [2][NO_SQUARES];
294 static small_short Mking [2][NO_SQUARES];
295 #ifndef MINISHOGI
296 static small_short Mlance [2][NO_SQUARES];
297 static small_short Mknight[2][NO_SQUARES];
298 #endif
299 static small_short Mbishop[2][NO_SQUARES];
300 static small_short Mrook [2][NO_SQUARES];
302 static Mpiece_array Mpawn,
303 #ifndef MINISHOGI
304 Mlance, Mknight,
305 #endif
306 Msilver, Mgold, Mbishop, Mrook, Mking;
308 Mpiece_array *Mpiece[NO_PIECES] =
309 { NULL, &Mpawn,
310 #ifndef MINISHOGI
311 &Mlance, &Mknight,
312 #endif
313 &Msilver, &Mgold, &Mbishop, &Mrook,
314 &Mgold,
315 #ifndef MINISHOGI
316 &Mgold, &Mgold,
317 #endif
318 &Mgold, &Mbishop, &Mrook, &Mking };
321 static short c1, c2;
322 static small_short *PC1, *PC2;
323 static small_short *fv1;
324 static long *atk1, *atk2;
325 static long a1, a2;
327 #define csquare(side, sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
328 #define crow(side, sq) row(csquare(side, sq))
329 #define ccolumn(side, sq) column(csquare(side, sq))
332 inline static short
333 on_csquare(short side, short piece, short square)
335 short sq;
336 /* FIXME: un-obfuscate this! */
337 return ((board[sq = csquare(side, square)] == piece)
338 && (color[sq] == side));
342 #ifndef MINISHOGI
343 inline static bool
344 on_column(short side, short piece, short c)
346 short sq;
348 for (sq = c; sq < NO_SQUARES; sq += NO_COLS)
350 if (on_csquare(side, piece, sq))
351 return true;
354 return false;
358 #define empty_csquare(side, square) \
359 (board[csquare(side, square)] == no_piece)
361 inline static bool
362 on_left_side(short side, short piece)
364 short c;
366 for (c = 0; c < 4; c++)
368 if (on_column(side, piece, c))
369 return true;
372 return false;
376 inline static bool
377 on_right_side(short side, short piece)
379 short c;
381 for (c = 5; c < NO_COLS; c++)
383 if (on_column(side, piece, c))
384 return true;
387 return false;
389 #endif
392 short pscore[2]; /* piece score for each side */
396 * Fill array attack[side][] with info about attacks to a square. Bits
397 * 16-31 are set if the piece (king .. pawn) attacks the square. Bits 0-15
398 * contain a count of total attacks to the square. Fill array sseed[] with
399 * info about occupation by a seed piece.
402 void
403 threats(short side)
405 short u, sq;
406 long c;
407 long *a;
408 #ifdef SAVE_NEXTPOS
409 short d;
410 #else
411 unsigned char *ppos, *pdir;
412 #endif
413 short i, kd, piece, xside;
414 small_short *PL;
416 if (MatchSignature(threats_signature[side]))
418 /* data valid for current positional signature */
419 return;
422 a = attack[side];
423 xside = side ^ 1;
425 array_zero(a, NO_SQUARES * sizeof(a[0]));
427 PL = PieceList[side];
429 for (i = PieceCnt[side]; i >= 0; i--)
431 short ptyp;
433 sq = PL[i];
434 piece = board[sq];
435 ptyp = ptype[side][piece];
436 c = control[piece];
437 #ifdef SAVE_NEXTPOS
438 u = first_direction(ptyp, &d, sq);
439 #else
440 ppos = (*nextpos[ptyp])[sq];
441 pdir = (*nextdir[ptyp])[sq];
442 u = ppos[sq];
443 #endif
447 a[u] = ((a[u] + 1) | c);
449 if ((kd = Kdist[xside][u]) < 2)
451 sseed[sq] += 2 - kd;
452 seed[side]++;
455 #ifdef SAVE_NEXTPOS
456 u = ((color[u] == neutral)
457 ? next_position(ptyp, &d, sq, u)
458 : next_direction(ptyp, &d, sq));
459 #else
460 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
461 #endif
463 while (u != sq);
466 /* data valid for current positional signature */
467 CopySignature(threats_signature[side]);
473 * Compute the board square with nunmap offset "id". If side == white,
474 * offset is negated. inunmap[sq] is the corresponding nunmap index isq.
475 * nunmap[isq + id] computes the board square. If negative, it is outside
476 * the board.
479 static void
480 add_target(short sq, short side, short id)
482 short isq, tsq, xside;
483 isq = inunmap[sq];
484 tsq = (side == black) ? nunmap[isq + id] : nunmap[isq - id];
486 if (tsq >= 0)
488 target[xside = side^1]++;
490 if (attack[side][tsq])
491 starget[xside][tsq]++; /* protected target square */
492 else
493 starget[xside][tsq] += 2; /* unprotected target square */
500 * Target squares can be vertically ahead, diagonally ahead
501 * or diagonally behind.
504 static void
505 CheckTargetPiece(short sq, short side)
507 switch (board[sq])
509 case pawn: /* vertically ahead if unprotected */
510 if (!attack[side][sq])
511 add_target(sq, side, 11);
512 break;
514 case king: /* diagonally and vertically ahead */
515 add_target(sq, side, 10);
516 add_target(sq, side, 11);
517 add_target(sq, side, 12);
518 break;
520 case rook: /* diagonally ahead and behind */
521 add_target(sq, side, 10);
522 add_target(sq, side, 12);
523 add_target(sq, side, -10);
524 add_target(sq, side, -12);
525 break;
527 case bishop: /* vertically ahead */
528 add_target(sq, side, 11);
529 break;
531 #ifndef MINISHOGI
532 case knight: /* vertically ahead if advanced */
533 /* FIXME: gotta love them magic numbers... */
534 if ((sq != 1) && (sq != 7) && (sq != 73) && (sq != 79))
535 add_target(sq, side, 11);
536 break;
537 #endif
543 static short
544 ScoreKingOpeningFeatures(void)
546 short s = 0, sq = OwnKing, ds;
548 if (GameType[c1] == STATIC_ROOK)
550 /* Penalty for king on right side or fifth file */
551 short c;
552 c = 4 - ccolumn(c1, sq);
554 if ((c < 0) || ((c == 0) && (sq != kingP[c1])))
555 s += (ds = -c - c - fv1[OPENWRONG]);
557 else if (GameType[c1] == RANGING_ROOK)
559 /* Penalty for king on left side or fifth file */
560 short c;
561 c = 4 - ccolumn(c1, sq);
563 if ((c > 0) || ((c == 0) && (sq != kingP[c1])))
565 s += (ds = -c - c - fv1[OPENWRONG]);
568 /* Penalty for king moved before rook switch */
569 if (sq != kingP[c1])
571 if (on_csquare(c1, rook, 16))
573 s += (ds = -4 * fv1[OPENWRONG]);
576 else
578 /* Penalty for sitting king after rook switch */
579 if (!on_csquare(c1, rook, 16))
581 s += (ds = -2 * fv1[OPENWRONG]);
585 /* Penalty for defending general moved
586 * before king switch to right side */
587 if (ccolumn(c1, sq) < 6)
589 if (Mvboard[csquare(c1, 5)] || Mvboard[csquare(c1, 6)])
591 s += (ds = -2 * fv1[OPENWRONG]);
596 return s;
602 inline static void
603 ExamineSquares(void)
605 short sq, side, piece, n;
607 if (MatchSignature(squares_signature))
609 /* data valid for current positional signature */
610 return;
613 array_zero(shole, sizeof(shole));
614 array_zero(sloose, sizeof(sloose));
615 array_zero(starget, sizeof(starget));
617 hole[0] = hole[1] = loose[0] = loose[1]
618 = target[0] = target[1] = 0;
620 for (sq = 0; sq < NO_SQUARES; sq++)
622 if ((side = color[sq]) == neutral)
624 if (InWhiteCamp(sq))
626 if (!attack[white][sq])
628 shole[sq] = 1;
629 hole[white]++;
632 else if (InBlackCamp(sq))
634 if (!attack[black][sq])
636 shole[sq] = 1;
637 hole[black]++;
641 else
643 /* occupied by "side" piece */
644 if (!attack[side][sq])
646 sloose[sq] = 1;
647 loose[side]++;
650 CheckTargetPiece(sq, side);
654 for (side = black; side <= white; side++)
656 captured[side] = dcaptured[side] = 0;
658 for (piece = pawn; piece <= rook; piece++)
660 if ((n = Captured[side][piece]) != 0)
662 if (piece != pawn)
663 captured[side] += n;
665 dcaptured[side]++;
670 /* Data valid for current positional signature */
671 CopySignature(squares_signature);
676 /* ............ POSITIONAL EVALUATION ROUTINES ............ */
679 * Inputs are:
680 * mtl[side] - value of all material
681 * hung[side] - count of hung pieces
682 * Tscore[ply] - search tree score for ply ply
683 * Pscore[ply] - positional score for ply ply
684 * INCscore - bonus score or penalty for certain moves
685 * Sdepth - search goal depth
686 * xwndw - evaluation window about alpha/beta
687 * EWNDW - second evaluation window about alpha/beta
688 * ChkFlag[ply] - checking piece at level ply or 0 if no check
689 * TesujiFlag[ply] - 1 if tesuji move at level ply or 0 if no tesuji
690 * PC1[column] - # of my pawns in this column
691 * PC2[column] - # of opponents pawns in column
692 * PieceCnt[side] - just what it says
699 * Compute an estimate of the score by adding the positional score from the
700 * previous ply to the material difference. If this score falls inside a
701 * window which is 180 points wider than the alpha-beta window (or within a
702 * 50 point window during quiescence search) call ScorePosition() to
703 * determine a score, otherwise return the estimated score. "side" is the
704 * side which has to move.
708 evaluate(short side,
709 short ply,
710 short alpha,
711 short beta,
712 short INCscore,
713 bool *InChk, /* output Check flag */
714 bool *blockable) /* king threat blockable */
716 short xside;
717 short s;
719 xside = side ^ 1;
720 s = -Pscore[ply - 1] + mtl[side] - mtl[xside] /* - INCscore */;
721 hung[black] = hung[white] = 0;
723 /* should we use the estimete or score the position */
724 if ((ply == 1)
725 || (ply == Sdepth)
726 || (ply > Sdepth && s >= (alpha - 30) && s <= (beta + 30))
727 #ifdef CACHE
728 || (use_etable && CheckEETable(side))
729 #endif
732 short sq;
734 /* score the position */
735 array_zero(sseed, sizeof(sseed));
737 seed[0] = seed[1] = 0;
738 threats(side);
740 if (Anyattack(side, sq = PieceList[xside][0]) && (board[sq] == king))
742 *InChk = (board[sq = PieceList[side][0]] == king)
743 ? SqAttacked(sq, xside, blockable)
744 : false;
746 return ((SCORE_LIMIT + 1001) - ply);
749 threats(xside);
750 *InChk = (board[sq = PieceList[side][0]] == king)
751 ? Anyattack(xside, sq)
752 : false;
753 *blockable = true;
754 EvalNodes++;
756 if (ply > 4)
757 PUTVAR = true;
759 ExamineSquares();
760 s = ScorePosition(side);
761 PUTVAR = false;
763 else
765 /* use the estimate but look at check */
766 short sq;
768 *InChk = (board[sq = PieceList[side][0]] == king)
769 ? SqAttacked(sq, xside, blockable)
770 : false;
772 if ((board[sq = PieceList[xside][0]] == king)
773 && SqAttacked(sq, side, blockable))
775 return ((SCORE_LIMIT + 1001) - ply);
779 Pscore[ply] = s - mtl[side] + mtl[xside];
780 ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0);
782 return s;
787 static short
788 value_of_weakest_attacker(long a2)
790 short piece;
791 short min_value, v;
792 min_value = SCORE_LIMIT;
794 for (piece = pawn; piece <= king; piece++)
796 if (control[piece] & a2)
798 if (min_value > (v = (*value)[stage][piece]))
799 min_value = v;
803 return min_value;
810 * Find (promoted) Bishop, (promoted) Rook, and Lance mobility, x-ray
811 * attacks, and pins. Let BRL be the bishop, rook, or lance. Let P be the
812 * first piece (not a king or a pawn) in a direction and let Q be the
813 * second piece in the same direction. If Q is an unprotected opponent's
814 * piece with bigger relative value than BRL, there is a pin if P is an
815 * opponent's piece and there is an x-ray attack if P belongs to this side.
816 * Increment the hung[] array if a pin is found.
819 inline int
820 BRLscan(short sq, short *mob)
822 #ifdef SAVE_NEXTPOS
823 short d, dd;
824 #else
825 unsigned char *ppos, *pdir;
826 #endif
828 short s, mobx;
829 short u, xu, pin, ptyp;
830 #ifndef MINISHOGI
831 short csq = column(sq);
832 #endif
833 short piece, upiece, xupiece, rvalue, ds;
834 small_short *Kd = Kdist[c2];
836 mobx = s = 0;
837 piece = board[sq];
839 rvalue = (*value)[stage][piece];
840 ptyp = ptype[c1][upiece = unpromoted[piece]];
841 rvalue = (*value)[stage][upiece];
843 #ifdef SAVE_NEXTPOS
844 u = first_direction(ptyp, &d, sq);
845 #else
846 ppos = (*nextpos[ptyp])[sq];
847 pdir = (*nextdir[ptyp])[sq];
848 u = ppos[sq];
849 #endif
851 pin = -1; /* start new direction */
855 if (Kd[u] < 2)
857 s += (ds = fv1[CTRLK] * (2 - Kd[u]));
860 if ((ds = starget[c1][u]) != 0)
862 /* threatening a target square */
863 if ((pin < 0) /* direct threat */
864 || (color[pin] == c2)) /* pin threat */
866 s += (ds *= fv1[TARGET]);
870 if ((ds = shole[u]) != 0)
872 /* attacking or protecting a hole */
873 s += (ds = fv1[HOLES]);
875 else if (InPromotionZone(c1, u))
877 /* attacking a square in promotion zone */
878 s += (ds = fv1[HOLES] / 2);
881 if (color[u] == neutral)
883 #ifdef SAVE_NEXTPOS
884 dd = d;
885 xu = next_position(ptyp, &d, sq, u);
887 if (xu == next_direction(ptyp, &dd, sq))
888 pin = -1; /* oops new direction */
889 #else
891 if ((xu = ppos[u]) == pdir[u])
892 pin = -1; /* oops new direction */
893 #endif
894 u = xu;
895 mobx++;
897 else
899 /* there is a piece in current direction */
900 if (pin < 0)
902 /* it's the first piece in the current direction */
903 if (color[u] == c1)
905 #ifndef MINISHOGI
906 /* own intercepting piece in x-ray attack */
907 if (upiece == lance)
909 /* lance x-ray */
910 if (board[u] == pawn)
912 s += (ds = 2*fv1[PROTECT]);
914 else if (in_opening_stage)
916 s += (ds = -2*fv1[PROTECT]);
919 else
920 #endif
922 /* bishop or rook x-ray */
923 if ((upiece == bishop) && (board[u] == pawn)
924 && (GameType[c1] == STATIC_ROOK))
926 s += (ds = -2*fv1[HCLSD]);
928 #ifndef MINISHOGI
929 else if ((upiece == rook) && (board[u] == lance)
930 && (GameType[c1] == STATIC_ROOK)
931 && (column(u) == csq))
933 s += (ds = fv1[XRAY]);
935 #endif
938 else
940 /* enemy's intercepting piece in pin attack */
941 #ifndef MINISHOGI
942 if (upiece == lance)
944 /* lance pin attack */
945 if (board[u] == pawn)
947 s += (ds = -2*fv1[PROTECT]);
949 else if (in_opening_stage)
951 s += (ds = 2 * fv1[PROTECT]);
954 else
955 #endif
957 /* bishop or rook pin attack */
958 if (board[u] == pawn)
960 s += (ds = -fv1[HCLSD]);
965 #ifdef SAVE_NEXTPOS
966 dd = d;
967 xu = next_position(ptyp, &d, sq, u);
969 if (xu != next_direction(ptyp, &dd, sq))
970 pin = u; /* not on the edge and on to find a pin */
971 #else
972 if ((xu = ppos[u]) != pdir[u])
973 pin = u; /* not on the edge and on to find a pin */
974 #endif
975 u = xu;
977 else
979 /* it's the second piece in the current direction */
981 if (color[u] == c1)
983 /* second piece is an own piece */
984 if ((upiece == bishop) && (board[u] == pawn)
985 && (GameType[c1] == STATIC_ROOK))
987 s += (ds = -fv1[HCLSD]);
990 else
992 /* second piece is an enemy piece */
993 if (upiece == bishop && board[u] == pawn)
995 s += (ds = -fv1[HCLSD]/2);
998 if (((*value)[stage][xupiece = unpromoted[board[u]]]
999 > rvalue)
1000 || (atk2[u] == 0))
1002 if (color[pin] == c2)
1004 if ((xupiece == king) && (in_endgame_stage))
1006 s += (ds = 2 * fv1[PINVAL]);
1008 else
1010 s += (ds = fv1[PINVAL]);
1013 if ((atk2[pin] == 0)
1014 || (atk1[pin] > control[board[pin]] + 1))
1016 hung[c2]++;
1017 shung[u]++;
1020 else
1022 #ifndef MINISHOGI
1023 if (upiece == lance)
1025 s += (ds = fv1[XRAY] / 2);
1027 else
1028 #endif
1030 s += (ds = fv1[XRAY]);
1036 pin = -1; /* new direction */
1038 #ifdef SAVE_NEXTPOS
1039 u = next_direction(ptyp, &d, sq);
1040 #else
1041 u = pdir[u];
1042 #endif
1046 while (u != sq);
1048 *mob = mobx;
1050 return s;
1054 #define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp)
1059 * Assign penalties if king can be threatened by checks, if squares near
1060 * the king are controlled by the enemy (especially by promoted pieces), or
1061 * if there are no own generals near the king.
1063 * The following must be true:
1064 * board[sq] == king, c1 == color[sq], c2 == otherside[c1]
1067 #define SCORETHREAT \
1069 if (color[u] != c2) \
1071 if ((atk1[u] == 0) || ((atk2[u] & CNT_MASK) != 0)) \
1073 ++cnt; \
1075 else \
1077 s += (ds = -fv1[CTRLK]); \
1085 inline short
1086 KingScan(short sq)
1088 short cnt;
1090 #ifdef SAVE_NEXTPOS
1091 short d;
1092 #else
1093 unsigned char *ppos, *pdir;
1094 #endif
1096 short s;
1097 short u, ptyp;
1098 short ds;
1099 bool ok;
1101 /* Penalties, if a king can be threatened by checks. */
1103 s = 0;
1104 cnt = 0;
1107 short p;
1109 for (p = pawn; p < king; p++)
1111 if (HasPiece[c2][p] || Captured[c2][p])
1113 short ptyp;
1115 /* if a c1 piece can reach u from sq,
1116 * then a c2 piece can reach sq from u.
1117 * That means, each u is a square, from which a
1118 * piece of type p and color c2 threats square sq.
1120 ptyp = ptype[c1][p];
1122 #ifdef SAVE_NEXTPOS
1123 u = first_direction(ptyp, &d, sq);
1124 #else
1125 ppos = (*nextpos[ptyp])[sq];
1126 pdir = (*nextdir[ptyp])[sq];
1127 u = ppos[sq];
1128 #endif
1132 /* If a p piece can reach (controls or can drop to)
1133 * square u, then score threat.
1136 if (atk2[u] & control[p])
1137 SCORETHREAT
1138 else if ((Captured[c2][p] && color[u]) == neutral)
1139 SCORETHREAT
1141 #ifdef SAVE_NEXTPOS
1142 u = ((color[u] == neutral)
1143 ? next_position(ptyp, &d, sq, u)
1144 : next_direction(ptyp, &d, sq));
1145 #else
1146 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1147 #endif
1149 while (u != sq);
1154 s += (ds = fv1[KSFTY] * KTHRT[cnt] / 16);
1156 /* Penalties, if squares near king are controlled by enemy. */
1158 cnt = 0;
1159 ok = false;
1160 ptyp = ptype[c1][king];
1162 #ifdef SAVE_NEXTPOS
1163 u = first_direction(ptyp, &d, sq);
1164 #else
1165 pdir = (*nextpos[ptyp])[sq];
1166 u = pdir[sq];
1167 #endif
1171 if (!ok && color[u] == c1)
1173 short ptype_piece = ptype[black][board[u]];
1175 if ((ptype_piece == ptype_silver) || (ptype_piece == ptype_gold))
1176 ok = true;
1179 if (atk2[u] > atk1[u])
1181 ++cnt;
1183 if (atk2[u] & ctlSG)
1185 s += (ds = -fv1[KSFTY] / 2);
1189 #ifdef SAVE_NEXTPOS
1190 u = next_direction(ptyp, &d, sq);
1191 #else
1192 u = pdir[u];
1193 #endif
1195 while (u != sq);
1197 if (!ok || (cnt > 1))
1199 if (cnt > 1)
1200 s += (ds = -fv1[KSFTY]/2);
1201 else
1202 s += (ds = -fv1[KSFTY]);
1205 return s;
1209 static bool checked_trapped;
1213 * See if the attacked piece has unattacked squares to move to. The following
1214 * must be true: c1 == color[sq] c2 == otherside[c1]
1217 static inline bool
1218 trapped(short sq)
1220 short u, ptyp;
1221 #ifdef SAVE_NEXTPOS
1222 short d;
1223 #else
1224 unsigned char *ppos, *pdir;
1225 #endif
1226 short piece;
1227 short rvalue;
1229 piece = board[sq];
1230 rvalue = (*value)[stage][piece];
1231 ptyp = ptype[c1][piece];
1233 #ifdef SAVE_NEXTPOS
1234 u = first_direction(ptyp, &d, sq);
1235 #else
1236 ppos = (*nextpos[ptyp])[sq];
1237 pdir = (*nextdir[ptyp])[sq];
1238 u = ppos[sq];
1239 #endif
1243 if (color[u] != c1)
1245 if ((atk2[u] == 0) || ((*value)[stage][board[u]] >= rvalue))
1246 return false;
1249 #ifdef SAVE_NEXTPOS
1250 u = ((color[u] == neutral)
1251 ? next_position(ptyp, &d, sq, u)
1252 : next_direction(ptyp, &d, sq));
1253 #else
1254 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1255 #endif
1257 while (u != sq);
1259 checked_trapped = true;
1261 return true;
1266 static int
1267 AttackedPieceValue(short sq)
1269 short s;
1271 s = 0;
1273 hung[c1]++;
1274 shung[sq]++;
1276 if (trapped(sq))
1278 hung[c1] += 2;
1279 shung[sq] += 2;
1282 return s;
1287 static inline int
1288 OpenFileValue(short sq, short hopn, short hopnx)
1290 short s = 0, fyle;
1292 if (PC1[fyle = column(sq)] == 0)
1294 s += hopn;
1297 if (PC2[fyle] == 0)
1299 s += hopnx;
1302 return s;
1308 /* Distance bonus */
1310 #define PromotionZoneDistanceValue(sq, dd) \
1311 if ((ds = fv1[PROMD])) \
1313 s += (ds = ds * PromotionZoneDistanceBonus[crow(c1, sq)] * dd); \
1316 #define OwnKingDistanceValue(sq, dd, maxd) \
1317 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd)) \
1319 s += (ds = ds * OwnKingDistanceBonus[ad] * dd); \
1322 #define EnemyKingDistanceValue(sq, dd, maxd) \
1323 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd)) \
1325 s += (ds = ds * EnemyKingDistanceBonus[ad] * dd); \
1333 * Calculate the positional value for a pawn on 'sq'.
1336 static inline int
1337 PawnValue(short sq, short side)
1339 short s = 0;
1340 short ds;
1341 #ifndef MINISHOGI
1342 short ccol = ccolumn(c1, sq);
1343 #endif
1345 PromotionZoneDistanceValue(sq, 3);
1347 /* pawn mobility */
1348 if (color[(c1 == black) ? (sq + NO_COLS) : (sq - NO_COLS)] == neutral)
1350 s += (ds = MBLTY[pawn]);
1353 if ((a1 & ((ctlR | ctlRp) | ctlL)))
1355 s += (ds = fv1[ATTACKED]);
1358 if (in_opening_stage)
1360 #ifndef MINISHOGI
1361 /* FIXME: [HGM] The 3rd-rank Pawn section is meaningless in mini-Shogi,
1362 * (which does not have opposing Pawns), and can do out-of-bound access,
1363 * as the promotion zone is only 1 rank, so Pawns can be closer than 3 ranks
1364 * to the board edge.
1366 if (crow(c1, sq) == 2) /* pawn on 3d rank */
1368 if (board[(c1 == black) ?
1369 (sq + 3*NO_COLS) : (sq - 3*NO_COLS)] == pawn)
1371 /* opposing pawn has been moved (even column == (sq & 1)) */
1373 short m;
1375 switch (ccol)
1377 case 0:
1378 case 8:
1379 m = (side == c1) ? 3 : 5;
1380 break;
1382 case 4:
1383 m = (side == c1) ? 2 : 3;
1384 break;
1386 default:
1387 m = (side == c1) ? 1 : 2;
1388 break;
1391 s += (ds = -m * MBLTY[pawn]);
1395 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1396 * board - and anyway we don't know the stage really :)
1398 if ((GameType[c1] == STATIC_ROOK) && (sq == csquare(c1, 43)))
1400 if ((atk2[csquare(c1, 52)] & CNT_MASK) < 2)
1402 s += (ds = fv1[ATTACKED]);
1406 if ((GameType[c2] == STATIC_ROOK) && (ccol == 1))
1408 if (sq == csquare(c1, 28))
1410 s += (ds = -fv1[ATTACKED]);
1413 if (((atk1[csquare(c1, 19)] & CNT_MASK) < 2)
1414 && ((atk1[csquare(c1, 28)] & CNT_MASK) < 2))
1416 s += (ds = -2 * fv1[ATTACKED]);
1419 #endif
1422 return s;
1426 #ifndef MINISHOGI
1428 * Calculate the positional value for a lance on 'sq'.
1431 static inline int
1432 LanceValue(short sq)
1434 short s = 0, ds, ad;
1436 OwnKingDistanceValue(sq, 1, 2);
1438 OpenFileValue(sq, -fv1[HOPN], fv1[HOPN]);
1440 if (!checked_trapped && (crow(c1, sq) > 2))
1442 if (in_opening_stage || trapped(sq))
1444 s += (ds = -3 * fv1[ATTACKED]);
1446 else
1448 s += (ds = -2 * fv1[ATTACKED]);
1452 return s;
1458 * Calculate the positional value for a knight on 'sq'.
1461 static inline int
1462 KnightValue(short sq)
1464 short s = 0, ad;
1465 short ds;
1466 bool checked_trapped = false;
1467 short c = column(sq);
1469 PromotionZoneDistanceValue(sq, 1);
1470 OwnKingDistanceValue(sq, 1, 2);
1472 if (!checked_trapped && (crow(c1, sq) > 2))
1474 if (trapped(sq))
1476 s += (ds = -4 * fv1[ATTACKED]);
1478 else
1480 s += (ds = -3 * fv1[ATTACKED]);
1484 if ((c == 0) || (c == 8))
1486 s += (ds = -fv1[ATTACKED]);
1489 return s;
1491 #endif
1496 * Calculate the positional value for a silver on 'sq'.
1499 static inline int
1500 SilverValue(short sq)
1502 short s= 0, ds, ad;
1504 OwnKingDistanceValue(sq, 2, 3);
1506 if ((Kdist[c1][sq] < 3)
1507 && (atk1[sq] & (control[gold] | control[silver])))
1509 s += (ds = fv1[COHESION]);
1512 if (in_opening_stage)
1514 #ifndef MINISHOGI
1515 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1516 * board - and anyway we don't know the stage really :)
1518 if (GameType[c1] == STATIC_ROOK)
1520 if (csquare(c1, sq) == 12)
1522 short csq;
1524 if ((board[csq = csquare(c1, 20)] == bishop)
1525 && (color[csq] == c1))
1527 s += (ds = -2 * fv1[OPENWRONG]);
1531 #endif
1533 else
1535 EnemyKingDistanceValue(sq, 2, 3);
1538 return s;
1544 * Calculate the positional value for a gold on 'sq'.
1547 static inline int
1548 GoldValue(short sq)
1550 short s = 0, ds, ad;
1552 OwnKingDistanceValue(sq, 2, 3);
1554 if ((Kdist[c1][sq] < 3)
1555 && (atk1[sq] & (control[gold] | control[silver])))
1557 s += (ds = fv1[COHESION]);
1560 if (in_opening_stage)
1562 #ifndef MINISHOGI
1563 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1564 * board - and anyway we don't know the stage really :)
1566 if ((GameType[c1] == STATIC_ROOK) && (GameType[c2] != STATIC_ROOK))
1568 if (Mvboard[csquare(c1, 3)])
1570 s += (ds = -2 * fv1[OPENWRONG]);
1573 #endif
1575 else
1577 EnemyKingDistanceValue(sq, 2, 3);
1580 return s;
1586 * Calculate the positional value for a bishop on 'sq'.
1589 static inline int
1590 BishopValue(short sq)
1592 short s = 0, ds, ad;
1594 if (in_opening_stage)
1596 #ifndef MINISHOGI
1597 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1598 * board - and anyway we don't know the stage really :)
1600 if (GameType[c1] == RANGING_ROOK)
1602 /* Bishops diagonal should not be open */
1603 if (!on_csquare(c1, pawn, 30))
1605 s += (ds = -fv1[OPENWRONG]);
1608 else if (GameType[c2] == RANGING_ROOK)
1610 /* Bishops diagonal should be open */
1611 if ((csquare(c1, sq) == 10)
1612 && (!empty_csquare(c1, 20) || !empty_csquare(c1, 30)))
1614 s += (ds = -fv1[OPENWRONG]);
1616 else if ((csquare(c1, sq) == 20) && !empty_csquare(c1, 30))
1618 s += (ds = -fv1[OPENWRONG]);
1621 #endif
1623 else
1625 EnemyKingDistanceValue(sq, 1, 3);
1628 return s;
1634 * Calculate the positional value for a rook on 'sq'.
1637 static inline int
1638 RookValue(short sq, short side)
1640 short s = 0, ds, ad;
1642 OpenFileValue(sq, 2 * fv1[HOPN], 4*fv1[HOPN]);
1644 if (in_opening_stage)
1646 #ifndef MINISHOGI
1647 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1648 * board - and anyway we don't know the stage really :)
1650 short WRONG = fv1[OPENWRONG], OPOK = WRONG / 3;
1652 if (GameType[c1] == STATIC_ROOK)
1654 short c = ccolumn(c1, sq);
1656 /* Bonus for rook on 8th file */
1657 if (c == 7)
1659 s += (ds = OPOK);
1663 * Bonus for rook on right side,
1664 * penalty for rook on left side
1667 c = 4 - c;
1668 ds = 0;
1670 if (c < 0)
1672 s += (ds = c + c + OPOK);
1674 else if (c >= 0)
1676 s += (ds = -c - c - WRONG);
1679 else if (GameType[c1] == RANGING_ROOK)
1681 /* Bonus for rook on left side and
1682 * bishops diagonal closed, penalty otherwise. */
1684 short c;
1685 c = 4 - ccolumn(c1, sq);
1686 ds = 0;
1688 if (c >= 0)
1690 /* Bishops diagonal should not be open. */
1691 if (on_csquare(c1, pawn, 30))
1692 s += (ds = OPOK);
1693 else
1694 s += (ds = -c - c - WRONG);
1696 else if (c < 0)
1698 s += (ds = -c - c - WRONG);
1700 /* Penalty for king not on initial square. */
1701 if (!on_csquare(side, king, 4))
1703 s += -4 * WRONG;
1704 ds += -4 * WRONG;
1708 #endif
1710 else
1712 EnemyKingDistanceValue(sq, 1, 3);
1715 return s;
1721 * Calculate the positional value for a promoted pawn on 'sq'.
1724 static inline int
1725 PPawnValue(short sq)
1727 short s = 0, ds, ad;
1729 EnemyKingDistanceValue(sq, 3, 10);
1731 return s;
1736 #ifndef MINISHOGI
1738 * Calculate the positional value for a promoted lance on 'sq'.
1741 static inline int
1742 PLanceValue(short sq)
1744 short s = 0, ds, ad;
1746 EnemyKingDistanceValue(sq, 3, 10);
1748 return s;
1754 * Calculate the positional value for a promoted knight on 'sq'.
1757 static inline int
1758 PKnightValue(short sq)
1760 short s = 0, ds, ad;
1762 EnemyKingDistanceValue(sq, 3, 10);
1764 return s;
1766 #endif
1771 * Calculate the positional value for a promoted silver on 'sq'.
1774 static inline int
1775 PSilverValue(short sq)
1777 short s = 0, ds, ad;
1779 EnemyKingDistanceValue(sq, 3, 10);
1781 return s;
1787 * Calculate the positional value for a promoted bishop on 'sq'.
1790 static inline int
1791 PBishopValue(short sq)
1793 short s = 0, ds, ad;
1795 EnemyKingDistanceValue(sq, 3, 4);
1797 return s;
1803 * Calculate the positional value for a promoted rook on 'sq'.
1806 static inline int
1807 PRookValue(short sq)
1809 short s = 0, ds, ad;
1811 EnemyKingDistanceValue(sq, 3, 4);
1813 OpenFileValue(sq, 3 * fv1[HOPN], 2 * fv1[HOPN]);
1815 return s;
1821 * Calculate the positional value for a king on 'sq'.
1824 static inline int
1825 KingValue(short sq)
1827 short s = 0, ds;
1829 if (fv1[KSFTY] != 0)
1830 s += KingScan(sq);
1832 #ifndef MINISHOGI
1833 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1834 * board - and anyway we don't know the stage really :)
1836 if (in_opening_stage)
1838 if ((GameType[c1] != UNKNOWN) && (ccolumn(c1, sq) == 4))
1840 s += (ds = -fv1[OPENWRONG] / 3);
1842 else if ((GameType[c1] == STATIC_ROOK) && on_right_side(c1, sq))
1844 s += (ds = -fv1[OPENWRONG] / 2);
1846 else if ((GameType[c1] == RANGING_ROOK) && on_left_side(c1, sq))
1848 s += (ds = -fv1[OPENWRONG] / 2);
1851 #endif
1853 /* CHECKME: is this correct? */
1854 if ((ds = fv1[HOPN]))
1856 s += OpenFileValue(sq, -2 * ds, -4 * ds);
1859 return s;
1865 * Calculate the positional value for a piece on 'sq'.
1868 static inline int
1869 PieceValue(short sq, short side)
1871 short s, piece, ds;
1872 short mob;
1874 piece = board[sq];
1876 if (piece == no_piece)
1877 return 0;
1879 s = (*Mpiece[piece])[c1][sq];
1881 checked_trapped = false;
1883 if (sweep[piece])
1885 /* pin/x-ray attack and mobility for sweeping pieces */
1886 s += (ds = BRLscan(sq, &mob));
1888 if ((piece == bishop) || (piece == pbishop))
1889 s += (ds = BMBLTY[mob] * fv1[MOBILITY] / 100);
1890 else if ((piece == rook) || (piece == prook))
1891 s += (ds = RMBLTY[mob] * fv1[MOBILITY] / 100);
1892 #ifndef MINISHOGI
1893 else
1894 s += (ds = LMBLTY[mob] * fv1[MOBILITY] / 100);
1895 #endif
1897 else
1899 /* mobility for non-sweeping pieces */
1902 a2 = atk2[sq];
1903 a1 = atk1[sq];
1905 if (a2 > 0)
1907 /* opponent attacks piece */
1908 if (a1 == 0)
1910 /* undefended piece */
1911 s += AttackedPieceValue(sq);
1913 else
1915 /* defended piece */
1916 short attack_value = value_of_weakest_attacker(a2);
1917 short piece_value = (*value)[stage][piece];
1919 if (attack_value < piece_value)
1921 /* attacked by a weaker piece */
1922 s += AttackedPieceValue(sq) / 2;
1924 else if (abs(attack_value - piece_value) < 10)
1926 /* opponent has the option to exchange equal pieces */
1927 s += (ds = -fv1[ATTACKED]);
1932 if (piece != king)
1935 if (a1 > 0)
1937 /* piece is defended */
1938 s += (ds = (a1 & CNT_MASK) * fv1[PROTECT]);
1941 if (sseed[sq])
1943 s += (ds = fv1[SEED]);
1946 if (sloose[sq])
1948 s += (ds = -fv1[LOOSE]);
1951 if (starget[c1][sq])
1953 if (sweep[piece])
1955 s -= (ds = -fv1[ATTACKED]/2);
1957 else if (piece == pawn)
1959 s += (ds = fv1[ATTACKED]);
1963 if (starget[c2][sq])
1965 if (piece != pawn)
1967 s -= (ds = -fv1[ATTACKED] / 3);
1969 else
1971 s += (ds = fv1[ATTACKED]);
1975 if (Kdist[c1][sq] == 1)
1977 s += (ds = fv1[KSFTY]);
1981 switch (piece)
1983 case pawn:
1984 s += PawnValue(sq, side);
1985 break;
1987 #ifndef MINISHOGI
1988 case lance:
1989 s += LanceValue(sq);
1990 break;
1992 case knight:
1993 s += KnightValue(sq);
1994 break;
1995 #endif
1997 case silver:
1998 s += SilverValue(sq);
1999 break;
2001 case gold:
2002 s += GoldValue(sq);
2003 break;
2005 case bishop:
2006 s += BishopValue(sq);
2007 break;
2009 case rook:
2010 s += RookValue(sq, side);
2011 break;
2013 case king:
2014 s += KingValue(sq);
2015 break;
2017 case ppawn:
2018 s += PPawnValue(sq);
2019 break;
2021 #ifndef MINISHOGI
2022 case plance:
2023 s += PLanceValue(sq);
2024 break;
2026 case pknight:
2027 s += PKnightValue(sq);
2028 break;
2029 #endif
2031 case psilver:
2032 s += PSilverValue(sq);
2033 break;
2035 case pbishop:
2036 s += PBishopValue(sq);
2037 break;
2039 case prook:
2040 s += PRookValue(sq);
2041 break;
2044 return s;
2050 * Score distance to pattern regarding the game type which side plays.
2053 short
2054 ScorePatternDistance(short c1)
2056 short ds, s = 0;
2057 small_short *fv1 = fvalue[c1];
2058 short os = 0;
2060 if ((MAXCDIST > 0) && (fv1[PCASTLE] != 0)
2061 && ((os = castle_opening_sequence[c1]) >= 0))
2063 ds = board_to_pattern_distance(c1, os, MAXCDIST, GameCnt);
2065 if (ds != 0)
2067 s += (ds *= fv1[PCASTLE]);
2071 if ((MAXADIST > 0) && (fv1[PATTACK] != 0)
2072 && ((os = attack_opening_sequence[c1]) >= 0))
2074 ds = board_to_pattern_distance(c1, os, MAXADIST, GameCnt);
2076 if (ds != 0)
2078 s += (ds *= fv1[PATTACK]);
2082 return s;
2089 * Determine castle and attack pattern which should be reached next.
2090 * Only patterns are considered, which have not been reached yet.
2093 static void
2094 UpdatePatterns(short side, short GameCnt)
2096 char s[12];
2097 short xside = side ^ 1;
2098 short os;
2099 short j, k, n = 0;
2101 strcpy(s, "CASTLE_?_?");
2102 s[7] = GameType[side];
2103 s[9] = GameType[xside];
2104 castle_opening_sequence[side] = os
2105 = locate_opening_sequence(side, s, GameCnt);
2107 if (flag.post && (os != END_OF_SEQUENCES))
2109 for (j = 0; j < MAX_SEQUENCE; j++)
2111 for (k = OpeningSequence[os].first_pattern[j];
2112 k != END_OF_PATTERNS;
2113 k = Pattern[k].next_pattern)
2115 if (Pattern[k].distance[side] >= 0)
2116 n++;
2121 if (os != END_OF_SEQUENCES)
2122 update_advance_bonus(side, os);
2124 strcpy(s, "ATTACK_?_?");
2125 s[7] = GameType[side];
2126 s[9] = GameType[xside];
2127 attack_opening_sequence[side] = os
2128 = locate_opening_sequence(side, s, GameCnt);
2130 if (flag.post && (os != END_OF_SEQUENCES))
2132 for (j = 0; j < MAX_SEQUENCE; j++)
2134 for (k = OpeningSequence[os].first_pattern[j];
2135 k != END_OF_PATTERNS;
2136 k = Pattern[k].next_pattern)
2138 if (Pattern[k].distance[side] >= 0)
2139 n++;
2144 if (flag.post)
2145 dsp->ShowPatternCount(side, n);
2147 if (os != END_OF_SEQUENCES)
2148 update_advance_bonus(side, os);
2153 static void
2154 ScoreCaptures(void)
2156 short ds, col, n, m, piece;
2158 if ((n = Captured[c1][pawn]))
2160 ds = m = 0;
2162 for (col = 0; col < NO_COLS; col++)
2164 if (!PC1[col])
2166 m++;
2167 ds += fv1[PWNDROP];
2171 /* FIXME! another great obfuscated line... */
2172 pscore[c1] += (ds *= ((n > 2) ? 3 : n));
2175 if ((m = seed[c1]))
2177 for (piece = pawn+1, n = 0; piece <= rook; piece++)
2179 if (Captured[c1][piece])
2180 n++;
2183 pscore[c1] += (ds = m * fv1[DFFDROP]);
2186 for (piece = pawn, n = 0; piece <= rook; piece++)
2188 if (Captured[c1][piece])
2190 switch (piece)
2192 case bishop:
2193 ds = BMBLTY[MAX_BMBLTY - 1];
2194 break;
2196 case rook:
2197 ds = RMBLTY[MAX_RMBLTY - 1];
2198 break;
2200 #ifndef MINISHOGI
2201 case lance:
2202 ds = LMBLTY[MAX_LMBLTY - 1];
2203 break;
2204 #endif
2206 default:
2207 ds = MBLTY[piece];
2210 pscore[c1] += ds;
2212 if (!Captured[c2][piece])
2213 n += relative_value[piece];
2217 if (n)
2219 pscore[c1] += (ds = -n * fv1[OPPDROP] / 2);
2228 * Perform normal static evaluation of board position. A score is generated
2229 * for each piece and these are summed to get a score for each side.
2232 short
2233 ScorePosition(short side)
2235 short score;
2236 short sq, i, xside;
2237 short s;
2238 short ds;
2240 xside = side ^ 1;
2242 UpdateWeights(side);
2244 hung[black] = hung[white] = pscore[black] = pscore[white] = 0;
2246 array_zero(shung, sizeof(shung));
2248 #ifdef CACHE
2249 if (!(use_etable && ProbeEETable(side, &s)))
2251 #endif
2252 for (c1 = black; c1 <= white; c1++)
2254 c2 = c1 ^ 1;
2256 /* atk1 is array of attacks on squares by my side */
2257 atk1 = attack[c1];
2259 /* atk2 is array of attacks on squares by other side */
2260 atk2 = attack[c2];
2262 /* same for PC1 and PC2 */
2263 PC1 = PawnCnt[c1];
2264 PC2 = PawnCnt[c2];
2266 /* same for fv1 and fv2 */
2267 fv1 = fvalue[c1];
2269 for (i = PieceCnt[c1]; i >= 0; i--)
2271 sq = PieceList[c1][i];
2273 #if defined SAVE_SVALUE
2274 pscore[c1] += PieceValue(sq, side);
2275 #else
2276 pscore[c1] += (svalue[sq] = PieceValue(sq, side));
2277 #endif
2280 ScoreCaptures();
2283 #ifndef MINISHOGI
2284 # define BLACKHOME_START 0
2285 # define BLACKHOME_END 26
2286 # define MIDDLEROW_START 36
2287 # define MIDDLEROW_END 44
2288 # define WHITEHOME_START 54
2289 # define WHITEHOME_END 80
2290 #else
2291 # define BLACKHOME_START 0
2292 # define BLACKHOME_END 4
2293 # define MIDDLEROW_START 10
2294 # define MIDDLEROW_END 14
2295 # define WHITEHOME_START 19
2296 # define WHITEHOME_END 24
2297 #endif
2298 for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2300 short n;
2302 fv1 = fvalue[c1];
2304 /* Score fifth rank */
2305 for (sq = MIDDLEROW_START, n = 0; sq <= MIDDLEROW_END; sq++)
2307 if ((color[sq] == c1) || (attack[c1][sq] != 0))
2308 n++;
2311 if (n != 0)
2313 pscore[c1] += (ds = n * fv1[CNTRL5TH]);
2316 /* Score holes */
2317 for (sq = ((c1 == black) ? BLACKHOME_START : WHITEHOME_START), n = 0;
2318 sq <= ((c1 == black) ? BLACKHOME_END : WHITEHOME_END);
2319 sq++)
2321 if (board[sq] == no_piece && attack[c1][sq] == 0)
2322 n++;
2325 if (n != 0)
2327 pscore[c1] += (ds = -n * fv1[HOLES]);
2330 if (hung[c1] > 1)
2332 pscore[c1] += (ds = -fv1[HUNGX]);
2335 /* Score opening features and
2336 * castle/attack pattern distances */
2338 if (in_opening_stage)
2340 pscore[c1] += (ds = ScoreKingOpeningFeatures());
2341 pscore[c1] += (ds = ScorePatternDistance(c1));
2345 score = mtl[side] - mtl[xside]
2346 + pscore[side] - pscore[xside] + 10;
2348 #ifdef CACHE
2349 if (use_etable && PUTVAR)
2350 PutInEETable(side, score);
2351 #endif
2353 return score;
2354 #ifdef CACHE /* CHECKME: this looks bad */
2357 return s;
2358 #endif
2364 * Try to determine the game type of "side".
2367 #ifndef MINISHOGI
2368 inline static void
2369 GuessGameType(short side_to_move)
2371 short side, gt;
2372 short StaticRook[2] = { 0, 0 };
2373 short RangingRook[2] = { 0, 0 };
2375 for (side = black; side <= white; side++)
2377 /* computer should not change its mind */
2379 extern int bookflag;
2381 gt = GameType[side];
2383 if (!bookflag && (side == side_to_move))
2385 if (gt == STATIC_ROOK)
2386 StaticRook[side] += 4;
2387 else if (gt == RANGING_ROOK)
2388 RangingRook[side] += 4;
2391 /* static rook conditions */
2393 if (on_column(side, rook, 7))
2394 StaticRook[side] += 3;
2396 if (on_csquare(side, pawn, 34))
2397 StaticRook[side] += 6;
2398 else if (on_csquare(side, pawn, 43))
2399 StaticRook[side] += 4;
2400 else if (!on_column(side, pawn, 7))
2401 StaticRook[side] += 5;
2403 if (empty_csquare(side, 5) || empty_csquare(side, 6))
2404 StaticRook[side] += 2;
2406 if (on_left_side(side, king))
2407 StaticRook[side] += 2;
2409 /* ranging rook conditions */
2411 if (on_left_side(side, rook))
2412 RangingRook[side] += 5;
2413 else if (!on_column(side, rook, 7))
2414 RangingRook[side] += 3;
2416 if (on_csquare(side, pawn, 25))
2417 RangingRook[side] += 1;
2419 if (on_csquare(side, pawn, 30))
2420 RangingRook[side] += 1;
2421 else
2422 RangingRook[side] -= 2;
2424 if (!on_right_side(side, rook))
2425 RangingRook[side] += 4;
2427 if (on_right_side(side, king))
2428 RangingRook[side] += 4;
2430 if (on_csquare(side, bishop, 20))
2432 if (on_csquare(side, silver, 11)
2433 || on_csquare(side, silver, 12)
2434 || on_csquare(side, silver, 21))
2436 RangingRook[side] += 3;
2440 if ((StaticRook[side] > 5) || (RangingRook[side] > 5))
2442 GameType[side] = (StaticRook[side] > RangingRook[side])
2443 ? STATIC_ROOK : RANGING_ROOK;
2445 else
2447 GameType[side] = UNKNOWN;
2451 if ((GameType[black] == UNKNOWN) || (GameType[white] == UNKNOWN))
2453 for (side = black; side <= white; side++)
2455 if ((side == computer) && (GameType[side] == UNKNOWN))
2458 * Game type is UNKNOWN.
2459 * Make a decision what type of game to play.
2460 * To make computer games more interesting, make a
2461 * random decision.
2464 if (!on_csquare(side, pawn, 25))
2466 /* Play static rook if rook pawn has been pushed! */
2467 GameType[side] = STATIC_ROOK;
2469 else
2471 unsigned int random = urand() % 100;
2472 short d = StaticRook[side] - RangingRook[side];
2474 switch (GameType[side ^ 1])
2476 case STATIC_ROOK:
2477 if (random < 35 + d)
2478 GameType[side] = STATIC_ROOK;
2479 else if (random < 95)
2480 GameType[side] = RANGING_ROOK;
2481 break;
2483 case RANGING_ROOK:
2484 if (random < 75 + d)
2485 GameType[side] = STATIC_ROOK;
2486 else if (random < 95)
2487 GameType[side] = RANGING_ROOK;
2488 break;
2490 default:
2491 if (random < 33 + d)
2492 GameType[side] = STATIC_ROOK;
2493 else if (random < 66)
2494 GameType[side] = RANGING_ROOK;
2501 #endif
2506 static void
2507 DetermineGameType(short side_to_move)
2509 short side;
2511 #ifndef MINISHOGI
2512 /* FIXME: calculations below are wrong for minishogi, all done for 9x9 */
2513 GuessGameType(side_to_move);
2514 #else
2515 GameType[black] = UNKNOWN;
2516 GameType[white] = UNKNOWN;
2517 #endif
2519 array_zero(Mpawn, sizeof(Mpawn));
2520 #ifndef MINISHOGI
2521 array_zero(Mlance, sizeof(Mlance));
2522 array_zero(Mknight, sizeof(Mknight));
2523 #endif
2524 array_zero(Msilver, sizeof(Msilver));
2525 array_zero(Mgold, sizeof(Mgold));
2526 array_zero(Mbishop, sizeof(Mbishop));
2527 array_zero(Mrook, sizeof(Mrook));
2528 array_zero(Mking, sizeof(Mking));
2530 if (in_opening_stage)
2532 for (side = black; side <= white; side++)
2533 UpdatePatterns(side, GameCnt);
2535 else
2537 dsp->ShowPatternCount(black, -1);
2538 dsp->ShowPatternCount(white, -1);
2545 * This is done one time before the search is started. Set up arrays
2546 * Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue()
2547 * function to determine the positional value of each piece.
2550 void
2551 ExaminePosition(short side)
2553 short c1, piece, sq, i, bsq, wsq;
2555 /* Build enemy king distance tables. */
2557 for (sq = 0, bsq = BlackKing, wsq = WhiteKing; sq < NO_SQUARES; sq++)
2559 Kdist[black][sq] = distance(sq, bsq);
2560 Kdist[white][sq] = distance(sq, wsq);
2563 threats(black);
2564 threats(white);
2566 ExamineSquares();
2568 DetermineGameType(side);
2569 DetermineStage(side);
2571 UpdateWeights(side);
2573 array_zero(HasPiece, sizeof(HasPiece));
2575 for (c1 = black; c1 <= white; c1++)
2577 for (i = PieceCnt[c1]; i >= 0; i--)
2579 ++HasPiece[c1][piece = board[sq = PieceList[c1][i]]];
2586 /* FIXME: calculations below are wrong for minishogi, all done for 9x9 */
2587 void
2588 DetermineStage(short side)
2590 short xside = side ^ 1, ds, db1, c1, c2, feature;
2592 /* Determine initial stage */
2594 balance[side] = balance[xside] = 50;
2596 if ((GameType[side] == STATIC_ROOK)
2597 && (GameType[xside] == STATIC_ROOK))
2599 if (GameCnt < 40)
2600 stage = 0;
2601 else if (GameCnt < 60)
2602 stage = 15;
2603 else if (GameCnt < 80)
2604 stage = 25;
2605 else
2606 stage = 30;
2608 else if ((GameType[side] == RANGING_ROOK)
2609 || (GameType[xside] == RANGING_ROOK))
2611 if (GameCnt < 30)
2612 stage = 0;
2613 else if (GameCnt < 50)
2614 stage = 15;
2615 else if (GameCnt < 70)
2616 stage = 25;
2617 else
2618 stage = 30;
2620 else
2622 if (GameCnt < 35)
2623 stage = 0;
2624 else if (GameCnt < 55)
2625 stage = 15;
2626 else if (GameCnt < 75)
2627 stage = 25;
2628 else
2629 stage = 30;
2632 #ifndef MINISHOGI
2633 /* Update stage depending on board features and attack balance value */
2635 if (abs(ds = (mtl[side] - mtl[xside]))
2636 > (db1 = (*value)[stage][lance]))
2638 db1 = abs(4 * ds / db1);
2640 if (ds < 0)
2641 balance[side] += db1;
2642 else if (ds > 0)
2643 balance[xside] += db1;
2645 stage += (ds = db1);
2647 #endif
2649 for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2651 if ((ds = seed[c1]) > 2)
2653 balance[c1] += (db1 = ds * 2);
2654 balance[c2] -= db1;
2656 if (stage < 30)
2657 stage = 30;
2659 stage += ds;
2662 if ((db1 = hung[c1]) > 2)
2664 balance[c1] -= (db1 *= 2);
2665 balance[c2] += db1;
2668 if ((db1 = loose[c1]) > 4)
2670 balance[c1] -= (db1 /= 2);
2671 balance[c2] += db1;
2672 stage += (ds = 1);
2675 if ((ds = hole[c1]))
2677 balance[c1] -= (db1 = ds);
2678 balance[c2] += db1;
2679 stage += (ds /= 2);
2682 if ((db1 = target[c1]) > 3)
2684 balance[c1] += (db1 /= 3);
2685 balance[c2] -= db1;
2686 stage += (ds = db1 / 4);
2689 stage += (ds = captured[c1] / 2);
2691 if ((db1 = captured[c1]) > 4)
2693 balance[c1] += (db1 /= 2);
2694 stage += (ds = 3);
2697 if ((db1 = dcaptured[c1]) > 3)
2699 balance[c1] += db1;
2700 stage += (ds = 3);
2703 if (balance[c1] > 99)
2704 balance[c1] = 99;
2705 else if (balance[c1] < 0)
2706 balance[c1] = 0;
2709 if (stage > 99)
2710 stage = 99;
2711 else if (stage < 0)
2712 stage = 0;
2714 if (flag.post)
2715 dsp->ShowStage();
2717 /* Determine stage dependant weights */
2719 ADVNCM[pawn] = 1; /* advanced pawn bonus increment */
2720 #ifndef MINISHOGI
2721 ADVNCM[lance] = 1;
2722 ADVNCM[knight] = 1;
2723 #endif
2724 ADVNCM[silver] = 1; /* advanced silver bonus increment */
2725 ADVNCM[gold] = 1; /* advanced gold bonus increment */
2726 ADVNCM[bishop] = 1;
2727 ADVNCM[rook] = 1;
2728 ADVNCM[king] = 1; /* advanced king bonus increment */
2730 MAXCDIST = (stage < 33) ? (33 - stage) / 4 : 0;
2731 MAXADIST = (stage < 30) ? (30 - stage) / 4 : 0;
2733 for (c1 = black; c1 <= white; c1++)
2735 for (feature = 0; feature < NO_FEATURES; feature++)
2737 fvalue[c1][feature] =
2738 ((((*fscore)[stage][feature][0] * (99 - balance[c1])) + 50)
2739 / 100)
2740 + ((((*fscore)[stage][feature][1] * balance[c1]) + 50)
2741 / 100);
2748 void
2749 UpdateWeights(short stage)
2751 /* FIXME: this was emptied between 1.1p02 ans 1.2p03, do we keep it ? */
2757 * Compute stage dependent relative material values assuming
2758 * linearity between the main stages:
2760 * minstage < stage < maxstage =>
2761 * stage - minstage value - minvalue
2762 * ------------------- = -------------------
2763 * maxstage - minstage maxvalue - minvalue
2767 static short
2768 linear_piece_value(short piece, short stage, short i, short j)
2770 short minvalue, maxvalue, minstage, maxstage;
2772 minstage = ispvalue[0][i];
2773 maxstage = ispvalue[0][j];
2774 minvalue = ispvalue[piece][i];
2775 maxvalue = ispvalue[piece][j];
2777 /* FIXME: set a variable then return it, puh-leeze! */
2778 return ((stage - minstage) * (maxvalue - minvalue)
2779 / (maxstage - minstage)) + minvalue;
2784 static short
2785 linear_feature_value(short feature, short stage, short i, short j)
2787 short minvalue, maxvalue, minstage, maxstage;
2789 minstage = ispvalue[0][i];
2790 maxstage = ispvalue[0][j];
2791 minvalue = weight[feature][i];
2792 maxvalue = weight[feature][j];
2794 /* FIXME: set a variable then return it, puh-leeze! */
2795 return ((stage - minstage) * (maxvalue - minvalue)
2796 / (maxstage - minstage)) + minvalue;
2801 * matweight = percentage_of_max_value * max_value(stage) / 100
2802 * max_value(0) = MAX_VALUE; max_value(100) = MIN_VALUE
2803 * => max_value(stage) = a * stage + b; b = MAX_VALUE,
2804 * a = (MIN_VALUE - MAX_VALUE)/100
2807 #define MIN_VALUE 300
2808 #define MAX_VALUE 1000
2810 #define max_value(stage) \
2811 ((long)(MIN_VALUE - MAX_VALUE) * stage + (long)100 * MAX_VALUE)
2812 #define matweight(value, stage) \
2813 ((long)max_value(stage) * value / 10000)
2817 void
2818 Initialize_eval(void)
2820 short stage, piece, feature, i;
2822 for (stage = 0; stage < NO_STAGES; stage++)
2824 for (i = 0; i < MAIN_STAGES; i++)
2826 if (stage == ispvalue[0][i])
2828 for (piece = 0; piece < NO_PIECES; piece++)
2830 (*value)[stage][piece] =
2831 matweight(ispvalue[piece][i], stage);
2834 for (feature = 0; feature < NO_FEATURES; feature++)
2836 (*fscore)[stage][feature][0] =
2837 (weight[feature][i]
2838 * weight[feature][MAIN_STAGES] + 50) / 100;
2840 (*fscore)[stage][feature][1] =
2841 (weight[feature][i]
2842 * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2845 break;
2848 if (stage < ispvalue[0][i + 1])
2850 for (piece = 0; piece < NO_PIECES; piece++)
2852 (*value)[stage][piece] =
2853 matweight(
2854 linear_piece_value(piece, stage, i, i + 1),
2855 stage);
2858 for (feature = 0; feature < NO_FEATURES; feature++)
2860 (*fscore)[stage][feature][0] =
2861 (linear_feature_value(feature, stage, i, i + 1)
2862 * weight[feature][MAIN_STAGES] + 50) / 100;
2864 (*fscore)[stage][feature][1] =
2865 (linear_feature_value(feature, stage, i, i + 1)
2866 * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2869 break;