Merge branch 'maint'
[gnushogi.git] / gnushogi / eval.c
blob6457e24eaf4d6117bac6bcfa2a30aae2dc6f7194
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
8 * GNU SHOGI is based on GNU CHESS
10 * Copyright (c) 1988, 1989, 1990 John Stanback
11 * Copyright (c) 1992 Free Software Foundation
13 * This file is part of GNU SHOGI.
15 * GNU Shogi is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 3 of the License,
18 * or (at your option) any later version.
20 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
21 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * for more details.
25 * You should have received a copy of the GNU General Public License along
26 * with GNU Shogi; see the file COPYING. If not, see
27 * <http://www.gnu.org/licenses/>.
28 * ----------------------------------------------------------------------
32 #include "gnushogi.h"
33 #include "pattern.h"
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 #ifndef MINISHOGI
45 const small_short Stboard[NO_SQUARES] =
47 lance, knight, silver, gold, king, gold, silver, knight, lance,
48 0, bishop, 0, 0, 0, 0, 0, rook, 0,
49 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
50 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
54 0, rook, 0, 0, 0, 0, 0, bishop, 0,
55 lance, knight, silver, gold, king, gold, silver, knight, lance
59 const small_short Stcolor[NO_SQUARES] =
61 black, black, black, black,
62 black, black, black, black, black,
63 neutral, black, neutral, neutral,
64 neutral, neutral, neutral, black, neutral,
65 black, black, black, black,
66 black, black, black, black, black,
67 neutral, neutral, neutral, neutral,
68 neutral, neutral, neutral, neutral, neutral,
69 neutral, neutral, neutral, neutral,
70 neutral, neutral, neutral, neutral, neutral,
71 neutral, neutral, neutral, neutral,
72 neutral, neutral, neutral, neutral, neutral,
73 white, white, white, white,
74 white, white, white, white, white,
75 neutral, white, neutral, neutral,
76 neutral, neutral, neutral, white, neutral,
77 white, white, white, white,
78 white, white, white, white, white
80 #else
81 const small_short Stboard[NO_SQUARES] =
83 king, gold, silver, bishop, rook,
84 pawn, 0, 0, 0, 0,
85 0, 0, 0, 0, 0,
86 0, 0, 0, 0, pawn,
87 rook, bishop, silver, gold, king,
91 const small_short Stcolor[NO_SQUARES] =
93 black, black, black, black, black,
94 black, neutral, neutral, neutral, neutral,
95 neutral, neutral, neutral, neutral, neutral,
96 neutral, neutral, neutral, neutral, white,
97 white, white, white, white, white
99 #endif
101 /* Actual pieces and colors */
103 small_short board[NO_SQUARES], color[NO_SQUARES];
106 /* relative piece values at the beginning of main stages */
108 #define MAIN_STAGES 4
110 static small_short ispvalue[NO_PIECES][MAIN_STAGES] =
112 { 0, 35, 70, 99 }, /* main stage borders */
113 /* ------------------------------------------ */
114 { 7, 7, 8, 10 }, /* Pawn */
115 #ifndef MINISHOGI
116 { 20, 35, 45, 60 }, /* Lance */
117 { 20, 35, 45, 60 }, /* Knight */
118 #endif
119 { 35, 40, 60, 80 }, /* Silver */
120 { 35, 50, 65, 80 }, /* Gold */
121 { 90, 90, 90, 90 }, /* Bishop */
122 { 95, 95, 95, 95 }, /* Rook */
123 { 15, 25, 40, 65 }, /* promoted Pawn */
124 #ifndef MINISHOGI
125 { 25, 45, 55, 65 }, /* promoted Lance */
126 { 25, 45, 55, 65 }, /* promoted Knight */
127 #endif
128 { 35, 55, 75, 75 }, /* promoted Silver */
129 { 99, 99, 99, 99 }, /* promoted Bishop */
130 { 97, 97, 99, 99 }, /* promoted Rook */
131 { 100, 100, 100, 100 }, /* King */
134 /* Features and Weights */
136 #define ATTACKED 0
137 #define HUNGP 1
138 #define HUNGX 2
139 #define CNTRL5TH 3
140 #define HOLES 4
141 #define PCASTLE 5
142 #define PATTACK 6
143 #define CTRLK 7
144 #define PROTECT 8
145 #define HCLSD 9
146 #define PINVAL 10
147 #define XRAY 11
148 #define OPENWRONG 12
149 #define SEED 13
150 #define LOOSE 14
151 #define MOBILITY 15
152 #define TARGET 16
153 #define KSFTY 17
154 #define HOPN 18
155 #define PROMD 19
156 #define KINGOD 20
157 #define PWNDROP 21
158 #define DFFDROP 22
159 #define FCLATTACK 23
160 #define KNGATTACK 24
161 #define KNGPROTECT 25
162 #define DNGLPC 26
163 #define LSATTACK 27
164 #define NIHATTACK 28
165 #define COHESION 29
166 #define OPPDROP 30
169 static small_short weight[NO_FEATURES + 1][MAIN_STAGES + 2] =
171 { 80, 100, 100, 40, 10, 15 }, /* ATTACKED */
172 { 80, 100, 100, 50, 14, 10 }, /* HUNGP */
173 { 80, 100, 100, 50, 18, 12 }, /* HUNGX */
174 { 100, 50, 0, 0, 2, 1 }, /* CNTRL5TH */
175 { 100, 100, 60, 10, 4, 2 }, /* HOLES */
176 { 100, 50, 0, 0, 14, 7 }, /* PCASTLE */
177 { 100, 50, 0, 0, 6, 12 }, /* PATTACK */
178 { 10, 40, 70, 100, 10, 15 }, /* CTRLK */
179 { 100, 80, 50, 40, 2, 1 }, /* PROTECT */
180 { 40, 100, 40, 5, 4, 4 }, /* HCLSD */
181 { 80, 100, 80, 30, 10, 15 }, /* PINVAL */
182 { 80, 100, 60, 15, 6, 10 }, /* XRAY */
183 { 100, 50, 0, 0, 15, 15 }, /* OPENWRONG */
184 { 0, 40, 70, 100, 8, 12 }, /* SEED */
185 { 50, 100, 80, 20, 5, 3 }, /* LOOSE */
186 { 50, 100, 80, 50, 100, 100 }, /* MOBILITY (%) */
187 { 50, 100, 80, 50, 4, 8 }, /* TARGET */
188 { 50, 40, 100, 80, 8, 4 }, /* KSFTY */
189 { 80, 100, 60, 20, 5, 5 }, /* HOPN */
190 { 20, 40, 80, 100, 3, 6 }, /* PROMD */
191 { 20, 40, 80, 100, 4, 1 }, /* KINGOD */
192 { 5, 40, 100, 50, 0, 4 }, /* PWNDROP */
193 { 0, 20, 80, 100, 0, 4 }, /* DFFDROP */
194 { 20, 50, 100, 80, 0, 4 }, /* FCLATTACK */
195 { 0, 20, 80, 100, 0, 8 }, /* KNGATTACK */
196 { 40, 80, 100, 80, 6, 0 }, /* KNGPROTECT */
197 { 50, 100, 60, 10, 0, 8 }, /* DNGPC */
198 { 30, 100, 60, 5, 0, 6 }, /* LSATTACK */
199 { 0, 50, 80, 100, 0, 8 }, /* NIHATTACK */
200 { 50, 100, 80, 60, 8, 0 }, /* COHESION */
201 { 100, 100, 80, 60, 4, 4 }, /* OPPDROP */
205 short ADVNCM[NO_PIECES];
207 /* distance to enemy king */
208 static const short EnemyKingDistanceBonus[10] =
209 { 0, 6, 4, -1, -3, -4, -6, -8, -10, -12 };
211 /* distance to own king */
212 static const short OwnKingDistanceBonus[10] =
213 { 0, 5, 2, 1, 0, -1, -2, -3, -4, -5 };
215 /* distance to promotion zone */
216 #ifndef MINISHOGI
217 static const int PromotionZoneDistanceBonus[NO_ROWS] =
218 { 0, 0, 0, 0, 2, 6, 6, 8, 8 };
219 #else
220 static const int PromotionZoneDistanceBonus[NO_ROWS] =
221 { 0, 0, 2, 6, 8 }; /* FIXME ? */
222 #endif
224 #define MAX_BMBLTY 20
225 #define MAX_RMBLTY 20
226 #define MAX_LMBLTY 8
228 /* Bishop mobility bonus indexed by # reachable squares */
229 static const short BMBLTY[MAX_BMBLTY] =
230 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
232 /* Rook mobility bonus indexed by # reachable squares */
233 static const short RMBLTY[MAX_RMBLTY] =
234 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
236 #ifndef MINISHOGI
237 /* Lance mobility bonus indexed by # reachable squares */
238 static const short LMBLTY[MAX_LMBLTY] =
239 { 0, 0, 0, 0, 4, 6, 8, 10 };
240 #endif
242 static const short MBLTY[NO_PIECES] =
243 { 0, 2,
244 #ifndef MINISHOGI
245 1, 10,
246 #endif
247 5, 5, 1, 1, 5,
248 #ifndef MINISHOGI
249 5, 5,
250 #endif
251 5, 1, 1, 4 };
253 static const short KTHRT[36] =
254 { 0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
255 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
256 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80 };
258 static small_short fvalue[2][NO_FEATURES];
260 long attack[2][NO_SQUARES]; /* threats to squares */
261 small_short sseed[NO_SQUARES]; /* square occupied by a seed piece? */
263 struct signature threats_signature[2] = /* statistics valid for position.. */
264 { { -1, -1 }, { -1, -1 } }; /* attack and sseed available */
266 small_short starget[2][NO_SQUARES]; /* significance as a target for a
267 * side of a square */
268 small_short sloose[NO_SQUARES]; /* square occupied by a loose piece? */
269 small_short shole[NO_SQUARES]; /* empty square a hole? */
270 small_short shung[NO_SQUARES]; /* hung piece? */
272 struct signature squares_signature = /* statistics valid for position ... */
273 { 0, 0 }; /* starget, sloose, shole, shung available */
275 short target[2], seed[2], loose[2], hole[2];
277 short captured[2]; /* number of captured pieces */
278 short dcaptured[2]; /* different types of captured pieces */
280 small_short Kdist[2][NO_SQUARES]; /* distance to king */
282 short MAXADIST, MAXCDIST; /* maximum half move distance to pattern */
284 char GameType[2] = { UNKNOWN, UNKNOWN }; /* chosen game type of each side */
287 static short attack_opening_sequence[2]; /* current castle patterns */
288 static short castle_opening_sequence[2]; /* current attack formations */
290 static small_short Mpawn [2][NO_SQUARES];
291 static small_short Msilver[2][NO_SQUARES];
292 static small_short Mgold [2][NO_SQUARES];
293 static small_short Mking [2][NO_SQUARES];
294 #ifndef MINISHOGI
295 static small_short Mlance [2][NO_SQUARES];
296 static small_short Mknight[2][NO_SQUARES];
297 #endif
298 static small_short Mbishop[2][NO_SQUARES];
299 static small_short Mrook [2][NO_SQUARES];
301 static Mpiece_array Mpawn,
302 #ifndef MINISHOGI
303 Mlance, Mknight,
304 #endif
305 Msilver, Mgold, Mbishop, Mrook, Mking;
307 Mpiece_array *Mpiece[NO_PIECES] =
308 { NULL, &Mpawn,
309 #ifndef MINISHOGI
310 &Mlance, &Mknight,
311 #endif
312 &Msilver, &Mgold, &Mbishop, &Mrook,
313 &Mgold,
314 #ifndef MINISHOGI
315 &Mgold, &Mgold,
316 #endif
317 &Mgold, &Mbishop, &Mrook, &Mking };
320 static short c1, c2;
321 static small_short *PC1, *PC2;
322 static small_short *fv1;
323 static long *atk1, *atk2;
324 static long a1, a2;
326 #define csquare(side, sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
327 #define crow(side, sq) row(csquare(side, sq))
328 #define ccolumn(side, sq) column(csquare(side, sq))
331 inline static short
332 on_csquare(short side, short piece, short square)
334 short sq;
335 /* FIXME: un-obfuscate this! */
336 return ((board[sq = csquare(side, square)] == piece)
337 && (color[sq] == side));
341 inline static short
342 on_column(short side, short piece, short c)
344 short sq;
346 for (sq = c; sq < NO_SQUARES; sq += NO_COLS)
348 if (on_csquare(side, piece, sq))
349 return true;
352 return false;
356 #define empty_csquare(side, square) \
357 (board[csquare(side, square)] == no_piece)
359 inline static short
360 on_left_side(short side, short piece)
362 short c;
364 for (c = 0; c < 4; c++)
366 if (on_column(side, piece, c))
367 return true;
370 return false;
374 inline static short
375 on_right_side(short side, short piece)
377 short c;
379 for (c = 5; c < NO_COLS; c++)
381 if (on_column(side, piece, c))
382 return true;
385 return false;
389 short pscore[2]; /* piece score for each side */
395 * Fill array attack[side][] with info about attacks to a square. Bits
396 * 16-31 are set if the piece (king .. pawn) attacks the square. Bits 0-15
397 * contain a count of total attacks to the square. Fill array sseed[] with
398 * info about occupation by a seed piece.
401 void
402 threats(short side)
404 short u, sq;
405 long c;
406 long *a;
407 #ifdef SAVE_NEXTPOS
408 short d;
409 #else
410 unsigned char *ppos, *pdir;
411 #endif
412 short i, kd, piece, xside;
413 small_short *PL;
415 if (MatchSignature(threats_signature[side]))
417 /* data valid for current positional signature */
418 return;
421 a = attack[side];
422 xside = side ^ 1;
424 array_zero(a, NO_SQUARES * sizeof(a[0]));
426 PL = PieceList[side];
428 for (i = PieceCnt[side]; i >= 0; i--)
430 short ptyp;
432 sq = PL[i];
433 piece = board[sq];
434 ptyp = ptype[side][piece];
435 c = control[piece];
436 #ifdef SAVE_NEXTPOS
437 u = first_direction(ptyp, &d, sq);
438 #else
439 ppos = (*nextpos[ptyp])[sq];
440 pdir = (*nextdir[ptyp])[sq];
441 u = ppos[sq];
442 #endif
446 a[u] = ((a[u] + 1) | c);
448 if ((kd = Kdist[xside][u]) < 2)
450 sseed[sq] += 2 - kd;
451 seed[side]++;
454 #ifdef SAVE_NEXTPOS
455 u = ((color[u] == neutral)
456 ? next_position(ptyp, &d, sq, u)
457 : next_direction(ptyp, &d, sq));
458 #else
459 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
460 #endif
462 while (u != sq);
465 /* data valid for current positional signature */
466 CopySignature(threats_signature[side]);
472 * Compute the board square with nunmap offset "id". If side == white,
473 * offset is negated. inunmap[sq] is the corresponding nunmap index isq.
474 * nunmap[isq + id] computes the board square. If negative, it is outside
475 * the board.
478 static void
479 add_target(short sq, short side, short id)
481 short isq, tsq, xside;
482 isq = inunmap[sq];
483 tsq = (side == black) ? nunmap[isq + id] : nunmap[isq - id];
485 if (tsq >= 0)
487 target[xside = side^1]++;
489 if (attack[side][tsq])
490 starget[xside][tsq]++; /* protected target square */
491 else
492 starget[xside][tsq] += 2; /* unprotected target square */
499 * Target squares can be vertically ahead, diagonally ahead
500 * or diagonally behind.
503 static void
504 CheckTargetPiece(short sq, short side)
506 switch (board[sq])
508 case pawn: /* vertically ahead if unprotected */
509 if (!attack[side][sq])
510 add_target(sq, side, 11);
511 break;
513 case king: /* diagonally and vertically ahead */
514 add_target(sq, side, 10);
515 add_target(sq, side, 11);
516 add_target(sq, side, 12);
517 break;
519 case rook: /* diagonally ahead and behind */
520 add_target(sq, side, 10);
521 add_target(sq, side, 12);
522 add_target(sq, side, -10);
523 add_target(sq, side, -12);
524 break;
526 case bishop: /* vertically ahead */
527 add_target(sq, side, 11);
528 break;
530 #ifndef MINISHOGI
531 case knight: /* vertically ahead if advanced */
532 /* FIXME: gotta love them magic numbers... */
533 if ((sq != 1) && (sq != 7) && (sq != 73) && (sq != 79))
534 add_target(sq, side, 11);
535 break;
536 #endif
542 static short
543 ScoreKingOpeningFeatures(void)
545 short s = 0, sq = OwnKing, ds;
547 if (GameType[c1] == STATIC_ROOK)
549 /* Penalty for king on right side or fifth file */
550 short c;
551 c = 4 - ccolumn(c1, sq);
553 if ((c < 0) || ((c == 0) && (sq != kingP[c1])))
554 s += (ds = -c - c - fv1[OPENWRONG]);
556 else if (GameType[c1] == RANGING_ROOK)
558 /* Penalty for king on left side or fifth file */
559 short c;
560 c = 4 - ccolumn(c1, sq);
562 if ((c > 0) || ((c == 0) && (sq != kingP[c1])))
564 s += (ds = -c - c - fv1[OPENWRONG]);
567 /* Penalty for king moved before rook switch */
568 if (sq != kingP[c1])
570 if (on_csquare(c1, rook, 16))
572 s += (ds = -4 * fv1[OPENWRONG]);
575 else
577 /* Penalty for sitting king after rook switch */
578 if (!on_csquare(c1, rook, 16))
580 s += (ds = -2 * fv1[OPENWRONG]);
584 /* Penalty for defending general moved
585 * before king switch to right side */
586 if (ccolumn(c1, sq) < 6)
588 if (Mvboard[csquare(c1, 5)] || Mvboard[csquare(c1, 6)])
590 s += (ds = -2 * fv1[OPENWRONG]);
595 return s;
601 inline static void
602 ExamineSquares(void)
604 short sq, side, piece, n;
606 if (MatchSignature(squares_signature))
608 /* data valid for current positional signature */
609 return;
612 array_zero(shole, sizeof(shole));
613 array_zero(sloose, sizeof(sloose));
614 array_zero(starget, sizeof(starget));
616 hole[0] = hole[1] = loose[0] = loose[1]
617 = target[0] = target[1] = 0;
619 for (sq = 0; sq < NO_SQUARES; sq++)
621 if ((side = color[sq]) == neutral)
623 if (InWhiteCamp(sq))
625 if (!attack[white][sq])
627 shole[sq] = 1;
628 hole[white]++;
631 else if (InBlackCamp(sq))
633 if (!attack[black][sq])
635 shole[sq] = 1;
636 hole[black]++;
640 else
642 /* occupied by "side" piece */
643 if (!attack[side][sq])
645 sloose[sq] = 1;
646 loose[side]++;
649 CheckTargetPiece(sq, side);
653 for (side = black; side <= white; side++)
655 captured[side] = dcaptured[side] = 0;
657 for (piece = pawn; piece <= rook; piece++)
659 if ((n = Captured[side][piece]) != 0)
661 if (piece != pawn)
662 captured[side] += n;
664 dcaptured[side]++;
669 /* Data valid for current positional signature */
670 CopySignature(squares_signature);
675 /* ............ POSITIONAL EVALUATION ROUTINES ............ */
678 * Inputs are:
679 * mtl[side] - value of all material
680 * hung[side] - count of hung pieces
681 * Tscore[ply] - search tree score for ply ply
682 * Pscore[ply] - positional score for ply ply
683 * INCscore - bonus score or penalty for certain moves
684 * Sdepth - search goal depth
685 * xwndw - evaluation window about alpha/beta
686 * EWNDW - second evaluation window about alpha/beta
687 * ChkFlag[ply] - checking piece at level ply or 0 if no check
688 * TesujiFlag[ply] - 1 if tesuji move at level ply or 0 if no tesuji
689 * PC1[column] - # of my pawns in this column
690 * PC2[column] - # of opponents pawns in column
691 * PieceCnt[side] - just what it says
698 * Compute an estimate of the score by adding the positional score from the
699 * previous ply to the material difference. If this score falls inside a
700 * window which is 180 points wider than the alpha-beta window (or within a
701 * 50 point window during quiescence search) call ScorePosition() to
702 * determine a score, otherwise return the estimated score. "side" is the
703 * side which has to move.
707 evaluate(short side,
708 short ply,
709 short alpha,
710 short beta,
711 short INCscore,
712 short *InChk, /* output Check flag */
713 short *blockable) /* king threat blockable */
715 short xside;
716 short s;
718 xside = side ^ 1;
719 s = -Pscore[ply - 1] + mtl[side] - mtl[xside] /* - INCscore */;
720 hung[black] = hung[white] = 0;
722 /* should we use the estimete or score the position */
723 if ((ply == 1)
724 || (ply == Sdepth)
725 || (ply > Sdepth && s >= (alpha - 30) && s <= (beta + 30))
726 #ifdef CACHE
727 || (use_etable && CheckEETable(side))
728 #endif
731 short sq;
733 /* score the position */
734 array_zero(sseed, sizeof(sseed));
736 seed[0] = seed[1] = 0;
737 threats(side);
739 if (Anyattack(side, sq = PieceList[xside][0]) && (board[sq] == king))
741 *InChk = (board[sq = PieceList[side][0]] == king)
742 ? SqAttacked(sq, xside, blockable)
743 : false;
745 return ((SCORE_LIMIT + 1001) - ply);
748 threats(xside);
749 *InChk = (board[sq = PieceList[side][0]] == king)
750 ? Anyattack(xside, sq)
751 : false;
752 *blockable = true;
753 EvalNodes++;
755 if (ply > 4)
756 PUTVAR = true;
758 ExamineSquares();
759 s = ScorePosition(side);
760 PUTVAR = false;
762 else
764 /* use the estimate but look at check */
765 short sq;
767 *InChk = (board[sq = PieceList[side][0]] == king)
768 ? SqAttacked(sq, xside, blockable)
769 : false;
771 if ((board[sq = PieceList[xside][0]] == king)
772 && SqAttacked(sq, side, blockable))
774 return ((SCORE_LIMIT + 1001) - ply);
778 Pscore[ply] = s - mtl[side] + mtl[xside];
779 ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0);
781 return s;
786 static short
787 value_of_weakest_attacker(long a2)
789 short piece;
790 short min_value, v;
791 min_value = SCORE_LIMIT;
793 for (piece = pawn; piece <= king; piece++)
795 if (control[piece] & a2)
797 if (min_value > (v = (*value)[stage][piece]))
798 min_value = v;
802 return min_value;
809 * Find (promoted) Bishop, (promoted) Rook, and Lance mobility, x-ray
810 * attacks, and pins. Let BRL be the bishop, rook, or lance. Let P be the
811 * first piece (not a king or a pawn) in a direction and let Q be the
812 * second piece in the same direction. If Q is an unprotected opponent's
813 * piece with bigger relative value than BRL, there is a pin if P is an
814 * opponent's piece and there is an x-ray attack if P belongs to this side.
815 * Increment the hung[] array if a pin is found.
818 inline int
819 BRLscan(short sq, short *mob)
821 #ifdef SAVE_NEXTPOS
822 short d, dd;
823 #else
824 unsigned char *ppos, *pdir;
825 #endif
827 short s, mobx;
828 short u, xu, pin, ptyp, csq = column(sq);
829 short piece, upiece, xupiece, rvalue, ds;
830 small_short *Kd = Kdist[c2];
832 mobx = s = 0;
833 piece = board[sq];
835 rvalue = (*value)[stage][piece];
836 ptyp = ptype[c1][upiece = unpromoted[piece]];
837 rvalue = (*value)[stage][upiece];
839 #ifdef SAVE_NEXTPOS
840 u = first_direction(ptyp, &d, sq);
841 #else
842 ppos = (*nextpos[ptyp])[sq];
843 pdir = (*nextdir[ptyp])[sq];
844 u = ppos[sq];
845 #endif
847 pin = -1; /* start new direction */
851 if (Kd[u] < 2)
853 s += (ds = fv1[CTRLK] * (2 - Kd[u]));
856 if ((ds = starget[c1][u]) != 0)
858 /* threatening a target square */
859 if ((pin < 0) /* direct threat */
860 || (color[pin] == c2)) /* pin threat */
862 s += (ds *= fv1[TARGET]);
866 if ((ds = shole[u]) != 0)
868 /* attacking or protecting a hole */
869 s += (ds = fv1[HOLES]);
871 else if (InPromotionZone(c1, u))
873 /* attacking a square in promotion zone */
874 s += (ds = fv1[HOLES] / 2);
877 if (color[u] == neutral)
879 #ifdef SAVE_NEXTPOS
880 dd = d;
881 xu = next_position(ptyp, &d, sq, u);
883 if (xu == next_direction(ptyp, &dd, sq))
884 pin = -1; /* oops new direction */
885 #else
887 if ((xu = ppos[u]) == pdir[u])
888 pin = -1; /* oops new direction */
889 #endif
890 u = xu;
891 mobx++;
893 else
895 /* there is a piece in current direction */
896 if (pin < 0)
898 /* it's the first piece in the current direction */
899 if (color[u] == c1)
901 #ifndef MINISHOGI
902 /* own intercepting piece in x-ray attack */
903 if (upiece == lance)
905 /* lance x-ray */
906 if (board[u] == pawn)
908 s += (ds = 2*fv1[PROTECT]);
910 else if (in_opening_stage)
912 s += (ds = -2*fv1[PROTECT]);
915 else
916 #endif
918 /* bishop or rook x-ray */
919 if ((upiece == bishop) && (board[u] == pawn)
920 && (GameType[c1] == STATIC_ROOK))
922 s += (ds = -2*fv1[HCLSD]);
924 #ifndef MINISHOGI
925 else if ((upiece == rook) && (board[u] == lance)
926 && (GameType[c1] == STATIC_ROOK)
927 && (column(u) == csq))
929 s += (ds = fv1[XRAY]);
931 #endif
934 else
936 /* enemy's intercepting piece in pin attack */
937 #ifndef MINISHOGI
938 if (upiece == lance)
940 /* lance pin attack */
941 if (board[u] == pawn)
943 s += (ds = -2*fv1[PROTECT]);
945 else if (in_opening_stage)
947 s += (ds = 2 * fv1[PROTECT]);
950 else
951 #endif
953 /* bishop or rook pin attack */
954 if (board[u] == pawn)
956 s += (ds = -fv1[HCLSD]);
961 #ifdef SAVE_NEXTPOS
962 dd = d;
963 xu = next_position(ptyp, &d, sq, u);
965 if (xu != next_direction(ptyp, &dd, sq))
966 pin = u; /* not on the edge and on to find a pin */
967 #else
968 if ((xu = ppos[u]) != pdir[u])
969 pin = u; /* not on the edge and on to find a pin */
970 #endif
971 u = xu;
973 else
975 /* it's the second piece in the current direction */
977 if (color[u] == c1)
979 /* second piece is an own piece */
980 if ((upiece == bishop) && (board[u] == pawn)
981 && (GameType[c1] == STATIC_ROOK))
983 s += (ds = -fv1[HCLSD]);
986 else
988 /* second piece is an enemy piece */
989 if (upiece == bishop && board[u] == pawn)
991 s += (ds = -fv1[HCLSD]/2);
994 if (((*value)[stage][xupiece = unpromoted[board[u]]]
995 > rvalue)
996 || (atk2[u] == 0))
998 if (color[pin] == c2)
1000 if ((xupiece == king) && (in_endgame_stage))
1002 s += (ds = 2 * fv1[PINVAL]);
1004 else
1006 s += (ds = fv1[PINVAL]);
1009 if ((atk2[pin] == 0)
1010 || (atk1[pin] > control[board[pin]] + 1))
1012 hung[c2]++;
1013 shung[u]++;
1016 else
1018 #ifndef MINISHOGI
1019 if (upiece == lance)
1021 s += (ds = fv1[XRAY] / 2);
1023 else
1024 #endif
1026 s += (ds = fv1[XRAY]);
1032 pin = -1; /* new direction */
1034 #ifdef SAVE_NEXTPOS
1035 u = next_direction(ptyp, &d, sq);
1036 #else
1037 u = pdir[u];
1038 #endif
1042 while (u != sq);
1044 *mob = mobx;
1046 return s;
1050 #define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp)
1055 * Assign penalties if king can be threatened by checks, if squares near
1056 * the king are controlled by the enemy (especially by promoted pieces), or
1057 * if there are no own generals near the king.
1059 * The following must be true:
1060 * board[sq] == king, c1 == color[sq], c2 == otherside[c1]
1063 #define SCORETHREAT \
1065 if (color[u] != c2) \
1067 if ((atk1[u] == 0) || ((atk2[u] & CNT_MASK) != 0)) \
1069 ++cnt; \
1071 else \
1073 s += (ds = -fv1[CTRLK]); \
1081 inline short
1082 KingScan(short sq)
1084 short cnt;
1086 #ifdef SAVE_NEXTPOS
1087 short d;
1088 #else
1089 unsigned char *ppos, *pdir;
1090 #endif
1092 short s;
1093 short u, ptyp;
1094 short ok, ds;
1096 /* Penalties, if a king can be threatened by checks. */
1098 s = 0;
1099 cnt = 0;
1102 short p;
1104 for (p = pawn; p < king; p++)
1106 if (HasPiece[c2][p] || Captured[c2][p])
1108 short ptyp;
1110 /* if a c1 piece can reach u from sq,
1111 * then a c2 piece can reach sq from u.
1112 * That means, each u is a square, from which a
1113 * piece of type p and color c2 threats square sq.
1115 ptyp = ptype[c1][p];
1117 #ifdef SAVE_NEXTPOS
1118 u = first_direction(ptyp, &d, sq);
1119 #else
1120 ppos = (*nextpos[ptyp])[sq];
1121 pdir = (*nextdir[ptyp])[sq];
1122 u = ppos[sq];
1123 #endif
1127 /* If a p piece can reach (controls or can drop to)
1128 * square u, then score threat.
1131 if (atk2[u] & control[p])
1132 SCORETHREAT
1133 else if ((Captured[c2][p] && color[u]) == neutral)
1134 SCORETHREAT
1136 #ifdef SAVE_NEXTPOS
1137 u = ((color[u] == neutral)
1138 ? next_position(ptyp, &d, sq, u)
1139 : next_direction(ptyp, &d, sq));
1140 #else
1141 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1142 #endif
1144 while (u != sq);
1149 s += (ds = fv1[KSFTY] * KTHRT[cnt] / 16);
1151 /* Penalties, if squares near king are controlled by enemy. */
1153 cnt = 0;
1154 ok = false;
1155 ptyp = ptype[c1][king];
1157 #ifdef SAVE_NEXTPOS
1158 u = first_direction(ptyp, &d, sq);
1159 #else
1160 pdir = (*nextpos[ptyp])[sq];
1161 u = pdir[sq];
1162 #endif
1166 if (!ok && color[u] == c1)
1168 short ptype_piece = ptype[black][board[u]];
1170 if ((ptype_piece == ptype_silver) || (ptype_piece == ptype_gold))
1171 ok = true;
1174 if (atk2[u] > atk1[u])
1176 ++cnt;
1178 if (atk2[u] & ctlSG)
1180 s += (ds = -fv1[KSFTY] / 2);
1184 #ifdef SAVE_NEXTPOS
1185 u = next_direction(ptyp, &d, sq);
1186 #else
1187 u = pdir[u];
1188 #endif
1190 while (u != sq);
1192 if (!ok || (cnt > 1))
1194 if (cnt > 1)
1195 s += (ds = -fv1[KSFTY]/2);
1196 else
1197 s += (ds = -fv1[KSFTY]);
1200 return s;
1204 static short checked_trapped;
1208 * See if the attacked piece has unattacked squares to move to. The following
1209 * must be true: c1 == color[sq] c2 == otherside[c1]
1212 inline int
1213 trapped(short sq)
1215 short u, ptyp;
1216 #ifdef SAVE_NEXTPOS
1217 short d;
1218 #else
1219 unsigned char *ppos, *pdir;
1220 #endif
1221 short piece;
1222 short rvalue;
1224 piece = board[sq];
1225 rvalue = (*value)[stage][piece];
1226 ptyp = ptype[c1][piece];
1228 #ifdef SAVE_NEXTPOS
1229 u = first_direction(ptyp, &d, sq);
1230 #else
1231 ppos = (*nextpos[ptyp])[sq];
1232 pdir = (*nextdir[ptyp])[sq];
1233 u = ppos[sq];
1234 #endif
1238 if (color[u] != c1)
1240 if ((atk2[u] == 0) || ((*value)[stage][board[u]] >= rvalue))
1241 return false;
1244 #ifdef SAVE_NEXTPOS
1245 u = ((color[u] == neutral)
1246 ? next_position(ptyp, &d, sq, u)
1247 : next_direction(ptyp, &d, sq));
1248 #else
1249 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1250 #endif
1252 while (u != sq);
1254 checked_trapped = true;
1256 return true;
1261 static int
1262 AttackedPieceValue(short sq)
1264 short s;
1266 s = 0;
1268 hung[c1]++;
1269 shung[sq]++;
1271 if (trapped(sq))
1273 hung[c1] += 2;
1274 shung[sq] += 2;
1277 return s;
1282 static inline int
1283 OpenFileValue(short sq, short hopn, short hopnx)
1285 short s = 0, fyle;
1287 if (PC1[fyle = column(sq)] == 0)
1289 s += hopn;
1292 if (PC2[fyle] == 0)
1294 s += hopnx;
1297 return s;
1303 /* Distance bonus */
1305 #define PromotionZoneDistanceValue(sq, dd) \
1306 if ((ds = fv1[PROMD])) \
1308 s += (ds = ds * PromotionZoneDistanceBonus[crow(c1, sq)] * dd); \
1311 #define OwnKingDistanceValue(sq, dd, maxd) \
1312 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd)) \
1314 s += (ds = ds * OwnKingDistanceBonus[ad] * dd); \
1317 #define EnemyKingDistanceValue(sq, dd, maxd) \
1318 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd)) \
1320 s += (ds = ds * EnemyKingDistanceBonus[ad] * dd); \
1328 * Calculate the positional value for a pawn on 'sq'.
1331 static inline int
1332 PawnValue(short sq, short side)
1334 short s = 0;
1335 short ds;
1336 short ccol = ccolumn(c1, sq);
1338 PromotionZoneDistanceValue(sq, 3);
1340 /* pawn mobility */
1341 if (color[(c1 == black) ? (sq + NO_COLS) : (sq - NO_COLS)] == neutral)
1343 s += (ds = MBLTY[pawn]);
1346 if ((a1 & ((ctlR | ctlRp) | ctlL)))
1348 s += (ds = fv1[ATTACKED]);
1351 if (in_opening_stage)
1353 #ifndef MINISHOGI
1354 /* FIXME: [HGM] The 3rd-rank Pawn section is meaningless in mini-Shogi,
1355 * (which does not have opposing Pawns), and can do out-of-bound access,
1356 * as the promotion zone is only 1 rank, so Pawns can be closer than 3 ranks
1357 * to the board edge.
1359 if (crow(c1, sq) == 2) /* pawn on 3d rank */
1361 if (board[(c1 == black) ?
1362 (sq + 3*NO_COLS) : (sq - 3*NO_COLS)] == pawn)
1364 /* opposing pawn has been moved (even column == (sq & 1)) */
1366 short m;
1368 switch (ccol)
1370 case 0:
1371 case 8:
1372 m = (side == c1) ? 3 : 5;
1373 break;
1375 case 4:
1376 m = (side == c1) ? 2 : 3;
1377 break;
1379 default:
1380 m = (side == c1) ? 1 : 2;
1381 break;
1384 s += (ds = -m * MBLTY[pawn]);
1388 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1389 * board - and anyway we don't know the stage really :)
1391 if ((GameType[c1] == STATIC_ROOK) && (sq == csquare(c1, 43)))
1393 if ((atk2[csquare(c1, 52)] & CNT_MASK) < 2)
1395 s += (ds = fv1[ATTACKED]);
1399 if ((GameType[c2] == STATIC_ROOK) && (ccol == 1))
1401 if (sq == csquare(c1, 28))
1403 s += (ds = -fv1[ATTACKED]);
1406 if (((atk1[csquare(c1, 19)] & CNT_MASK) < 2)
1407 && ((atk1[csquare(c1, 28)] & CNT_MASK) < 2))
1409 s += (ds = -2 * fv1[ATTACKED]);
1412 #endif
1415 return s;
1419 #ifndef MINISHOGI
1421 * Calculate the positional value for a lance on 'sq'.
1424 static inline int
1425 LanceValue(short sq)
1427 short s = 0, ds, ad;
1429 OwnKingDistanceValue(sq, 1, 2);
1431 OpenFileValue(sq, -fv1[HOPN], fv1[HOPN]);
1433 if (!checked_trapped && (crow(c1, sq) > 2))
1435 if (in_opening_stage || trapped(sq))
1437 s += (ds = -3 * fv1[ATTACKED]);
1439 else
1441 s += (ds = -2 * fv1[ATTACKED]);
1445 return s;
1451 * Calculate the positional value for a knight on 'sq'.
1454 static inline int
1455 KnightValue(short sq)
1457 short s = 0, ad;
1458 short ds, checked_trapped = false;
1459 short c = column(sq);
1461 PromotionZoneDistanceValue(sq, 1);
1462 OwnKingDistanceValue(sq, 1, 2);
1464 if (!checked_trapped && (crow(c1, sq) > 2))
1466 if (trapped(sq))
1468 s += (ds = -4 * fv1[ATTACKED]);
1470 else
1472 s += (ds = -3 * fv1[ATTACKED]);
1476 if ((c == 0) || (c == 8))
1478 s += (ds = -fv1[ATTACKED]);
1481 return s;
1483 #endif
1488 * Calculate the positional value for a silver on 'sq'.
1491 static inline int
1492 SilverValue(short sq)
1494 short s= 0, ds, ad;
1496 OwnKingDistanceValue(sq, 2, 3);
1498 if ((Kdist[c1][sq] < 3)
1499 && (atk1[sq] & (control[gold] | control[silver])))
1501 s += (ds = fv1[COHESION]);
1504 if (in_opening_stage)
1506 #ifndef MINISHOGI
1507 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1508 * board - and anyway we don't know the stage really :)
1510 if (GameType[c1] == STATIC_ROOK)
1512 if (csquare(c1, sq) == 12)
1514 short csq;
1516 if ((board[csq = csquare(c1, 20)] == bishop)
1517 && (color[csq] == c1))
1519 s += (ds = -2 * fv1[OPENWRONG]);
1523 #endif
1525 else
1527 EnemyKingDistanceValue(sq, 2, 3);
1530 return s;
1536 * Calculate the positional value for a gold on 'sq'.
1539 static inline int
1540 GoldValue(short sq)
1542 short s = 0, ds, ad;
1544 OwnKingDistanceValue(sq, 2, 3);
1546 if ((Kdist[c1][sq] < 3)
1547 && (atk1[sq] & (control[gold] | control[silver])))
1549 s += (ds = fv1[COHESION]);
1552 if (in_opening_stage)
1554 #ifndef MINISHOGI
1555 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1556 * board - and anyway we don't know the stage really :)
1558 if ((GameType[c1] == STATIC_ROOK) && (GameType[c2] != STATIC_ROOK))
1560 if (Mvboard[csquare(c1, 3)])
1562 s += (ds = -2 * fv1[OPENWRONG]);
1565 #endif
1567 else
1569 EnemyKingDistanceValue(sq, 2, 3);
1572 return s;
1578 * Calculate the positional value for a bishop on 'sq'.
1581 static inline int
1582 BishopValue(short sq)
1584 short s = 0, ds, ad;
1586 if (in_opening_stage)
1588 #ifndef MINISHOGI
1589 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1590 * board - and anyway we don't know the stage really :)
1592 if (GameType[c1] == RANGING_ROOK)
1594 /* Bishops diagonal should not be open */
1595 if (!on_csquare(c1, pawn, 30))
1597 s += (ds = -fv1[OPENWRONG]);
1600 else if (GameType[c2] == RANGING_ROOK)
1602 /* Bishops diagonal should be open */
1603 if ((csquare(c1, sq) == 10)
1604 && (!empty_csquare(c1, 20) || !empty_csquare(c1, 30)))
1606 s += (ds = -fv1[OPENWRONG]);
1608 else if ((csquare(c1, sq) == 20) && !empty_csquare(c1, 30))
1610 s += (ds = -fv1[OPENWRONG]);
1613 #endif
1615 else
1617 EnemyKingDistanceValue(sq, 1, 3);
1620 return s;
1626 * Calculate the positional value for a rook on 'sq'.
1629 static inline int
1630 RookValue(short sq, short side)
1632 short s = 0, ds, ad;
1634 OpenFileValue(sq, 2 * fv1[HOPN], 4*fv1[HOPN]);
1636 if (in_opening_stage)
1638 #ifndef MINISHOGI
1639 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1640 * board - and anyway we don't know the stage really :)
1642 short WRONG = fv1[OPENWRONG], OPOK = WRONG / 3;
1644 if (GameType[c1] == STATIC_ROOK)
1646 short c = ccolumn(c1, sq);
1648 /* Bonus for rook on 8th file */
1649 if (c == 7)
1651 s += (ds = OPOK);
1655 * Bonus for rook on right side,
1656 * penalty for rook on left side
1659 c = 4 - c;
1660 ds = 0;
1662 if (c < 0)
1664 s += (ds = c + c + OPOK);
1666 else if (c >= 0)
1668 s += (ds = -c - c - WRONG);
1671 else if (GameType[c1] == RANGING_ROOK)
1673 /* Bonus for rook on left side and
1674 * bishops diagonal closed, penalty otherwise. */
1676 short c;
1677 c = 4 - ccolumn(c1, sq);
1678 ds = 0;
1680 if (c >= 0)
1682 /* Bishops diagonal should not be open. */
1683 if (on_csquare(c1, pawn, 30))
1684 s += (ds = OPOK);
1685 else
1686 s += (ds = -c - c - WRONG);
1688 else if (c < 0)
1690 s += (ds = -c - c - WRONG);
1692 /* Penalty for king not on initial square. */
1693 if (!on_csquare(side, king, 4))
1695 s += -4 * WRONG;
1696 ds += -4 * WRONG;
1700 #endif
1702 else
1704 EnemyKingDistanceValue(sq, 1, 3);
1707 return s;
1713 * Calculate the positional value for a promoted pawn on 'sq'.
1716 static inline int
1717 PPawnValue(short sq)
1719 short s = 0, ds, ad;
1721 EnemyKingDistanceValue(sq, 3, 10);
1723 return s;
1728 #ifndef MINISHOGI
1730 * Calculate the positional value for a promoted lance on 'sq'.
1733 static inline int
1734 PLanceValue(short sq)
1736 short s = 0, ds, ad;
1738 EnemyKingDistanceValue(sq, 3, 10);
1740 return s;
1746 * Calculate the positional value for a promoted knight on 'sq'.
1749 static inline int
1750 PKnightValue(short sq)
1752 short s = 0, ds, ad;
1754 EnemyKingDistanceValue(sq, 3, 10);
1756 return s;
1758 #endif
1763 * Calculate the positional value for a promoted silver on 'sq'.
1766 static inline int
1767 PSilverValue(short sq)
1769 short s = 0, ds, ad;
1771 EnemyKingDistanceValue(sq, 3, 10);
1773 return s;
1779 * Calculate the positional value for a promoted bishop on 'sq'.
1782 static inline int
1783 PBishopValue(short sq)
1785 short s = 0, ds, ad;
1787 EnemyKingDistanceValue(sq, 3, 4);
1789 return s;
1795 * Calculate the positional value for a promoted rook on 'sq'.
1798 static inline int
1799 PRookValue(short sq)
1801 short s = 0, ds, ad;
1803 EnemyKingDistanceValue(sq, 3, 4);
1805 OpenFileValue(sq, 3 * fv1[HOPN], 2 * fv1[HOPN]);
1807 return s;
1813 * Calculate the positional value for a king on 'sq'.
1816 static inline int
1817 KingValue(short sq)
1819 short s = 0, ds;
1821 if (fv1[KSFTY] != 0)
1822 s += KingScan(sq);
1824 #ifndef MINISHOGI
1825 /* FIXME: calculations below are wrong for minishogi, all done for 9x9
1826 * board - and anyway we don't know the stage really :)
1828 if (in_opening_stage)
1830 if ((GameType[c1] != UNKNOWN) && (ccolumn(c1, sq) == 4))
1832 s += (ds = -fv1[OPENWRONG] / 3);
1834 else if ((GameType[c1] == STATIC_ROOK) && on_right_side(c1, sq))
1836 s += (ds = -fv1[OPENWRONG] / 2);
1838 else if ((GameType[c1] == RANGING_ROOK) && on_left_side(c1, sq))
1840 s += (ds = -fv1[OPENWRONG] / 2);
1843 #endif
1845 /* CHECKME: is this correct? */
1846 if ((ds = fv1[HOPN]))
1848 s += OpenFileValue(sq, -2 * ds, -4 * ds);
1851 return s;
1857 * Calculate the positional value for a piece on 'sq'.
1860 static inline int
1861 PieceValue(short sq, short side)
1863 short s, piece, ds;
1864 short mob;
1866 piece = board[sq];
1868 if (piece == no_piece)
1869 return 0;
1871 s = (*Mpiece[piece])[c1][sq];
1873 checked_trapped = false;
1875 if (sweep[piece])
1877 /* pin/x-ray attack and mobility for sweeping pieces */
1878 s += (ds = BRLscan(sq, &mob));
1880 if ((piece == bishop) || (piece == pbishop))
1881 s += (ds = BMBLTY[mob] * fv1[MOBILITY] / 100);
1882 else if ((piece == rook) || (piece == prook))
1883 s += (ds = RMBLTY[mob] * fv1[MOBILITY] / 100);
1884 #ifndef MINISHOGI
1885 else
1886 s += (ds = LMBLTY[mob] * fv1[MOBILITY] / 100);
1887 #endif
1889 else
1891 /* mobility for non-sweeping pieces */
1894 a2 = atk2[sq];
1895 a1 = atk1[sq];
1897 if (a2 > 0)
1899 /* opponent attacks piece */
1900 if (a1 == 0)
1902 /* undefended piece */
1903 s += AttackedPieceValue(sq);
1905 else
1907 /* defended piece */
1908 short attack_value = value_of_weakest_attacker(a2);
1909 short piece_value = (*value)[stage][piece];
1911 if (attack_value < piece_value)
1913 /* attacked by a weaker piece */
1914 s += AttackedPieceValue(sq) / 2;
1916 else if (abs(attack_value - piece_value) < 10)
1918 /* opponent has the option to exchange equal pieces */
1919 s += (ds = -fv1[ATTACKED]);
1924 if (piece != king)
1927 if (a1 > 0)
1929 /* piece is defended */
1930 s += (ds = (a1 & CNT_MASK) * fv1[PROTECT]);
1933 if (sseed[sq])
1935 s += (ds = fv1[SEED]);
1938 if (sloose[sq])
1940 s += (ds = -fv1[LOOSE]);
1943 if (starget[c1][sq])
1945 if (sweep[piece])
1947 s -= (ds = -fv1[ATTACKED]/2);
1949 else if (piece == pawn)
1951 s += (ds = fv1[ATTACKED]);
1955 if (starget[c2][sq])
1957 if (piece != pawn)
1959 s -= (ds = -fv1[ATTACKED] / 3);
1961 else
1963 s += (ds = fv1[ATTACKED]);
1967 if (Kdist[c1][sq] == 1)
1969 s += (ds = fv1[KSFTY]);
1973 switch (piece)
1975 case pawn:
1976 s += PawnValue(sq, side);
1977 break;
1979 #ifndef MINISHOGI
1980 case lance:
1981 s += LanceValue(sq);
1982 break;
1984 case knight:
1985 s += KnightValue(sq);
1986 break;
1987 #endif
1989 case silver:
1990 s += SilverValue(sq);
1991 break;
1993 case gold:
1994 s += GoldValue(sq);
1995 break;
1997 case bishop:
1998 s += BishopValue(sq);
1999 break;
2001 case rook:
2002 s += RookValue(sq, side);
2003 break;
2005 case king:
2006 s += KingValue(sq);
2007 break;
2009 case ppawn:
2010 s += PPawnValue(sq);
2011 break;
2013 #ifndef MINISHOGI
2014 case plance:
2015 s += PLanceValue(sq);
2016 break;
2018 case pknight:
2019 s += PKnightValue(sq);
2020 break;
2021 #endif
2023 case psilver:
2024 s += PSilverValue(sq);
2025 break;
2027 case pbishop:
2028 s += PBishopValue(sq);
2029 break;
2031 case prook:
2032 s += PRookValue(sq);
2033 break;
2036 return s;
2042 * Score distance to pattern regarding the game type which side plays.
2045 short
2046 ScorePatternDistance(short c1)
2048 short ds, s = 0;
2049 small_short *fv1 = fvalue[c1];
2050 short os = 0;
2052 if ((MAXCDIST > 0) && (fv1[PCASTLE] != 0)
2053 && ((os = castle_opening_sequence[c1]) >= 0))
2055 ds = board_to_pattern_distance(c1, os, MAXCDIST, GameCnt);
2057 if (ds != 0)
2059 s += (ds *= fv1[PCASTLE]);
2063 if ((MAXADIST > 0) && (fv1[PATTACK] != 0)
2064 && ((os = attack_opening_sequence[c1]) >= 0))
2066 ds = board_to_pattern_distance(c1, os, MAXADIST, GameCnt);
2068 if (ds != 0)
2070 s += (ds *= fv1[PATTACK]);
2074 return s;
2081 * Determine castle and attack pattern which should be reached next.
2082 * Only patterns are considered, which have not been reached yet.
2085 static void
2086 UpdatePatterns(short side, short GameCnt)
2088 char s[12];
2089 short xside = side ^ 1;
2090 short os;
2091 short j, k, n = 0;
2093 strcpy(s, "CASTLE_?_?");
2094 s[7] = GameType[side];
2095 s[9] = GameType[xside];
2096 castle_opening_sequence[side] = os
2097 = locate_opening_sequence(side, s, GameCnt);
2099 if (flag.post && (os != END_OF_SEQUENCES))
2101 for (j = 0; j < MAX_SEQUENCE; j++)
2103 for (k = OpeningSequence[os].first_pattern[j];
2104 k != END_OF_PATTERNS;
2105 k = Pattern[k].next_pattern)
2107 if (Pattern[k].distance[side] >= 0)
2108 n++;
2113 if (os != END_OF_SEQUENCES)
2114 update_advance_bonus(side, os);
2116 strcpy(s, "ATTACK_?_?");
2117 s[7] = GameType[side];
2118 s[9] = GameType[xside];
2119 attack_opening_sequence[side] = os
2120 = locate_opening_sequence(side, s, GameCnt);
2122 if (flag.post && (os != END_OF_SEQUENCES))
2124 for (j = 0; j < MAX_SEQUENCE; j++)
2126 for (k = OpeningSequence[os].first_pattern[j];
2127 k != END_OF_PATTERNS;
2128 k = Pattern[k].next_pattern)
2130 if (Pattern[k].distance[side] >= 0)
2131 n++;
2136 if (flag.post)
2137 dsp->ShowPatternCount(side, n);
2139 if (os != END_OF_SEQUENCES)
2140 update_advance_bonus(side, os);
2145 static void
2146 ScoreCaptures(void)
2148 short ds, col, n, m, piece;
2150 if ((n = Captured[c1][pawn]))
2152 ds = m = 0;
2154 for (col = 0; col < NO_COLS; col++)
2156 if (!PC1[col])
2158 m++;
2159 ds += fv1[PWNDROP];
2163 /* FIXME! another great obfuscated line... */
2164 pscore[c1] += (ds *= ((n > 2) ? 3 : n));
2167 if ((m = seed[c1]))
2169 for (piece = pawn+1, n = 0; piece <= rook; piece++)
2171 if (Captured[c1][piece])
2172 n++;
2175 pscore[c1] += (ds = m * fv1[DFFDROP]);
2178 for (piece = pawn, n = 0; piece <= rook; piece++)
2180 if (Captured[c1][piece])
2182 switch (piece)
2184 case bishop:
2185 ds = BMBLTY[MAX_BMBLTY - 1];
2186 break;
2188 case rook:
2189 ds = RMBLTY[MAX_RMBLTY - 1];
2190 break;
2192 #ifndef MINISHOGI
2193 case lance:
2194 ds = LMBLTY[MAX_LMBLTY - 1];
2195 break;
2196 #endif
2198 default:
2199 ds = MBLTY[piece];
2202 pscore[c1] += ds;
2204 if (!Captured[c2][piece])
2205 n += relative_value[piece];
2209 if (n)
2211 pscore[c1] += (ds = -n * fv1[OPPDROP] / 2);
2220 * Perform normal static evaluation of board position. A score is generated
2221 * for each piece and these are summed to get a score for each side.
2224 short
2225 ScorePosition(short side)
2227 short score;
2228 short sq, i, xside;
2229 short s;
2230 short ds;
2232 xside = side ^ 1;
2234 UpdateWeights(side);
2236 hung[black] = hung[white] = pscore[black] = pscore[white] = 0;
2238 array_zero(shung, sizeof(shung));
2240 #ifdef CACHE
2241 if (!(use_etable && ProbeEETable(side, &s)))
2243 #endif
2244 for (c1 = black; c1 <= white; c1++)
2246 c2 = c1 ^ 1;
2248 /* atk1 is array of attacks on squares by my side */
2249 atk1 = attack[c1];
2251 /* atk2 is array of attacks on squares by other side */
2252 atk2 = attack[c2];
2254 /* same for PC1 and PC2 */
2255 PC1 = PawnCnt[c1];
2256 PC2 = PawnCnt[c2];
2258 /* same for fv1 and fv2 */
2259 fv1 = fvalue[c1];
2261 for (i = PieceCnt[c1]; i >= 0; i--)
2263 sq = PieceList[c1][i];
2265 #if defined SAVE_SVALUE
2266 pscore[c1] += PieceValue(sq, side);
2267 #else
2268 pscore[c1] += (svalue[sq] = PieceValue(sq, side));
2269 #endif
2272 ScoreCaptures();
2275 #ifndef MINISHOGI
2276 # define BLACKHOME_START 0
2277 # define BLACKHOME_END 26
2278 # define MIDDLEROW_START 36
2279 # define MIDDLEROW_END 44
2280 # define WHITEHOME_START 54
2281 # define WHITEHOME_END 80
2282 #else
2283 # define BLACKHOME_START 0
2284 # define BLACKHOME_END 4
2285 # define MIDDLEROW_START 10
2286 # define MIDDLEROW_END 14
2287 # define WHITEHOME_START 19
2288 # define WHITEHOME_END 24
2289 #endif
2290 for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2292 short n;
2294 fv1 = fvalue[c1];
2296 /* Score fifth rank */
2297 for (sq = MIDDLEROW_START, n = 0; sq <= MIDDLEROW_END; sq++)
2299 if ((color[sq] == c1) || (attack[c1][sq] != 0))
2300 n++;
2303 if (n != 0)
2305 pscore[c1] += (ds = n * fv1[CNTRL5TH]);
2308 /* Score holes */
2309 for (sq = ((c1 == black) ? BLACKHOME_START : WHITEHOME_START), n = 0;
2310 sq <= ((c1 == black) ? BLACKHOME_END : WHITEHOME_END);
2311 sq++)
2313 if (board[sq] == no_piece && attack[c1][sq] == 0)
2314 n++;
2317 if (n != 0)
2319 pscore[c1] += (ds = -n * fv1[HOLES]);
2322 if (hung[c1] > 1)
2324 pscore[c1] += (ds = -fv1[HUNGX]);
2327 /* Score opening features and
2328 * castle/attack pattern distances */
2330 if (in_opening_stage)
2332 pscore[c1] += (ds = ScoreKingOpeningFeatures());
2333 pscore[c1] += (ds = ScorePatternDistance(c1));
2337 score = mtl[side] - mtl[xside]
2338 + pscore[side] - pscore[xside] + 10;
2340 #ifdef CACHE
2341 if (use_etable && PUTVAR)
2342 PutInEETable(side, score);
2343 #endif
2345 return score;
2346 #ifdef CACHE /* CHECKME: this looks bad */
2349 return s;
2350 #endif
2356 * Try to determine the game type of "side".
2359 #ifndef MINISHOGI
2360 inline static void
2361 GuessGameType(short side_to_move)
2363 short side, gt;
2364 short StaticRook[2] = { 0, 0 };
2365 short RangingRook[2] = { 0, 0 };
2367 for (side = black; side <= white; side++)
2369 /* computer should not change its mind */
2371 extern int bookflag;
2373 gt = GameType[side];
2375 if (!bookflag && (side == side_to_move))
2377 if (gt == STATIC_ROOK)
2378 StaticRook[side] += 4;
2379 else if (gt == RANGING_ROOK)
2380 RangingRook[side] += 4;
2383 /* static rook conditions */
2385 if (on_column(side, rook, 7))
2386 StaticRook[side] += 3;
2388 if (on_csquare(side, pawn, 34))
2389 StaticRook[side] += 6;
2390 else if (on_csquare(side, pawn, 43))
2391 StaticRook[side] += 4;
2392 else if (!on_column(side, pawn, 7))
2393 StaticRook[side] += 5;
2395 if (empty_csquare(side, 5) || empty_csquare(side, 6))
2396 StaticRook[side] += 2;
2398 if (on_left_side(side, king))
2399 StaticRook[side] += 2;
2401 /* ranging rook conditions */
2403 if (on_left_side(side, rook))
2404 RangingRook[side] += 5;
2405 else if (!on_column(side, rook, 7))
2406 RangingRook[side] += 3;
2408 if (on_csquare(side, pawn, 25))
2409 RangingRook[side] += 1;
2411 if (on_csquare(side, pawn, 30))
2412 RangingRook[side] += 1;
2413 else
2414 RangingRook[side] -= 2;
2416 if (!on_right_side(side, rook))
2417 RangingRook[side] += 4;
2419 if (on_right_side(side, king))
2420 RangingRook[side] += 4;
2422 if (on_csquare(side, bishop, 20))
2424 if (on_csquare(side, silver, 11)
2425 || on_csquare(side, silver, 12)
2426 || on_csquare(side, silver, 21))
2428 RangingRook[side] += 3;
2432 if ((StaticRook[side] > 5) || (RangingRook[side] > 5))
2434 GameType[side] = (StaticRook[side] > RangingRook[side])
2435 ? STATIC_ROOK : RANGING_ROOK;
2437 else
2439 GameType[side] = UNKNOWN;
2443 if ((GameType[black] == UNKNOWN) || (GameType[white] == UNKNOWN))
2445 for (side = black; side <= white; side++)
2447 if ((side == computer) && (GameType[side] == UNKNOWN))
2450 * Game type is UNKNOWN.
2451 * Make a decision what type of game to play.
2452 * To make computer games more interesting, make a
2453 * random decision.
2456 if (!on_csquare(side, pawn, 25))
2458 /* Play static rook if rook pawn has been pushed! */
2459 GameType[side] = STATIC_ROOK;
2461 else
2463 unsigned int random = urand() % 100;
2464 short d = StaticRook[side] - RangingRook[side];
2466 switch (GameType[side ^ 1])
2468 case STATIC_ROOK:
2469 if (random < 35 + d)
2470 GameType[side] = STATIC_ROOK;
2471 else if (random < 95)
2472 GameType[side] = RANGING_ROOK;
2473 break;
2475 case RANGING_ROOK:
2476 if (random < 75 + d)
2477 GameType[side] = STATIC_ROOK;
2478 else if (random < 95)
2479 GameType[side] = RANGING_ROOK;
2480 break;
2482 default:
2483 if (random < 33 + d)
2484 GameType[side] = STATIC_ROOK;
2485 else if (random < 66)
2486 GameType[side] = RANGING_ROOK;
2493 #endif
2498 static void
2499 DetermineGameType(short side_to_move)
2501 short side;
2503 #ifndef MINISHOGI
2504 /* FIXME: calculations below are wrong for minishogi, all done for 9x9 */
2505 GuessGameType(side_to_move);
2506 #else
2507 GameType[black] = UNKNOWN;
2508 GameType[white] = UNKNOWN;
2509 #endif
2511 array_zero(Mpawn, sizeof(Mpawn));
2512 #ifndef MINISHOGI
2513 array_zero(Mlance, sizeof(Mlance));
2514 array_zero(Mknight, sizeof(Mknight));
2515 #endif
2516 array_zero(Msilver, sizeof(Msilver));
2517 array_zero(Mgold, sizeof(Mgold));
2518 array_zero(Mbishop, sizeof(Mbishop));
2519 array_zero(Mrook, sizeof(Mrook));
2520 array_zero(Mking, sizeof(Mking));
2522 if (in_opening_stage)
2524 for (side = black; side <= white; side++)
2525 UpdatePatterns(side, GameCnt);
2527 else
2529 dsp->ShowPatternCount(black, -1);
2530 dsp->ShowPatternCount(white, -1);
2537 * This is done one time before the search is started. Set up arrays
2538 * Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue()
2539 * function to determine the positional value of each piece.
2542 void
2543 ExaminePosition(short side)
2545 short c1, piece, sq, i, bsq, wsq;
2547 /* Build enemy king distance tables. */
2549 for (sq = 0, bsq = BlackKing, wsq = WhiteKing; sq < NO_SQUARES; sq++)
2551 Kdist[black][sq] = distance(sq, bsq);
2552 Kdist[white][sq] = distance(sq, wsq);
2555 threats(black);
2556 threats(white);
2558 ExamineSquares();
2560 DetermineGameType(side);
2561 DetermineStage(side);
2563 UpdateWeights(side);
2565 array_zero(HasPiece, sizeof(HasPiece));
2567 for (c1 = black; c1 <= white; c1++)
2569 for (i = PieceCnt[c1]; i >= 0; i--)
2571 ++HasPiece[c1][piece = board[sq = PieceList[c1][i]]];
2578 /* FIXME: calculations below are wrong for minishogi, all done for 9x9 */
2579 void
2580 DetermineStage(short side)
2582 short xside = side ^ 1, ds, db1, c1, c2, feature;
2584 /* Determine initial stage */
2586 balance[side] = balance[xside] = 50;
2588 if ((GameType[side] == STATIC_ROOK)
2589 && (GameType[xside] == STATIC_ROOK))
2591 if (GameCnt < 40)
2592 stage = 0;
2593 else if (GameCnt < 60)
2594 stage = 15;
2595 else if (GameCnt < 80)
2596 stage = 25;
2597 else
2598 stage = 30;
2600 else if ((GameType[side] == RANGING_ROOK)
2601 || (GameType[xside] == RANGING_ROOK))
2603 if (GameCnt < 30)
2604 stage = 0;
2605 else if (GameCnt < 50)
2606 stage = 15;
2607 else if (GameCnt < 70)
2608 stage = 25;
2609 else
2610 stage = 30;
2612 else
2614 if (GameCnt < 35)
2615 stage = 0;
2616 else if (GameCnt < 55)
2617 stage = 15;
2618 else if (GameCnt < 75)
2619 stage = 25;
2620 else
2621 stage = 30;
2624 #ifndef MINISHOGI
2625 /* Update stage depending on board features and attack balance value */
2627 if (abs(ds = (mtl[side] - mtl[xside]))
2628 > (db1 = (*value)[stage][lance]))
2630 db1 = abs(4 * ds / db1);
2632 if (ds < 0)
2633 balance[side] += db1;
2634 else if (ds > 0)
2635 balance[xside] += db1;
2637 stage += (ds = db1);
2639 #endif
2641 for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2643 if ((ds = seed[c1]) > 2)
2645 balance[c1] += (db1 = ds * 2);
2646 balance[c2] -= db1;
2648 if (stage < 30)
2649 stage = 30;
2651 stage += ds;
2654 if ((db1 = hung[c1]) > 2)
2656 balance[c1] -= (db1 *= 2);
2657 balance[c2] += db1;
2660 if ((db1 = loose[c1]) > 4)
2662 balance[c1] -= (db1 /= 2);
2663 balance[c2] += db1;
2664 stage += (ds = 1);
2667 if ((ds = hole[c1]))
2669 balance[c1] -= (db1 = ds);
2670 balance[c2] += db1;
2671 stage += (ds /= 2);
2674 if ((db1 = target[c1]) > 3)
2676 balance[c1] += (db1 /= 3);
2677 balance[c2] -= db1;
2678 stage += (ds = db1 / 4);
2681 stage += (ds = captured[c1] / 2);
2683 if ((db1 = captured[c1]) > 4)
2685 balance[c1] += (db1 /= 2);
2686 stage += (ds = 3);
2689 if ((db1 = dcaptured[c1]) > 3)
2691 balance[c1] += db1;
2692 stage += (ds = 3);
2695 if (balance[c1] > 99)
2696 balance[c1] = 99;
2697 else if (balance[c1] < 0)
2698 balance[c1] = 0;
2701 if (stage > 99)
2702 stage = 99;
2703 else if (stage < 0)
2704 stage = 0;
2706 if (flag.post)
2707 dsp->ShowStage();
2709 /* Determine stage dependant weights */
2711 ADVNCM[pawn] = 1; /* advanced pawn bonus increment */
2712 #ifndef MINISHOGI
2713 ADVNCM[lance] = 1;
2714 ADVNCM[knight] = 1;
2715 #endif
2716 ADVNCM[silver] = 1; /* advanced silver bonus increment */
2717 ADVNCM[gold] = 1; /* advanced gold bonus increment */
2718 ADVNCM[bishop] = 1;
2719 ADVNCM[rook] = 1;
2720 ADVNCM[king] = 1; /* advanced king bonus increment */
2722 MAXCDIST = (stage < 33) ? (33 - stage) / 4 : 0;
2723 MAXADIST = (stage < 30) ? (30 - stage) / 4 : 0;
2725 for (c1 = black; c1 <= white; c1++)
2727 for (feature = 0; feature < NO_FEATURES; feature++)
2729 fvalue[c1][feature] =
2730 ((((*fscore)[stage][feature][0] * (99 - balance[c1])) + 50)
2731 / 100)
2732 + ((((*fscore)[stage][feature][1] * balance[c1]) + 50)
2733 / 100);
2740 void
2741 UpdateWeights(short stage)
2743 /* FIXME: this was emptied between 1.1p02 ans 1.2p03, do we keep it ? */
2749 * Compute stage dependent relative material values assuming
2750 * linearity between the main stages:
2752 * minstage < stage < maxstage =>
2753 * stage - minstage value - minvalue
2754 * ------------------- = -------------------
2755 * maxstage - minstage maxvalue - minvalue
2759 static short
2760 linear_piece_value(short piece, short stage, short i, short j)
2762 short minvalue, maxvalue, minstage, maxstage;
2764 minstage = ispvalue[0][i];
2765 maxstage = ispvalue[0][j];
2766 minvalue = ispvalue[piece][i];
2767 maxvalue = ispvalue[piece][j];
2769 /* FIXME: set a variable then return it, puh-leeze! */
2770 return ((stage - minstage) * (maxvalue - minvalue)
2771 / (maxstage - minstage)) + minvalue;
2776 static short
2777 linear_feature_value(short feature, short stage, short i, short j)
2779 short minvalue, maxvalue, minstage, maxstage;
2781 minstage = ispvalue[0][i];
2782 maxstage = ispvalue[0][j];
2783 minvalue = weight[feature][i];
2784 maxvalue = weight[feature][j];
2786 /* FIXME: set a variable then return it, puh-leeze! */
2787 return ((stage - minstage) * (maxvalue - minvalue)
2788 / (maxstage - minstage)) + minvalue;
2793 * matweight = percentage_of_max_value * max_value(stage) / 100
2794 * max_value(0) = MAX_VALUE; max_value(100) = MIN_VALUE
2795 * => max_value(stage) = a * stage + b; b = MAX_VALUE,
2796 * a = (MIN_VALUE - MAX_VALUE)/100
2799 #define MIN_VALUE 300
2800 #define MAX_VALUE 1000
2802 #define max_value(stage) \
2803 ((long)(MIN_VALUE - MAX_VALUE) * stage + (long)100 * MAX_VALUE)
2804 #define matweight(value, stage) \
2805 ((long)max_value(stage) * value / 10000)
2809 void
2810 Initialize_eval(void)
2812 short stage, piece, feature, i;
2814 for (stage = 0; stage < NO_STAGES; stage++)
2816 for (i = 0; i < MAIN_STAGES; i++)
2818 if (stage == ispvalue[0][i])
2820 for (piece = 0; piece < NO_PIECES; piece++)
2822 (*value)[stage][piece] =
2823 matweight(ispvalue[piece][i], stage);
2826 for (feature = 0; feature < NO_FEATURES; feature++)
2828 (*fscore)[stage][feature][0] =
2829 (weight[feature][i]
2830 * weight[feature][MAIN_STAGES] + 50) / 100;
2832 (*fscore)[stage][feature][1] =
2833 (weight[feature][i]
2834 * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2837 break;
2840 if (stage < ispvalue[0][i + 1])
2842 for (piece = 0; piece < NO_PIECES; piece++)
2844 (*value)[stage][piece] =
2845 matweight(
2846 linear_piece_value(piece, stage, i, i + 1),
2847 stage);
2850 for (feature = 0; feature < NO_FEATURES; feature++)
2852 (*fscore)[stage][feature][0] =
2853 (linear_feature_value(feature, stage, i, i + 1)
2854 * weight[feature][MAIN_STAGES] + 50) / 100;
2856 (*fscore)[stage][feature][1] =
2857 (linear_feature_value(feature, stage, i, i + 1)
2858 * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2861 break;