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 * ----------------------------------------------------------------------
35 /* #define DONTUSE_HEURISTIC */
39 static struct leaf *node;
40 static short sqking, sqxking;
41 static short InCheck = false, GenerateAllMoves = false;
42 static short check_determined = false;
44 short deepsearchcut = true;
45 short tas = false, taxs = false, ssa = false;
47 short generate_move_flags = false;
51 * Ply limits for deep search cut. No moves or drops flagged with "stupid"
52 * are considered beyond ply BEYOND_STUPID. Only moves or drops flagged
53 * with "kingattack" are considered beyond ply BEYOND_KINGATTACK. No moves
54 * or drops flagged with "questionable" are considered beyond ply
55 * BEYOND_QUESTIONABLE. Only moves or drops flagged with "tesuji" are
56 * considered beyond ply BEYOND_TESUJI. No drops are considered beyond ply
57 * BEYOND_DROP. Exceptions: moves or drops that prevent check or give
58 * check are always considered.
61 #define BEYOND_STUPID 0
62 #define BEYOND_TIMEOUT 2
63 #define BEYOND_KINGATTACK 6
64 #define BEYOND_QUESTIONABLE 8
65 #define BEYOND_TESUJI 8
66 #define BEYOND_DROP 10
68 #ifdef DONTUSE_HEURISTIC
69 static short MaxNum[MAXDEPTH] =
71 -1, 40, 80, 20, 40, 10, 5, 5, 5, 5,
72 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
73 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
74 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
79 extern int CheckHashKey();
80 extern char mvstr[4][6];
85 * Update Arrays board[] and color[] to reflect the new board
86 * position obtained after making the move pointed to by node.
90 GenMakeMove(short side,
93 short *tempb, /* piece at to square */
94 short *tempc, /* color of to square */
97 short piece, upiece, n;
103 piece = f - NO_SQUARES;
105 if (piece > NO_PIECES)
110 n = (Captured[side][piece])--;
111 UpdateDropHashbd(side, piece, n);
112 UpdateHashbd(side, piece, -1, t);
113 UpdatePieceList(side, t, ADD_PIECE);
120 if (*tempb != no_piece)
122 n = ++Captured[side][upiece = unpromoted[*tempb]];
123 UpdateDropHashbd(side, upiece, n);
124 UpdateHashbd(*tempc, *tempb, -1, t);
125 UpdatePieceList(*tempc, t, REMOVE_PIECE);
129 Pindex[t] = Pindex[f];
130 PieceList[side][Pindex[t]] = t;
137 UpdateHashbd(side, piece, f, -1);
138 board[t] = promoted[piece];
139 UpdateHashbd(side, board[t], -1, t);
144 UpdateHashbd(side, piece, f, t);
152 printf("error in GenMakeMove: %s\n", mvstr[0]);
165 GenUnmakeMove(short side,
172 short piece, upiece, n;
178 piece = f - NO_SQUARES;
180 if (piece > NO_PIECES)
185 n = ++Captured[side][piece];
186 UpdateDropHashbd(side, piece, n);
187 UpdateHashbd(side, piece, -1, t);
188 UpdatePieceList(side, t, REMOVE_PIECE);
195 Pindex[f] = Pindex[t];
196 PieceList[side][Pindex[f]] = f;
198 if (tempb != no_piece)
200 /* FIXME: make this next line a bit more reasonable... */
201 n = (Captured[side][upiece = unpromoted[tempb]])--;
202 UpdateDropHashbd(side, upiece, n);
203 UpdateHashbd(tempc, tempb, -1, t);
204 UpdatePieceList(tempc, t, ADD_PIECE);
211 UpdateHashbd(side, piece, -1, t);
212 board[f] = unpromoted[piece];
213 UpdateHashbd(side, board[f], f, -1);
218 UpdateHashbd(side, piece, f, t);
226 printf("error in GenUnmakeMove: %s\n", mvstr[0]);
235 gives_check_flag(unsigned short *flags, short side, short f, short t)
237 short tempb, tempc, blockable, promote_piece;
238 promote_piece = (*flags & promote) != 0;
239 GenMakeMove(side, f, t, &tempb, &tempc, promote_piece);
241 if (SqAttacked(sqxking, side, &blockable))
244 GenUnmakeMove(side, f, t, tempb, tempc, promote_piece);
250 short from, short to, unsigned short local_flag, short s)
254 dsp->ShowMessage("TREE overflow\n");
259 node->t = (local_flag & promote) ? (to | 0x80) : to;
261 node->flags = local_flag;
263 node->INCscore = INCscore;
265 if (GenerateAllMoves)
267 /* FIXME: gimme a break! */
272 /* only moves out of check */
273 short tempb, tempc, sq, threat, blockable, promote_piece;
274 promote_piece = (node->flags & promote) != 0;
275 GenMakeMove(side, node->f, node->t,
276 &tempb, &tempc, promote_piece);
277 sq = (from == sqking) ? to : sqking;
278 threat = SqAttacked(sq, side ^ 1, &blockable);
279 GenUnmakeMove(side, node->f, node->t,
280 tempb, tempc, promote_piece);
284 /* FIXME! Gimme a break! */
290 /* only moves that give check */
291 if (!(node->flags & check) && !check_determined)
293 /* determine check flag */
294 gives_check_flag(&node->flags, side, node->f, node->t);
297 if (node->flags & check)
299 /* FIXME! Gimme a break! */
305 /* FIXME! Gimme a break! */
313 PromotionPossible(short color, short f, short t, short p)
317 if ((!InWhiteCamp(f)) && (!InWhiteCamp(t)))
322 if ((!InBlackCamp(f)) && (!InBlackCamp(t)))
326 /* FIXME: this can be simplified... */
345 NonPromotionPossible(short color,
359 : (generate_move_flags ? ILLEGAL_TRAPPED : false));
369 : (generate_move_flags ? ILLEGAL_TRAPPED : false));
378 : (generate_move_flags ? ILLEGAL_TRAPPED : false));
384 : (generate_move_flags ? ILLEGAL_TRAPPED : false));
392 : (generate_move_flags ? ILLEGAL_TRAPPED : false));
398 : (generate_move_flags ? ILLEGAL_TRAPPED : false));
407 #if defined FIELDBONUS || defined DROPBONUS
409 /* bonus for possible next moves */
412 field_bonus(short side, short piece,
413 short f, short t, unsigned short *local_flag)
416 unsigned char *ppos, *pdir;
426 check_determined = true;
428 ptyp = ptype[side][piece];
431 u = first_direction(ptyp, &d, t);
433 ppos = (*nextpos[ptyp])[t];
434 pdir = (*nextdir[ptyp])[t];
440 short coloru = color[u];
442 if (piece != king && GameCnt > 40)
444 if (distance(u, EnemyKing) <= 1)
446 /* can reach square near own king */
448 *local_flag |= kingattack;
450 else if (distance(u, OwnKing) <= 1)
452 /* can reach square near enemy king */
454 *local_flag |= kingattack;
460 /* impossible next move */
462 u = next_direction(ptyp, &d, t);
469 /* possible next move */
470 if (PromotionPossible(side, t, u, piece))
472 /* possible promotion in next move */
477 if (!InPromotionZone(side, t))
479 *local_flag |= tesuji; /* The dangling pawn */
490 if (coloru == neutral)
492 /* next move to an empty square */
495 /* opponent has just left this square */
500 u = next_position(ptyp, &d, t, u);
507 /* attack opponents piece */
509 short boardu, upiece, rvupiece, rvuboard;
513 if (u == TOsquare) /* opponent has moved to TOsquare */
516 if ((boardu = board[u]) == king)
518 s += 20; INCscore -= 18;
519 *local_flag |= check; /* move threatens
524 upiece = unpromoted[piece];
525 rvupiece = relative_value[upiece];
526 rvuboard = relative_value[unpromoted[boardu]];
528 if ((upiece == pawn) && (Captured[side][pawn] > 1))
530 *local_flag |= tesuji; /* The joining pawn attack */
534 if (rvupiece <= rvuboard)
536 *local_flag |= tesuji; /* The striking pawn
547 /* CHECKME: is this right? */
548 if (((rvupiece == rvuboard) && (upiece == pawn))
549 || (upiece == bishop)
551 || (upiece == knight)
555 s++; /* The opposing pawn (piece) */
564 u = next_direction(ptyp, &d, t);
584 * Add a move to the tree. Assign a bonus to order the moves as follows:
585 * 1. Principle variation 2. Capture of last moved piece 3. Other captures
586 * (major pieces first) 4. Killer moves 5. Tesuji drops 6. Other Moves
587 * 7. Other drops. 8. Non-promoting moves
588 * If the flag.tsume is set, assign a high bonus for checks.
592 LinkMove(short ply, short f,
594 unsigned short local_flag,
596 short score_if_impossible)
599 short side, piece, mv;
600 short flag_tsume, try_link = true;
601 short c1, c2, ds, is_drop = f > NO_SQUARES;
602 unsigned long as = 0;
604 flag_tsume = flag.tsume;
606 c1 = side = xside ^ 1;
610 * Is it determined whether the move gives check ?
613 check_determined = ((local_flag & check) != 0);
615 mv = (f << 8) | ((local_flag & promote) ? (t | 0x80) : t);
619 piece = f - NO_SQUARES;
621 if (piece > NO_PIECES)
629 if (score_if_impossible < 0)
631 /* The move is flagged as illegal. */
633 f, t, local_flag, score_if_impossible);
641 s += history[hindex(side, mv)];
644 /* If we're running short of tree nodes, go into tsume mode. */
646 if (!(local_flag & capture))
648 if (*TrP > (TREE - 300))
650 /* too close to tree table limit */
655 /* Guess strength of move and set flags. */
657 if ((piece != king) && (!in_opening_stage))
659 if (distance(t, EnemyKing) <= 1)
661 /* bonus for square near enemy king */
664 local_flag |= kingattack;
666 else if (distance(t, OwnKing) <= 1)
668 /* bonus for square near own king */
671 local_flag |= kingattack;
675 if (tas) /* own attack array available */
677 /* square t defended by own piece (don't count piece to move) ? */
679 ? (as = attack[side][t])
680 : (as = ((attack[side][t] & CNT_MASK) > 1)))
681 s += (ds = in_endgame_stage ? 100 : 10);
684 if (taxs) /* opponents attack array available */
686 /* square t not threatened by opponent or
687 * defended and only threatened by opponents king ?
691 if (!(axs = attack[xside][t])
692 || (tas && as && (axs & control[king]) && (axs & CNT_MASK) == 1))
694 /* FIXME: this is a mess; clean up. */
695 s += (ds = in_endgame_stage
698 ? (InPromotionZone(side, t)
699 ? 40 + relative_value[piece]
705 /* target square near area of action */
708 s += (9 - distance(TOsquare, t));
711 s += (9 - distance(FROMsquare, t)) / 2;
713 /* target square near own or enemy king */
715 if (!in_opening_stage && piece != king)
717 if (balance[c1] < 50)
718 s += (9 - distance(EnemyKing, t)) * (50 - balance[c1]) / 20;
720 s += (9 - distance(OwnKing, t)) * (balance[c1] - 50) / 20;
725 /* bonus for drops, in order to place
726 * drops before questionable moves */
727 s += in_endgame_stage ? 25 : 10;
731 /* drop to the square the opponent has just left */
736 s -= 32 / Captured[side][gold];
737 else if (piece == silver)
738 s -= 16 / Captured[side][silver];
740 #if defined DROPBONUS
741 s += field_bonus(side, piece, f, t, &local_flag);
743 if (s == 10 && piece != pawn)
744 local_flag |= questionable;
749 /* bonus for moves (non-drops) */
750 int consider_last = false;
752 if (in_endgame_stage && Captured[side][gold])
759 /* move to the square the opponent has just left */
760 s += in_endgame_stage ? 10 : 1;
763 if (color[t] != neutral)
766 if (in_endgame_stage)
768 s += relative_value[board[t]] - relative_value[piece];
772 s += (*value)[stage][board[t]] - relative_value[piece];
775 if (t == TOsquare) /* Capture of last moved piece */
776 s += in_endgame_stage ? 5 : 50;
779 if (local_flag & promote)
781 /* bonus for promotions */
783 INCscore += value[stage][promoted[piece]] - value[stage][piece];
787 /* bonus for non-promotions */
788 if (PromotionPossible(side, f, t, piece))
791 /* Look at non-promoting silver or knight */
798 local_flag |= tesuji; /* Non-promotion */
804 consider_last = true;
806 if (piece == pawn || piece == bishop || piece == rook)
808 local_flag |= stupid;
813 local_flag |= questionable;
822 if (local_flag & stupid)
829 #if defined FIELDBONUS
830 s += field_bonus(side, piece, f, t, &local_flag);
835 #if defined CHECKBONUS
836 /* determine check flag */
837 if (!(local_flag & check) && !check_determined)
839 gives_check_flag(&local_flag, side, f, t);
841 if (local_flag & check)
846 /* check conditions for deep search cut (flag.tsume = true) */
849 if (!flag.tsume && deepsearchcut)
851 if ((ply > BEYOND_STUPID) && (local_flag & stupid))
853 try_link = flag.force || ((ply == 1) && (side != computer));
855 else if (hard_time_limit && (ply > BEYOND_TIMEOUT) && flag.timeout)
859 else if ((ply > BEYOND_KINGATTACK) && !(local_flag & kingattack))
863 else if ((ply > BEYOND_QUESTIONABLE) && (local_flag & questionable))
868 else if ((ply > BEYOND_TESUJI) && !(local_flag & tesuji))
873 else if ((ply > BEYOND_DROP) && (f > NO_SQUARES))
880 if (try_link || GenerateAllMoves)
882 Link(side, f, t, local_flag,
883 s - ((SCORE_LIMIT + 1000) * 2));
886 flag.tsume = flag_tsume;
892 DropPossible(short piece, short side, short sq)
894 short r = row(sq), possible = true;
896 if (board[sq] != no_piece)
900 else if (piece == pawn)
902 if ((side == black) && (r == 8))
904 possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
906 else if ((side == white) && (r == 0))
908 possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
910 else if (PawnCnt[side][column(sq)])
912 possible = (generate_move_flags ? ILLEGAL_DOUBLED : false);
915 /* Pawn drops are invalid if they mate the opponent. */
918 short f, tempb, tempc;
919 f = pawn + NO_SQUARES;
924 GenMakeMove(side, f, sq, &tempb, &tempc, false);
926 if (IsCheckmate(side^1, -1, -1))
927 possible = (generate_move_flags ? ILLEGAL_MATE : false);
929 GenUnmakeMove(side, f, sq, tempb, tempc, false);
933 else if (piece == lance)
935 if ((side == black) && (r == 8))
936 possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
937 else if ((side == white) && (r == 0))
938 possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
940 else if (piece == knight)
942 if ((side == black) && (r >= 7))
943 possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
944 else if ((side == white) && (r <= 1))
945 possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
953 #if defined DONTUSE_HEURISTIC
959 for (p = TrPnt[ply]; p < TrPnt[ply+1]; p++)
960 pick(p, TrPnt[ply+1] - 1);
962 #endif /* DONTUSE_HEURISTIC */
965 #ifdef DONTUSE_HEURISTIC
968 DontUseMoves(short ply, short n)
973 /* k = number of check moves + number of captures */
974 for (i = TrPnt[ply], k = 0; i < TrPnt[ply+1]; i++)
978 if ((p->flags & check) || (p->flags & capture))
986 for (i = TrPnt[ply]; i < TrPnt[ply+1]; i++)
990 if (!((p->flags & check) || (p->flags & capture)))
1007 * Generate moves for a piece. The moves are taken from the precalculated
1008 * array nextpos/nextdir. If the board is free, next move is chosen from
1009 * nextpos else from nextdir.
1013 GenMoves(short ply, short sq, short side,
1017 short ptyp, possible;
1021 unsigned char *ppos, *pdir;
1025 ptyp = ptype[side][piece];
1028 u = first_direction(ptyp, &d, sq);
1030 ppos = (*nextpos[ptyp])[sq];
1031 pdir = (*nextdir[ptyp])[sq];
1037 unsigned short local_flag;
1040 if ((c = color[u]) == xside)
1041 local_flag = capture;
1045 if (c != side && board[u] != king)
1047 if (PromotionPossible(color[sq], sq, u, piece))
1049 LinkMove(ply, sq, u, local_flag | promote, xside, true);
1052 = NonPromotionPossible(color[sq], u, piece)))
1054 LinkMove(ply, sq, u, local_flag, xside, possible);
1059 LinkMove(ply, sq, u, local_flag, xside, true);
1066 u = next_position(ptyp, &d, sq, u);
1070 u = next_direction(ptyp, &d, sq);
1089 * Drop each piece in hand of "side" to square "u" (if allowed).
1093 DropToSquare(short side, short xside, short ply, short u)
1097 for (i = pawn; i < king; i++)
1099 if (Captured[side][i])
1101 if ((possible = DropPossible(i, side, u)))
1109 LinkMove(ply, f, u, (dropmask | i), xside, possible);
1118 * Add drops of side that prevent own king from being in check
1119 * from xside's sweeping pieces.
1123 LinkPreventCheckDrops(short side, short xside, short ply)
1128 unsigned char *ppos, *pdir;
1130 short piece, u, xu, square, ptyp;
1131 short n, drop_square[9];
1133 if (board[square = PieceList[side][0]] != king)
1136 for (piece = pawn+1; piece <= rook; piece++)
1142 piece == bishop || piece == rook)
1144 /* check for threat of xside piece */
1145 ptyp = ptype[side][piece];
1148 u = first_direction(ptyp, &d, square);
1150 ppos = (*nextpos[ptyp])[square];
1151 pdir = (*nextdir[ptyp])[square];
1157 if (color[u] == neutral)
1161 xu = next_position(ptyp, &d, square, u);
1163 if (xu == next_direction(ptyp, &dd, square))
1165 n = 0; /* oops new direction */
1169 drop_square[n++] = u;
1173 if ((xu = ppos[u]) == pdir[u])
1175 n = 0; /* oops new direction */
1179 drop_square[n++] = u;
1186 if (color[u] == xside && (unpromoted[board[u]] == piece))
1188 /* king is threatened by opponents piece */
1191 DropToSquare(side, xside, ply, drop_square[--n]);
1199 u = next_direction(ptyp, &d, square);
1205 while (u != square);
1213 * Add drops that check enemy king.
1217 LinkCheckDrops(short side, short xside, short ply)
1222 unsigned char *ppos, *pdir;
1225 short square, piece;
1227 if (board[square = PieceList[xside][0]] != king)
1230 for (piece = pawn; piece < king; piece++)
1232 if (Captured[side][piece])
1235 * "side" has "piece" in hand. Try to make a piece move from
1236 * opponents king square and drop this piece to each reachable
1237 * empty square. This definitely gives check! For a pawn drop
1238 * it must not double pawns and it must not be checkmate!
1241 ptyp = ptype[xside][piece];
1243 u = first_direction(ptyp, &d, square);
1245 ppos = (*nextpos[ptyp])[square];
1246 pdir = (*nextdir[ptyp])[square];
1251 if (color[u] == neutral)
1253 if (piece != pawn || DropPossible(pawn, side, u))
1256 f = NO_SQUARES + piece;
1262 (dropmask | piece | check), xside, true);
1266 u = next_position(ptyp, &d, square, u);
1274 u = next_direction(ptyp, &d, square);
1280 while (u != square);
1288 * Fill the array Tree[] with all available moves for side to play. Array
1289 * TrPnt[ply] contains the index into Tree[] of the first move at a ply.
1290 * in_check = 0 side is not in check
1291 * in_check > 1 side is in check
1292 * in_check < 0 don't know
1293 * in_check -2 indicates move generation for book moves
1297 MoveList(short side, short ply,
1298 short in_check, short blockable)
1301 struct leaf *firstnode;
1302 short flag_tsume, num;
1305 unsigned short hiHt = 0, hi0 = 0, hi1 = 0, hi2 = 0, hi3 = 0, hi4 = 0;
1308 flag_tsume = flag.tsume;
1312 sqking = PieceList[side][0];
1313 sqxking = PieceList[xside][0];
1321 InCheck = (board[sqking] == king)
1322 ? SqAttacked(sqking, xside, &blockable)
1326 GenerateAllMoves = (in_check == -2) || generate_move_flags;
1328 if (InCheck /* && (ply > 1 || side == computer) */)
1330 /* Own king in check */
1334 TrP = &TrPnt[ply + 1];
1337 firstnode = node = &Tree[*TrP];
1340 Swag0 = killr0[ply];
1344 Swag1 = killr1[ply];
1345 Swag2 = killr2[ply];
1346 Swag3 = killr3[ply];
1349 Swag4 = killr1[ply - 2];
1356 history[hiHt = hindex(side, SwagHt)] += 5000;
1357 history[hi0 = hindex(side, Swag0)] += 2000;
1358 history[hi1 = hindex(side, Swag1)] += 60;
1359 history[hi2 = hindex(side, Swag2)] += 50;
1360 history[hi3 = hindex(side, Swag3)] += 40;
1361 history[hi4 = hindex(side, Swag4)] += 30;
1365 for (i = PieceCnt[side]; i >= 0; i--)
1366 GenMoves(ply, PieceList[side][i], side, xside);
1368 if (!InCheck || blockable)
1372 /* special drop routine for tsume problems */
1374 LinkPreventCheckDrops(side, xside, ply);
1376 LinkCheckDrops(side, xside, ply);
1380 for (u = 0; u < NO_SQUARES; u++)
1381 DropToSquare(side, xside, ply, u);
1388 history[hiHt] -= 5000;
1389 history[hi0] -= 2000;
1397 SwagHt = 0; /* SwagHt is only used once */
1399 if (flag.tsume && node == firstnode)
1402 GenCnt += (num = (TrPnt[ply+1] - TrPnt[ply]));
1404 #ifdef DONTUSE_HEURISTIC
1405 /* remove some nodes in case of wide spread in depth */
1406 if (!flag.tsume && (i = MaxNum[ply]) > 0 && num > i)
1409 DontUseMoves(ply, i);
1413 flag.tsume = flag_tsume;
1419 * Fill the array Tree[] with all available captures for side to play. If
1420 * there is a non-promote option, discard the non-promoting move. Array
1421 * TrPnt[ply] contains the index into Tree[] of the first move at a ply.
1422 * If flag.tsume is set, only add captures (but also the non-promoting)
1423 * that threaten the opponents king.
1425 * in_check = 0: side is not in check
1426 * in_check > 1: side is in check
1427 * in_check < 0: we don't know
1431 CaptureList(short side, short ply,
1432 short in_check, short blockable)
1438 unsigned char *ppos, *pdir;
1440 short i, piece, flag_tsume;
1445 TrP = &TrPnt[ply + 1];
1449 flag_tsume = flag.tsume;
1451 sqking = PieceList[side][0];
1452 sqxking = PieceList[xside][0];
1460 InCheck = (board[sqking] == king)
1461 ? SqAttacked(sqking, xside, &blockable)
1465 GenerateAllMoves = (in_check == -2);
1467 if (InCheck && (ply > 1 || side == computer))
1469 /* Own king is in check */
1473 check_determined = false;
1475 PL = PieceList[side];
1477 for (i = 0; i <= PieceCnt[side]; i++)
1482 ptyp = ptype[side][piece];
1484 u = first_direction(ptyp, &d, sq);
1486 ppos = (*nextpos[ptyp])[sq];
1487 pdir = (*nextdir[ptyp])[sq];
1492 if (color[u] == neutral)
1495 u = next_position(ptyp, &d, sq, u);
1502 if (color[u] == xside && board[u] != king)
1506 if ((PP = PromotionPossible(color[sq], sq, u, piece)))
1509 sq, u, capture | promote,
1510 (*value)[stage][board[u]]
1511 #if !defined SAVE_SVALUE
1514 - relative_value[piece]);
1517 if (!PP || flag.tsume)
1521 (*value)[stage][board[u]]
1522 #if !defined SAVE_SVALUE
1525 - relative_value[piece]);
1530 u = next_direction(ptyp, &d, sq);
1539 flag.tsume = flag_tsume;
1541 SwagHt = 0; /* SwagHt is only used once */
1548 * If the king is in check, try to find a move that prevents check.
1549 * If such a move is found, return false, otherwise return true.
1550 * in_check = 0: side is not in check
1551 * in_check > 1: side is in check
1552 * in_check < 0: don't know
1553 * blockable > 0 && check: check can possibly be prevented by a drop
1554 * blockable = 0 && check: check can definitely not be prevented by a drop
1555 * blockable < 0 && check: nothing known about type of check
1559 IsCheckmate(short side, short in_check, short blockable)
1565 unsigned char *ppos, *pdir;
1569 short tempb, tempc, ksq, threat, dummy, sqking;
1574 sqking = PieceList[side][0];
1577 * Checkmate is possible only if king is in check.
1582 else if (board[sqking] == king)
1583 InCheck = SqAttacked(sqking, xside, &blockable);
1591 * Try to find a move that prevents check.
1594 PL = PieceList[side];
1596 for (i = 0; i <= PieceCnt[side]; i++)
1601 ptyp = ptype[side][piece];
1603 u = first_direction(ptyp, &d, sq);
1605 ppos = (*nextpos[ptyp])[sq];
1606 pdir = (*nextdir[ptyp])[sq];
1611 if (color[u] == neutral || color[u] == xside)
1613 GenMakeMove(side, sq, u, &tempb, &tempc, false);
1614 ksq = (sq == sqking) ? u : sqking;
1615 threat = SqAttacked(ksq, xside, &dummy);
1616 GenUnmakeMove(side, sq, u, tempb, tempc, false);
1623 u = (color[u] == neutral)
1624 ? next_position(ptyp, &d, sq, u)
1625 : next_direction(ptyp, &d, sq);
1627 u = (color[u] == neutral) ? ppos[u] : pdir[u];
1634 * Couldn't find a move that prevents check.
1635 * Try to find a drop that prevents check.
1640 for (piece = king - 1; piece >= pawn; piece--)
1642 if (Captured[side][piece])
1644 for (u = 0; u < NO_SQUARES; u++)
1646 if (DropPossible(piece, side, u))
1649 f = NO_SQUARES + piece;
1654 GenMakeMove(side, f, u, &tempb, &tempc, false);
1655 threat = SqAttacked(sqking, xside, &dummy);
1656 GenUnmakeMove(side, f, u, tempb, tempc, false);
1664 * If the piece could be dropped at any square, it is
1665 * impossible for any other piece drop to prevent check.
1666 * Drops are restricted for pawns, lances, and knights.
1669 if (piece >= silver)