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
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 * ----------------------------------------------------------------------
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 */
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
82 const small_short Stboard
[NO_SQUARES
] =
84 king
, gold
, silver
, bishop
, rook
,
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
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 */
117 { 20, 35, 45, 60 }, /* Lance */
118 { 20, 35, 45, 60 }, /* Knight */
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 */
126 { 25, 45, 55, 65 }, /* promoted Lance */
127 { 25, 45, 55, 65 }, /* promoted Knight */
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 */
162 #define KNGPROTECT 25
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 */
218 static const int PromotionZoneDistanceBonus
[NO_ROWS
] =
219 { 0, 0, 0, 0, 2, 6, 6, 8, 8 };
221 static const int PromotionZoneDistanceBonus
[NO_ROWS
] =
222 { 0, 0, 2, 6, 8 }; /* FIXME ? */
225 #define MAX_BMBLTY 20
226 #define MAX_RMBLTY 20
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 };
238 /* Lance mobility bonus indexed by # reachable squares */
239 static const short LMBLTY
[MAX_LMBLTY
] =
240 { 0, 0, 0, 0, 4, 6, 8, 10 };
243 static const short MBLTY
[NO_PIECES
] =
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
];
296 static small_short Mlance
[2][NO_SQUARES
];
297 static small_short Mknight
[2][NO_SQUARES
];
299 static small_short Mbishop
[2][NO_SQUARES
];
300 static small_short Mrook
[2][NO_SQUARES
];
302 static Mpiece_array Mpawn
,
306 Msilver
, Mgold
, Mbishop
, Mrook
, Mking
;
308 Mpiece_array
*Mpiece
[NO_PIECES
] =
313 &Msilver
, &Mgold
, &Mbishop
, &Mrook
,
318 &Mgold
, &Mbishop
, &Mrook
, &Mking
};
322 static small_short
*PC1
, *PC2
;
323 static small_short
*fv1
;
324 static long *atk1
, *atk2
;
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))
333 on_csquare(short side
, short piece
, short square
)
336 /* FIXME: un-obfuscate this! */
337 return ((board
[sq
= csquare(side
, square
)] == piece
)
338 && (color
[sq
] == side
));
344 on_column(short side
, short piece
, short c
)
348 for (sq
= c
; sq
< NO_SQUARES
; sq
+= NO_COLS
)
350 if (on_csquare(side
, piece
, sq
))
358 #define empty_csquare(side, square) \
359 (board[csquare(side, square)] == no_piece)
362 on_left_side(short side
, short piece
)
366 for (c
= 0; c
< 4; c
++)
368 if (on_column(side
, piece
, c
))
377 on_right_side(short side
, short piece
)
381 for (c
= 5; c
< NO_COLS
; c
++)
383 if (on_column(side
, piece
, c
))
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.
411 unsigned char *ppos
, *pdir
;
413 short i
, kd
, piece
, xside
;
416 if (MatchSignature(threats_signature
[side
]))
418 /* data valid for current positional signature */
425 array_zero(a
, NO_SQUARES
* sizeof(a
[0]));
427 PL
= PieceList
[side
];
429 for (i
= PieceCnt
[side
]; i
>= 0; i
--)
435 ptyp
= ptype
[side
][piece
];
438 u
= first_direction(ptyp
, &d
, sq
);
440 ppos
= (*nextpos
[ptyp
])[sq
];
441 pdir
= (*nextdir
[ptyp
])[sq
];
447 a
[u
] = ((a
[u
] + 1) | c
);
449 if ((kd
= Kdist
[xside
][u
]) < 2)
456 u
= ((color
[u
] == neutral
)
457 ? next_position(ptyp
, &d
, sq
, u
)
458 : next_direction(ptyp
, &d
, sq
));
460 u
= ((color
[u
] == neutral
) ? ppos
[u
] : pdir
[u
]);
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
480 add_target(short sq
, short side
, short id
)
482 short isq
, tsq
, xside
;
484 tsq
= (side
== black
) ? nunmap
[isq
+ id
] : nunmap
[isq
- id
];
488 target
[xside
= side
^1]++;
490 if (attack
[side
][tsq
])
491 starget
[xside
][tsq
]++; /* protected target square */
493 starget
[xside
][tsq
] += 2; /* unprotected target square */
500 * Target squares can be vertically ahead, diagonally ahead
501 * or diagonally behind.
505 CheckTargetPiece(short sq
, short side
)
509 case pawn
: /* vertically ahead if unprotected */
510 if (!attack
[side
][sq
])
511 add_target(sq
, side
, 11);
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);
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);
527 case bishop
: /* vertically ahead */
528 add_target(sq
, side
, 11);
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);
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 */
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 */
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 */
571 if (on_csquare(c1
, rook
, 16))
573 s
+= (ds
= -4 * fv1
[OPENWRONG
]);
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
]);
605 short sq
, side
, piece
, n
;
607 if (MatchSignature(squares_signature
))
609 /* data valid for current positional signature */
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
)
626 if (!attack
[white
][sq
])
632 else if (InBlackCamp(sq
))
634 if (!attack
[black
][sq
])
643 /* occupied by "side" piece */
644 if (!attack
[side
][sq
])
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)
670 /* Data valid for current positional signature */
671 CopySignature(squares_signature
);
676 /* ............ POSITIONAL EVALUATION ROUTINES ............ */
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.
713 bool *InChk
, /* output Check flag */
714 bool *blockable
) /* king threat blockable */
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 */
726 || (ply
> Sdepth
&& s
>= (alpha
- 30) && s
<= (beta
+ 30))
728 || (use_etable
&& CheckEETable(side
))
734 /* score the position */
735 array_zero(sseed
, sizeof(sseed
));
737 seed
[0] = seed
[1] = 0;
740 if (Anyattack(side
, sq
= PieceList
[xside
][0]) && (board
[sq
] == king
))
742 *InChk
= (board
[sq
= PieceList
[side
][0]] == king
)
743 ? SqAttacked(sq
, xside
, blockable
)
746 return ((SCORE_LIMIT
+ 1001) - ply
);
750 *InChk
= (board
[sq
= PieceList
[side
][0]] == king
)
751 ? Anyattack(xside
, sq
)
760 s
= ScorePosition(side
);
765 /* use the estimate but look at check */
768 *InChk
= (board
[sq
= PieceList
[side
][0]] == king
)
769 ? SqAttacked(sq
, xside
, blockable
)
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);
788 value_of_weakest_attacker(long a2
)
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
]))
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.
820 BRLscan(short sq
, short *mob
)
825 unsigned char *ppos
, *pdir
;
829 short u
, xu
, pin
, ptyp
;
831 short csq
= column(sq
);
833 short piece
, upiece
, xupiece
, rvalue
, ds
;
834 small_short
*Kd
= Kdist
[c2
];
839 rvalue
= (*value
)[stage
][piece
];
840 ptyp
= ptype
[c1
][upiece
= unpromoted
[piece
]];
841 rvalue
= (*value
)[stage
][upiece
];
844 u
= first_direction(ptyp
, &d
, sq
);
846 ppos
= (*nextpos
[ptyp
])[sq
];
847 pdir
= (*nextdir
[ptyp
])[sq
];
851 pin
= -1; /* start new direction */
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
)
885 xu
= next_position(ptyp
, &d
, sq
, u
);
887 if (xu
== next_direction(ptyp
, &dd
, sq
))
888 pin
= -1; /* oops new direction */
891 if ((xu
= ppos
[u
]) == pdir
[u
])
892 pin
= -1; /* oops new direction */
899 /* there is a piece in current direction */
902 /* it's the first piece in the current direction */
906 /* own intercepting piece in x-ray attack */
910 if (board
[u
] == pawn
)
912 s
+= (ds
= 2*fv1
[PROTECT
]);
914 else if (in_opening_stage
)
916 s
+= (ds
= -2*fv1
[PROTECT
]);
922 /* bishop or rook x-ray */
923 if ((upiece
== bishop
) && (board
[u
] == pawn
)
924 && (GameType
[c1
] == STATIC_ROOK
))
926 s
+= (ds
= -2*fv1
[HCLSD
]);
929 else if ((upiece
== rook
) && (board
[u
] == lance
)
930 && (GameType
[c1
] == STATIC_ROOK
)
931 && (column(u
) == csq
))
933 s
+= (ds
= fv1
[XRAY
]);
940 /* enemy's intercepting piece in pin attack */
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
]);
957 /* bishop or rook pin attack */
958 if (board
[u
] == pawn
)
960 s
+= (ds
= -fv1
[HCLSD
]);
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 */
972 if ((xu
= ppos
[u
]) != pdir
[u
])
973 pin
= u
; /* not on the edge and on to find a pin */
979 /* it's the second piece in the current direction */
983 /* second piece is an own piece */
984 if ((upiece
== bishop
) && (board
[u
] == pawn
)
985 && (GameType
[c1
] == STATIC_ROOK
))
987 s
+= (ds
= -fv1
[HCLSD
]);
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
]]]
1002 if (color
[pin
] == c2
)
1004 if ((xupiece
== king
) && (in_endgame_stage
))
1006 s
+= (ds
= 2 * fv1
[PINVAL
]);
1010 s
+= (ds
= fv1
[PINVAL
]);
1013 if ((atk2
[pin
] == 0)
1014 || (atk1
[pin
] > control
[board
[pin
]] + 1))
1023 if (upiece
== lance
)
1025 s
+= (ds
= fv1
[XRAY
] / 2);
1030 s
+= (ds
= fv1
[XRAY
]);
1036 pin
= -1; /* new direction */
1039 u
= next_direction(ptyp
, &d
, sq
);
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)) \
1077 s += (ds = -fv1[CTRLK]); \
1093 unsigned char *ppos
, *pdir
;
1101 /* Penalties, if a king can be threatened by checks. */
1109 for (p
= pawn
; p
< king
; p
++)
1111 if (HasPiece
[c2
][p
] || Captured
[c2
][p
])
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
];
1123 u
= first_direction(ptyp
, &d
, sq
);
1125 ppos
= (*nextpos
[ptyp
])[sq
];
1126 pdir
= (*nextdir
[ptyp
])[sq
];
1132 /* If a p piece can reach (controls or can drop to)
1133 * square u, then score threat.
1136 if (atk2
[u
] & control
[p
])
1138 else if ((Captured
[c2
][p
] && color
[u
]) == neutral
)
1142 u
= ((color
[u
] == neutral
)
1143 ? next_position(ptyp
, &d
, sq
, u
)
1144 : next_direction(ptyp
, &d
, sq
));
1146 u
= ((color
[u
] == neutral
) ? ppos
[u
] : pdir
[u
]);
1154 s
+= (ds
= fv1
[KSFTY
] * KTHRT
[cnt
] / 16);
1156 /* Penalties, if squares near king are controlled by enemy. */
1160 ptyp
= ptype
[c1
][king
];
1163 u
= first_direction(ptyp
, &d
, sq
);
1165 pdir
= (*nextpos
[ptyp
])[sq
];
1171 if (!ok
&& color
[u
] == c1
)
1173 short ptype_piece
= ptype
[black
][board
[u
]];
1175 if ((ptype_piece
== ptype_silver
) || (ptype_piece
== ptype_gold
))
1179 if (atk2
[u
] > atk1
[u
])
1183 if (atk2
[u
] & ctlSG
)
1185 s
+= (ds
= -fv1
[KSFTY
] / 2);
1190 u
= next_direction(ptyp
, &d
, sq
);
1197 if (!ok
|| (cnt
> 1))
1200 s
+= (ds
= -fv1
[KSFTY
]/2);
1202 s
+= (ds
= -fv1
[KSFTY
]);
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]
1224 unsigned char *ppos
, *pdir
;
1230 rvalue
= (*value
)[stage
][piece
];
1231 ptyp
= ptype
[c1
][piece
];
1234 u
= first_direction(ptyp
, &d
, sq
);
1236 ppos
= (*nextpos
[ptyp
])[sq
];
1237 pdir
= (*nextdir
[ptyp
])[sq
];
1245 if ((atk2
[u
] == 0) || ((*value
)[stage
][board
[u
]] >= rvalue
))
1250 u
= ((color
[u
] == neutral
)
1251 ? next_position(ptyp
, &d
, sq
, u
)
1252 : next_direction(ptyp
, &d
, sq
));
1254 u
= ((color
[u
] == neutral
) ? ppos
[u
] : pdir
[u
]);
1259 checked_trapped
= true;
1267 AttackedPieceValue(short sq
)
1288 OpenFileValue(short sq
, short hopn
, short hopnx
)
1292 if (PC1
[fyle
= column(sq
)] == 0)
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'.
1337 PawnValue(short sq
, short side
)
1342 short ccol
= ccolumn(c1
, sq
);
1345 PromotionZoneDistanceValue(sq
, 3);
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
)
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)) */
1379 m
= (side
== c1
) ? 3 : 5;
1383 m
= (side
== c1
) ? 2 : 3;
1387 m
= (side
== c1
) ? 1 : 2;
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
]);
1428 * Calculate the positional value for a lance on 'sq'.
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
]);
1448 s
+= (ds
= -2 * fv1
[ATTACKED
]);
1458 * Calculate the positional value for a knight on 'sq'.
1462 KnightValue(short sq
)
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))
1476 s
+= (ds
= -4 * fv1
[ATTACKED
]);
1480 s
+= (ds
= -3 * fv1
[ATTACKED
]);
1484 if ((c
== 0) || (c
== 8))
1486 s
+= (ds
= -fv1
[ATTACKED
]);
1496 * Calculate the positional value for a silver on 'sq'.
1500 SilverValue(short sq
)
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
)
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)
1524 if ((board
[csq
= csquare(c1
, 20)] == bishop
)
1525 && (color
[csq
] == c1
))
1527 s
+= (ds
= -2 * fv1
[OPENWRONG
]);
1535 EnemyKingDistanceValue(sq
, 2, 3);
1544 * Calculate the positional value for a gold on '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
)
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
]);
1577 EnemyKingDistanceValue(sq
, 2, 3);
1586 * Calculate the positional value for a bishop on 'sq'.
1590 BishopValue(short sq
)
1592 short s
= 0, ds
, ad
;
1594 if (in_opening_stage
)
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
]);
1625 EnemyKingDistanceValue(sq
, 1, 3);
1634 * Calculate the positional value for a rook on 'sq'.
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
)
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 */
1663 * Bonus for rook on right side,
1664 * penalty for rook on left side
1672 s
+= (ds
= c
+ c
+ OPOK
);
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. */
1685 c
= 4 - ccolumn(c1
, sq
);
1690 /* Bishops diagonal should not be open. */
1691 if (on_csquare(c1
, pawn
, 30))
1694 s
+= (ds
= -c
- c
- WRONG
);
1698 s
+= (ds
= -c
- c
- WRONG
);
1700 /* Penalty for king not on initial square. */
1701 if (!on_csquare(side
, king
, 4))
1712 EnemyKingDistanceValue(sq
, 1, 3);
1721 * Calculate the positional value for a promoted pawn on 'sq'.
1725 PPawnValue(short sq
)
1727 short s
= 0, ds
, ad
;
1729 EnemyKingDistanceValue(sq
, 3, 10);
1738 * Calculate the positional value for a promoted lance on 'sq'.
1742 PLanceValue(short sq
)
1744 short s
= 0, ds
, ad
;
1746 EnemyKingDistanceValue(sq
, 3, 10);
1754 * Calculate the positional value for a promoted knight on 'sq'.
1758 PKnightValue(short sq
)
1760 short s
= 0, ds
, ad
;
1762 EnemyKingDistanceValue(sq
, 3, 10);
1771 * Calculate the positional value for a promoted silver on 'sq'.
1775 PSilverValue(short sq
)
1777 short s
= 0, ds
, ad
;
1779 EnemyKingDistanceValue(sq
, 3, 10);
1787 * Calculate the positional value for a promoted bishop on 'sq'.
1791 PBishopValue(short sq
)
1793 short s
= 0, ds
, ad
;
1795 EnemyKingDistanceValue(sq
, 3, 4);
1803 * Calculate the positional value for a promoted rook on 'sq'.
1807 PRookValue(short sq
)
1809 short s
= 0, ds
, ad
;
1811 EnemyKingDistanceValue(sq
, 3, 4);
1813 OpenFileValue(sq
, 3 * fv1
[HOPN
], 2 * fv1
[HOPN
]);
1821 * Calculate the positional value for a king on 'sq'.
1829 if (fv1
[KSFTY
] != 0)
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);
1853 /* CHECKME: is this correct? */
1854 if ((ds
= fv1
[HOPN
]))
1856 s
+= OpenFileValue(sq
, -2 * ds
, -4 * ds
);
1865 * Calculate the positional value for a piece on 'sq'.
1869 PieceValue(short sq
, short side
)
1876 if (piece
== no_piece
)
1879 s
= (*Mpiece
[piece
])[c1
][sq
];
1881 checked_trapped
= false;
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);
1894 s
+= (ds
= LMBLTY
[mob
] * fv1
[MOBILITY
] / 100);
1899 /* mobility for non-sweeping pieces */
1907 /* opponent attacks piece */
1910 /* undefended piece */
1911 s
+= AttackedPieceValue(sq
);
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
]);
1937 /* piece is defended */
1938 s
+= (ds
= (a1
& CNT_MASK
) * fv1
[PROTECT
]);
1943 s
+= (ds
= fv1
[SEED
]);
1948 s
+= (ds
= -fv1
[LOOSE
]);
1951 if (starget
[c1
][sq
])
1955 s
-= (ds
= -fv1
[ATTACKED
]/2);
1957 else if (piece
== pawn
)
1959 s
+= (ds
= fv1
[ATTACKED
]);
1963 if (starget
[c2
][sq
])
1967 s
-= (ds
= -fv1
[ATTACKED
] / 3);
1971 s
+= (ds
= fv1
[ATTACKED
]);
1975 if (Kdist
[c1
][sq
] == 1)
1977 s
+= (ds
= fv1
[KSFTY
]);
1984 s
+= PawnValue(sq
, side
);
1989 s
+= LanceValue(sq
);
1993 s
+= KnightValue(sq
);
1998 s
+= SilverValue(sq
);
2006 s
+= BishopValue(sq
);
2010 s
+= RookValue(sq
, side
);
2018 s
+= PPawnValue(sq
);
2023 s
+= PLanceValue(sq
);
2027 s
+= PKnightValue(sq
);
2032 s
+= PSilverValue(sq
);
2036 s
+= PBishopValue(sq
);
2040 s
+= PRookValue(sq
);
2050 * Score distance to pattern regarding the game type which side plays.
2054 ScorePatternDistance(short c1
)
2057 small_short
*fv1
= fvalue
[c1
];
2060 if ((MAXCDIST
> 0) && (fv1
[PCASTLE
] != 0)
2061 && ((os
= castle_opening_sequence
[c1
]) >= 0))
2063 ds
= board_to_pattern_distance(c1
, os
, MAXCDIST
, GameCnt
);
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
);
2078 s
+= (ds
*= fv1
[PATTACK
]);
2089 * Determine castle and attack pattern which should be reached next.
2090 * Only patterns are considered, which have not been reached yet.
2094 UpdatePatterns(short side
, short GameCnt
)
2097 short xside
= side
^ 1;
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)
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)
2145 dsp
->ShowPatternCount(side
, n
);
2147 if (os
!= END_OF_SEQUENCES
)
2148 update_advance_bonus(side
, os
);
2156 short ds
, col
, n
, m
, piece
;
2158 if ((n
= Captured
[c1
][pawn
]))
2162 for (col
= 0; col
< NO_COLS
; col
++)
2171 /* FIXME! another great obfuscated line... */
2172 pscore
[c1
] += (ds
*= ((n
> 2) ? 3 : n
));
2177 for (piece
= pawn
+1, n
= 0; piece
<= rook
; piece
++)
2179 if (Captured
[c1
][piece
])
2183 pscore
[c1
] += (ds
= m
* fv1
[DFFDROP
]);
2186 for (piece
= pawn
, n
= 0; piece
<= rook
; piece
++)
2188 if (Captured
[c1
][piece
])
2193 ds
= BMBLTY
[MAX_BMBLTY
- 1];
2197 ds
= RMBLTY
[MAX_RMBLTY
- 1];
2202 ds
= LMBLTY
[MAX_LMBLTY
- 1];
2212 if (!Captured
[c2
][piece
])
2213 n
+= relative_value
[piece
];
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.
2233 ScorePosition(short side
)
2242 UpdateWeights(side
);
2244 hung
[black
] = hung
[white
] = pscore
[black
] = pscore
[white
] = 0;
2246 array_zero(shung
, sizeof(shung
));
2249 if (!(use_etable
&& ProbeEETable(side
, &s
)))
2252 for (c1
= black
; c1
<= white
; c1
++)
2256 /* atk1 is array of attacks on squares by my side */
2259 /* atk2 is array of attacks on squares by other side */
2262 /* same for PC1 and PC2 */
2266 /* same for fv1 and fv2 */
2269 for (i
= PieceCnt
[c1
]; i
>= 0; i
--)
2271 sq
= PieceList
[c1
][i
];
2273 #if defined SAVE_SVALUE
2274 pscore
[c1
] += PieceValue(sq
, side
);
2276 pscore
[c1
] += (svalue
[sq
] = PieceValue(sq
, side
));
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
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
2298 for (c1
= black
, c2
= white
; c1
<= white
; c1
++, c2
--)
2304 /* Score fifth rank */
2305 for (sq
= MIDDLEROW_START
, n
= 0; sq
<= MIDDLEROW_END
; sq
++)
2307 if ((color
[sq
] == c1
) || (attack
[c1
][sq
] != 0))
2313 pscore
[c1
] += (ds
= n
* fv1
[CNTRL5TH
]);
2317 for (sq
= ((c1
== black
) ? BLACKHOME_START
: WHITEHOME_START
), n
= 0;
2318 sq
<= ((c1
== black
) ? BLACKHOME_END
: WHITEHOME_END
);
2321 if (board
[sq
] == no_piece
&& attack
[c1
][sq
] == 0)
2327 pscore
[c1
] += (ds
= -n
* fv1
[HOLES
]);
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;
2349 if (use_etable
&& PUTVAR
)
2350 PutInEETable(side
, score
);
2354 #ifdef CACHE /* CHECKME: this looks bad */
2364 * Try to determine the game type of "side".
2369 GuessGameType(short side_to_move
)
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;
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
;
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
2464 if (!on_csquare(side
, pawn
, 25))
2466 /* Play static rook if rook pawn has been pushed! */
2467 GameType
[side
] = STATIC_ROOK
;
2471 unsigned int random
= urand() % 100;
2472 short d
= StaticRook
[side
] - RangingRook
[side
];
2474 switch (GameType
[side
^ 1])
2477 if (random
< 35 + d
)
2478 GameType
[side
] = STATIC_ROOK
;
2479 else if (random
< 95)
2480 GameType
[side
] = RANGING_ROOK
;
2484 if (random
< 75 + d
)
2485 GameType
[side
] = STATIC_ROOK
;
2486 else if (random
< 95)
2487 GameType
[side
] = RANGING_ROOK
;
2491 if (random
< 33 + d
)
2492 GameType
[side
] = STATIC_ROOK
;
2493 else if (random
< 66)
2494 GameType
[side
] = RANGING_ROOK
;
2507 DetermineGameType(short side_to_move
)
2512 /* FIXME: calculations below are wrong for minishogi, all done for 9x9 */
2513 GuessGameType(side_to_move
);
2515 GameType
[black
] = UNKNOWN
;
2516 GameType
[white
] = UNKNOWN
;
2519 array_zero(Mpawn
, sizeof(Mpawn
));
2521 array_zero(Mlance
, sizeof(Mlance
));
2522 array_zero(Mknight
, sizeof(Mknight
));
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
);
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.
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
);
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 */
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
))
2601 else if (GameCnt
< 60)
2603 else if (GameCnt
< 80)
2608 else if ((GameType
[side
] == RANGING_ROOK
)
2609 || (GameType
[xside
] == RANGING_ROOK
))
2613 else if (GameCnt
< 50)
2615 else if (GameCnt
< 70)
2624 else if (GameCnt
< 55)
2626 else if (GameCnt
< 75)
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
);
2641 balance
[side
] += db1
;
2643 balance
[xside
] += db1
;
2645 stage
+= (ds
= db1
);
2649 for (c1
= black
, c2
= white
; c1
<= white
; c1
++, c2
--)
2651 if ((ds
= seed
[c1
]) > 2)
2653 balance
[c1
] += (db1
= ds
* 2);
2662 if ((db1
= hung
[c1
]) > 2)
2664 balance
[c1
] -= (db1
*= 2);
2668 if ((db1
= loose
[c1
]) > 4)
2670 balance
[c1
] -= (db1
/= 2);
2675 if ((ds
= hole
[c1
]))
2677 balance
[c1
] -= (db1
= ds
);
2682 if ((db1
= target
[c1
]) > 3)
2684 balance
[c1
] += (db1
/= 3);
2686 stage
+= (ds
= db1
/ 4);
2689 stage
+= (ds
= captured
[c1
] / 2);
2691 if ((db1
= captured
[c1
]) > 4)
2693 balance
[c1
] += (db1
/= 2);
2697 if ((db1
= dcaptured
[c1
]) > 3)
2703 if (balance
[c1
] > 99)
2705 else if (balance
[c1
] < 0)
2717 /* Determine stage dependant weights */
2719 ADVNCM
[pawn
] = 1; /* advanced pawn bonus increment */
2724 ADVNCM
[silver
] = 1; /* advanced silver bonus increment */
2725 ADVNCM
[gold
] = 1; /* advanced gold bonus increment */
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)
2740 + ((((*fscore
)[stage
][feature
][1] * balance
[c1
]) + 50)
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
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
;
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)
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] =
2838 * weight
[feature
][MAIN_STAGES
] + 50) / 100;
2840 (*fscore
)[stage
][feature
][1] =
2842 * weight
[feature
][MAIN_STAGES
+ 1] + 50) / 100;
2848 if (stage
< ispvalue
[0][i
+ 1])
2850 for (piece
= 0; piece
< NO_PIECES
; piece
++)
2852 (*value
)[stage
][piece
] =
2854 linear_piece_value(piece
, stage
, i
, i
+ 1),
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;