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
)