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 1, or (at your option) any
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
25
* You should have received a copy of the GNU General Public License along
26
* with GNU Shogi; see the file COPYING. If not, write to the Free
27
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
28
* ----------------------------------------------------------------------
34
/* #define DONTUSE_HEURISTIC */
38
static struct leaf *node;
39
static short sqking, sqxking;
40
static short InCheck = false, GenerateAllMoves = false;
41
static short check_determined = false;
43
static short INCscore = 0;
45
short deepsearchcut = true;
46
short tas = false, taxs = false, ssa = false;
48
short generate_move_flags = false;
52
* Ply limits for deep search cut. No moves or drops flagged with "stupid"
53
* are considered beyond ply BEYOND_STUPID. Only moves or drops flagged
54
* with "kingattack" are considered beyond ply BEYOND_KINGATTACK. No moves
55
* or drops flagged with "questionable" are considered beyond ply
56
* BEYOND_QUESTIONABLE. Only moves or drops flagged with "tesuji" are
57
* considered beyond ply BEYOND_TESUJI. No drops are considered beyond ply
58
* BEYOND_DROP. Exceptions: moves or drops that prevent check or give
59
* check are always considered.
62
#define BEYOND_STUPID 0
63
#define BEYOND_TIMEOUT 2
64
#define BEYOND_KINGATTACK 6
65
#define BEYOND_QUESTIONABLE 8
66
#define BEYOND_TESUJI 8
67
#define BEYOND_DROP 10
69
#ifdef DONTUSE_HEURISTIC
70
static short MaxNum[MAXDEPTH] =
72
-1, 40, 80, 20, 40, 10, 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,
75
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
80
extern int CheckHashKey();
81
extern char mvstr[4][6];
86
* Update Arrays board[] and color[] to reflect the new board
87
* position obtained after making the move pointed to by node.
91
GenMakeMove(short side,
94
short *tempb, /* piece at to square */
95
short *tempc, /* color of to square */
98
short piece, upiece, n;
104
piece = f - NO_SQUARES;
106
if (piece > NO_PIECES)
111
n = (Captured[side][piece])--;
112
UpdateDropHashbd(side, piece, n);
113
UpdateHashbd(side, piece, -1, t);
114
UpdatePieceList(side, t, ADD_PIECE);
121
if (*tempb != no_piece)
123
n = ++Captured[side][upiece = unpromoted[*tempb]];
124
UpdateDropHashbd(side, upiece, n);
125
UpdateHashbd(*tempc, *tempb, -1, t);
126
UpdatePieceList(*tempc, t, REMOVE_PIECE);
130
Pindex[t] = Pindex[f];
131
PieceList[side][Pindex[t]] = t;
138
UpdateHashbd(side, piece, f, -1);
139
board[t] = promoted[piece];
140
UpdateHashbd(side, board[t], -1, t);
145
UpdateHashbd(side, piece, f, t);
153
printf("error in GenMakeMove: %s\n", mvstr[0]);
166
GenUnmakeMove(short side,
173
short piece, upiece, n;
179
piece = f - NO_SQUARES;
181
if (piece > NO_PIECES)
186
n = ++Captured[side][piece];
187
UpdateDropHashbd(side, piece, n);
188
UpdateHashbd(side, piece, -1, t);
189
UpdatePieceList(side, t, REMOVE_PIECE);
196
Pindex[f] = Pindex[t];
197
PieceList[side][Pindex[f]] = f;
199
if (tempb != no_piece)
201
/* FIXME: make this next line a bit more reasonable... */
202
n = (Captured[side][upiece = unpromoted[tempb]])--;
203
UpdateDropHashbd(side, upiece, n);
204
UpdateHashbd(tempc, tempb, -1, t);
205
UpdatePieceList(tempc, t, ADD_PIECE);
212
UpdateHashbd(side, piece, -1, t);
213
board[f] = unpromoted[piece];
214
UpdateHashbd(side, board[f], f, -1);
219
UpdateHashbd(side, piece, f, t);
227
printf("error in GenUnmakeMove: %s\n", mvstr[0]);
236
gives_check_flag(unsigned short *flags, short side, short f, short t)
238
short tempb, tempc, blockable, promote_piece;
239
promote_piece = (*flags & promote) != 0;
240
GenMakeMove(side, f, t, &tempb, &tempc, promote_piece);
242
if (SqAttacked(sqxking, side, &blockable))
245
GenUnmakeMove(side, f, t, tempb, tempc, promote_piece);
250
Link(short side, short piece,
251
short from, short to, unsigned short local_flag, short s)
255
ShowMessage("TREE overflow\n");
260
node->t = (local_flag & promote) ? (to | 0x80) : to;
262
node->flags = local_flag;
264
node->INCscore = INCscore;
266
if (GenerateAllMoves)
268
/* FIXME: gimme a break! */
273
/* only moves out of check */
274
short tempb, tempc, sq, threat, blockable, promote_piece;
275
promote_piece = (node->flags & promote) != 0;
276
GenMakeMove(side, node->f, node->t,
277
&tempb, &tempc, promote_piece);
278
sq = (from == sqking) ? to : sqking;
279
threat = SqAttacked(sq, side ^ 1, &blockable);
280
GenUnmakeMove(side, node->f, node->t,
281
tempb, tempc, promote_piece);
285
/* FIXME! Gimme a break! */
291
/* only moves that give check */
292
if (!(node->flags & check) && !check_determined)
294
/* determine check flag */
295
gives_check_flag(&node->flags, side, node->f, node->t);
298
if (node->flags & check)
300
/* FIXME! Gimme a break! */
306
/* FIXME! Gimme a break! */
314
PromotionPossible(short color, short f, short t, short p)
318
if ((f < 54) && (t < 54))
323
if ((f > 26) && (t > 26))
327
/* FIXME: this can be simplified... */
344
NonPromotionPossible(short color, short f,
354
: (generate_move_flags ? ILLEGAL_TRAPPED : false));
360
: (generate_move_flags ? ILLEGAL_TRAPPED : false));
368
: (generate_move_flags ? ILLEGAL_TRAPPED : false));
374
: (generate_move_flags ? ILLEGAL_TRAPPED : false));
382
: (generate_move_flags ? ILLEGAL_TRAPPED : false));
388
: (generate_move_flags ? ILLEGAL_TRAPPED : false));
396
#if defined FIELDBONUS || defined DROPBONUS
398
/* bonus for possible next moves */
401
field_bonus(short ply, short side, short piece,
402
short f, short t, unsigned short *local_flag)
405
unsigned char *ppos, *pdir;
415
check_determined = true;
417
ptyp = ptype[side][piece];
420
u = first_direction(ptyp, &d, t);
422
ppos = (*nextpos[ptyp])[t];
423
pdir = (*nextdir[ptyp])[t];
429
short coloru = color[u];
431
if (piece != king && GameCnt > 40)
433
if (distance(u, EnemyKing) <= 1)
435
/* can reach square near own king */
437
*local_flag |= kingattack;
439
else if (distance(u, OwnKing) <= 1)
441
/* can reach square near enemy king */
443
*local_flag |= kingattack;
449
/* impossible next move */
451
u = next_direction(ptyp, &d, t);
458
/* possible next move */
459
if (PromotionPossible(side, t, u, piece))
461
/* possible promotion in next move */
466
if (!InPromotionZone(side, t))
468
*local_flag |= tesuji; /* The dangling pawn */
479
if (coloru == neutral)
481
/* next move to an empty square */
484
/* opponent has just left this square */
489
u = next_position(ptyp, &d, t, u);
496
/* attack opponents piece */
498
short boardu, upiece, rvupiece, rvuboard;
502
if (u == TOsquare) /* opponent has moved to TOsquare */
505
if ((boardu = board[u]) == king)
507
s += 20; INCscore -= 18;
508
*local_flag |= check; /* move threatens
513
upiece = unpromoted[piece];
514
rvupiece = relative_value[upiece];
515
rvuboard = relative_value[unpromoted[boardu]];
517
if ((upiece == pawn) && (Captured[side][pawn] > 1))
519
*local_flag |= tesuji; /* The joining pawn attack */
523
if (rvupiece <= rvuboard)
525
*local_flag |= tesuji; /* The striking pawn
536
/* CHECKME: is this right? */
537
if (((rvupiece == rvuboard) && (upiece == pawn))
538
|| (upiece == bishop) || (upiece == knight))
540
s++; /* The opposing pawn (piece) */
549
u = next_direction(ptyp, &d, t);
569
* Add a move to the tree. Assign a bonus to order the moves as follows:
570
* 1. Principle variation 2. Capture of last moved piece 3. Other captures
571
* (major pieces first) 4. Killer moves 5. Tesuji drops 6. Other Moves
572
* 7. Other drops. 8. Non-promoting moves
573
* If the flag.tsume is set, assign a high bonus for checks.
577
LinkMove(short ply, short f,
579
unsigned short local_flag,
581
short score_if_impossible)
584
short side, piece, mv;
585
short flag_tsume, try_link = true;
586
short c1, c2, ds, is_drop = f > NO_SQUARES;
587
unsigned long as = 0;
589
flag_tsume = flag.tsume;
591
c1 = side = xside ^ 1;
595
* Is it determined whether the move gives check ?
598
check_determined = ((local_flag & check) != 0);
600
mv = (f << 8) | ((local_flag & promote) ? (t | 0x80) : t);
604
piece = f - NO_SQUARES;
606
if (piece > NO_PIECES)
614
if (score_if_impossible < 0)
616
/* The move is flagged as illegal. */
618
f, t, local_flag, score_if_impossible);
626
s += history[hindex(side, mv)];
629
/* If we're running short of tree nodes, go into tsume mode. */
631
if (!(local_flag & capture))
633
if (*TrP > (TREE - 300))
635
/* too close to tree table limit */
640
/* Guess strength of move and set flags. */
642
if ((piece != king) && (!in_opening_stage))
644
if (distance(t, EnemyKing) <= 1)
646
/* bonus for square near enemy king */
649
local_flag |= kingattack;
651
else if (distance(t, OwnKing) <= 1)
653
/* bonus for square near own king */
656
local_flag |= kingattack;
660
if (tas) /* own attack array available */
662
/* square t defended by own piece (don't count piece to move) ? */
664
? (as = attack[side][t])
665
: (as = ((attack[side][t] & CNT_MASK) > 1)))
666
s += (ds = in_endgame_stage ? 100 : 10);
669
if (taxs) /* opponents attack array available */
671
/* square t not threatened by opponent or
672
* defended and only threatened by opponents king ?
676
if (!(axs = attack[xside][t])
677
|| (tas && as && (axs & control[king]) && (axs & CNT_MASK) == 1))
679
/* FIXME: this is a mess; clean up. */
680
s += (ds = in_endgame_stage
683
? (InPromotionZone(side, t)
684
? 40 + relative_value[piece]
690
/* target square near area of action */
693
s += (9 - distance(TOsquare, t));
696
s += (9 - distance(FROMsquare, t)) / 2;
698
/* target square near own or enemy king */
700
if (!in_opening_stage && piece != king)
702
if (balance[c1] < 50)
703
s += (9 - distance(EnemyKing, t)) * (50 - balance[c1]) / 20;
705
s += (9 - distance(OwnKing, t)) * (balance[c1] - 50) / 20;
710
/* bonus for drops, in order to place
711
* drops before questionable moves */
712
s += in_endgame_stage ? 25 : 10;
716
/* drop to the square the opponent has just left */
721
s -= 32 / Captured[side][gold];
722
else if (piece == silver)
723
s -= 16 / Captured[side][silver];
725
#if defined DROPBONUS
726
s += field_bonus(ply, side, piece, f, t, &local_flag);
728
if (s == 10 && piece != pawn)
729
local_flag |= questionable;
734
/* bonus for moves (non-drops) */
735
int consider_last = false;
737
if (in_endgame_stage && Captured[side][gold])
744
/* move to the square the opponent has just left */
745
s += in_endgame_stage ? 10 : 1;
748
if (color[t] != neutral)
751
if (in_endgame_stage)
753
s += relative_value[board[t]] - relative_value[piece];
757
s += (*value)[stage][board[t]] - relative_value[piece];
760
if (t == TOsquare) /* Capture of last moved piece */
761
s += in_endgame_stage ? 5 : 50;
764
if (local_flag & promote)
766
/* bonus for promotions */
768
INCscore += value[stage][promoted[piece]] - value[stage][piece];
772
/* bonus for non-promotions */
773
if (PromotionPossible(side, f, t, piece))
776
/* Look at non-promoting silver or knight */
777
if (piece == silver || piece == knight)
779
local_flag |= tesuji; /* Non-promotion */
785
consider_last = true;
787
if (piece == pawn || piece == bishop || piece == rook)
789
local_flag |= stupid;
794
local_flag |= questionable;
803
if (local_flag & stupid)
810
#if defined FIELDBONUS
811
s += field_bonus(ply, side, piece, f, t, &local_flag);
816
#if defined CHECKBONUS
817
/* determine check flag */
818
if (!(local_flag & check) && !check_determined)
820
gives_check_flag(&local_flag, side, f, t);
822
if (local_flag & check)
827
/* check conditions for deep search cut (flag.tsume = true) */
830
if (!flag.tsume && deepsearchcut)
832
if ((ply > BEYOND_STUPID) && (local_flag & stupid))
834
try_link = flag.force || ((ply == 1) && (side != computer));
836
else if (hard_time_limit && (ply > BEYOND_TIMEOUT) && flag.timeout)
840
else if ((ply > BEYOND_KINGATTACK) && !(local_flag & kingattack))
844
else if ((ply > BEYOND_QUESTIONABLE) && (local_flag & questionable))
849
else if ((ply > BEYOND_TESUJI) && !(local_flag & tesuji))
854
else if ((ply > BEYOND_DROP) && (f > NO_SQUARES))
861
if (try_link || GenerateAllMoves)
863
Link(side, piece, f, t, local_flag,
864
s - ((SCORE_LIMIT + 1000) * 2));
867
flag.tsume = flag_tsume;
873
DropPossible(short piece, short side, short sq)
875
short r = row(sq), possible = true;
877
if (board[sq] != no_piece)
881
else if (piece == pawn)
883
if ((side == black) && (r == 8))
885
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
887
else if ((side == white) && (r == 0))
889
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
891
else if (PawnCnt[side][column(sq)])
893
possible = (generate_move_flags ? ILLEGAL_DOUBLED : false);
896
/* Pawn drops are invalid if they mate the opponent. */
899
short f, tempb, tempc;
900
f = pawn + NO_SQUARES;
905
GenMakeMove(side, f, sq, &tempb, &tempc, false);
907
if (IsCheckmate(side^1, -1, -1))
908
possible = (generate_move_flags ? ILLEGAL_MATE : false);
910
GenUnmakeMove(side, f, sq, tempb, tempc, false);
913
else if (piece == lance)
915
if ((side == black) && (r == 8))
916
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
917
else if ((side == white) && (r == 0))
918
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
920
else if (piece == knight)
922
if ((side == black) && (r >= 7))
923
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
924
else if ((side == white) && (r <= 1))
925
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
932
#if defined DONTUSE_HEURISTIC
938
for (p = TrPnt[ply]; p < TrPnt[ply+1]; p++)
939
pick(p, TrPnt[ply+1] - 1);
941
#endif /* DONTUSE_HEURISTIC */
944
#ifdef DONTUSE_HEURISTIC
947
DontUseMoves(short ply, short n)
952
/* k = number of check moves + number of captures */
953
for (i = TrPnt[ply], k = 0; i < TrPnt[ply+1]; i++)
957
if ((p->flags & check) || (p->flags & capture))
965
for (i = TrPnt[ply]; i < TrPnt[ply+1]; i++)
969
if (!((p->flags & check) || (p->flags & capture)))
986
* Generate moves for a piece. The moves are taken from the precalculated
987
* array nextpos/nextdir. If the board is free, next move is chosen from
988
* nextpos else from nextdir.
992
GenMoves(short ply, short sq, short side,
996
short ptyp, possible;
1000
unsigned char *ppos, *pdir;
1004
ptyp = ptype[side][piece];
1007
u = first_direction(ptyp, &d, sq);
1009
ppos = (*nextpos[ptyp])[sq];
1010
pdir = (*nextdir[ptyp])[sq];
1016
unsigned short local_flag;
1019
if ((c = color[u]) == xside)
1020
local_flag = capture;
1024
if (c != side && board[u] != king)
1026
if (PromotionPossible(color[sq], sq, u, piece))
1028
LinkMove(ply, sq, u, local_flag | promote, xside, true);
1031
= NonPromotionPossible(color[sq], sq, u, piece)))
1033
LinkMove(ply, sq, u, local_flag, xside, possible);
1038
LinkMove(ply, sq, u, local_flag, xside, true);
1045
u = next_position(ptyp, &d, sq, u);
1049
u = next_direction(ptyp, &d, sq);
1068
* Drop each piece in hand of "side" to square "u" (if allowed).
1072
DropToSquare(short side, short xside, short ply, short u)
1076
for (i = pawn; i < king; i++)
1078
if (Captured[side][i])
1080
if ((possible = DropPossible(i, side, u)))
1088
LinkMove(ply, f, u, (dropmask | i), xside, possible);
1097
* Add drops of side that prevent own king from being in check
1098
* from xside's sweeping pieces.
1102
LinkPreventCheckDrops(short side, short xside, short ply)
1107
unsigned char *ppos, *pdir;
1109
short piece, u, xu, square, ptyp;
1110
short n, drop_square[9];
1112
if (board[square = PieceList[side][0]] != king)
1115
for (piece = lance; piece <= rook; piece++)
1117
if (piece == lance || piece == bishop || piece == rook)
1119
/* check for threat of xside piece */
1120
ptyp = ptype[side][piece];
1123
u = first_direction(ptyp, &d, square);
1125
ppos = (*nextpos[ptyp])[square];
1126
pdir = (*nextdir[ptyp])[square];
1132
if (color[u] == neutral)
1136
xu = next_position(ptyp, &d, square, u);
1138
if (xu == next_direction(ptyp, &dd, square))
1140
n = 0; /* oops new direction */
1144
drop_square[n++] = u;
1148
if ((xu = ppos[u]) == pdir[u])
1150
n = 0; /* oops new direction */
1154
drop_square[n++] = u;
1161
if (color[u] == xside && (unpromoted[board[u]] == piece))
1163
/* king is threatened by opponents piece */
1166
DropToSquare(side, xside, ply, drop_square[--n]);
1174
u = next_direction(ptyp, &d, square);
1180
while (u != square);
1188
* Add drops that check enemy king.
1192
LinkCheckDrops(short side, short xside, short ply)
1197
unsigned char *ppos, *pdir;
1200
short square, piece;
1202
if (board[square = PieceList[xside][0]] != king)
1205
for (piece = pawn; piece < king; piece++)
1207
if (Captured[side][piece])
1210
* "side" has "piece" in hand. Try to make a piece move from
1211
* opponents king square and drop this piece to each reachable
1212
* empty square. This definitely gives check! For a pawn drop
1213
* it must not double pawns and it must not be checkmate!
1216
ptyp = ptype[xside][piece];
1218
u = first_direction(ptyp, &d, square);
1220
ppos = (*nextpos[ptyp])[square];
1221
pdir = (*nextdir[ptyp])[square];
1226
if (color[u] == neutral)
1228
if (piece != pawn || DropPossible(pawn, side, u))
1231
f = NO_SQUARES + piece;
1237
(dropmask | piece | check), xside, true);
1241
u = next_position(ptyp, &d, square, u);
1249
u = next_direction(ptyp, &d, square);
1255
while (u != square);
1263
* Fill the array Tree[] with all available moves for side to play. Array
1264
* TrPnt[ply] contains the index into Tree[] of the first move at a ply.
1265
* in_check = 0 side is not in check
1266
* in_check > 1 side is in check
1267
* in_check < 0 don't know
1268
* in_check -2 indicates move generation for book moves
1272
MoveList(short side, short ply,
1273
short in_check, short blockable)
1276
struct leaf *firstnode;
1277
short flag_tsume, num;
1280
unsigned short hiHt = 0, hi0 = 0, hi1 = 0, hi2 = 0, hi3 = 0, hi4 = 0;
1283
flag_tsume = flag.tsume;
1287
sqking = PieceList[side][0];
1288
sqxking = PieceList[xside][0];
1296
InCheck = (board[sqking] == king)
1297
? SqAttacked(sqking, xside, &blockable)
1301
GenerateAllMoves = (in_check == -2) || generate_move_flags;
1303
if (InCheck /* && (ply > 1 || side == computer) */)
1305
/* Own king in check */
1309
TrP = &TrPnt[ply + 1];
1312
firstnode = node = &Tree[*TrP];
1315
Swag0 = killr0[ply];
1319
Swag1 = killr1[ply];
1320
Swag2 = killr2[ply];
1321
Swag3 = killr3[ply];
1324
Swag4 = killr1[ply - 2];
1331
history[hiHt = hindex(side, SwagHt)] += 5000;
1332
history[hi0 = hindex(side, Swag0)] += 2000;
1333
history[hi1 = hindex(side, Swag1)] += 60;
1334
history[hi2 = hindex(side, Swag2)] += 50;
1335
history[hi3 = hindex(side, Swag3)] += 40;
1336
history[hi4 = hindex(side, Swag4)] += 30;
1340
for (i = PieceCnt[side]; i >= 0; i--)
1341
GenMoves(ply, PieceList[side][i], side, xside);
1343
if (!InCheck || blockable)
1347
/* special drop routine for tsume problems */
1349
LinkPreventCheckDrops(side, xside, ply);
1351
LinkCheckDrops(side, xside, ply);
1355
for (u = 0; u < NO_SQUARES; u++)
1356
DropToSquare(side, xside, ply, u);
1363
history[hiHt] -= 5000;
1364
history[hi0] -= 2000;
1372
SwagHt = 0; /* SwagHt is only used once */
1374
if (flag.tsume && node == firstnode)
1377
GenCnt += (num = (TrPnt[ply+1] - TrPnt[ply]));
1379
#ifdef DONTUSE_HEURISTIC
1380
/* remove some nodes in case of wide spread in depth */
1381
if (!flag.tsume && (i = MaxNum[ply]) > 0 && num > i)
1384
DontUseMoves(ply, i);
1388
flag.tsume = flag_tsume;
1394
* Fill the array Tree[] with all available captures for side to play. If
1395
* there is a non-promote option, discard the non-promoting move. Array
1396
* TrPnt[ply] contains the index into Tree[] of the first move at a ply.
1397
* If flag.tsume is set, only add captures (but also the non-promoting)
1398
* that threaten the opponents king.
1400
* in_check = 0: side is not in check
1401
* in_check > 1: side is in check
1402
* in_check < 0: we don't know
1406
CaptureList(short side, short ply,
1407
short in_check, short blockable)
1413
unsigned char *ppos, *pdir;
1415
short i, piece, flag_tsume;
1420
TrP = &TrPnt[ply + 1];
1424
flag_tsume = flag.tsume;
1426
sqking = PieceList[side][0];
1427
sqxking = PieceList[xside][0];
1435
InCheck = (board[sqking] == king)
1436
? SqAttacked(sqking, xside, &blockable)
1440
GenerateAllMoves = (in_check == -2);
1442
if (InCheck && (ply > 1 || side == computer))
1444
/* Own king is in check */
1448
check_determined = false;
1450
PL = PieceList[side];
1452
for (i = 0; i <= PieceCnt[side]; i++)
1457
ptyp = ptype[side][piece];
1459
u = first_direction(ptyp, &d, sq);
1461
ppos = (*nextpos[ptyp])[sq];
1462
pdir = (*nextdir[ptyp])[sq];
1467
if (color[u] == neutral)
1470
u = next_position(ptyp, &d, sq, u);
1477
if (color[u] == xside && board[u] != king)
1481
if ((PP = PromotionPossible(color[sq], sq, u, piece)))
1484
sq, u, capture | promote,
1485
(*value)[stage][board[u]]
1486
#if !defined SAVE_SVALUE
1489
- relative_value[piece]);
1492
if (!PP || flag.tsume)
1496
(*value)[stage][board[u]]
1497
#if !defined SAVE_SVALUE
1500
- relative_value[piece]);
1505
u = next_direction(ptyp, &d, sq);
1514
flag.tsume = flag_tsume;
1516
SwagHt = 0; /* SwagHt is only used once */
1523
* If the king is in check, try to find a move that prevents check.
1524
* If such a move is found, return false, otherwise return true.
1525
* in_check = 0: side is not in check
1526
* in_check > 1: side is in check
1527
* in_check < 0: don't know
1528
* blockable > 0 && check: check can possibly be prevented by a drop
1529
* blockable = 0 && check: check can definitely not be prevented by a drop
1530
* blockable < 0 && check: nothing known about type of check
1534
IsCheckmate(short side, short in_check, short blockable)
1540
unsigned char *ppos, *pdir;
1544
short tempb, tempc, ksq, threat, dummy, sqking;
1549
sqking = PieceList[side][0];
1552
* Checkmate is possible only if king is in check.
1557
else if (board[sqking] == king)
1558
InCheck = SqAttacked(sqking, xside, &blockable);
1566
* Try to find a move that prevents check.
1569
PL = PieceList[side];
1571
for (i = 0; i <= PieceCnt[side]; i++)
1576
ptyp = ptype[side][piece];
1578
u = first_direction(ptyp, &d, sq);
1580
ppos = (*nextpos[ptyp])[sq];
1581
pdir = (*nextdir[ptyp])[sq];
1586
if (color[u] == neutral || color[u] == xside)
1588
GenMakeMove(side, sq, u, &tempb, &tempc, false);
1589
ksq = (sq == sqking) ? u : sqking;
1590
threat = SqAttacked(ksq, xside, &dummy);
1591
GenUnmakeMove(side, sq, u, tempb, tempc, false);
1598
u = (color[u] == neutral)
1599
? next_position(ptyp, &d, sq, u)
1600
: next_direction(ptyp, &d, sq);
1602
u = (color[u] == neutral) ? ppos[u] : pdir[u];
1609
* Couldn't find a move that prevents check.
1610
* Try to find a drop that prevents check.
1615
for (piece = king - 1; piece >= pawn; piece--)
1617
if (Captured[side][piece])
1619
for (u = 0; u < NO_SQUARES; u++)
1621
if (DropPossible(piece, side, u))
1624
f = NO_SQUARES + piece;
1629
GenMakeMove(side, f, u, &tempb, &tempc, false);
1630
threat = SqAttacked(sqking, xside, &dummy);
1631
GenUnmakeMove(side, f, u, tempb, tempc, false);
1639
* If the piece could be dropped at any square, it is
1640
* impossible for any other piece drop to prevent check.
1641
* Drops are restricted for pawns, lances, and knights.