2
* genmoves.c - C source for GNU SHOGI
4
* Copyright (c) 1993, 1994 Matthias Mutz
6
* GNU SHOGI is based on GNU CHESS
8
* Copyright (c) 1988,1989,1990 John Stanback
9
* Copyright (c) 1992 Free Software Foundation
11
* This file is part of GNU SHOGI.
13
* GNU Shogi is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License as published by
15
* the Free Software Foundation; either version 1, or (at your option)
18
* GNU Shogi is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
23
* You should have received a copy of the GNU General Public License
24
* along with GNU Shogi; see the file COPYING. If not, write to
25
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30
/* #define DONTUSE_HEURISTIC */
38
static struct leaf far *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.
53
* No moves or drops flagged with "stupid" are considered beyond ply BEYOND_STUPID.
54
* Only moves or drops flagged with "kingattack" are considered beyond ply BEYOND_KINGATTACK.
55
* No moves or drops flagged with "questionable" are considered beyond ply BEYOND_QUESTIONABLE.
56
* Only moves or drops flagged with "tesuji" are considered beyond ply BEYOND_TESUJI.
57
* No drops are considered beyond ply BEYOND_DROP.
58
* Exceptions: moves or drops that prevent check or give check are always considered.
61
#if defined THINK_C || defined MSDOS
62
#define BEYOND_STUPID 0
63
#define BEYOND_TIMEOUT 2
64
#define BEYOND_KINGATTACK 4
65
#define BEYOND_QUESTIONABLE 6
66
#define BEYOND_TESUJI 6
69
#define BEYOND_STUPID 0
70
#define BEYOND_TIMEOUT 2
71
#define BEYOND_KINGATTACK 6
72
#define BEYOND_QUESTIONABLE 8
73
#define BEYOND_TESUJI 8
74
#define BEYOND_DROP 10
77
static short MaxNum[MAXDEPTH] =
78
{-1,40,80,20,40,10, 5, 5, 5, 5,
79
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
80
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
81
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
85
extern int CheckHashKey ();
86
extern char mvstr[4][6];
93
GenMakeMove (short int side,
96
short int *tempb, /* piece at to square */
97
short int *tempc, /* color of to square */
98
short int promote_piece)
101
* Update Arrays board[] and color[] to reflect the new board
102
* position obtained after making the move pointed to by node.
106
register short int piece, upiece, n;
111
assert(f!=NO_SQUARES);
116
piece = f - NO_SQUARES;
117
if ( piece > NO_PIECES ) piece -= NO_PIECES;
120
n = Captured[side][piece]--;
121
UpdateDropHashbd (side, piece, n);
122
UpdateHashbd (side, piece, -1, t);
123
UpdatePieceList (side, t, ADD_PIECE);
129
if ( *tempb != no_piece ) {
130
n = ++Captured[side][upiece = unpromoted[*tempb]];
131
UpdateDropHashbd (side, upiece, n);
132
UpdateHashbd (*tempc, *tempb, -1, t);
133
UpdatePieceList (*tempc, t, REMOVE_PIECE);
136
Pindex[t] = Pindex[f];
137
PieceList[side][Pindex[t]] = t;
141
if ( promote_piece ) {
142
UpdateHashbd(side,piece,f,-1);
143
board[t] = promoted[piece];
144
UpdateHashbd(side,board[t],-1,t);
147
UpdateHashbd(side,piece,f,t);
151
assert(Captured[black][0]==0 && Captured[white][0]==0);
154
if ( CheckHashKey () ) {
156
printf("error in GenMakeMove: %s\n",mvstr[0]);
164
GenUnmakeMove (short int side,
169
short int promote_piece)
176
register short piece, upiece, n;
181
assert(f!=NO_SQUARES);
186
piece = f - NO_SQUARES;
187
if ( piece > NO_PIECES ) piece -= NO_PIECES;
190
n = ++Captured[side][piece];
191
UpdateDropHashbd (side, piece, n);
192
UpdateHashbd (side, piece, -1, t);
193
UpdatePieceList (side, t, REMOVE_PIECE);
200
Pindex[f] = Pindex[t];
201
PieceList[side][Pindex[f]] = f;
202
if ( tempb != no_piece ) {
203
n = Captured[side][upiece=unpromoted[tempb]]--;
204
UpdateDropHashbd (side, upiece, n);
205
UpdateHashbd (tempc, tempb, -1, t);
206
UpdatePieceList (tempc, t, ADD_PIECE);
209
if ( promote_piece ) {
210
UpdateHashbd(side,piece,-1,t);
211
board[f] = unpromoted[piece];
212
UpdateHashbd(side,board[f],f,-1);
215
UpdateHashbd(side,piece,f,t);
219
assert(Captured[black][0]==0 && Captured[white][0]==0);
222
if ( CheckHashKey () ) {
224
printf("error in GenUnmakeMove: %s\n",mvstr[0]);
233
gives_check_flag (unsigned short *flags, short side, short f, short t)
235
short tempb, tempc, blockable, promote_piece;
236
promote_piece = (*flags & promote) != 0;
237
GenMakeMove (side, f, t, &tempb, &tempc, promote_piece);
238
if ( SqAtakd(sqxking, side, &blockable) )
240
GenUnmakeMove (side, f, t, tempb, tempc, promote_piece);
247
Link (short side, short piece,
248
short from, short to, unsigned short local_flag, short s)
252
fprintf ( debug_eval_file, "link from %d to %d InCheck %d tsume %d\n",
253
from, to, InCheck, flag.tsume );
257
if ( *TrP == TREE ) {
259
printf("TREE overflow\n");
261
ShowMessage("TREE overflow\n");
265
node->t = (local_flag & promote) ? (to | 0x80) : to;
267
node->flags = local_flag;
269
node->INCscore = INCscore;
270
if ( GenerateAllMoves )
276
/* only moves out of check */
277
short tempb, tempc, sq, threat, blockable, promote_piece;
278
promote_piece = (node->flags & promote) != 0;
279
GenMakeMove (side, node->f, node->t, &tempb, &tempc, promote_piece);
280
sq = (from == sqking) ? to : sqking;
281
threat = SqAtakd(sq, side ^ 1, &blockable);
282
GenUnmakeMove (side, node->f, node->t, tempb, tempc, promote_piece);
286
else if ( flag.tsume )
288
/* only moves that give check */
289
if ( !(node->flags & check) && !check_determined ) {
290
/* determine check flag */
291
gives_check_flag(&node->flags,side,node->f,node->t);
293
if ( node->flags & check )
304
PromotionPossible (short int color, short int f, short int t, short int p)
306
if ( color == black ) {
307
if ( f < 54 && t < 54 ) return(false);
309
if ( f > 26 && t > 26 ) return(false);
313
case pawn: return(true);
314
case lance: return(true);
315
case knight: return(true);
316
case silver: return(true);
317
case bishop: return(true);
318
case rook: return(true);
327
NonPromotionPossible (short int color, short int f, short int t, short int p)
331
if ( color == black )
332
return ((t < 72) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
334
return ((t > 8) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
336
if ( color == black )
337
return ((t < 72) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
339
return ((t > 8) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
341
if ( color == black )
342
return ((t < 63) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
344
return ((t > 17) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
351
#if defined FIELDBONUS || defined DROPBONUS
356
field_bonus (short int ply, short int side, short int piece, short int f, short int t,
357
unsigned short *local_flag)
359
/* bonus for possible next moves */
362
register short s, u, ptyp;
363
register unsigned char *ppos, *pdir;
364
register short c1, c2;
374
check_determined = true;
376
ptyp = ptype[side][piece];
379
u = first_direction(ptyp,&d,t);
381
ppos = (*nextpos[ptyp])[t];
382
pdir = (*nextdir[ptyp])[t];
387
{ short coloru = color[u];
388
if ( piece != king && GameCnt > 40 ) {
389
if ( distance(u,EnemyKing) <= 1 ) {
390
/* can reach square near own king */
392
*local_flag |= kingattack;
393
} else if ( distance(u,OwnKing) <= 1 ) {
394
/* can reach square near enemy king */
396
*local_flag |= kingattack;
399
if (coloru == side ) {
400
/* impossible next move */
402
u = next_direction(ptyp,&d,t);
407
/* possible next move */
408
if (PromotionPossible(side,t,u,piece)) {
409
/* possible promotion in next move */
414
if ( !InPromotionZone(side,t) ) {
415
*local_flag |= tesuji; /* The dangling pawn */
423
if (coloru == neutral) {
424
/* next move to an empty square */
425
if ( u == FROMsquare ) {
426
/* opponent has just left this square */
430
u = next_position(ptyp,&d,t,u);
435
/* attack opponents piece */
437
short boardu, upiece, rvupiece, rvuboard;
441
/* opponent has moved to TOsquare */
443
if ( (boardu = board[u]) == king ) {
444
s += 20; INCscore -= 18;
445
*local_flag |= check; /* move threatens opponents king */
448
upiece = unpromoted[piece];
449
rvupiece = relative_value[upiece];
450
rvuboard = relative_value[unpromoted[boardu]];
451
if ( upiece == pawn && Captured[side][pawn] > 1 )
453
*local_flag |= tesuji; /* The joining pawn attack */
456
if ( rvupiece <= rvuboard )
458
*local_flag |= tesuji; /* The striking pawn (piece) attack */
459
if ( f > NO_SQUARES )
463
if ( upiece == pawn ) {
466
if ( rvupiece == rvuboard &&
467
upiece == pawn || upiece == bishop || upiece == knight ) {
468
s++; /* The opposing pawn (piece) */
469
if ( upiece == pawn )
475
u = next_direction(ptyp,&d,t);
494
LinkMove (short int ply, short int f,
495
register short int t,
496
unsigned short local_flag,
498
short int score_if_impossible)
501
* Add a move to the tree. Assign a bonus to order the moves as follows:
502
* 1. Principle variation 2. Capture of last moved piece 3. Other captures
503
* (major pieces first) 4. Killer moves 5. Tesuji drops 6. Other Moves
504
* 7. Other drops. 8. Non-promoting moves
505
* If the flag.tsume is set, assign a high bonus for checks.
509
register short s = 0;
510
register short side, piece, mv;
511
short flag_tsume, try_link = true;
512
short c1, c2, ds, is_drop = f > NO_SQUARES;
513
unsigned long as = 0;
515
flag_tsume = flag.tsume;
517
c1 = side = xside ^ 1;
521
* Is it determined whether the move gives check ?
524
check_determined = ((local_flag & check) != 0);
526
mv = (f << 8) | ((local_flag & promote) ? (t | 0x80) : t);
528
if ( f > NO_SQUARES ) {
529
piece = f - NO_SQUARES;
530
if ( piece > NO_PIECES ) piece -= NO_PIECES;
535
if ( score_if_impossible < 0 ) {
536
/* The move is flagged as illegal. */
538
f, t, local_flag, score_if_impossible);
549
s += (ds = history[hi = hindex(side,mv)]);
552
s += history[hindex(side,mv)];
556
/* If we're running short of tree node, go into tsume mode. */
558
if ( !(local_flag & capture) )
559
if ( *TrP > TREE - 300 ) {
560
/* too close to tree table limit */
564
/* Guess strength of move and set flags. */
566
if ( piece != king && !in_opening_stage ) {
567
if ( distance(t,EnemyKing) <= 1 ) {
568
/* bonus for square near enemy king */
569
s += 15; INCscore += 2;
570
local_flag |= kingattack;
571
} else if ( distance(t,OwnKing) <= 1 ) {
572
/* bonus for square near own king */
574
local_flag |= kingattack;
578
if ( tas /* own attack array available */ ) {
579
/* square t defended by own piece (don't count piece to move) ? */
580
if ( is_drop ? (as = atak[side][t]) : (as = ((atak[side][t] & CNT_MASK) > 1)) )
581
s += (ds = in_endgame_stage ? 100 : 10);
583
if ( taxs /* opponents attack array available */ ) {
584
/* square t not threatened by opponent or
585
* defended and only threatened by opponents king ?
588
if ( !(axs = atak[xside][t]) ||
589
(tas && as && (axs & control[king]) && (axs & CNT_MASK) == 1) )
590
s += (ds = in_endgame_stage ? 200 :
591
(is_drop ? (InPromotionZone(side,t) ? 40 + relative_value[piece]: 10) : 20));
594
/* target square near area of action */
597
s += (9-distance(TOsquare,t));
598
if ( FROMsquare >= 0 )
599
s += (9-distance(FROMsquare,t)) / 2;
601
/* target square near own or enemy king */
603
if ( !in_opening_stage && piece != king ) {
604
if ( balance[c1] < 50 )
605
s += (9-distance(EnemyKing,t)) * (50 - balance[c1]) / 20;
607
s += (9-distance(OwnKing,t)) * (balance[c1] - 50) / 20;
610
if ( f > NO_SQUARES )
612
/* bonus for drops, in order to place drops before questionable moves */
613
s += in_endgame_stage ? 25 : 10;
614
if (t == FROMsquare) {
615
/* drop to the square the opponent has just left */
619
s -= 32 / Captured[side][gold];
620
else if ( piece == silver )
621
s -= 16 / Captured[side][silver];
622
#if defined DROPBONUS
623
s += field_bonus(ply,side,piece,f,t,&local_flag);
624
if ( s == 10 && piece != pawn )
625
local_flag |= questionable;
630
/* bonus for moves (non-drops) */
631
int consider_last = false;
632
if ( in_endgame_stage && Captured[side][gold] )
635
if (t == FROMsquare) {
636
/* move to the square the opponent has just left */
637
s += in_endgame_stage ? 10 : 1;
639
if (color[t] != neutral)
642
if ( in_endgame_stage ) {
643
s += relative_value[board[t]] - relative_value[piece];
645
s += (*value)[stage][board[t]] - relative_value[piece];
648
/* Capture of last moved piece */
649
s += in_endgame_stage ? 5 : 50;
651
if ( local_flag & promote )
653
/* bonus for promotions */
655
INCscore += value[stage][promoted[piece]] - value[stage][piece];
659
/* bonus for non-promotions */
660
if ( PromotionPossible(side,f,t,piece) )
662
/* Look at non-promoting silver or knight */
663
if ( piece == silver || piece == knight )
665
local_flag |= tesuji; /* Non-promotion */
671
consider_last = true;
672
if ( piece == pawn || piece == bishop || piece == rook ) {
673
local_flag |= stupid;
676
local_flag |= questionable;
683
if ( local_flag & stupid )
691
#if defined FIELDBONUS
692
s += field_bonus(ply,side,piece,f,t,&local_flag);
697
#if defined CHECKBONUS
698
/* determine check flag */
699
if ( !(local_flag & check) && !check_determined )
701
gives_check_flag(&local_flag, side, f, t);
702
if ( local_flag & check )
707
/* check conditions for deep search cut (flag.tsume = true) */
710
if ( !flag.tsume && deepsearchcut )
712
if ( ply > BEYOND_STUPID && (local_flag & stupid) ) {
713
try_link = flag.force || (ply == 1 && side != computer);
715
} else if ( ply > BEYOND_TIMEOUT && flag.timeout ) {
718
} else if ( ply > BEYOND_KINGATTACK && !(local_flag & kingattack) ) {
720
} else if ( ply > BEYOND_QUESTIONABLE && (local_flag & questionable) ) {
723
} else if ( ply > BEYOND_TESUJI && !(local_flag & tesuji) ) {
726
} else if ( ply > BEYOND_DROP && (f > NO_SQUARES) ) {
732
if ( try_link || GenerateAllMoves )
734
f, t, local_flag, s - ((SCORE_LIMIT+1000)*2));
736
flag.tsume = flag_tsume;
742
DropPossible (short int piece, short int side, short int sq)
745
short r = row(sq), possible = true;
747
if ( board[sq] != no_piece )
749
else if ( piece == pawn )
751
if ( side == black && r == 8 ) {
752
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
753
} else if ( side == white && r == 0 ) {
754
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
755
} else if ( PawnCnt[side][column(sq)] ) {
756
possible = (generate_move_flags ? ILLEGAL_DOUBLED : false);
758
/* pawn drops are invalid, if they mate the opponent */
760
{ short f, tempb, tempc;
761
f = pawn + NO_SQUARES;
762
if ( side == white ) f += NO_PIECES;
763
GenMakeMove (side, f, sq, &tempb, &tempc, false);
764
if ( IsCheckmate(side^1,-1,-1) )
765
possible = (generate_move_flags ? ILLEGAL_MATE : false);
766
GenUnmakeMove (side, f, sq, tempb, tempc, false);
769
else if ( piece == lance )
771
if ( side == black && r == 8 )
772
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
773
else if ( side == white && r == 0 )
774
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
776
else if ( piece == knight )
778
if ( side == black && r >= 7 )
779
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
780
else if ( side == white && r <= 1 )
781
possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
791
SortMoves(short int ply)
794
for (p = TrPnt[ply]; p < TrPnt[ply+1]; p++)
795
pick(p,TrPnt[ply+1]-1);
799
#ifdef DONTUSE_HEURISTIC
802
DontUseMoves(short int ply, short int n)
804
register struct leaf far *p;
809
/* k = number of check moves + number of captures */
810
for (i = TrPnt[ply], k=0; i < TrPnt[ply+1]; i++) {
812
if ( (p->flags & check) || (p->flags & capture) )
813
if (++k >= n) return;
816
for (i = TrPnt[ply]; i < TrPnt[ply+1]; i++) {
818
if ( !((p->flags & check) || (p->flags & capture)) ) {
831
printf("skipping %d moves at ply %d with allowed %d moves\n",j,ply,n);
841
GenMoves (register short int ply, register short int sq, short int side,
845
* Generate moves for a piece. The moves are taken from the precalulated
846
* array nextpos/nextdir. If the board is free, next move is choosen from
847
* nextpos else from nextdir.
851
register short u, piece, col;
852
short ptyp, possible;
856
register unsigned char *ppos, *pdir;
860
ptyp = ptype[side][piece];
863
u = first_direction(ptyp,&d,sq);
865
ppos = (*nextpos[ptyp])[sq];
866
pdir = (*nextdir[ptyp])[sq];
871
{ unsigned short int local_flag;
873
if ( (c = color[u]) == xside )
874
local_flag = capture;
877
if ( c != side && board[u] != king ) {
878
if ( PromotionPossible(color[sq],sq,u,piece) ) {
879
LinkMove (ply, sq, u, local_flag | promote, xside, true);
880
if ( possible = NonPromotionPossible(color[sq],sq,u,piece) )
881
LinkMove (ply, sq, u, local_flag, xside, possible);
883
LinkMove (ply, sq, u, local_flag, xside, true);
888
u = next_position(ptyp,&d,sq,u);
890
u = next_direction(ptyp,&d,sq);
902
DropToSquare (short side, short xside, short ply, short u)
905
* Drop each piece in hand of "side" to square "u" (if allowed).
911
for (i = pawn; i < king; i++)
912
if ( Captured[side][i] )
913
if ( possible = DropPossible(i,side,u) )
916
if ( side == white ) f += NO_PIECES;
917
LinkMove (ply, f, u, (dropmask | i), xside, possible);
923
LinkPreventCheckDrops (short side, short xside, short ply)
926
* Add drops of side that prevent own king from being in check
927
* from xside's sweeping pieces.
934
register unsigned char *ppos, *pdir;
936
register short piece, u, xu, square, ptyp;
937
short i, n, drop_square[9];
939
if ( board[square = PieceList[side][0]] != king )
942
for (piece = lance; piece <= rook; piece++ )
943
if ( piece == lance || piece == bishop || piece == rook ) {
944
/* check for threat of xside piece */
945
ptyp = ptype[side][piece];
948
u = first_direction(ptyp,&d,square);
950
ppos = (*nextpos[ptyp])[square];
951
pdir = (*nextdir[ptyp])[square];
957
if (color[u] == neutral)
961
xu = next_position(ptyp,&d,square,u);
962
if ( xu == next_direction(ptyp,&dd,square) )
963
n = 0; /* oops new direction */
968
drop_square[n++] = u;
971
if ((xu = ppos[u]) == pdir[u])
972
n = 0; /* oops new direction */
977
drop_square[n++] = u;
984
if (color[u] == xside && (unpromoted[board[u]] == piece))
986
/* king is threatened by opponents piece */
988
DropToSquare(side,xside,ply,drop_square[--n]);
994
u = next_direction(ptyp,&d,square);
999
} while (u != square);
1007
LinkCheckDrops (short side, short xside, short ply)
1010
* Add drops that check enemy king.
1017
register unsigned char *ppos, *pdir;
1019
register short u, ptyp;
1020
short square, piece;
1022
if ( board[square = PieceList[xside][0]] != king )
1025
for (piece = pawn; piece < king; piece++)
1026
if ( Captured[side][piece] ) {
1028
* "side" has "piece" in hand. Try to make a piece move from
1029
* opponents king square and drop this piece to each
1030
* reachable empty square. This definitely gives check!
1031
* For a pawn drop it must not double pawns and
1032
* it must not be checkmate!
1034
ptyp = ptype[xside][piece];
1036
u = first_direction(ptyp,&d,square);
1038
ppos = (*nextpos[ptyp])[square];
1039
pdir = (*nextdir[ptyp])[square];
1044
if (color[u] == neutral)
1046
if ( piece != pawn || DropPossible(pawn,side,u) ) {
1048
f = NO_SQUARES + piece;
1049
if ( side == white ) f += NO_PIECES;
1050
LinkMove (ply, f, u, (dropmask | piece | check), xside, true);
1053
u = next_position(ptyp,&d,square,u);
1061
u = next_direction(ptyp,&d,square);
1066
} while (u != square);
1073
MoveList (short int side, register short int ply,
1074
short int in_check, short int blockable)
1077
* Fill the array Tree[] with all available moves for side to play. Array
1078
* TrPnt[ply] contains the index into Tree[] of the first move at a ply.
1079
* in_check = 0 side is not in check
1080
* in_check > 1 side is in check
1081
* in_check < 0 don't know
1082
* in_check -2 indicates move generation for book moves
1086
register short i, xside, f, u;
1087
struct leaf far *firstnode;
1088
short flag_tsume, num;
1091
unsigned short hiHt=0, hi0=0, hi1=0, hi2=0, hi3=0, hi4=0;
1094
flag_tsume = flag.tsume;
1098
sqking = PieceList[side][0];
1099
sqxking = PieceList[xside][0];
1101
if ( in_check >= 0 )
1104
InCheck = (board[sqking] == king) ? SqAtakd(sqking,xside, &blockable) : false;
1106
GenerateAllMoves = (in_check == -2) || generate_move_flags;
1110
fprintf ( debug_eval_file, "%s king is %sin check\n",
1111
ColorStr[side],(InCheck ? "" : "not ") );
1114
if ( InCheck /* && (ply > 1 || side == computer) */ )
1116
/* Own king in check */
1120
TrP = &TrPnt[ply + 1];
1123
firstnode = node = &Tree[*TrP];
1126
Swag0 = killr0[ply];
1128
Swag1 = killr1[ply];
1129
Swag2 = killr2[ply];
1130
Swag3 = killr3[ply];
1132
Swag4 = killr1[ply - 2]; else Swag4 = 0;
1135
if ( debug_eval && (ply == 1 || debug_moves) )
1137
char bufHt[8], buf0[8], buf1[8], buf2[8], buf3[8], buf4[8];
1138
movealgbr(SwagHt,bufHt);
1139
movealgbr(Swag0,buf0);
1140
movealgbr(Swag1,buf1);
1141
movealgbr(Swag2,buf2);
1142
movealgbr(Swag3,buf3);
1143
movealgbr(Swag4,buf4);
1144
fprintf(debug_eval_file, "SwagHt=%x %s 0=%x %s 1=%x %s 2=%x %s 3=%x %s 4=%x %s\n",
1145
SwagHt, bufHt, Swag0, buf0, Swag1, buf1, Swag2, buf2, Swag3, buf3, Swag4, buf4);
1150
if ( use_history ) {
1151
history[hiHt = hindex(side,SwagHt)] += 5000;
1152
history[hi0 = hindex(side,Swag0)] += 2000;
1153
history[hi1 = hindex(side,Swag1)] += 60;
1154
history[hi2 = hindex(side,Swag2)] += 50;
1155
history[hi3 = hindex(side,Swag3)] += 40;
1156
history[hi4 = hindex(side,Swag4)] += 30;
1160
if ( tas = MatchSignature(threats_signature[side]) ) {
1161
#if defined notdef && defined DEBUG_EVAL && defined NONDSP
1162
printf("threats available at ply %d for side=%s\n",ply,ColorStr[side]);
1165
if ( taxs = MatchSignature(threats_signature[xside]) ) {
1166
#if defined notdef && defined DEBUG_EVAL && defined NONDSP
1167
printf("threats available at ply %d for xside=%s\n",ply,ColorStr[xside]);
1170
if ( ssa = MatchSignature(squares_signature) ) {
1171
#if defined notdef && defined DEBUG_EVAL && defined NONDSP
1172
printf("square statistics available at ply %d\n",ply);
1176
for (i = PieceCnt[side]; i >= 0; i--)
1177
GenMoves (ply, PieceList[side][i], side, xside);
1179
if ( !InCheck || blockable )
1181
{ /* special drop routine for tsume problems */
1183
LinkPreventCheckDrops (side, xside, ply);
1185
LinkCheckDrops (side, xside, ply);
1191
for ( u = 0; u < NO_SQUARES; u++ )
1192
DropToSquare(side,xside,ply,u);
1196
if ( use_history ) {
1197
history[hiHt] -= 5000;
1198
history[hi0] -= 2000;
1206
SwagHt = 0; /* SwagHt is only used once */
1208
if ( flag.tsume && node == firstnode )
1211
GenCnt += (num = (TrPnt[ply+1] - TrPnt[ply]));
1217
#ifdef DONTUSE_HEURISTIC
1218
/* remove some nodes in case of wide spread in depth */
1219
if ( !flag.tsume && (i = MaxNum[ply]) > 0 && num > i) {
1221
DontUseMoves(ply,i);
1226
printf("%d moves at ply %d\n",num,ply);
1229
flag.tsume = flag_tsume;
1234
CaptureList (register short int side, short int ply,
1235
short int in_check, short int blockable)
1238
* Fill the array Tree[] with all available captures for side to play.
1239
* If there is a non-promote option, discard the non-promoting move.
1240
* Array TrPnt[ply] contains the index into Tree[] of the first move
1242
* If flag.tsume is set, only add captures (but also the non-promoting)
1243
* that threaten the opponents king.
1244
* in_check = 0 side is not in check
1245
* in_check > 1 side is in check
1246
* in_check < 0 don't know
1250
register short u, sq, xside;
1254
register unsigned char *ppos, *pdir;
1256
short i, piece, flag_tsume;
1261
TrP = &TrPnt[ply + 1];
1265
flag_tsume = flag.tsume;
1267
sqking = PieceList[side][0];
1268
sqxking = PieceList[xside][0];
1270
if ( in_check >= 0 )
1273
InCheck = (board[sqking] == king) ? SqAtakd(sqking,xside,&blockable) : false;
1275
GenerateAllMoves = (in_check == -2);
1279
fprintf ( debug_eval_file, "%s king is %sin check\n",
1280
ColorStr[side],(InCheck ? "" : "not ") );
1283
if ( InCheck && (ply > 1 || side == computer) )
1285
/* Own king is in check */
1289
check_determined = false;
1291
PL = PieceList[side];
1293
for (i = 0; i <= PieceCnt[side]; i++)
1297
ptyp = ptype[side][piece];
1299
u = first_direction(ptyp,&d,sq);
1301
ppos = (*nextpos[ptyp])[sq];
1302
pdir = (*nextdir[ptyp])[sq];
1307
if (color[u] == neutral)
1310
u = next_position(ptyp,&d,sq,u);
1317
if ( color[u] == xside && board[u] != king )
1320
if ( PP = PromotionPossible(color[sq],sq,u,piece) ) {
1322
sq, u, capture | promote,
1323
(*value)[stage][board[u]]
1324
#if !defined SAVE_SVALUE
1327
- relative_value[piece]);
1329
if ( !PP || flag.tsume ) {
1332
(*value)[stage][board[u]]
1333
#if !defined SAVE_SVALUE
1336
- relative_value[piece]);
1340
u = next_direction(ptyp,&d,sq);
1348
flag.tsume = flag_tsume;
1350
SwagHt = 0; /* SwagHt is only used once */
1361
IsCheckmate (short int side, short int in_check, short int blockable)
1364
* If the king is in check, try to find a move that prevents check.
1365
* If such a move is found, return false, otherwise return true.
1366
* in_check = 0: side is not in check
1367
* in_check > 1: side is in check
1368
* in_check < 0: don't know
1369
* blockable > 0 && check: check can possibly prevented by a drop
1370
* blockable = 0 && check: check can definitely not prevented by a drop
1371
* blockable < 0 && check: nothing known about type of check
1375
register short u, sq, xside;
1379
register unsigned char *ppos, *pdir;
1381
short i, piece, flag_tsume;
1383
struct leaf far *firstnode;
1384
short tempb, tempc, ksq, threat, dummy, sqking;
1389
sqking = PieceList[side][0];
1392
* Checkmate is possible only if king is in check.
1395
if ( in_check >= 0 )
1397
else if ( board[sqking] == king )
1398
InCheck = SqAtakd(sqking,xside,&blockable);
1406
* Try to find a move, that prevents check.
1409
PL = PieceList[side];
1411
for (i = 0; i <= PieceCnt[side]; i++)
1415
ptyp = ptype[side][piece];
1417
u = first_direction(ptyp,&d,sq);
1419
ppos = (*nextpos[ptyp])[sq];
1420
pdir = (*nextdir[ptyp])[sq];
1425
if (color[u] == neutral || color[u] == xside)
1427
GenMakeMove (side, sq, u, &tempb, &tempc, false);
1428
ksq = (sq == sqking) ? u : sqking;
1429
threat = SqAtakd(ksq,xside,&dummy);
1430
GenUnmakeMove (side, sq, u, tempb, tempc, false);
1435
u = (color[u] == neutral) ? next_position(ptyp,&d,sq,u)
1436
: next_direction(ptyp,&d,sq);
1438
u = (color[u] == neutral) ? ppos[u] : pdir[u];
1444
* Couldn't find a move that prevents check.
1445
* Try to find a drop, that prevents check.
1448
if ( blockable != 0 )
1450
for (piece = king-1; piece >= pawn; piece--)
1451
if ( Captured[side][piece] )
1453
for (u = 0; u < NO_SQUARES; u++)
1454
if ( DropPossible(piece,side,u) )
1456
f = NO_SQUARES + piece;
1457
if ( side == white ) f += NO_PIECES;
1458
GenMakeMove (side, f, u, &tempb, &tempc, false);
1459
threat = SqAtakd(sqking,xside,&dummy);
1460
GenUnmakeMove (side, f, u, tempb, tempc, false);
1465
* If the piece could be dropped at any square, it is
1466
* impossible for any other piece drop to prevent check.
1467
* Drops are restricted for pawns, lances, and knights.
1469
if ( piece > knight )