quiesrch.o evaluate.o swap.o hash.o root.o next.o movgenex.o \
genevasn.o gencap.o gennocap.o gendrop.o mate1ply.o rand.o learn1.o \
learn2.o evaldiff.o problem.o ponder.o thread.o sckt.o debug.o mate3.o \
- genchk.o phash.o
+ genchk.o phash.o dfpn.o dfpnhash.o
# Compile Options
#
-# -DNDEBUG (DEBUG) builds release (debug) version of Bonanza.
-# -DMINIMUM disables some auxiliary functions that are not necessary to
-# play a game, e.g., book composition and optimization of
-# evaluation function.
-# -DTLP enables thread-level parallel search.
-# -DMPV enables multi-PV search.
-# -DCSA_LAN enables bonanza to talk CSA Shogi TCP/IP protcol.
-# -DMNJ_LAN enables a client-mode of cluster computing.
-# -DNO_LOGGING suppresses dumping log files.
-
-OPT =-DNDEBUG -DMINIMUM -DTLP -DCSA_LAN -DMNJ_LAN
+# -DNDEBUG (DEBUG) builds release (debug) version of Bonanza.
+# -DMINIMUM disables some auxiliary functions that are not necessary
+# to play a game, e.g., book composition and optimization
+# of evaluation function.
+# -DHAVE_SSE2 -msse2 use SSE2 instructions for speed
+# -DHAVE_SSE4 -msse4.1 use SSE2 and SSE4.1 instructions for speed
+# -DTLP enables thread-level parallel search.
+# -DMPV enables multi-PV search.
+# -DCSA_LAN enables bonanza to talk CSA Shogi TCP/IP protcol.
+# -DMNJ_LAN enables a client-mode of cluster searches.
+# -DNO_LOGGING suppresses dumping log files.
+# -DUSI enables USI mode (not implemented).
+# -DINANIWA_SHIFT enables an Inaniwa strategy detection.
+# -DDFPN build the DFPN worker of mate-problems server.
+# -DDFPN_CLIENT enables the client-mode of mate-problem server.
+
+OPT =-DNDEBUG -DMINIMUM -DHAVE_SSE4 -msse4.1 -DDFPN -DTLP -DDFPN_CLIENT -DINANIWA_SHIFT -DMNJ_LAN -DCSA_LAN
help:
@echo "try targets as:"
@echo
@echo " gcc"
+ @echo " gcc-pg"
+ @echo " gcc-pgo"
@echo " icc"
+ @echo " icc-pgo"
+ @echo " icc-ampl"
gcc:
- $(MAKE) CC=gcc CFLAGS='-std=gnu99 -O3 -Wall $(OPT)' LDFLAG1='-lm -lpthread' bonanza
+ $(MAKE) CC=gcc CFLAGS='-std=gnu99 -O2 -Wall $(OPT)' LDFLAG1='-lm -lpthread' bonanza
+
+gcc-pgo:
+ $(MAKE) clean
+ gcc -std=gnu99 -O2 -Wall $(OPT) -fprofile-generate -o bonanza -lm -lpthread $(OBJS:.o=.c)
+ $(MAKE) run-prof
+ gcc -std=gnu99 -O2 -Wall $(OPT) -fprofile-use -o bonanza -lm -lpthread $(OBJS:.o=.c)
+
+icc-ampl:
+ $(MAKE) CC=icc CFLAGS='-w2 $(OPT) -std=gnu99 -g -O2 -fno-inline-functions' LDFLAG1='-pthread -g' bonanza
icc:
$(MAKE) CC=icc CFLAGS='-w2 $(OPT) -std=gnu99 -O2 -ipo' LDFLAG1='-static -ipo -pthread' bonanza
+icc-pgo:
+ $(MAKE) clean
+ mkdir profdir
+ $(MAKE) CC=icc CFLAGS='-w2 $(OPT) -std=gnu99 -O2 -prof_gen -prof_dir ./profdir' LDFLAG1='-static -pthread' bonanza
+ $(MAKE) run-prof
+ touch *.[ch]
+ $(MAKE) CC=icc CFLAGS='-w2 $(OPT) -std=gnu99 -O2 -ipo -prof_use -prof_dir ./profdir' LDFLAG1='-static -ipo -pthread' bonanza
+
bonanza : $(OBJS)
$(CC) $(LDFLAG1) -o bonanza $(OBJS) $(LDFLAG2)
-$(OBJS) : shogi.h param.h
+$(OBJS) : shogi.h param.h bitop.h
+dfpn.o dfpnhash.o: dfpn.h
.c.o :
$(CC) -c $(CFLAGS) $*.c
clean :
- rm *.o
+ rm -f *.o *.il *.da *.gcda *.gcno *.bb *.bbg *.dyn
+ rm -f bonanza gmon.out runprof
rm -fr profdir
- rm bonanza
+
+run-prof:
+ @if [ ! -d log ]; then mkdir log; fi
+ @echo "peek off" > runprof
+# @echo "dfpn hash 22" >> runprof
+# @echo "problem mate" >> runprof
+# @echo "learn no-ini 32 32 1 2 2" >> runprof
+ @echo "limit time extendable" >> runprof
+ @echo "limit time 0 1" >> runprof
+ @echo "tlp num 2" >> runprof
+ @echo "move 77" >> runprof
+ @echo "new" >> runprof
+ @echo "move 77" >> runprof
+ @echo "new" >> runprof
+ @echo "move 77" >> runprof
+ @echo "new" >> runprof
+ @echo "move 77" >> runprof
+ @echo "new" >> runprof
+ @echo "move 77" >> runprof
+ @echo "new" >> runprof
+ @echo "move 77" >> runprof
+ @echo "new" >> runprof
+ @echo "move 77" >> runprof
+ @echo "quit" >> runprof
+ @./bonanza < runprof
help:
@echo try targets as:
@echo cl
+ @echo cl-pgo
@echo icl
+ @echo icl-pgo
# Compile Options
#
-# /DNDEBUG (DEBUG) builds release (debug) version of Bonanza.
+# /DDEBUG (DEBUG) builds release (debug) version of Bonanza.
# /DMINIMUM disables some auxiliary functions that are not necessary to
# play a game, e.g., book composition and optimization of
# evaluation function.
+# /DHAVE_SSE2 use SSE2 instructions for speed (N/A MS C/C++)
+# /DHAVE_SSE4 use SSE2 and SSE4.1 instructions for speed (N/A MS C/C++)
# /DTLP enables thread-level parallel search.
# /DMPV enables multi-PV search.
# /DCSA_LAN enables bonanza to talk CSA Shogi TCP/IP protcol.
-# /DMNJ_LAN enables a client-mode of distributed computing.
-# /DDEKUNOBOU enables dekunobou interface (avairable only for Windows).
-# /DCSASHOGI builds an engine for CSA Shogi (avairable only for
-# Windows).
+# /DMNJ_LAN enables client-mode of distributed computing.
+# /DUSI enables USI mode (not implemented).
+# /DCSASHOGI builds an engine for CSA Shogi (only Windows).
# /DNO_LOGGING suppresses dumping log files.
+# /DINANIWA_SHIFT enables an Inaniwa strategy detection.
+# /DDFPN build the DFPN worker of mate-problems server.
+# /DDFPN_CLIENT enables the client-mode of mate-problem server.
-FLAG = /DNDEBUG /DMINIMUM /DTLP /DMPV /DCSASHOGI /DNO_LOGGING
+FLAG = /DNDEBUG /DMINIMUM /DTLP /DHAVE_SSE2 /DINANIWA_SHIFT /DCSASHOGI /DNO_LOGGING
OBJS = data.obj main.obj io.obj proce.obj ini.obj utility.obj attack.obj\
gencap.obj gennocap.obj gendrop.obj genevasn.obj mate3.obj genchk.obj\
next.obj search.obj searchr.obj book.obj iterate.obj quiesrch.obj\
swap.obj evaluate.obj root.obj hash.obj mate1ply.obj bitop.obj\
rand.obj learn1.obj learn2.obj evaldiff.obj problem.obj ponder.obj\
- thread.obj dek.obj sckt.obj debug.obj phash.obj
+ thread.obj sckt.obj debug.obj phash.obj dfpn.obj dfpnhash.obj
cl:
$(MAKE) -f Makefile.vs bonanza.exe CC="cl" LD="link"\
- CFLAGS="$(FLAG) /MT /W4 /nologo /O2 /Ob2 /Gr /GS- /GL"\
+ CFLAGS="$(FLAG) /MT /W4 /nologo /O2 /Ob2 /GS- /GL"\
LDFLAGS="/NOLOGO /out:bonanza.exe /LTCG"
+cl-pgo:
+ $(MAKE) -f Makefile.vs clean
+ $(MAKE) -f Makefile.vs bonanza.exe CC="cl" LD="link"\
+ CFLAGS="$(FLAG) /MT /W4 /nologo /O2 /Ob2 /GS- /GL"\
+ LDFLAGS="/NOLOGO /out:bonanza.exe /LTCG:PGI"
+ $(MAKE) -f Makefile.vs pgo-run
+ del bonanza.exe
+ $(MAKE) -f Makefile.vs bonanza.exe LD="link"\
+ LDFLAGS="/NOLOGO /out:bonanza.exe /LTCG:PGO"
+
icl:
$(MAKE) -f Makefile.vs bonanza.exe CC="icl" LD="icl"\
- CFLAGS="/nologo $(FLAG) /Wall /O2 /Qipo /Gr"\
+ CFLAGS="/nologo $(FLAG) /Wall /O2 /Qipo"\
LDFLAGS="/nologo /Febonanza.exe"
+icl-pgo:
+ $(MAKE) -f Makefile.vs clean
+ $(MAKE) -f Makefile.vs bonanza.exe CC="icl" LD="icl"\
+ CFLAGS="/nologo $(FLAG) /Wall /O2 /Qprof-gen"\
+ LDFLAGS="/nologo /Febonanza.exe /Qprof-gen"
+ $(MAKE) -f Makefile.vs pgo-run
+ del *.obj bonanza.exe
+ $(MAKE) -f Makefile.vs bonanza.exe CC="icl" LD="icl"\
+ CFLAGS="/nologo $(FLAG) /Wall /O2 /Qipo /Qprof-use"\
+ LDFLAGS="/nologo /Febonanza.exe /Qprof-use"
+
+pgo-run:
+# echo learn no-ini 32 32 1 2 2 >> runprof
+ echo limit time extendable >> runprof
+ echo limit time 0 1 >> runprof
+ echo tlp num 2 >> runprof
+ echo peek off >> runprof
+ echo move 77 >> runprof
+ echo new >> runprof
+ echo move 77 >> runprof
+ echo new >> runprof
+ echo move 77 >> runprof
+ echo new >> runprof
+ echo move 77 >> runprof
+ echo new >> runprof
+ echo move 77 >> runprof
+ echo new >> runprof
+ echo move 77 >> runprof
+ echo new >> runprof
+ echo move 77 >> runprof
+ echo quit >> runprof
+ bonanza.exe csa_shogi < runprof
+
bonanza.exe : $(OBJS) bonanza.res
$(LD) $(LDFLAGS) $(OBJS) bonanza.res User32.lib Ws2_32.lib
-$(OBJS) : shogi.h param.h
+$(OBJS) : shogi.h param.h bitop.h
+dfpn.obj dfpnhash.obj: dfpn.h
bonanza.res : bonanza.rc bonanza.ico
rc /fobonanza.res bonanza.rc
$(CC) $(CFLAGS) /c $*.c
clean :
+ del /q runprof
+ del /q *.pdb
+ del /q *.ilk
+ del /q *.pgd
+ del /q *.pgc
+ del /q *.dyn
del /q *.obj
del /q *.res
del /q bonanza.exe
#include <stdlib.h>
#include "shogi.h"
-
-unsigned int
+unsigned int CONV
is_pinned_on_white_king( const tree_t * restrict ptree, int isquare,
int idirec )
{
- unsigned int ubb_attacks;
bitboard_t bb_attacks, bb_attacker;
switch ( idirec )
{
case direc_rank:
- ubb_attacks = AttackRank( isquare );
- if ( ubb_attacks & (BB_WKING.p[aslide[isquare].ir0]) )
+ bb_attacks = AttackRank( isquare );
+ if ( BBContract( bb_attacks, BB_WKING ) )
{
- return ubb_attacks & BB_B_RD.p[aslide[isquare].ir0];
+ return BBContract( bb_attacks, BB_B_RD );
}
break;
}
-unsigned int
+unsigned int CONV
is_pinned_on_black_king( const tree_t * restrict ptree, int isquare,
int idirec )
{
- unsigned int ubb_attacks;
bitboard_t bb_attacks, bb_attacker;
switch ( idirec )
{
case direc_rank:
- ubb_attacks = AttackRank( isquare );
- if ( ubb_attacks & (BB_BKING.p[aslide[isquare].ir0]) )
+ bb_attacks = AttackRank( isquare );
+ if ( BBContract( bb_attacks, BB_BKING ) )
{
- return ubb_attacks & BB_W_RD.p[aslide[isquare].ir0];
+ return BBContract( bb_attacks, BB_W_RD );
}
break;
/* perpetual check detections are omitted. */
-int
+int CONV
is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop )
{
bitboard_t bb, bb_sum, bb_move;
BBOr( bb, BB_WHORSE, BB_WDRAGON );
BBAndOr( bb_sum, bb, abb_king_attacks[sq_drop] );
- while ( BBToU( bb_sum ) )
+ while ( BBTest( bb_sum ) )
{
ifrom = FirstOne( bb_sum );
Xor( ifrom, bb_sum );
XorDiag2( sq_drop, OCCUPIED_DIAG2 );
XorDiag1( sq_drop, OCCUPIED_DIAG1 );
- BBNot( bb_move, BB_WOCCUPY );
- BBAnd( bb_move, bb_move, abb_king_attacks[iwk] );
- while ( BBToU( bb_move ) )
+ BBNotAnd( bb_move, abb_king_attacks[iwk], BB_WOCCUPY );
+ while ( BBTest( bb_move ) )
{
ito = FirstOne( bb_move );
if ( ! is_white_attacked( ptree, ito ) )
}
-int
+int CONV
is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop )
{
bitboard_t bb, bb_sum, bb_move;
BBOr( bb, BB_BHORSE, BB_BDRAGON );
BBAndOr( bb_sum, bb, abb_king_attacks[sq_drop] );
- while ( BBToU( bb_sum ) )
+ while ( BBTest( bb_sum ) )
{
ifrom = FirstOne( bb_sum );
Xor( ifrom, bb_sum );
XorDiag2( sq_drop, OCCUPIED_DIAG2 );
XorDiag1( sq_drop, OCCUPIED_DIAG1 );
- BBNot( bb_move, BB_BOCCUPY );
- BBAnd( bb_move, bb_move, abb_king_attacks[ibk] );
- while ( BBToU( bb_move ) )
+ BBNotAnd( bb_move, abb_king_attacks[ibk], BB_BOCCUPY );
+ while ( BBTest( bb_move ) )
{
ito = FirstOne( bb_move );
if ( ! is_black_attacked( ptree, ito ) )
}
-bitboard_t
+int CONV
+is_move_check_b( const tree_t * restrict ptree, unsigned int move )
+{
+ const int from = (int)I2From(move);
+ const int to = (int)I2To(move);
+ int ipiece_move, idirec;
+ bitboard_t bb;
+
+ if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
+ else {
+ ipiece_move = (int)I2PieceMove(move);
+ if ( I2IsPromote(move) ) { ipiece_move += promote; }
+
+ idirec = (int)adirec[SQ_WKING][from];
+ if ( idirec && idirec != (int)adirec[SQ_WKING][to]
+ && is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ switch ( ipiece_move )
+ {
+ case pawn:
+ return BOARD[to-nfile] == -king;
+
+ case lance:
+ AttackBLance( bb, to );
+ return BBContract( bb, BB_WKING );
+
+ case knight:
+ return BBContract( abb_b_knight_attacks[to], BB_WKING );
+
+ case silver:
+ return BBContract( abb_b_silver_attacks[to], BB_WKING );
+
+ case bishop:
+ AttackBishop( bb, to );
+ return BBContract( bb, BB_WKING );
+
+ case rook:
+ AttackRook( bb, to );
+ return BBContract( bb, BB_WKING );
+
+ case king:
+ return 0;
+
+ case horse:
+ AttackHorse( bb, to );
+ return BBContract( bb, BB_WKING );
+
+ case dragon:
+ assert( ipiece_move == dragon );
+ AttackDragon( bb, to );
+ return BBContract( bb, BB_WKING );
+ }
+ /*
+ case gold: case pro_pawn:
+ case pro_lance: case pro_knight:
+ case pro_silver:
+ */
+ return BBContract( abb_b_gold_attacks[to], BB_WKING );
+}
+
+
+int CONV
+is_move_check_w( const tree_t * restrict ptree, unsigned int move )
+{
+ const int from = (int)I2From(move);
+ const int to = (int)I2To(move);
+ int ipiece_move, idirec;
+ bitboard_t bb;
+
+ if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
+ else {
+ ipiece_move = (int)I2PieceMove(move);
+ if ( I2IsPromote(move) ) { ipiece_move += promote; }
+
+ idirec = (int)adirec[SQ_BKING][from];
+ if ( idirec && idirec != (int)adirec[SQ_BKING][to]
+ && is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ switch ( ipiece_move )
+ {
+ case pawn:
+ return BOARD[to+nfile] == king;
+
+ case lance:
+ AttackWLance( bb, to );
+ return BBContract( bb, BB_BKING );
+
+ case knight:
+ return BBContract( abb_w_knight_attacks[to], BB_BKING );
+
+ case silver:
+ return BBContract( abb_w_silver_attacks[to], BB_BKING );
+
+ case bishop:
+ AttackBishop( bb, to );
+ return BBContract( bb, BB_BKING );
+
+ case rook:
+ AttackRook( bb, to );
+ return BBContract( bb, BB_BKING );
+
+ case king:
+ return 0;
+
+ case horse:
+ AttackHorse( bb, to );
+ return BBContract( bb, BB_BKING );
+
+ case dragon:
+ AttackDragon( bb, to );
+ return BBContract( bb, BB_BKING );
+ }
+
+ /*
+ case gold: case pro_pawn:
+ case pro_lance: case pro_knight:
+ case pro_silver:
+ */
+ return BBContract( abb_w_gold_attacks[to], BB_BKING );
+}
+
+
+bitboard_t CONV
attacks_to_piece( const tree_t * restrict ptree, int sq )
{
bitboard_t bb_ret, bb_attacks, bb;
BBAndOr( bb_ret, BB_BKNIGHT, abb_w_knight_attacks[sq] );
BBAndOr( bb_ret, BB_WKNIGHT, abb_b_knight_attacks[sq] );
-
BBAndOr( bb_ret, BB_BSILVER, abb_w_silver_attacks[sq] );
BBAndOr( bb_ret, BB_WSILVER, abb_b_silver_attacks[sq] );
-
BBAndOr( bb_ret, BB_BTGOLD, abb_w_gold_attacks[sq] );
BBAndOr( bb_ret, BB_WTGOLD, abb_b_gold_attacks[sq] );
BBAndOr( bb_ret, bb, bb_attacks );
BBOr( bb, BB_B_RD, BB_W_RD );
- bb_ret.p[aslide[sq].ir0]
- |= bb.p[aslide[sq].ir0] & AttackRank( sq );
+ BBAndOr( bb_ret, bb, AttackRank( sq ) );
+ BBAndOr( bb, BB_BLANCE, abb_plus_rays[sq] );
+ BBAndOr( bb, BB_WLANCE, abb_minus_rays[sq] );
+ BBAndOr( bb_ret, bb, AttackFile( sq ) );
+ return bb_ret;
+}
+
+
+bitboard_t CONV
+b_attacks_to_piece( const tree_t * restrict ptree, int sq )
+{
+ bitboard_t bb_ret, bb_attacks, bb;
+
+ BBIni( bb_ret );
+ if ( sq < rank9*nfile && BOARD[sq+nfile] == pawn )
+ {
+ bb_ret = abb_mask[sq+nfile];
+ }
+
+ BBAndOr( bb_ret, BB_BKNIGHT, abb_w_knight_attacks[sq] );
+ BBAndOr( bb_ret, BB_BSILVER, abb_w_silver_attacks[sq] );
+ BBAndOr( bb_ret, BB_BTGOLD, abb_w_gold_attacks[sq] );
+ BBAndOr( bb_ret, BB_B_HDK, abb_king_attacks[sq] );
+
+ AttackBishop( bb_attacks, sq );
+ BBAndOr( bb_ret, BB_B_BH, bb_attacks );
+
+ bb = BB_B_RD;
+ BBAndOr( bb_ret, bb, AttackRank(sq) );
BBAndOr( bb, BB_BLANCE, abb_plus_rays[sq] );
+ BBAndOr( bb_ret, bb, AttackFile(sq) );
+
+ return bb_ret;
+}
+
+
+bitboard_t CONV
+w_attacks_to_piece( const tree_t * restrict ptree, int sq )
+{
+ bitboard_t bb_ret, bb_attacks, bb;
+
+ BBIni( bb_ret );
+ if ( nfile <= sq && BOARD[sq-nfile] == -pawn )
+ {
+ bb_ret = abb_mask[sq-nfile];
+ }
+
+ BBAndOr( bb_ret, BB_WKNIGHT, abb_b_knight_attacks[sq] );
+ BBAndOr( bb_ret, BB_WSILVER, abb_b_silver_attacks[sq] );
+ BBAndOr( bb_ret, BB_WTGOLD, abb_b_gold_attacks[sq] );
+ BBAndOr( bb_ret, BB_W_HDK, abb_king_attacks[sq] );
+
+ AttackBishop( bb_attacks, sq );
+ BBAndOr( bb_ret, BB_W_BH, bb_attacks );
+
+ bb = BB_W_RD;
+ BBAndOr( bb_ret, bb, AttackRank(sq) );
BBAndOr( bb, BB_WLANCE, abb_minus_rays[sq] );
- bb_attacks = AttackFile( sq );
- BBAndOr( bb_ret, bb, bb_attacks );
+ BBAndOr( bb_ret, bb, AttackFile(sq) );
return bb_ret;
}
-unsigned int
+unsigned int CONV
is_white_attacked( const tree_t * restrict ptree, int sq )
{
- bitboard_t bb;
- unsigned int u;
-
- u = BBContract( BB_BPAWN_ATK, abb_mask[sq] );
- u |= BBContract( BB_BKNIGHT, abb_w_knight_attacks[sq] );
- u |= BBContract( BB_BSILVER, abb_w_silver_attacks[sq] );
- u |= BBContract( BB_BTGOLD, abb_w_gold_attacks[sq] );
- u |= BBContract( BB_B_HDK, abb_king_attacks[sq] );
+ bitboard_t bb, bb1, bb_atk;
- AttackBishop( bb, sq );
- u |= BBContract( BB_B_BH, bb );
+ BBAnd ( bb, BB_BPAWN_ATK, abb_mask[sq] );
+ BBAndOr( bb, BB_BKNIGHT, abb_w_knight_attacks[sq] );
+ BBAndOr( bb, BB_BSILVER, abb_w_silver_attacks[sq] );
+ BBAndOr( bb, BB_BTGOLD, abb_w_gold_attacks[sq] );
+ BBAndOr( bb, BB_B_HDK, abb_king_attacks[sq] );
- u |= BB_B_RD.p[aslide[sq].ir0] & AttackRank( sq );
+ AttackBishop( bb_atk, sq );
+ BBAndOr( bb, BB_B_BH, bb_atk );
- bb = AttackFile( sq );
- u |= ( ( BB_BLANCE.p[0] & abb_plus_rays[sq].p[0] )
- | BB_B_RD.p[0] ) & bb.p[0];
- u |= ( ( BB_BLANCE.p[1] & abb_plus_rays[sq].p[1] )
- | BB_B_RD.p[1] ) & bb.p[1];
- u |= ( ( BB_BLANCE.p[2] & abb_plus_rays[sq].p[2] )
- | BB_B_RD.p[2] ) & bb.p[2];
+ bb1 = BB_B_RD;
+ BBAndOr( bb1, BB_BLANCE, abb_plus_rays[sq] );
+ BBAndOr( bb, bb1, AttackFile( sq ) );
+ BBAndOr( bb, BB_B_RD, AttackRank( sq ) );
- return u;
+ return BBToU(bb);
}
-unsigned int
+unsigned int CONV
is_black_attacked( const tree_t * restrict ptree, int sq )
{
- bitboard_t bb;
- unsigned int u;
-
- u = BBContract( BB_WPAWN_ATK, abb_mask[sq] );
- u |= BBContract( BB_WKNIGHT, abb_b_knight_attacks[sq] );
- u |= BBContract( BB_WSILVER, abb_b_silver_attacks[sq] );
- u |= BBContract( BB_WTGOLD, abb_b_gold_attacks[sq] );
- u |= BBContract( BB_W_HDK, abb_king_attacks[sq] );
+ bitboard_t bb, bb1, bb_atk;
- AttackBishop( bb, sq );
- u |= BBContract( BB_W_BH, bb );
+ BBAnd ( bb, BB_WPAWN_ATK, abb_mask[sq] );
+ BBAndOr( bb, BB_WKNIGHT, abb_b_knight_attacks[sq] );
+ BBAndOr( bb, BB_WSILVER, abb_b_silver_attacks[sq] );
+ BBAndOr( bb, BB_WTGOLD, abb_b_gold_attacks[sq] );
+ BBAndOr( bb, BB_W_HDK, abb_king_attacks[sq] );
- u |= BB_W_RD.p[aslide[sq].ir0] & AttackRank( sq );
+ AttackBishop( bb_atk, sq );
+ BBAndOr( bb, BB_W_BH, bb_atk );
- bb = AttackFile( sq );
- u |= ( ( BB_WLANCE.p[0] & abb_minus_rays[sq].p[0] )
- | BB_W_RD.p[0] ) & bb.p[0];
- u |= ( ( BB_WLANCE.p[1] & abb_minus_rays[sq].p[1] )
- | BB_W_RD.p[1] ) & bb.p[1];
- u |= ( ( BB_WLANCE.p[2] & abb_minus_rays[sq].p[2] )
- | BB_W_RD.p[2] ) & bb.p[2];
+ bb1 = BB_W_RD;
+ BBAndOr( bb1, BB_WLANCE, abb_minus_rays[sq] );
+ BBAndOr( bb, bb1, AttackFile( sq ) );
+ BBAndOr( bb, BB_W_RD, AttackRank( sq ) );
- return u;
+ return BBTest(bb);
}
#include "shogi.h"
-int
+int CONV
popu_count012( unsigned int u0, unsigned int u1, unsigned int u2 )
{
int counter = 0;
#if defined(_MSC_VER)
-int
+int CONV
first_one012( unsigned int u0, unsigned int u1, unsigned int u2 )
{
unsigned long index;
return 80 - index;
}
-int
+int CONV
last_one210( unsigned int u2, unsigned int u1, unsigned int u0 )
{
unsigned long index;
return 26 - index;
}
-int
+int CONV
first_one01( unsigned int u0, unsigned int u1 )
{
unsigned long index;
return 53 - index;
}
-int
+int CONV
first_one12( unsigned int u1, unsigned int u2 )
{
unsigned long index;
return 80 - index;
}
-int
+int CONV
last_one01( unsigned int u0, unsigned int u1 )
{
unsigned long index;
return 26 - index;
}
-int
+int CONV
last_one12( unsigned int u1, unsigned u2 )
{
unsigned long index;
return 53 - index;
}
-int
+int CONV
first_one1( unsigned int u1 )
{
unsigned long index;
return 53 - index;
}
-int
+int CONV
first_one2( unsigned int u2 )
{
unsigned long index;
return 80 - index;
}
-int
+int CONV
last_one0( unsigned int u0 )
{
unsigned long index;
return 26 - index;
}
-int
+int CONV
last_one1( unsigned int u1 )
{
unsigned long index;
typedef struct { int from, to; } ft_t;
-static int book_read( uint64_t key, book_move_t *pbook_move,
+static int CONV book_read( uint64_t key, book_move_t *pbook_move,
unsigned int *pposition );
-static uint64_t book_hash_func( const tree_t * restrict ptree,int *pis_flip );
-static unsigned int bm2move( const tree_t * restrict ptree, unsigned int bmove,
- int is_flip );
-static ft_t flip_ft( ft_t ft, int turn, int is_flip );
-static int normalize_book_move( book_move_t * restrict pbook_move, int moves );
+static uint64_t CONV book_hash_func( const tree_t * restrict ptree,
+ int *pis_flip );
+static unsigned int CONV bm2move( const tree_t * restrict ptree,
+ unsigned int bmove, int is_flip );
+static ft_t CONV flip_ft( ft_t ft, int turn, int is_flip );
+static int CONV normalize_book_move( book_move_t * restrict pbook_move,
+ int moves );
-int
+int CONV
book_on( void )
{
int iret = file_close( pf_book );
}
-int
+int CONV
book_off( void )
{
int iret = file_close( pf_book );
}
-int
+int CONV
book_probe( tree_t * restrict ptree )
{
book_move_t abook_move[ BK_MAX_MOVE+1 ];
ply = record_game.moves;
if ( game_status & flag_pondering ) { ply++; }
- if ( ply < HASH_REG_HIST_LEN )
- {
- history_book_learn[ ply ].key_book = key;
- history_book_learn[ ply ].move_probed = move;
- history_book_learn[ ply ].key_probed = (unsigned int)HASH_KEY;
- history_book_learn[ ply ].hand_probed = HAND_B;
- history_book_learn[ ply ].data = (unsigned int)is_flip << 30;
- if ( game_status & flag_narrow_book )
- {
- history_book_learn[ ply ].data |= 1U << 29;
- }
- }
ptree->current_move[1] = move;
}
-static int
+static int CONV
book_read( uint64_t key, book_move_t *pbook_move, unsigned int *pposition )
{
uint64_t book_key;
}
-static ft_t
+static ft_t CONV
flip_ft( ft_t ft, int turn, int is_flip )
{
int ito_rank, ito_file, ifrom_rank, ifrom_file;
}
-static unsigned int
+static unsigned int CONV
bm2move( const tree_t * restrict ptree, unsigned int bmove, int is_flip )
{
ft_t ft;
}
-static uint64_t
+static uint64_t CONV
book_hash_func( const tree_t * restrict ptree, int *pis_flip )
{
uint64_t key, key_flip;
}
-static int
+static int CONV
normalize_book_move( book_move_t * restrict pbook_move, int moves )
{
book_move_t swap;
#if ! defined(MINIMUM)
#define MaxNumCell 0x400000
-#if defined(BK_SMALL)
+#if defined(BK_SMALL) || defined(BK_TINY)
# define MaxPlyBook 64
#else
# define MaxPlyBook 128
unsigned char result;
} cell_t;
-static unsigned int move2bm( unsigned int move, int turn, int is_flip );
-static int find_min_cell( const cell_t *pcell, int ntemp );
-static int read_a_cell( cell_t *pcell, FILE *pf );
-static int CONV_CDECL compare( const void * p1, const void *p2 );
-static int dump_cell( cell_t *pcell, int ncell, int num_tmpfile );
-static int examine_game( tree_t * restrict ptree, record_t *pr,
- int *presult, unsigned int *pmoves );
-static int move_selection( const record_move_t *p, int ngame, int nwin );
-static int make_cell_csa( tree_t * restrict ptree, record_t *pr,
- cell_t *pcell, int num_tmpfile );
-static int merge_cell( record_move_t *precord_move, FILE **ppf,
- int num_tmpfile );
-static int read_anti_book( tree_t * restrict ptree, record_t * pr );
-
-int
+static unsigned int CONV move2bm( unsigned int move, int turn, int is_flip );
+static int CONV find_min_cell( const cell_t *pcell, int ntemp );
+static int CONV read_a_cell( cell_t *pcell, FILE *pf );
+static int compare( const void * p1, const void *p2 );
+static int CONV dump_cell( cell_t *pcell, int ncell, int num_tmpfile );
+static int CONV examine_game( tree_t * restrict ptree, record_t *pr,
+ int *presult, unsigned int *pmoves );
+static int CONV move_selection( const record_move_t *p, int ngame, int nwin );
+static int CONV make_cell_csa( tree_t * restrict ptree, record_t *pr,
+ cell_t *pcell, int num_tmpfile );
+static int CONV merge_cell( record_move_t *precord_move, FILE **ppf,
+ int num_tmpfile );
+static int CONV read_anti_book( tree_t * restrict ptree, record_t * pr );
+
+int CONV
book_create( tree_t * restrict ptree )
{
record_t record;
}
-static int
+static int CONV
read_anti_book( tree_t * restrict ptree, record_t * pr )
{
uint64_t key;
}
-static int
+static int CONV
make_cell_csa( tree_t * restrict ptree, record_t *pr, cell_t *pcell,
int num_tmpfile )
{
}
-static int
+static int CONV
merge_cell( record_move_t *precord_move, FILE **ppf, int num_tmpfile )
{
double dscale;
}
-static int
+static int CONV
move_selection( const record_move_t *p, int ngame, int nwin )
{
double total_win_norm, win_norm, win, game, win_move, game_move;
-#if defined(BK_SMALL)
- if ( ! p->nwin || p->ngame < 3 ) { return 0; }
+#if defined(BK_TINY)
+ if ( p->nwin < 15 ) { return 0; }
+#elif defined(BK_SMALL)
+ if ( p->nwin < 3 ) { return 0; }
#else
if ( ! p->nwin || p->ngame < 2 ) { return 0; }
#endif
}
-static int
+static int CONV
find_min_cell( const cell_t *pcell, int num_tmpfile )
{
int imin, i;
}
-static int
+static int CONV
read_a_cell( cell_t *pcell, FILE *pf )
{
if ( fread( &pcell->key, sizeof(uint64_t), 1, pf ) != 1 )
}
-static int
+static int CONV
examine_game( tree_t * restrict ptree, record_t *pr, int *presult,
unsigned int *pmoves )
{
}
-static int
+static int CONV
dump_cell( cell_t *pcell, int ncell, int num_tmpfile )
{
char str_filename[SIZE_FILENAME];
}
-static int CONV_CDECL
-compare( const void * p1, const void * p2 )
+static int compare( const void * p1, const void * p2 )
{
const cell_t * pcell1 = p1;
const cell_t * pcell2 = p2;
}
-static unsigned int
+static unsigned int CONV
move2bm( unsigned int move, int turn, int is_flip )
{
ft_t ft;
const char *
-str_CSA_move_plus( tree_t * restrict ptree, unsigned int move, int ply,
- int turn )
-{
- static char str[ 13 ];
- const unsigned int *pmove_last;
- unsigned int amove[ MAX_LEGAL_EVASION ];
- char *p;
- int is_promo, ipiece_cap, ipiece_move, ifrom, ito, turn_next;
-
- is_promo = (int)I2IsPromote(move);
- ipiece_move = (int)I2PieceMove(move);
- ifrom = (int)I2From(move);
- ito = (int)I2To(move);
- ipiece_cap = (int)UToCap(move);
- turn_next = Flip( turn );
-
- if ( is_promo && ipiece_cap )
- {
- snprintf( str, 13, "%d%d%d%d%spx%s",
- 9-aifile[ifrom], airank[ifrom]+1,
- 9-aifile[ito], airank[ito] +1,
- astr_table_piece[ ipiece_move + promote ],
- astr_table_piece[ ipiece_cap ] );
- p = str + 10;
- }
- else if ( ipiece_cap )
- {
- snprintf( str, 13, "%d%d%d%d%sx%s",
- 9-aifile[ifrom], airank[ifrom]+1,
- 9-aifile[ito], airank[ito] +1,
- astr_table_piece[ ipiece_move ],
- astr_table_piece[ ipiece_cap ] );
- p = str + 9;
- }
- else if ( is_promo )
- {
- snprintf( str, 13, "%d%d%d%d%sp",
- 9-aifile[ifrom], airank[ifrom]+1,
- 9-aifile[ito], airank[ito] +1,
- astr_table_piece[ ipiece_move + promote ] );
- p = str + 7;
- }
- else if ( ifrom < nsquare )
- {
- snprintf( str, 13, "%d%d%d%d%s",
- 9-aifile[ifrom], airank[ifrom]+1,
- 9-aifile[ito], airank[ito] +1,
- astr_table_piece[ ipiece_move ] );
- p = str + 6;
- }
- else {
- snprintf( str, 13, "00%d%d%s", 9-aifile[ito], airank[ito]+1,
- astr_table_piece[ From2Drop(ifrom) ] );
- p = str + 6;
- }
-
- MakeMove( turn, move, ply );
- if ( InCheck( turn_next ) )
- {
- pmove_last = GenEvasion( turn_next, amove );
- if ( pmove_last == amove ) { *p++ = '#'; }
- else { *p++ = '!'; }
- *p = '\0';
- }
- UnMakeMove( turn, move, ply );
-
- return str;
-}
-
-
-const char *
str_CSA_move( unsigned int move )
{
static char str[7];
}
+#if defined(USI)
+int CONV
+usi2csa( const tree_t * restrict ptree, const char *str_usi, char *str_csa )
+{
+ int sq_file, sq_rank, sq, pc;
+
+ if ( '1' <= str_usi[0] && str_usi[0] <= '9'
+ && 'a' <= str_usi[1] && str_usi[1] <= 'i'
+ && '1' <= str_usi[2] && str_usi[2] <= '9'
+ && 'a' <= str_usi[3] && str_usi[3] <= 'i' )
+ {
+ str_csa[0] = str_usi[0];
+ str_csa[1] = (char)( str_usi[1] + '1' - 'a' );
+ str_csa[2] = str_usi[2];
+ str_csa[3] = (char)( str_usi[3] + '1' - 'a' );
+
+ sq_file = str_csa[0]-'0';
+ sq_file = 9 - sq_file;
+ sq_rank = str_csa[1]-'0';
+ sq_rank = sq_rank - 1;
+ sq = sq_rank * 9 + sq_file;
+ pc = abs(BOARD[sq]);
+ if ( str_usi[4] == '+' ) { pc += promote; }
+
+ str_csa[4] = astr_table_piece[pc][0];
+ str_csa[5] = astr_table_piece[pc][1];
+ str_csa[6] = '\0';
+
+ return 1;
+ }
+
+ if ( isascii( (int)str_usi[0] )
+ && isalpha( (int)str_usi[0] )
+ && str_usi[1] == '*'
+ && '1' <= str_usi[2] && str_usi[2] <= '9'
+ && 'a' <= str_usi[3] && str_usi[3] <= 'i' )
+ {
+ str_csa[0] = '0';
+ str_csa[1] = '0';
+ str_csa[2] = str_usi[2];
+ str_csa[3] = (char)( str_usi[3] - 'a' + '1' );
+
+ switch ( str_usi[0] )
+ {
+ case 'P': pc = pawn; break;
+ case 'L': pc = lance; break;
+ case 'N': pc = knight; break;
+ case 'S': pc = silver; break;
+ case 'G': pc = gold; break;
+ case 'B': pc = bishop; break;
+ case 'R': pc = rook; break;
+ default: return -1;
+ }
+
+ str_csa[4] = astr_table_piece[pc][0];
+ str_csa[5] = astr_table_piece[pc][1];
+ str_csa[6] = '\0';
+
+ return 1;
+ }
+
+ snprintf( str_message, SIZE_MESSAGE, "%s: %s", str_illegal_move, str_usi );
+ str_error = str_message;
+ return -1;
+}
+
+
+int CONV
+csa2usi( const tree_t * restrict ptree, const char *str_csa, char *str_usi )
+{
+ if ( str_csa[0] == '0' && str_csa[1] == '0'
+ && '1' <= str_csa[2] && str_csa[2] <= '9'
+ && '1' <= str_csa[3] && str_csa[3] <= '9'
+ && 'A' <= str_csa[4] && str_csa[4] <= 'Z'
+ && 'A' <= str_csa[5] && str_csa[5] <= 'Z' )
+ {
+ switch ( str2piece( str_csa + 4 ) )
+ {
+ case pawn: str_usi[0] = 'P'; break;
+ case lance: str_usi[0] = 'L'; break;
+ case knight: str_usi[0] = 'N'; break;
+ case silver: str_usi[0] = 'S'; break;
+ case gold: str_usi[0] = 'G'; break;
+ case bishop: str_usi[0] = 'B'; break;
+ case rook: str_usi[0] = 'R'; break;
+ default: return -1; break;
+ }
+
+ str_usi[1] = '*';
+ str_usi[2] = str_csa[2];
+ str_usi[3] = (char)( str_csa[3] + 'a' - '1' );
+ str_usi[4] = '\0';
+
+ return 1;
+ }
+
+
+ if ( '1' <= str_csa[0] && str_csa[0] <= '9'
+ && '1' <= str_csa[1] && str_csa[1] <= '9'
+ && '1' <= str_csa[2] && str_csa[2] <= '9'
+ && '1' <= str_csa[3] && str_csa[3] <= '9'
+ && 'A' <= str_csa[4] && str_csa[4] <= 'Z'
+ && 'A' <= str_csa[5] && str_csa[5] <= 'Z' )
+ {
+ int sq_file, sq_rank, sq, pc;
+
+
+ str_usi[0] = str_csa[0];
+ str_usi[1] = (char)( str_csa[1] + 'a' - '1' );
+ str_usi[2] = str_csa[2];
+ str_usi[3] = (char)( str_csa[3] + 'a' - '1' );
+
+ sq_file = str_csa[0]-'0';
+ sq_file = 9 - sq_file;
+
+ sq_rank = str_csa[1]-'0';
+ sq_rank = sq_rank - 1;
+ sq = sq_rank * 9 + sq_file;
+ pc = abs(BOARD[sq]);
+
+ if ( pc + promote == str2piece( str_csa + 4 ) )
+ {
+ str_usi[4] = '+';
+ str_usi[5] = '\0';
+ }
+ else { str_usi[4] = '\0'; }
+
+
+ return 1;
+ }
+
+ str_usi[0] = '*';
+ str_usi[1] = '\0';
+ return 1;
+}
+#endif
+
+
static void
out_CSA_header( const tree_t * restrict ptree, record_t *pr )
{
#include "shogi.h"
FILE *pf_book;
-FILE *pf_hash;
uint64_t ehash_tbl[ EHASH_MASK + 1 ];
-unsigned char hash_rejections_parent[ REJEC_MASK+1 ];
-rejections_t hash_rejections[ REJEC_MASK+1 ];
trans_table_t *ptrans_table_orig;
SHARE trans_table_t *ptrans_table;
-history_book_learn_t history_book_learn[ HASH_REG_HIST_LEN ];
record_t record_problems;
record_t record_game;
rand_work_t rand_work;
root_move_t root_move_list[ MAX_LEGAL_MOVES ];
pv_t last_pv;
-pv_t last_pv_save;
+pv_t alast_pv_save[NUM_UNMAKE];
slide_tbl_t aslide[ nsquare ];
bitboard_t abb_b_knight_attacks[ nsquare ];
bitboard_t abb_b_silver_attacks[ nsquare ];
bitboard_t abb_king_attacks[ nsquare ];
bitboard_t abb_bishop_attacks_rl45[ nsquare ][ 128 ];
bitboard_t abb_bishop_attacks_rr45[ nsquare ][ 128 ];
+bitboard_t abb_rank_attacks[ nsquare ][ 128 ];
bitboard_t abb_file_attacks[ nsquare ][ 128 ];
bitboard_t abb_obstacle[ nsquare ][ nsquare ];
bitboard_t abb_mask[ nsquare ];
uint64_t w_hand_rook_rand[ nrook_max ];
uint64_t node_limit;
SHARE unsigned int game_status;
+unsigned int amove_save[NUM_UNMAKE];
unsigned int move_evasion_pchk;
unsigned int node_per_second;
unsigned int node_next_signal;
unsigned int time_limit;
unsigned int time_max_limit;
unsigned int time_last_search;
-unsigned int time_last_eff_search;
unsigned int time_response;
-unsigned int ai_rook_attacks_r0[ nsquare ][ 128 ];
unsigned int ponder_move;
-int p_value_ex[31];
-int benefit2promo[15];
int easy_abs;
int easy_min;
int easy_max;
unsigned int ponder_move_list[ MAX_LEGAL_MOVES ];
int ponder_nmove;
SHARE int root_abort;
-int root_nrep;
int root_nmove;
int root_alpha;
int root_beta;
int root_value;
int root_turn;
-int root_move_cap;
+int root_index;
int root_nfail_high;
int root_nfail_low;
int trans_table_age;
int log2_ntrans_table;
-int n_nobook_move;
int last_root_value;
-int last_root_value_save;
int iteration_depth;
int depth_limit;
-int irecord_game;
+int record_num;
int npawn_box;
int nlance_box;
int nknight_box;
int nbishop_box;
int nrook_box;
int resign_threshold;
-short p_value[31];
+int amaterial_save[NUM_UNMAKE];
+int alast_root_value_save[NUM_UNMAKE];
+int p_value_ex[31];
+int p_value_pm[15];
+int p_value[31];
short pc_on_sq[nsquare][pos_n];
short kkp[nsquare][nsquare][kkp_end];
+unsigned char ansuc_check_save[NUM_UNMAKE];
unsigned char book_section[ MAX_SIZE_SECTION+1 ];
unsigned char adirec[ nsquare ][ nsquare ];
unsigned char is_same[ 16 ][ 16 ];
pv_t mpv_pv[ MPV_MAX_PV*2 + 1 ];
#endif
-#if defined(TLP)
-# if !defined(_WIN32)
+#if defined(DFPN)
+unsigned int dfpn_hash_log2;
+sckt_t dfpn_sckt;
+#endif
+
+# if ! defined(_WIN32) && ( defined(DFPN_CLIENT) || defined(TLP) )
pthread_attr_t pthread_attr;
# endif
+
+#if defined(TLP) || defined(DFPN_CLIENT)
+lock_t io_lock;
+#endif
+
+#if defined(DFPN_CLIENT)
+volatile sckt_t dfpn_client_sckt;
+volatile int dfpn_client_flag_read;
+volatile unsigned int dfpn_client_move_unlocked;
+volatile int dfpn_client_rresult_unlocked;
+volatile int dfpn_client_rresult;
+volatile int dfpn_client_num_cresult;
+volatile char dfpn_client_signature[ DFPN_CLIENT_SIZE_SIGNATURE ];
+volatile dfpn_client_cresult_t dfpn_client_cresult[ MAX_LEGAL_MOVES ];
+volatile char dfpn_client_str_move[7];
+unsigned int dfpn_client_best_move;
+lock_t dfpn_client_lock;
+char dfpn_client_str_addr[256];
+int dfpn_client_port;
+int dfpn_client_cresult_index;
+#endif
+
+#if defined(TLP)
lock_t tlp_lock;
tree_t tlp_atree_work[ TLP_NUM_WORK ];
tree_t * volatile tlp_ptrees[ TLP_MAX_THREADS ];
int tlp_nsplit;
int tlp_nabort;
int tlp_nslot;
-volatile unsigned short tlp_rejections_slot[ REJEC_MASK+1 ];
#else
tree_t tree;
#endif
const char *str_dir_logs = "log";
#endif
-#if defined(CSA_LAN) || defined(MNJ_LAN)
+#if defined(CSA_LAN)||defined(MNJ_LAN)|| defined(DFPN_CLIENT)|| defined(DFPN)
unsigned int time_last_send;
#endif
sckt_t sckt_csa;
#endif
+#if defined(MNJ_LAN) || defined(USI)
+unsigned int moves_ignore[MAX_LEGAL_MOVES];
+#endif
+
#if defined(MNJ_LAN)
-short mnj_tbl[ MNJ_MASK + 1 ];
sckt_t sckt_mnj;
int mnj_posi_id;
-unsigned int mnj_move_last;
+int mnj_depth_stable;
+unsigned int mnj_moves_ignore[MAX_LEGAL_MOVES];
#endif
-#if defined(DEKUNOBOU)
-SOCKET dek_socket_in;
-SOCKET dek_s_accept;
-u_long dek_ul_addr;
-unsigned int dek_ngame;
-unsigned int dek_lost;
-unsigned int dek_win;
-int dek_turn;
-u_short dek_ns;
+#if defined(USI)
+enum usi_mode usi_mode;
+unsigned int usi_time_out_last;
+unsigned int usi_byoyomi;
#endif
check_table_t b_chk_tbl[nsquare];
unsigned int easy_move;
#endif
-const char *str_resign = "%TORYO";
-const char *str_repetition = "%SENNICHITE";
-const char *str_jishogi = "%JISHOGI";
-const char *str_record_error = "%ERROR";
-const char *str_delimiters = " \t,";
-const char *str_fmt_line = "Line %u: %s";
-const char *str_on = "on";
-const char *str_off = "off";
-const char *str_book = "book.bin";
-const char *str_hash = "hash.bin";
-const char *str_fv = "fv.bin";
-const char *str_book_error = "invalid opening book";
-const char *str_io_error = "I/O error";
-const char *str_perpet_check = "perpetual check";
-const char *str_bad_cmdline = "invalid command line";
-const char *str_busy_think = "I'm busy in thinking now";
-const char *str_bad_record = "invalid record of game";
-const char *str_bad_board = "invalid board representation";
-const char *str_illegal_move = "illegal move";
-const char *str_double_pawn = "double pawn";
-const char *str_mate_drppawn = "mated by a droped pawn";
-const char *str_unexpect_eof = "unexpected end of file";
-const char *str_king_hang = "The king is hang.";
-const char *str_game_ended = "move after a game was concluded";
-const char *str_fopen_error = "Can't open a file";
-const char *str_ovrflw_line = "Too many characters in a line.";
-const char *str_warning = "WARNING: ";
+#if defined(INANIWA_SHIFT)
+int inaniwa_flag;
+#endif
+
+const char *str_resign = "%TORYO";
+const char *str_repetition = "%SENNICHITE";
+const char *str_jishogi = "%JISHOGI";
+const char *str_record_error = "%ERROR";
+const char *str_delimiters = " \t,";
+const char *str_fmt_line = "Line %u: %s";
+const char *str_on = "on";
+const char *str_off = "off";
+const char *str_book = "book.bin";
+const char *str_fv = "fv.bin";
+const char *str_book_error = "invalid opening book";
+const char *str_io_error = "I/O error";
+const char *str_perpet_check = "perpetual check";
+const char *str_bad_cmdline = "invalid command line";
+const char *str_busy_think = "I'm busy in thinking now";
+const char *str_bad_record = "invalid record of game";
+const char *str_bad_board = "invalid board representation";
+const char *str_illegal_move = "illegal move";
+const char *str_double_pawn = "double pawn";
+const char *str_mate_drppawn = "mated by a droped pawn";
+const char *str_unexpect_eof = "unexpected end of file";
+const char *str_king_hang = "The king is hang.";
+const char *str_game_ended = "move after a game was concluded";
+const char *str_fopen_error = "Can't open a file";
+const char *str_ovrflw_line = "Too many characters in a line.";
+const char *str_no_legal_move = "No legal moves to search";
+const char *str_warning = "WARNING: ";
#if defined(CSA_LAN)
const char *str_server_err = "received invalid message from the server";
#endif
const char ach_turn[2] = { '+', '-' };
-const char ashell_h[ SHELL_H_LEN ] = { 1, 3, 7, 15, 31, 63, 127 };
+const int ashell_h[ SHELL_H_LEN ] = { 1, 3, 7, 15, 31, 63, 127 };
+
+const int aikpp[31] = { e_dragon, e_horse, 0, e_gold,
+ e_gold, e_gold, e_gold, 0,
+ e_rook, e_bishop, e_gold, e_silver,
+ e_knight, e_lance, e_pawn, 0,
+ f_pawn, f_lance, f_knight,
+ f_silver, f_gold, f_bishop, f_rook,
+ 0, f_gold, f_gold, f_gold,
+ f_gold, 0, f_horse, f_dragon };
+
+const int aikkp[16] = { 0, kkp_pawn, kkp_lance, kkp_knight,
+ kkp_silver, kkp_gold, kkp_bishop, kkp_rook,
+ 0, kkp_gold, kkp_gold, kkp_gold,
+ kkp_gold, kkp_gold, kkp_horse, kkp_dragon };
-const short aipos[31] = { e_dragon, e_horse, 0, e_gold,
- e_gold, e_gold, e_gold, 0,
- e_rook, e_bishop, e_gold, e_silver,
- e_knight, e_lance, e_pawn, 0,
- f_pawn, f_lance, f_knight,
- f_silver, f_gold, f_bishop, f_rook,
- 0, f_gold, f_gold, f_gold,
- f_gold, 0, f_horse, f_dragon };
+const int aikkp_hand[8] = { 0, kkp_hand_pawn, kkp_hand_lance,
+ kkp_hand_knight, kkp_hand_silver, kkp_hand_gold,
+ kkp_hand_bishop, kkp_hand_rook };
const unsigned char aifile[ nsquare ]= {
file1, file2, file3, file4, file5, file6, file7, file8, file9,
# define CheckBoard( PIECE, piece ) \
bb = BB_B ## PIECE; \
- while( BBToU( bb ) ) { \
+ while( BBTest( bb ) ) { \
sq = FirstOne( bb ); \
Xor( sq, bb ); \
if ( BOARD[sq] != piece ) { DOut( "BB_B" # PIECE ); } \
} \
bb = BB_W ## PIECE; \
- while( BBToU( bb ) ) { \
+ while( BBTest( bb ) ) { \
sq = FirstOne( bb ); \
Xor( sq, bb ); \
if ( BOARD[sq] != -piece ) { DOut( "BB_W" # PIECE ); } \
+++ /dev/null
-#include <string.h>
-#include <stdarg.h>
-#include "shogi.h"
-
-#if defined(DEKUNOBOU)
-
-int
-dek_start( const char *str_addr, int port_dek, int port_bnz )
-{
- SOCKADDR_IN service;
- WSADATA wsaData;
- u_short dek_ns_bnz;
-
- /* initialize winsock */
- if ( WSAStartup( MAKEWORD(1,1), &wsaData ) )
- {
- str_error = "WSAStartup() failed.";
- return -2;
- }
-
- dek_ul_addr = inet_addr( str_addr );
- if ( dek_ul_addr == INADDR_NONE )
- {
- struct hostent *phe = gethostbyname( str_addr );
- if ( ! phe )
- {
- str_error = str_WSAError( "gethostbyname() faild." );
- return -2;
- }
- dek_ul_addr = *( (u_long *)phe->h_addr_list[0] );
- }
-
- dek_ns = htons( (u_short)port_dek );
- dek_ns_bnz = htons( (u_short)port_bnz );
-
- dek_socket_in = socket( AF_INET, SOCK_STREAM, 0 );
- if ( dek_socket_in == INVALID_SOCKET )
- {
- str_error = str_WSAError( "socket() failed." );
- return -2;
- }
-
- service.sin_family = AF_INET;
- service.sin_addr.s_addr = dek_ul_addr;
- service.sin_port = dek_ns_bnz;
- if ( bind( dek_socket_in, (SOCKADDR *)&service, sizeof(service) )
- == SOCKET_ERROR )
- {
- str_error = "bind() failed.";
- return -2;
- }
-
- if ( listen( dek_socket_in, 1 ) == SOCKET_ERROR )
- {
- str_error = "listen() failed.";
- return -2;
- }
-
- dek_s_accept = (SOCKET)SOCKET_ERROR;
-
- return 1;
-}
-
-
-int
-dek_next_game( tree_t * restrict ptree )
-{
- if ( dek_ngame != 1 && dek_turn )
- {
- Out( "take a nap ..." );
- Sleep( 37000 );
- Out( " done\n" );
- }
-
- if ( ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL ) < 0
- || get_elapsed( &time_turn_start ) < 0
- || ( dek_turn && com_turn_start( ptree, 0 ) < 0 ) ) { return -1; }
-
- dek_turn ^= 1;
- dek_ngame += 1;
-
- return 1;
-}
-
-
-int
-dek_check( void )
-{
- struct timeval tv;
- fd_set readfds;
- int iret;
- char ch;
-
- tv.tv_sec = tv.tv_usec = 0;
-
- if ( dek_s_accept == SOCKET_ERROR )
- {
- FD_ZERO( &readfds );
-#if defined(_MSC_VER)
-# pragma warning(disable:4127)
-#endif
- FD_SET( dek_socket_in, &readfds );
-#if defined(_MSC_VER)
-# pragma warning(default:4127)
-#endif
- iret = select( 1, &readfds, NULL, NULL, &tv );
- if ( iret == SOCKET_ERROR )
- {
- snprintf( str_message, SIZE_MESSAGE,
- "select() with a socket listening failed:%d",
- WSAGetLastError() );
- str_error = str_message;
- return -1;
-
- }
- if ( ! iret ) { return 0; } /* no connection is pending. */
-
- dek_s_accept = accept( dek_socket_in, NULL, NULL );
- if ( dek_s_accept == SOCKET_ERROR )
- {
- snprintf( str_message, SIZE_MESSAGE,
- "accept() following select() failed:%d",
- WSAGetLastError() );
- str_error = str_message;
- return -1;
- }
- }
-
- FD_ZERO( &readfds );
-#if defined(_MSC_VER)
-# pragma warning(disable:4127)
-#endif
- FD_SET( dek_s_accept, &readfds );
-#if defined(_MSC_VER)
-# pragma warning(default:4127)
-#endif
-
- iret = select( 0, &readfds, NULL, NULL, &tv );
- if ( iret == SOCKET_ERROR )
- {
- snprintf( str_message, SIZE_MESSAGE,
- "select() with a socket accepted failed:%d",
- WSAGetLastError() );
- str_error = str_message;
- return -1;
- }
- if ( ! iret ) { return 0; } /* the connection isn't closed,
- nor has available data. */
-
- iret = recv( dek_s_accept, &ch, 1, MSG_PEEK );
- if ( iret == SOCKET_ERROR )
- {
- closesocket( dek_s_accept );
- dek_s_accept = (SOCKET)SOCKET_ERROR;
- snprintf( str_message, SIZE_MESSAGE,
- "recv() with flag MSG_PEEK failed:%d",
- WSAGetLastError() );
- str_error = str_message;
- return -1;
- }
- if ( ! iret )
- {
- if ( closesocket( dek_s_accept ) )
- {
- dek_s_accept = (SOCKET)SOCKET_ERROR;
- snprintf( str_message, SIZE_MESSAGE,
- "closesocket() failed:%d", WSAGetLastError() );
- str_error = str_message;
- return -1;
- }
- dek_s_accept = (SOCKET)SOCKET_ERROR;
- return 0; /* the connection has been closed. */
- }
-
- return 1; /* data is available for reading. */
-}
-
-
-int
-dek_in( char *str, int n )
-{
-#if defined(_MSC_VER)
-# pragma warning(disable:4127)
-#endif
- int count_byte;
-
- for (;;) {
- if ( dek_s_accept == SOCKET_ERROR )
- {
- Out( "\nwait for new connection...\n" );
- dek_s_accept = accept( dek_socket_in, NULL, NULL );
- if ( dek_s_accept == SOCKET_ERROR )
- {
- str_error = str_WSAError( "accept() failed." );
- return -1;
- }
- }
-
- count_byte = recv( dek_s_accept, str, n, 0 );
- if ( count_byte == SOCKET_ERROR )
- {
- closesocket( dek_s_accept );
- dek_s_accept = (SOCKET)SOCKET_ERROR;
- str_error = str_WSAError( "recv() failed." );
- return -1;
- }
- if ( count_byte ) { break; }
-
- if ( closesocket( dek_s_accept ) )
- {
- dek_s_accept = (SOCKET)SOCKET_ERROR;
- str_error = str_WSAError( "closesocket() failed." );
- return -1;
- }
- dek_s_accept = (SOCKET)SOCKET_ERROR;
- }
-
- *( str + count_byte ) = '\0';
- Out( "recieved %s", str );
-
- return count_byte;
-#if defined(_MSC_VER)
-# pragma warning(default:4127)
-#endif
-}
-
-
-int
-dek_out( const char *format, ... )
-{
- SOCKADDR_IN service;
- SOCKET socket_out;
- int nch, iret;
- char buf[256];
- va_list arg;
-
- va_start( arg, format );
- nch = vsnprintf( buf, 256, format, arg );
- va_end( arg );
-
- Out( "send %s", buf );
-
- socket_out = socket( AF_INET, SOCK_STREAM, 0 );
- if ( socket_out == INVALID_SOCKET )
- {
- snprintf( str_message, SIZE_MESSAGE,
- "socket() failed:%d", WSAGetLastError() );
- str_error = str_message;
- return -2;
- }
-
- service.sin_family = AF_INET;
- service.sin_addr.s_addr = dek_ul_addr;
- service.sin_port = dek_ns;
- if ( connect( socket_out, (SOCKADDR *)&service, sizeof(service) )
- == SOCKET_ERROR )
- {
- snprintf( str_message, SIZE_MESSAGE,
- "connect() failed:%d", WSAGetLastError() );
- str_error = str_message;
- return -2;
- }
-
- iret = send( socket_out, buf, nch, 0 );
- if ( iret == SOCKET_ERROR )
- {
- closesocket( socket_out );
- snprintf( str_message, SIZE_MESSAGE,
- "send() failed:%d", WSAGetLastError() );
- str_error = str_message;
- return -2;
- }
- if ( iret != nch )
- {
- closesocket( socket_out );
- str_error = "send() wrote partial number of bytes.";
- return -2;
- }
-
- if ( closesocket( socket_out ) )
- {
- snprintf( str_message, SIZE_MESSAGE,
- "closesocket() failed:%d", WSAGetLastError() );
- str_error = str_message;
- return -2;
- }
-
- return 1;
-}
-
-int
-dek_parse( char *str, int len )
-{
- if ( *str == '+' || *str == '-' )
- {
- memmove( str, str+1, 6 );
- str[6] = '\0';
- }
- else if ( ! strcmp( str, str_resign ) )
- {
- strncpy( str, "resign", len-1 );
- str[len-1] = '\0';
- dek_win += 1;
- Out( "Bonanza won against Dekunobou\n" );
- }
- else {
- str_error = "unknown command is recieved from Deknobou.";
- return -2;
- }
-
- return 1;
-}
-
-# endif /* DEKUNOBOU */
#include <assert.h>
#include "shogi.h"
-void
+void CONV
check_futile_score_quies( const tree_t * restrict ptree, unsigned int move,
int old_val, int new_val, int turn )
{
const int ifrom = I2From(move);
int fsp, fmt, ipc_cap;
+ old_val /= FV_SCALE;
+ new_val /= FV_SCALE;
+
if ( I2PieceMove(move) == king )
{
fmt = new_val;
else {
if ( I2IsPromote(move) )
{
- fmt -= benefit2promo[7+I2PieceMove(move)];
+ fmt -= p_value_pm[7+I2PieceMove(move)];
}
if ( ipc_cap )
}
-int
+int CONV
eval_max_score( const tree_t * restrict ptree, unsigned int move,
- int stand_pat, int turn, int diff )
+ int value, int turn, int diff )
{
int score_mt, score_sp, ipc_cap;
+ value /= FV_SCALE;
+
if ( I2From(move) >= nsquare )
{
- score_sp = stand_pat + diff + fmg_drop + FMG_MG;
+ score_sp = value + diff + fmg_drop + FMG_MG;
score_mt = ( turn ? -MATERIAL : MATERIAL ) + fmg_mt + FMG_MG_MT;
}
else {
- score_sp = diff + stand_pat;
+ score_sp = diff + value;
score_mt = fmg_mt + FMG_MG_MT;
if ( turn )
{
if ( I2IsPromote(move) )
{
- score_mt += benefit2promo[7+I2PieceMove(move)];
+ score_mt += p_value_pm[7+I2PieceMove(move)];
}
score_sp += FMG_MG;
}
-int
+int CONV
estimate_score_diff( const tree_t * restrict ptree, unsigned int move,
int turn )
{
ipc_cap = (int)UToCap(move);
if ( ipc_cap )
{
- diff = -(int)PcOnSq( ibk, aipos[15+ipc_cap]+ito );
- diff += (int)PcOnSq( iwk, aipos[15-ipc_cap]+Inv(ito) );
+ diff = -(int)PcOnSq( ibk, aikpp[15+ipc_cap]+ito );
+ diff += (int)PcOnSq( iwk, aikpp[15-ipc_cap]+Inv(ito) );
diff /= FV_SCALE;
if ( turn ) { diff -= p_value_ex[15+ipc_cap]; }
else { diff += p_value_ex[15-ipc_cap]; }
else if ( ifrom >= nsquare )
{
ipc_move = turn ? -(int)From2Drop(ifrom) : (int)From2Drop(ifrom);
- diff = (int)PcOnSq( ibk, aipos[15+ipc_move]+ito );
- diff -= (int)PcOnSq( iwk, aipos[15-ipc_move]+Inv(ito) );
+ diff = (int)PcOnSq( ibk, aikpp[15+ipc_move]+ito );
+ diff -= (int)PcOnSq( iwk, aikpp[15-ipc_move]+Inv(ito) );
diff /= FV_SCALE;
}
else {
}
if ( I2IsPromote(move) && ipc_cap )
{
- diff = -(int)PcOnSq( ibk, aipos[15+ipc_move] + ifrom );
- diff += (int)PcOnSq( ibk, aipos[15+ipro_pc_move] + ito );
- diff += -(int)PcOnSq( ibk, aipos[15+ipc_cap] + ito );
- diff += (int)PcOnSq( iwk, aipos[15-ipc_move] + Inv(ifrom) );
- diff += -(int)PcOnSq( iwk, aipos[15-ipro_pc_move] + Inv(ito) );
- diff += (int)PcOnSq( iwk, aipos[15-ipc_cap] + Inv(ito) );
+ diff = -(int)PcOnSq( ibk, aikpp[15+ipc_move] + ifrom );
+ diff += (int)PcOnSq( ibk, aikpp[15+ipro_pc_move] + ito );
+ diff += -(int)PcOnSq( ibk, aikpp[15+ipc_cap] + ito );
+ diff += (int)PcOnSq( iwk, aikpp[15-ipc_move] + Inv(ifrom) );
+ diff += -(int)PcOnSq( iwk, aikpp[15-ipro_pc_move] + Inv(ito) );
+ diff += (int)PcOnSq( iwk, aikpp[15-ipc_cap] + Inv(ito) );
diff /= FV_SCALE;
if ( turn )
{
- diff -= benefit2promo[7+ipc_move];
+ diff -= p_value_pm[7+ipc_move];
diff -= p_value_ex[15+ipc_cap];
}
else {
- diff += benefit2promo[7+ipc_move];
+ diff += p_value_pm[7+ipc_move];
diff += p_value_ex[15+ipc_cap];
}
}
else if ( ipc_cap )
{
- diff = -(int)PcOnSq( ibk, aipos[15+ipc_move] + ifrom );
- diff += (int)PcOnSq( ibk, aipos[15+ipc_move] + ito );
- diff += -(int)PcOnSq( ibk, aipos[15+ipc_cap] + ito );
- diff += (int)PcOnSq( iwk, aipos[15-ipc_move] + Inv(ifrom) );
- diff += -(int)PcOnSq( iwk, aipos[15-ipc_move] + Inv(ito) );
- diff += (int)PcOnSq( iwk, aipos[15-ipc_cap] + Inv(ito) );
+ diff = -(int)PcOnSq( ibk, aikpp[15+ipc_move] + ifrom );
+ diff += (int)PcOnSq( ibk, aikpp[15+ipc_move] + ito );
+ diff += -(int)PcOnSq( ibk, aikpp[15+ipc_cap] + ito );
+ diff += (int)PcOnSq( iwk, aikpp[15-ipc_move] + Inv(ifrom) );
+ diff += -(int)PcOnSq( iwk, aikpp[15-ipc_move] + Inv(ito) );
+ diff += (int)PcOnSq( iwk, aikpp[15-ipc_cap] + Inv(ito) );
diff /= FV_SCALE;
diff += turn ? -p_value_ex[15+ipc_cap] : p_value_ex[15+ipc_cap];
}
else if ( I2IsPromote(move) )
{
- diff = -(int)PcOnSq( ibk, aipos[15+ipc_move] + ifrom );
- diff += (int)PcOnSq( ibk, aipos[15+ipro_pc_move] + ito );
- diff += (int)PcOnSq( iwk, aipos[15-ipc_move] + Inv(ifrom) );
- diff += -(int)PcOnSq( iwk, aipos[15-ipro_pc_move] + Inv(ito) );
+ diff = -(int)PcOnSq( ibk, aikpp[15+ipc_move] + ifrom );
+ diff += (int)PcOnSq( ibk, aikpp[15+ipro_pc_move] + ito );
+ diff += (int)PcOnSq( iwk, aikpp[15-ipc_move] + Inv(ifrom) );
+ diff += -(int)PcOnSq( iwk, aikpp[15-ipro_pc_move] + Inv(ito) );
diff /= FV_SCALE;
- diff += turn ? -benefit2promo[7+ipc_move] : benefit2promo[7+ipc_move];
+ diff += turn ? -p_value_pm[7+ipc_move] : p_value_pm[7+ipc_move];
}
else {
- diff = -(int)PcOnSq( ibk, aipos[15+ipc_move] + ifrom );
- diff += (int)PcOnSq( ibk, aipos[15+ipc_move] + ito );
- diff += (int)PcOnSq( iwk, aipos[15-ipc_move] + Inv(ifrom) );
- diff += -(int)PcOnSq( iwk, aipos[15-ipc_move] + Inv(ito) );
+ diff = -(int)PcOnSq( ibk, aikpp[15+ipc_move] + ifrom );
+ diff += (int)PcOnSq( ibk, aikpp[15+ipc_move] + ito );
+ diff += (int)PcOnSq( iwk, aikpp[15-ipc_move] + Inv(ifrom) );
+ diff += -(int)PcOnSq( iwk, aikpp[15-ipc_move] + Inv(ito) );
diff /= FV_SCALE;
}
}
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <limits.h>
#include "shogi.h"
-static int ehash_probe( uint64_t current_key, unsigned int hand_b,
- int *pscore );
-static void ehash_store( uint64_t key, unsigned int hand_b, int score );
-static int make_list( const tree_t * restrict ptree, int * restrict pscore,
- int list0[52], int list1[52] );
+#define PcPcOnSqAny(k,i,j) ( i >= j ? PcPcOnSq(k,i,j) : PcPcOnSq(k,j,i) )
+
+static int CONV doacapt( const tree_t * restrict ptree, int pc, int turn,
+ int hand_index, const int list0[52],
+ const int list1[52], int nlist );
+static int CONV doapc( const tree_t * restrict ptree, int pc, int sq,
+ const int list0[52], const int list1[52], int nlist );
+static int CONV ehash_probe( uint64_t current_key, unsigned int hand_b,
+ int * restrict pscore );
+static void CONV ehash_store( uint64_t key, unsigned int hand_b, int score );
+static int CONV calc_difference( const tree_t * restrict ptree, int ply,
+ int turn, int list0[52], int list1[52],
+ int * restrict pscore );
+static int CONV make_list( const tree_t * restrict ptree,
+ int * restrict pscore,
+ int list0[52], int list1[52] );
+
+#if defined(INANIWA_SHIFT)
+static int inaniwa_score( const tree_t * restrict ptree );
+#endif
-int
+int CONV
eval_material( const tree_t * restrict ptree )
{
int material, itemp;
}
-int
+int CONV
evaluate( tree_t * restrict ptree, int ply, int turn )
{
int list0[52], list1[52];
int nlist, score, sq_bk, sq_wk, k0, k1, l0, l1, i, j, sum;
+ assert( 0 < ply );
ptree->neval_called++;
- if ( ptree->stand_pat[ply] != score_bound )
+ if ( ptree->save_eval[ply] != INT_MAX )
{
- return (int)ptree->stand_pat[ply];
+ return (int)ptree->save_eval[ply] / FV_SCALE;
}
if ( ehash_probe( HASH_KEY, HAND_B, &score ) )
{
score = turn ? -score : score;
- ptree->stand_pat[ply] = (short)score;
+ ptree->save_eval[ply] = score;
- return score;
+ return score / FV_SCALE;
}
+ list0[ 0] = f_hand_pawn + I2HandPawn(HAND_B);
+ list0[ 1] = e_hand_pawn + I2HandPawn(HAND_W);
+ list0[ 2] = f_hand_lance + I2HandLance(HAND_B);
+ list0[ 3] = e_hand_lance + I2HandLance(HAND_W);
+ list0[ 4] = f_hand_knight + I2HandKnight(HAND_B);
+ list0[ 5] = e_hand_knight + I2HandKnight(HAND_W);
+ list0[ 6] = f_hand_silver + I2HandSilver(HAND_B);
+ list0[ 7] = e_hand_silver + I2HandSilver(HAND_W);
+ list0[ 8] = f_hand_gold + I2HandGold(HAND_B);
+ list0[ 9] = e_hand_gold + I2HandGold(HAND_W);
+ list0[10] = f_hand_bishop + I2HandBishop(HAND_B);
+ list0[11] = e_hand_bishop + I2HandBishop(HAND_W);
+ list0[12] = f_hand_rook + I2HandRook(HAND_B);
+ list0[13] = e_hand_rook + I2HandRook(HAND_W);
+
+ list1[ 0] = f_hand_pawn + I2HandPawn(HAND_W);
+ list1[ 1] = e_hand_pawn + I2HandPawn(HAND_B);
+ list1[ 2] = f_hand_lance + I2HandLance(HAND_W);
+ list1[ 3] = e_hand_lance + I2HandLance(HAND_B);
+ list1[ 4] = f_hand_knight + I2HandKnight(HAND_W);
+ list1[ 5] = e_hand_knight + I2HandKnight(HAND_B);
+ list1[ 6] = f_hand_silver + I2HandSilver(HAND_W);
+ list1[ 7] = e_hand_silver + I2HandSilver(HAND_B);
+ list1[ 8] = f_hand_gold + I2HandGold(HAND_W);
+ list1[ 9] = e_hand_gold + I2HandGold(HAND_B);
+ list1[10] = f_hand_bishop + I2HandBishop(HAND_W);
+ list1[11] = e_hand_bishop + I2HandBishop(HAND_B);
+ list1[12] = f_hand_rook + I2HandRook(HAND_W);
+ list1[13] = e_hand_rook + I2HandRook(HAND_B);
+
+ if ( calc_difference( ptree, ply, turn, list0, list1, &score ) )
+ {
+ ehash_store( HASH_KEY, HAND_B, score );
+ score = turn ? -score : score;
+ ptree->save_eval[ply] = score;
+
+ return score / FV_SCALE;
+ }
- score = 0;
nlist = make_list( ptree, &score, list0, list1 );
sq_bk = SQ_BKING;
sq_wk = Inv( SQ_WKING );
}
score += sum;
- score /= FV_SCALE;
+ score += MATERIAL * FV_SCALE;
+#if defined(INANIWA_SHIFT)
+ score += inaniwa_score( ptree );
+#endif
- score += MATERIAL;
+ ehash_store( HASH_KEY, HAND_B, score );
-#if defined(MNJ_LAN)
- if ( sckt_mnj != SCKT_NULL ) { score += mnj_tbl[ HASH_KEY & MNJ_MASK ]; }
-#endif
+ score = turn ? -score : score;
+
+ ptree->save_eval[ply] = score;
+
+ score /= FV_SCALE;
#if ! defined(MINIMUM)
if ( abs(score) > score_max_eval )
}
#endif
- ehash_store( HASH_KEY, HAND_B, score );
-
- score = turn ? -score : score;
- ptree->stand_pat[ply] = (short)score;
-
return score;
}
-void ehash_clear( void )
-{
- memset( ehash_tbl, 0, sizeof(ehash_tbl) );
-}
+void CONV ehash_clear( void ) { memset( ehash_tbl, 0, sizeof(ehash_tbl) ); }
-static int ehash_probe( uint64_t current_key, unsigned int hand_b,
- int *pscore )
+static int CONV ehash_probe( uint64_t current_key, unsigned int hand_b,
+ int * restrict pscore )
{
uint64_t hash_word, hash_key;
hash_word ^= hash_word << 32;
#endif
- current_key ^= (uint64_t)hand_b << 16;
- current_key &= ~(uint64_t)0xffffU;
+ current_key ^= (uint64_t)hand_b << 21;
+ current_key &= ~(uint64_t)0x1fffffU;
hash_key = hash_word;
- hash_key &= ~(uint64_t)0xffffU;
+ hash_key &= ~(uint64_t)0x1fffffU;
if ( hash_key != current_key ) { return 0; }
- *pscore = (int)( (unsigned int)hash_word & 0xffffU ) - 32768;
+ *pscore = (int)( (unsigned int)hash_word & 0x1fffffU ) - 0x100000;
return 1;
}
-static void ehash_store( uint64_t key, unsigned int hand_b, int score )
+static void CONV ehash_store( uint64_t key, unsigned int hand_b, int score )
{
uint64_t hash_word;
hash_word = key;
- hash_word ^= (uint64_t)hand_b << 16;
- hash_word &= ~(uint64_t)0xffffU;
- hash_word |= (uint64_t)( score + 32768 );
+ hash_word ^= (uint64_t)hand_b << 21;
+ hash_word &= ~(uint64_t)0x1fffffU;
+ hash_word |= (uint64_t)( score + 0x100000 );
#if ! defined(__x86_64__)
hash_word ^= hash_word << 32;
}
-static int
+static int CONV
+calc_difference( const tree_t * restrict ptree, int ply, int turn,
+ int list0[52], int list1[52], int * restrict pscore )
+{
+ bitboard_t bb;
+ int nlist, diff, from, to, sq, pc;
+
+#if defined(INANIWA_SHIFT)
+ if ( inaniwa_flag ) { return 0; }
+#endif
+
+ if ( ptree->save_eval[ply-1] == INT_MAX ) { return 0; }
+ if ( I2PieceMove(MOVE_LAST) == king ) { return 0; }
+
+ assert( MOVE_LAST != MOVE_PASS );
+
+ nlist = 14;
+ diff = 0;
+ from = I2From(MOVE_LAST);
+ to = I2To(MOVE_LAST);
+
+ BBOr( bb, BB_BOCCUPY, BB_WOCCUPY );
+ Xor( SQ_BKING, bb );
+ Xor( SQ_WKING, bb );
+ Xor( to, bb );
+
+ while ( BBTest(bb) )
+ {
+ sq = FirstOne(bb);
+ Xor( sq, bb );
+
+ pc = BOARD[sq];
+ list0[nlist ] = aikpp[15+pc] + sq;
+ list1[nlist++] = aikpp[15-pc] + Inv(sq);
+ }
+
+ pc = BOARD[to];
+ list0[nlist ] = aikpp[15+pc] + to;
+ list1[nlist++] = aikpp[15-pc] + Inv(to);
+
+ diff = doapc( ptree, pc, to, list0, list1, nlist );
+ nlist -= 1;
+
+ if ( from >= nsquare )
+ {
+ unsigned int hand;
+ int hand_index;
+
+ pc = From2Drop(from);
+ hand = turn ? HAND_B : HAND_W;
+
+ switch ( pc )
+ {
+ case pawn: hand_index = I2HandPawn(hand); break;
+ case lance: hand_index = I2HandLance(hand); break;
+ case knight: hand_index = I2HandKnight(hand); break;
+ case silver: hand_index = I2HandSilver(hand); break;
+ case gold: hand_index = I2HandGold(hand); break;
+ case bishop: hand_index = I2HandBishop(hand); break;
+ default: hand_index = I2HandRook(hand); break;
+ }
+
+ diff += doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+
+ list0[ 2*(pc-1) + 1 - turn ] += 1;
+ list1[ 2*(pc-1) + turn ] += 1;
+ hand_index += 1;
+
+ diff -= doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+ }
+ else {
+ int pc_cap = UToCap(MOVE_LAST);
+ if ( pc_cap )
+ {
+ unsigned int hand;
+ int hand_index;
+
+ pc = pc_cap & ~promote;
+ hand = turn ? HAND_B : HAND_W;
+ pc_cap = turn ? -pc_cap : pc_cap;
+ diff += turn ? p_value_ex[15+pc_cap] * FV_SCALE
+ : -p_value_ex[15+pc_cap] * FV_SCALE;
+
+ switch ( pc )
+ {
+ case pawn: hand_index = I2HandPawn(hand); break;
+ case lance: hand_index = I2HandLance(hand); break;
+ case knight: hand_index = I2HandKnight(hand); break;
+ case silver: hand_index = I2HandSilver(hand); break;
+ case gold: hand_index = I2HandGold(hand); break;
+ case bishop: hand_index = I2HandBishop(hand); break;
+ default: hand_index = I2HandRook(hand); break;
+ }
+
+ diff += doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+
+ list0[ 2*(pc-1) + 1 - turn ] -= 1;
+ list1[ 2*(pc-1) + turn ] -= 1;
+ hand_index -= 1;
+
+ diff -= doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+
+ list0[nlist ] = aikpp[15+pc_cap] + to;
+ list1[nlist++] = aikpp[15-pc_cap] + Inv(to);
+
+ diff -= doapc( ptree, pc_cap, to, list0, list1, nlist );
+ }
+
+ pc = I2PieceMove(MOVE_LAST);
+ if ( I2IsPromote(MOVE_LAST) )
+ {
+ diff += ( turn ? p_value_pm[7+pc] : -p_value_pm[7+pc] ) * FV_SCALE;
+ }
+
+ pc = turn ? pc : -pc;
+
+ list0[nlist ] = aikpp[15+pc] + from;
+ list1[nlist++] = aikpp[15-pc] + Inv(from);
+
+ diff -= doapc( ptree, pc, from, list0, list1, nlist );
+
+ }
+
+ diff += turn ? ptree->save_eval[ply-1] : - ptree->save_eval[ply-1];
+
+ *pscore = diff;
+
+ return 1;
+}
+
+
+static int CONV
make_list( const tree_t * restrict ptree, int * restrict pscore,
int list0[52], int list1[52] )
{
sq_bk1 = Inv(SQ_WKING);
sq_wk1 = Inv(SQ_BKING);
- list0[ 0] = f_hand_pawn + I2HandPawn(HAND_B);
- list0[ 1] = e_hand_pawn + I2HandPawn(HAND_W);
- list0[ 2] = f_hand_lance + I2HandLance(HAND_B);
- list0[ 3] = e_hand_lance + I2HandLance(HAND_W);
- list0[ 4] = f_hand_knight + I2HandKnight(HAND_B);
- list0[ 5] = e_hand_knight + I2HandKnight(HAND_W);
- list0[ 6] = f_hand_silver + I2HandSilver(HAND_B);
- list0[ 7] = e_hand_silver + I2HandSilver(HAND_W);
- list0[ 8] = f_hand_gold + I2HandGold(HAND_B);
- list0[ 9] = e_hand_gold + I2HandGold(HAND_W);
- list0[10] = f_hand_bishop + I2HandBishop(HAND_B);
- list0[11] = e_hand_bishop + I2HandBishop(HAND_W);
- list0[12] = f_hand_rook + I2HandRook(HAND_B);
- list0[13] = e_hand_rook + I2HandRook(HAND_W);
-
- list1[ 0] = f_hand_pawn + I2HandPawn(HAND_W);
- list1[ 1] = e_hand_pawn + I2HandPawn(HAND_B);
- list1[ 2] = f_hand_lance + I2HandLance(HAND_W);
- list1[ 3] = e_hand_lance + I2HandLance(HAND_B);
- list1[ 4] = f_hand_knight + I2HandKnight(HAND_W);
- list1[ 5] = e_hand_knight + I2HandKnight(HAND_B);
- list1[ 6] = f_hand_silver + I2HandSilver(HAND_W);
- list1[ 7] = e_hand_silver + I2HandSilver(HAND_B);
- list1[ 8] = f_hand_gold + I2HandGold(HAND_W);
- list1[ 9] = e_hand_gold + I2HandGold(HAND_B);
- list1[10] = f_hand_bishop + I2HandBishop(HAND_W);
- list1[11] = e_hand_bishop + I2HandBishop(HAND_B);
- list1[12] = f_hand_rook + I2HandRook(HAND_W);
- list1[13] = e_hand_rook + I2HandRook(HAND_B);
-
score += kkp[sq_bk0][sq_wk0][ kkp_hand_pawn + I2HandPawn(HAND_B) ];
score += kkp[sq_bk0][sq_wk0][ kkp_hand_lance + I2HandLance(HAND_B) ];
score += kkp[sq_bk0][sq_wk0][ kkp_hand_knight + I2HandKnight(HAND_B) ];
n2 = 0;
bb = BB_BPAWN;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WPAWN;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BLANCE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WLANCE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BKNIGHT;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WKNIGHT;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BSILVER;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WSILVER;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BTGOLD;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WTGOLD;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BBISHOP;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WBISHOP;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BROOK;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WROOK;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
for ( i = 0; i < n2; i++ ) { list1[nlist-i-1] = list2[i]; }
assert( nlist <= 52 );
- *pscore += score;
+
+ *pscore = score;
return nlist;
}
+
+
+static int CONV doapc( const tree_t * restrict ptree, int pc, int sq,
+ const int list0[52], const int list1[52], int nlist )
+{
+ int i, sum;
+ int index_b = aikpp[15+pc] + sq;
+ int index_w = aikpp[15-pc] + Inv(sq);
+ int sq_bk = SQ_BKING;
+ int sq_wk = Inv(SQ_WKING);
+
+ sum = 0;
+ for( i = 0; i < 14; i++ )
+ {
+ sum += PcPcOnSq( sq_bk, index_b, list0[i] );
+ sum -= PcPcOnSq( sq_wk, index_w, list1[i] );
+ }
+
+ for( i = 14; i < nlist; i++ )
+ {
+ sum += PcPcOnSqAny( sq_bk, index_b, list0[i] );
+ sum -= PcPcOnSqAny( sq_wk, index_w, list1[i] );
+ }
+
+ if ( pc > 0 )
+ {
+ sq_bk = SQ_BKING;
+ sq_wk = SQ_WKING;
+ sum += kkp[sq_bk][sq_wk][ aikkp[pc] + sq ];
+ }
+ else {
+ sq_bk = Inv(SQ_WKING);
+ sq_wk = Inv(SQ_BKING);
+ sum -= kkp[sq_bk][sq_wk][ aikkp[-pc] + Inv(sq) ];
+ }
+
+ return sum;
+}
+
+
+static int CONV
+doacapt( const tree_t * restrict ptree, int pc, int turn, int hand_index,
+ const int list0[52], const int list1[52], int nlist )
+{
+ int i, sum, sq_bk, sq_wk, index_b, index_w;
+
+ index_b = 2*(pc-1) + 1 - turn;
+ index_w = 2*(pc-1) + turn;
+ sq_bk = SQ_BKING;
+ sq_wk = Inv(SQ_WKING);
+
+ sum = 0;
+ for( i = 14; i < nlist; i++ )
+ {
+ sum += PcPcOnSq( sq_bk, list0[i], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[i], list1[index_w] );
+ }
+
+ for( i = 0; i <= 2*(pc-1); i++ )
+ {
+ sum += PcPcOnSq( sq_bk, list0[index_b], list0[i] );
+ sum -= PcPcOnSq( sq_wk, list1[index_w], list1[i] );
+ }
+
+ for( i += 1; i < 14; i++ )
+ {
+ sum += PcPcOnSq( sq_bk, list0[i], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[i], list1[index_w] );
+ }
+
+ if ( turn )
+ {
+ sum += PcPcOnSq( sq_bk, list0[index_w], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[index_w], list1[index_w] );
+ sq_bk = SQ_BKING;
+ sq_wk = SQ_WKING;
+ sum += kkp[sq_bk][sq_wk][ aikkp_hand[pc] + hand_index ];
+ }
+ else {
+ sum += PcPcOnSq( sq_bk, list0[index_b], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[index_b], list1[index_w] );
+ sq_bk = Inv(SQ_WKING);
+ sq_wk = Inv(SQ_BKING);
+ sum -= kkp[sq_bk][sq_wk][ aikkp_hand[pc] + hand_index ];
+ }
+
+ return sum;
+}
+
+
+#if defined(INANIWA_SHIFT)
+static int
+inaniwa_score( const tree_t * restrict ptree )
+{
+ int score;
+
+ if ( ! inaniwa_flag ) { return 0; }
+
+ score = 0;
+ if ( inaniwa_flag == 2 ) {
+
+ if ( BOARD[B9] == -knight ) { score += 700 * FV_SCALE; }
+ if ( BOARD[H9] == -knight ) { score += 700 * FV_SCALE; }
+
+ if ( BOARD[A7] == -knight ) { score += 700 * FV_SCALE; }
+ if ( BOARD[C7] == -knight ) { score += 400 * FV_SCALE; }
+ if ( BOARD[G7] == -knight ) { score += 400 * FV_SCALE; }
+ if ( BOARD[I7] == -knight ) { score += 700 * FV_SCALE; }
+
+ if ( BOARD[B5] == -knight ) { score += 700 * FV_SCALE; }
+ if ( BOARD[D5] == -knight ) { score += 100 * FV_SCALE; }
+ if ( BOARD[F5] == -knight ) { score += 100 * FV_SCALE; }
+ if ( BOARD[H5] == -knight ) { score += 700 * FV_SCALE; }
+
+ if ( BOARD[E3] == pawn ) { score += 200 * FV_SCALE; }
+ if ( BOARD[E4] == pawn ) { score += 200 * FV_SCALE; }
+ if ( BOARD[E5] == pawn ) { score += 200 * FV_SCALE; }
+
+ } else {
+
+ if ( BOARD[B1] == knight ) { score -= 700 * FV_SCALE; }
+ if ( BOARD[H1] == knight ) { score -= 700 * FV_SCALE; }
+
+ if ( BOARD[A3] == knight ) { score -= 700 * FV_SCALE; }
+ if ( BOARD[C3] == knight ) { score -= 400 * FV_SCALE; }
+ if ( BOARD[G3] == knight ) { score -= 400 * FV_SCALE; }
+ if ( BOARD[I3] == knight ) { score -= 700 * FV_SCALE; }
+
+ if ( BOARD[B5] == knight ) { score -= 700 * FV_SCALE; }
+ if ( BOARD[D5] == knight ) { score -= 100 * FV_SCALE; }
+ if ( BOARD[F5] == knight ) { score -= 100 * FV_SCALE; }
+ if ( BOARD[H5] == knight ) { score -= 700 * FV_SCALE; }
+
+ if ( BOARD[E7] == -pawn ) { score -= 200 * FV_SCALE; }
+ if ( BOARD[E6] == -pawn ) { score -= 200 * FV_SCALE; }
+ if ( BOARD[E5] == -pawn ) { score -= 200 * FV_SCALE; }
+ }
+
+ return score;
+}
+#endif
#include "shogi.h"
-unsigned int *
+unsigned int * CONV
b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove )
{
bitboard_t bb_movable, bb_capture, bb_piece, bb_desti;
}
bb_piece = BB_BSILVER;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
BBAnd( bb_desti, bb_capture, abb_b_silver_attacks[ifrom] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_BTGOLD;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
BBAnd( bb_desti, bb_capture, abb_b_gold_attacks[ifrom] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
ifrom = SQ_BKING;
BBAnd( bb_desti, bb_capture, abb_king_attacks[ifrom] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_BBISHOP;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[2] &= bb_capture.p[2];
}
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_BROOK;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[2] &= bb_capture.p[2];
}
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_BHORSE;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
AttackHorse( bb_desti, ifrom );
BBAnd( bb_desti, bb_desti, bb_capture );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_BDRAGON;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
AttackDragon( bb_desti, ifrom );
BBAnd( bb_desti, bb_desti, bb_capture );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_BLANCE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[1] &= bb_capture.p[1];
bb_desti.p[2] &= bb_capture.p[2];
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_BKNIGHT;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
ifrom = LastOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[1] &= bb_capture.p[1];
bb_desti.p[2] &= bb_capture.p[2];
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = LastOne( bb_desti );
Xor( ito, bb_desti );
}
-unsigned int *
+unsigned int * CONV
w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove )
{
bitboard_t bb_movable, bb_capture, bb_piece, bb_desti;
}
bb_piece = BB_WSILVER;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
BBAnd( bb_desti, bb_capture, abb_w_silver_attacks[ifrom] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_WTGOLD;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
BBAnd( bb_desti, bb_capture, abb_w_gold_attacks[ifrom] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
ifrom = SQ_WKING;
BBAnd( bb_desti, bb_capture, abb_king_attacks[ifrom] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_WBISHOP;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[0] &= bb_capture.p[0];
}
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_WROOK;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[0] &= bb_capture.p[0];
}
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_WHORSE;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
AttackHorse( bb_desti, ifrom );
BBAnd( bb_desti, bb_desti, bb_capture );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_WDRAGON;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
AttackDragon( bb_desti, ifrom );
BBAnd( bb_desti, bb_desti, bb_capture );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_WLANCE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[1] &= bb_capture.p[1];
bb_desti.p[0] &= bb_capture.p[0];
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
}
bb_piece = BB_WKNIGHT;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
ifrom = FirstOne( bb_piece );
Xor( ifrom, bb_piece );
bb_desti.p[1] &= bb_capture.p[1];
bb_desti.p[0] &= bb_capture.p[0];
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
ito = FirstOne( bb_desti );
Xor( ito, bb_desti );
-#include <assert.h>\r
-#include "shogi.h"\r
-\r
-\r
-static bitboard_t add_behind_attacks( int idirec, int ik, bitboard_t bb );\r
-\r
-\r
-unsigned int *\r
-b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
-{\r
- bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
- bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
- const tree_t * restrict ptree = __ptree__;\r
- unsigned int u0, u1, u2;\r
- int from, to, sq_wk, idirec;\r
-\r
- sq_wk = SQ_WKING;\r
- bb_rook_chk = bb_file_chk = AttackFile( sq_wk );\r
- bb_rook_chk.p[aslide[sq_wk].ir0] |= AttackRank( sq_wk );\r
- bb_diag1_chk = AttackDiag1( sq_wk );\r
- bb_diag2_chk = AttackDiag2( sq_wk );\r
- BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );\r
- BBNot( bb_move_to, BB_BOCCUPY );\r
- BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
- BBNot( bb_drop_to, bb_drop_to );\r
-\r
- from = SQ_BKING;\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBIni( bb_chk );\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_BDRAGON;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- AttackDragon( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- bb_piece = BB_BHORSE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- AttackHorse( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- u1 = BB_BROOK.p[1];\r
- u2 = BB_BROOK.p[2];\r
- while( u1 | u2 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u1 ^= abb_mask[from].p[1];\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_rook_chk;\r
- bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[1] | bb_chk.p[2] )\r
- {\r
- to = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- u0 = BB_BROOK.p[0];\r
- while( u0 )\r
- {\r
- from = last_one0( u0 );\r
- u0 ^= abb_mask[from].p[0];\r
- \r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
- u1 = BB_BBISHOP.p[1];\r
- u2 = BB_BBISHOP.p[2];\r
- while( u1 | u2 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u1 ^= abb_mask[from].p[1];\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_bishop_chk;\r
- bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[1] | bb_chk.p[2] )\r
- {\r
- to = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- u0 = BB_BBISHOP.p[0];\r
- while( u0 )\r
- {\r
- from = last_one0( u0 );\r
- u0 ^= abb_mask[from].p[0];\r
- \r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_BTGOLD;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_w_gold_attacks[sq_wk];\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = ( To2Move(to) | From2Move(from)\r
- | Piece2Move(BOARD[from])\r
- | Cap2Move(-BOARD[to]) );\r
- }\r
- }\r
- \r
-\r
- u0 = BB_BSILVER.p[0];\r
- while( u0 )\r
- {\r
- from = last_one0( u0 );\r
- u0 ^= abb_mask[from].p[0];\r
-\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];\r
- bb_chk.p[2] = 0;\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
- bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];\r
-\r
- while( bb_chk.p[0] | bb_chk.p[1] )\r
- {\r
- to = last_one01( bb_chk.p[0], bb_chk.p[1] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u1 = BB_BSILVER.p[1] & 0x7fc0000U;\r
- while( u1 )\r
- {\r
- from = last_one1( u1 );\r
- u1 ^= abb_mask[from].p[1];\r
- \r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = bb_chk.p[2] = 0;\r
- \r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
- while ( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- bb_piece = BB_BSILVER;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_w_silver_attacks[sq_wk];\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
- \r
-\r
- u0 = BB_BKNIGHT.p[0];\r
- u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;\r
- while( u0 | u1 )\r
- {\r
- from = last_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = bb_chk.p[2] = 0;\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];\r
-\r
- while( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u2 = BB_BKNIGHT.p[2];\r
- u1 = BB_BKNIGHT.p[1] & 0x3ffffU;\r
- while( u2 | u1 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk = abb_w_knight_attacks[sq_wk];\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_BLANCE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = bb_chk.p[2] = 0;\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u1 = BB_BLANCE.p[1];\r
- u2 = BB_BLANCE.p[2];\r
- while( u1| u2 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u1 ^= abb_mask[from].p[1];\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- bb_chk = bb_file_chk;\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
- }\r
- else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from - nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag1( from );\r
- if ( BBContract( bb_desti, BB_B_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
- if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from - nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag2( from );\r
- if ( BBContract( bb_desti, BB_B_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
- if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBIni( bb_chk );\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );\r
- while ( BBToU(bb_chk) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
-\r
- from = to + nfile;\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
- if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
-\r
-\r
- if ( IsHandGold(HAND_B) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(gold);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandSilver(HAND_B) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(silver);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandKnight(HAND_B) && sq_wk < A2 )\r
- {\r
- to = sq_wk + 2*nfile - 1;\r
- if ( aifile[sq_wk] != file1 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
-\r
- to = sq_wk + 2*nfile + 1;\r
- if ( aifile[sq_wk] != file9 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandPawn(HAND_B)\r
- && sq_wk < A1\r
- && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )\r
- {\r
- to = sq_wk + nfile;\r
- if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(pawn);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandLance(HAND_B) )\r
- {\r
- unsigned int move;\r
- int dist, min_dist;\r
-\r
- if ( (int)aifile[sq_wk] == file1\r
- || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
- to += nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(lance);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandRook(HAND_B) )\r
- {\r
- unsigned int move;\r
- int file, dist, min_dist;\r
-\r
- if ( (int)aifile[sq_wk] == file1\r
- || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
- to += nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;\r
- file >= file1 && BOARD[to] == empty;\r
- file -= 1, to -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;\r
- file <= file9 && BOARD[to] == empty;\r
- file += 1, to += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
- to -= nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandBishop(HAND_B) )\r
- {\r
- unsigned int move;\r
- int file, rank, dist;\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
- file >= 0 && rank >= 0 && BOARD[to] == empty;\r
- to -= 10, file -= 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
- file <= file9 && rank >= 0 && BOARD[to] == empty;\r
- to -= 8, file += 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to += 8, file -= 1, rank += 1, dist = 1;\r
- file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
- to += 8, file -= 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to += 10, file += 1, rank += 1, dist = 1;\r
- file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
- to += 10, file += 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- return pmove;\r
-}\r
-\r
-\r
-unsigned int *\r
-w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
-{\r
- bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
- bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
- const tree_t * restrict ptree = __ptree__;\r
- unsigned int u0, u1, u2;\r
- int from, to, sq_bk, idirec;\r
-\r
- sq_bk = SQ_BKING;\r
- bb_rook_chk = bb_file_chk = AttackFile( sq_bk );\r
- bb_rook_chk.p[aslide[sq_bk].ir0] |= AttackRank( sq_bk );\r
- bb_diag1_chk = AttackDiag1( sq_bk );\r
- bb_diag2_chk = AttackDiag2( sq_bk );\r
- AttackBishop( bb_bishop_chk, sq_bk );\r
- BBNot( bb_move_to, BB_WOCCUPY );\r
- BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
- BBNot( bb_drop_to, bb_drop_to );\r
-\r
-\r
- from = SQ_WKING;\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBIni( bb_chk );\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WDRAGON;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- AttackDragon( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WHORSE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- AttackHorse( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- u0 = BB_WROOK.p[0];\r
- u1 = BB_WROOK.p[1];\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_rook_chk;\r
- bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[0] | bb_chk.p[1] )\r
- {\r
- to = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- u2 = BB_WROOK.p[2];\r
- while( u2 )\r
- {\r
- from = first_one2( u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- \r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
- u0 = BB_WBISHOP.p[0];\r
- u1 = BB_WBISHOP.p[1];\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_bishop_chk;\r
- bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[0] | bb_chk.p[1] )\r
- {\r
- to = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- u2 = BB_WBISHOP.p[2];\r
- while( u2 )\r
- {\r
- from = first_one2( u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- \r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WTGOLD;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_b_gold_attacks[sq_bk];\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = ( To2Move(to) | From2Move(from)\r
- | Piece2Move(-BOARD[from])\r
- | Cap2Move(BOARD[to]) );\r
- }\r
- }\r
-\r
- \r
- u2 = BB_WSILVER.p[2];\r
- while( u2 )\r
- {\r
- from = first_one2( u2 );\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];\r
- bb_chk.p[0] = 0;\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
- bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];\r
-\r
- while( bb_chk.p[2] | bb_chk.p[1] )\r
- {\r
- to = first_one12( bb_chk.p[1], bb_chk.p[2] );\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u1 = BB_WSILVER.p[1] & 0x1ffU;\r
- while( u1 )\r
- {\r
- from = first_one1( u1 );\r
- u1 ^= abb_mask[from].p[1];\r
- \r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = bb_chk.p[0] = 0;\r
- \r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
- while ( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- bb_piece = BB_WSILVER;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_b_silver_attacks[sq_bk];\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- \r
- u2 = BB_WKNIGHT.p[2];\r
- u1 = BB_WKNIGHT.p[1] & 0x3ffffU;\r
- while( u2 | u1 )\r
- {\r
- from = first_one12( u1, u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = bb_chk.p[0] = 0;\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];\r
-\r
- while( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u0 = BB_WKNIGHT.p[0];\r
- u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk = abb_b_knight_attacks[sq_bk];\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WLANCE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = bb_chk.p[0] = 0;\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u0 = BB_WLANCE.p[0];\r
- u1 = BB_WLANCE.p[1];\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk = bb_file_chk;\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
- }\r
- else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from + nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag1( from );\r
- if ( BBContract( bb_desti, BB_W_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
- if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from + nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag2( from );\r
- if ( BBContract( bb_desti, BB_W_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
- if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBIni( bb_chk );\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );\r
- while ( BBToU(bb_chk) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
-\r
- from = to - nfile;\r
- *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)\r
- | Cap2Move(BOARD[to]);\r
- if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
-\r
-\r
- if ( IsHandGold(HAND_W) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(gold);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandSilver(HAND_W) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(silver);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandKnight(HAND_W) && sq_bk > I8 )\r
- {\r
- to = sq_bk - 2*nfile - 1;\r
- if ( aifile[sq_bk] != file1 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
-\r
- to = sq_bk - 2*nfile + 1;\r
- if ( aifile[sq_bk] != file9 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandPawn(HAND_W)\r
- && sq_bk > I9\r
- && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )\r
- {\r
- to = sq_bk - nfile;\r
- if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(pawn);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandLance(HAND_W) )\r
- {\r
- unsigned int move;\r
- int dist, min_dist;\r
-\r
- if ( (int)aifile[sq_bk] == file1\r
- || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
- to -= nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(lance);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandRook(HAND_W) )\r
- {\r
- unsigned int move;\r
- int file, dist, min_dist;\r
-\r
- if ( (int)aifile[sq_bk] == file1\r
- || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
- to -= nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
- to += nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
-\r
- if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;\r
- file <= file9 && BOARD[to] == empty;\r
- file += 1, to += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;\r
- file >= file1 && BOARD[to] == empty;\r
- file -= 1, to -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandBishop(HAND_W) )\r
- {\r
- unsigned int move;\r
- int file, rank, dist;\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to += 10, file += 1, rank += 1, dist = 1;\r
- file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
- to += 10, file += 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to += 8, file -= 1, rank += 1, dist = 1;\r
- file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
- to += 8, file -= 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
- file <= file9 && rank >= 0 && BOARD[to] == empty;\r
- to -= 8, file += 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
- file >= 0 && rank >= 0 && BOARD[to] == empty;\r
- to -= 10, file -= 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- return pmove;\r
-}\r
-\r
-\r
-static bitboard_t\r
-add_behind_attacks( int idirec, int ik, bitboard_t bb )\r
-{\r
- bitboard_t bb_tmp;\r
-\r
- if ( idirec == direc_diag1 )\r
- {\r
- bb_tmp = abb_bishop_attacks_rr45[ik][0];\r
- }\r
- else if ( idirec == direc_diag2 )\r
- {\r
- bb_tmp = abb_bishop_attacks_rl45[ik][0];\r
- }\r
- else if ( idirec == direc_file )\r
- {\r
- bb_tmp = abb_file_attacks[ik][0];\r
- }\r
- else {\r
- assert( idirec == direc_rank );\r
- BBIni( bb_tmp );\r
- bb_tmp.p[aslide[ik].ir0] = ai_rook_attacks_r0[ik][0];\r
- }\r
- BBNot( bb_tmp, bb_tmp );\r
- BBOr( bb, bb, bb_tmp );\r
-\r
- return bb;\r
-}\r
+#include <assert.h>
+#include "shogi.h"
+
+
+static void CONV add_behind_attacks( bitboard_t * restrict pbb, int idirec,
+ int ik );
+
+unsigned int * CONV
+b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_wk, idirec;
+
+ sq_wk = SQ_WKING;
+ bb_file_chk = AttackFile( sq_wk );
+ bb_rank_chk = AttackRank( sq_wk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_wk );
+ bb_diag2_chk = AttackDiag2( sq_wk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_BOCCUPY );
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+ from = SQ_BKING;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_BDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ bb_piece = BB_BHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ u1 = BB_BROOK.p[1];
+ u2 = BB_BROOK.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[1] | bb_chk.p[2] )
+ {
+ to = last_one12( bb_chk.p[1], bb_chk.p[2] );
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ u0 = BB_BROOK.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+ u1 = BB_BBISHOP.p[1];
+ u2 = BB_BBISHOP.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[1] | bb_chk.p[2] )
+ {
+ to = last_one12( bb_chk.p[1], bb_chk.p[2] );
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ u0 = BB_BBISHOP.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_BTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_gold_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = ( To2Move(to) | From2Move(from)
+ | Piece2Move(BOARD[from])
+ | Cap2Move(-BOARD[to]) );
+ }
+ }
+
+
+ u0 = BB_BSILVER.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
+ bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
+
+ while( bb_chk.p[0] | bb_chk.p[1] )
+ {
+ to = last_one01( bb_chk.p[0], bb_chk.p[1] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u1 = BB_BSILVER.p[1] & 0x7fc0000U;
+ while( u1 )
+ {
+ from = last_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+ while ( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_BSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_silver_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+
+ u0 = BB_BKNIGHT.p[0];
+ u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = last_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
+
+ while( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u2 = BB_BKNIGHT.p[2];
+ u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = last_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_w_knight_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_BLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u1 = BB_BLANCE.p[1];
+ u2 = BB_BLANCE.p[2];
+ while( u1| u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); }
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+ if ( BBContract( bb_desti, BB_B_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+ if ( BBContract( bb_desti, BB_B_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_B_RD ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ while ( BBTest(bb_chk) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+
+ from = to + nfile;
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+
+
+ if ( IsHandGold(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(gold);
+ }
+ }
+
+
+ if ( IsHandSilver(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(silver);
+ }
+ }
+
+
+ if ( IsHandKnight(HAND_B) && sq_wk < A2 )
+ {
+ to = sq_wk + 2*nfile - 1;
+ if ( aifile[sq_wk] != file1 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+
+ to = sq_wk + 2*nfile + 1;
+ if ( aifile[sq_wk] != file9 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+ }
+
+
+ if ( IsHandPawn(HAND_B)
+ && sq_wk < A1
+ && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )
+ {
+ to = sq_wk + nfile;
+ if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(pawn);
+ }
+ }
+
+
+ if ( IsHandLance(HAND_B) )
+ {
+ unsigned int move;
+ int dist, min_dist;
+
+ if ( (int)aifile[sq_wk] == file1
+ || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+ to += nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(lance);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandRook(HAND_B) )
+ {
+ unsigned int move;
+ int file, dist, min_dist;
+
+ if ( (int)aifile[sq_wk] == file1
+ || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+ to += nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;
+ file >= file1 && BOARD[to] == empty;
+ file -= 1, to -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;
+ file <= file9 && BOARD[to] == empty;
+ file += 1, to += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+ to -= nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandBishop(HAND_B) )
+ {
+ unsigned int move;
+ int file, rank, dist;
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to -= 10, file -= 1, rank -= 1, dist = 1;
+ file >= 0 && rank >= 0 && BOARD[to] == empty;
+ to -= 10, file -= 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to -= 8, file += 1, rank -= 1, dist = 1;
+ file <= file9 && rank >= 0 && BOARD[to] == empty;
+ to -= 8, file += 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to += 8, file -= 1, rank += 1, dist = 1;
+ file >= 0 && rank <= rank9 && BOARD[to] == empty;
+ to += 8, file -= 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to += 10, file += 1, rank += 1, dist = 1;
+ file <= file9 && rank <= rank9 && BOARD[to] == empty;
+ to += 10, file += 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ return pmove;
+}
+
+
+unsigned int * CONV
+w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_bk, idirec;
+
+ sq_bk = SQ_BKING;
+ bb_file_chk = AttackFile( sq_bk );
+ bb_rank_chk = AttackRank( sq_bk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_bk );
+ bb_diag2_chk = AttackDiag2( sq_bk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_WOCCUPY );
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+
+ from = SQ_WKING;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_WDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_WHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ u0 = BB_WROOK.p[0];
+ u1 = BB_WROOK.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[0] | bb_chk.p[1] )
+ {
+ to = first_one01( bb_chk.p[0], bb_chk.p[1] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ u2 = BB_WROOK.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+ u0 = BB_WBISHOP.p[0];
+ u1 = BB_WBISHOP.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[0] | bb_chk.p[1] )
+ {
+ to = first_one01( bb_chk.p[0], bb_chk.p[1] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ u2 = BB_WBISHOP.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_WTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_gold_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = ( To2Move(to) | From2Move(from)
+ | Piece2Move(-BOARD[from])
+ | Cap2Move(BOARD[to]) );
+ }
+ }
+
+
+ u2 = BB_WSILVER.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
+ bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
+
+ while( bb_chk.p[2] | bb_chk.p[1] )
+ {
+ to = first_one12( bb_chk.p[1], bb_chk.p[2] );
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u1 = BB_WSILVER.p[1] & 0x1ffU;
+ while( u1 )
+ {
+ from = first_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+ while ( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_WSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_silver_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ u2 = BB_WKNIGHT.p[2];
+ u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = first_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
+
+ while( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u0 = BB_WKNIGHT.p[0];
+ u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_b_knight_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_WLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u0 = BB_WLANCE.p[0];
+ u1 = BB_WLANCE.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); }
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+ if ( BBContract( bb_desti, BB_W_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+ if ( BBContract( bb_desti, BB_W_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_W_RD ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ while ( BBTest(bb_chk) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+
+ from = to - nfile;
+ *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)
+ | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+
+
+ if ( IsHandGold(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(gold);
+ }
+ }
+
+
+ if ( IsHandSilver(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(silver);
+ }
+ }
+
+
+ if ( IsHandKnight(HAND_W) && sq_bk > I8 )
+ {
+ to = sq_bk - 2*nfile - 1;
+ if ( aifile[sq_bk] != file1 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+
+ to = sq_bk - 2*nfile + 1;
+ if ( aifile[sq_bk] != file9 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+ }
+
+
+ if ( IsHandPawn(HAND_W)
+ && sq_bk > I9
+ && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )
+ {
+ to = sq_bk - nfile;
+ if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(pawn);
+ }
+ }
+
+
+ if ( IsHandLance(HAND_W) )
+ {
+ unsigned int move;
+ int dist, min_dist;
+
+ if ( (int)aifile[sq_bk] == file1
+ || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+ to -= nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(lance);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandRook(HAND_W) )
+ {
+ unsigned int move;
+ int file, dist, min_dist;
+
+ if ( (int)aifile[sq_bk] == file1
+ || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+ to -= nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+ to += nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+
+ if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;
+ file <= file9 && BOARD[to] == empty;
+ file += 1, to += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;
+ file >= file1 && BOARD[to] == empty;
+ file -= 1, to -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandBishop(HAND_W) )
+ {
+ unsigned int move;
+ int file, rank, dist;
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to += 10, file += 1, rank += 1, dist = 1;
+ file <= file9 && rank <= rank9 && BOARD[to] == empty;
+ to += 10, file += 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to += 8, file -= 1, rank += 1, dist = 1;
+ file >= 0 && rank <= rank9 && BOARD[to] == empty;
+ to += 8, file -= 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to -= 8, file += 1, rank -= 1, dist = 1;
+ file <= file9 && rank >= 0 && BOARD[to] == empty;
+ to -= 8, file += 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to -= 10, file -= 1, rank -= 1, dist = 1;
+ file >= 0 && rank >= 0 && BOARD[to] == empty;
+ to -= 10, file -= 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ return pmove;
+}
+
+
+int CONV b_have_checks( tree_t * restrict __ptree__ )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_wk, idirec;
+
+ sq_wk = SQ_WKING;
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+ if ( IsHandGold(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandSilver(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandKnight(HAND_B) && sq_wk < A2 )
+ {
+ if ( aifile[sq_wk] != file1
+ && BOARD[sq_wk + 2*nfile - 1] == empty ) { return 1; }
+
+ if ( aifile[sq_wk] != file9
+ && BOARD[sq_wk + 2*nfile + 1] == empty ) { return 1; }
+ }
+
+ if ( IsHandLance(HAND_B)
+ && sq_wk + nfile < nsquare
+ && BOARD[sq_wk + nfile] == empty ) { return 1; }
+
+ if ( IsHandRook(HAND_B) )
+ {
+ if ( sq_wk + nfile < nsquare
+ && BOARD[sq_wk + nfile] == empty ) { return 1; }
+
+ if ( file1 < (int)aifile[sq_wk]
+ && BOARD[sq_wk - 1] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_wk] < file9
+ && BOARD[sq_wk + 1] == empty ) { return 1; }
+
+ if ( 0 <= sq_wk - nfile
+ && BOARD[sq_wk - nfile] == empty ) { return 1; }
+ }
+
+ if ( IsHandBishop(HAND_B) )
+ {
+ if ( 0 < (int)aifile[sq_wk]
+ && 0 < (int)airank[sq_wk]
+ && BOARD[sq_wk - 10] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_wk] < file9
+ && 0 < (int)airank[sq_wk]
+ && BOARD[sq_wk - 8] == empty ) { return 1; }
+
+ if ( 0 < (int)aifile[sq_wk]
+ && (int)airank[sq_wk] < rank9
+ && BOARD[sq_wk + 8] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_wk] < file9
+ && (int)airank[sq_wk] < rank9
+ && BOARD[sq_wk + 10] == empty ) { return 1; }
+ }
+
+ if ( IsHandPawn(HAND_B)
+ && sq_wk < A1
+ && BOARD[sq_wk+nfile] == empty
+ && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) )
+ && ! is_mate_b_pawn_drop( __ptree__, sq_wk+nfile ) )
+ {
+ return 1;
+ }
+
+
+ bb_file_chk = AttackFile( sq_wk );
+ bb_rank_chk = AttackRank( sq_wk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_wk );
+ bb_diag2_chk = AttackDiag2( sq_wk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_BOCCUPY );
+
+ from = SQ_BKING;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_BDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ bb_piece = BB_BHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u1 = BB_BROOK.p[1];
+ u2 = BB_BROOK.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_BROOK.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u1 = BB_BBISHOP.p[1];
+ u2 = BB_BBISHOP.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_BBISHOP.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_BTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_gold_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u0 = BB_BSILVER.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
+ bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
+
+ if ( bb_chk.p[0] | bb_chk.p[1] ) { return 1; }
+ }
+
+
+ u1 = BB_BSILVER.p[1] & 0x7fc0000U;
+ while( u1 )
+ {
+ from = last_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+
+ if ( bb_chk.p[0] ) { return 1; }
+ }
+
+
+ bb_piece = BB_BSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_silver_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u0 = BB_BKNIGHT.p[0];
+ u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = last_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
+
+ if ( bb_chk.p[0] ) { return 1; }
+ }
+
+
+ u2 = BB_BKNIGHT.p[2];
+ u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = last_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_w_knight_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_BLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u1 = BB_BLANCE.p[1];
+ u2 = BB_BLANCE.p[2];
+ while( u1| u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
+ if ( BBTest(bb_chk) ) { return 1; }
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+
+ if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+
+ if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_B_RD ) ) { return 1; }
+ }
+
+ return 0;
+}
+
+
+int CONV w_have_checks( tree_t * restrict __ptree__ )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_bk, idirec;
+
+ sq_bk = SQ_BKING;
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+ if ( IsHandGold(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandSilver(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandKnight(HAND_W) && sq_bk > I8 )
+ {
+ if ( aifile[sq_bk] != file1
+ && BOARD[sq_bk - 2*nfile - 1] == empty ) { return 1; }
+
+ if ( aifile[sq_bk] != file9
+ && BOARD[sq_bk - 2*nfile + 1] == empty ) { return 1; }
+ }
+
+ if ( IsHandLance(HAND_W)
+ && 0 <= sq_bk - nfile
+ && BOARD[sq_bk - nfile] == empty ) { return 1; }
+
+ if ( IsHandRook(HAND_W) )
+ {
+ if ( sq_bk + nfile < nsquare
+ && BOARD[sq_bk + nfile] == empty ) { return 1; }
+
+ if ( file1 < (int)aifile[sq_bk]
+ && BOARD[sq_bk - 1] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_bk] < file9
+ && BOARD[sq_bk + 1] == empty ) { return 1; }
+
+ if ( 0 <= sq_bk - nfile
+ && BOARD[sq_bk - nfile] == empty ) { return 1; }
+ }
+
+ if ( IsHandBishop(HAND_W) )
+ {
+ if ( 0 < (int)aifile[sq_bk]
+ && 0 < (int)airank[sq_bk]
+ && BOARD[sq_bk - 10] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_bk] < file9
+ && 0 < (int)airank[sq_bk]
+ && BOARD[sq_bk - 8] == empty ) { return 1; }
+
+ if ( 0 < (int)aifile[sq_bk]
+ && (int)airank[sq_bk] < rank9
+ && BOARD[sq_bk + 8] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_bk] < file9
+ && (int)airank[sq_bk] < rank9
+ && BOARD[sq_bk + 10] == empty ) { return 1; }
+ }
+
+ if ( IsHandPawn(HAND_W)
+ && sq_bk > I9
+ && BOARD[sq_bk - nfile] == empty
+ && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) )
+ && ! is_mate_w_pawn_drop( __ptree__, sq_bk - nfile ) )
+ {
+ return 1;
+ }
+
+
+ bb_file_chk = AttackFile( sq_bk );
+ bb_rank_chk = AttackRank( sq_bk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_bk );
+ bb_diag2_chk = AttackDiag2( sq_bk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_WOCCUPY );
+
+
+ from = SQ_WKING;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_WROOK.p[0];
+ u1 = BB_WROOK.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u2 = BB_WROOK.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_WBISHOP.p[0];
+ u1 = BB_WBISHOP.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u2 = BB_WBISHOP.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_gold_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u2 = BB_WSILVER.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
+ bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
+
+ if ( bb_chk.p[2] | bb_chk.p[1] ) { return 1; }
+ }
+
+
+ u1 = BB_WSILVER.p[1] & 0x1ffU;
+ while( u1 )
+ {
+ from = first_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+
+ if ( bb_chk.p[2] ) { return 1; }
+ }
+
+
+ bb_piece = BB_WSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_silver_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u2 = BB_WKNIGHT.p[2];
+ u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = first_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
+
+ if ( bb_chk.p[2] ) { return 1; }
+ }
+
+
+ u0 = BB_WKNIGHT.p[0];
+ u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_b_knight_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u0 = BB_WLANCE.p[0];
+ u1 = BB_WLANCE.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
+ if ( BBTest( bb_chk ) ) { return 1; }
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+
+ if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+
+ if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_W_RD ) ) { return 1; }
+ }
+
+ return 0;
+}
+
+
+static void CONV
+add_behind_attacks( bitboard_t * restrict pbb, int idirec, int ik )
+{
+ bitboard_t bb_tmp;
+
+ if ( idirec == direc_diag1 )
+ {
+ bb_tmp = abb_bishop_attacks_rr45[ik][0];
+ }
+ else if ( idirec == direc_diag2 )
+ {
+ bb_tmp = abb_bishop_attacks_rl45[ik][0];
+ }
+ else if ( idirec == direc_file )
+ {
+ bb_tmp = abb_file_attacks[ik][0];
+ }
+ else {
+ assert( idirec == direc_rank );
+ bb_tmp = abb_rank_attacks[ik][0];
+ }
+ BBNot( bb_tmp, bb_tmp );
+ BBOr( *pbb, *pbb, bb_tmp );
+}
#include "shogi.h"
-unsigned int *
+unsigned int * CONV
b_gen_drop( tree_t * restrict __ptree__, unsigned int * restrict pmove )
{
const tree_t * restrict ptree = __ptree__;
if ( IsHandPawn( ihand ) )
{
- ibb_pawn_cmp= BB_BPAWN_ATK.p[0] | BB_BPAWN_ATK.p[1] | BB_BPAWN_ATK.p[2];
+ ibb_pawn_cmp= BBToU( BB_BPAWN_ATK );
ais_pawn[0] = ibb_pawn_cmp & ( mask_file1 >> 0 );
ais_pawn[1] = ibb_pawn_cmp & ( mask_file1 >> 1 );
ais_pawn[2] = ibb_pawn_cmp & ( mask_file1 >> 2 );
}
-unsigned int *
+unsigned int * CONV
w_gen_drop( tree_t * restrict __ptree__, unsigned int * restrict pmove )
{
const tree_t * restrict ptree = __ptree__;
if ( IsHandPawn( ihand ) )
{
- ibb_pawn_cmp= BB_WPAWN_ATK.p[0] | BB_WPAWN_ATK.p[1] | BB_WPAWN_ATK.p[2];
+ ibb_pawn_cmp= BBToU( BB_WPAWN_ATK );
ais_pawn[0] = ibb_pawn_cmp & ( mask_file1 >> 0 );
ais_pawn[1] = ibb_pawn_cmp & ( mask_file1 >> 1 );
ais_pawn[2] = ibb_pawn_cmp & ( mask_file1 >> 2 );
#include "shogi.h"
-unsigned int *
+unsigned int * CONV
b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove )
{
bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
XorDiag2( sq_bk, OCCUPIED_DIAG2 );
XorDiag1( sq_bk, OCCUPIED_DIAG1 );
- BBNot( bb_desti, BB_BOCCUPY );
- BBAnd( bb_desti, bb_desti, abb_king_attacks[sq_bk] );
+ BBNotAnd( bb_desti, abb_king_attacks[sq_bk], BB_BOCCUPY );
utemp = From2Move(sq_bk) | Piece2Move(king);
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
if ( ! is_black_attacked( ptree, to ) )
XorDiag2( sq_bk, OCCUPIED_DIAG2 );
XorDiag1( sq_bk, OCCUPIED_DIAG1 );
- bb_checker = attacks_to_piece( ptree, sq_bk );
- BBAnd( bb_checker, bb_checker, BB_WOCCUPY );
+ bb_checker = w_attacks_to_piece( ptree, sq_bk );
nchecker = PopuCount( bb_checker );
if ( nchecker == 2 ) { return pmove; }
BBOr( bb_target, bb_inter, bb_checker );
BBAnd( bb_desti, bb_target, BB_BPAWN_ATK );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_BLANCE;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
bb_desti = AttackFile( from );
BBAnd( bb_desti, bb_desti, abb_minus_rays[from] );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
}
bb_piece = BB_BKNIGHT;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_target, abb_b_knight_attacks[from] );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
if ( to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
if ( to >= A7 ) { *pmove++ = utemp; }
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_BSILVER;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_target, abb_b_silver_attacks[from] );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
| Cap2Move(-BOARD[to]) );
if ( from < A6 || to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
*pmove++ = utemp;
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_BTGOLD;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_target, abb_b_gold_attacks[from] );
- if ( ! BBToU(bb_desti) ) { continue; }
+ if ( ! BBTest(bb_desti) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
*pmove++ = ( To2Move(to) | From2Move(from)
| Piece2Move(BOARD[from])
| Cap2Move(-BOARD[to]) );
- } while( BBToU( bb_desti ) );
+ } while( BBTest( bb_desti ) );
}
bb_piece = BB_BBISHOP;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
AttackBishop( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
do {
| Cap2Move(-BOARD[to]) );
if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
*pmove++ = utemp;
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_BROOK;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
AttackRook( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
do {
| Cap2Move(-BOARD[to]) );
if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
*pmove++ = utemp;
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_BHORSE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
AttackHorse( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU(bb_desti) ) { continue; }
+ if ( ! BBTest(bb_desti) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
Xor( to, bb_desti);
*pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
| Cap2Move(-BOARD[to]) );
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_BDRAGON;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
AttackDragon( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU(bb_desti) ) { continue; }
+ if ( ! BBTest(bb_desti) ) { continue; }
idirec = (int)adirec[sq_bk][from];
if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
Xor( to, bb_desti );
*pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
| Cap2Move(-BOARD[to]) );
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
if ( ! HAND_B ) { return pmove; }
- if ( ! BBToU(bb_inter) ) { return pmove; }
+ if ( ! BBTest(bb_inter) ) { return pmove; }
/* drops */
bb_target = bb_inter;
ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
- while ( BBToU( bb_target ) )
+ while ( BBTest( bb_target ) )
{
to = LastOne( bb_target );
utemp = To2Move(to);
}
}
else {
- while ( BBToU( bb_target ) )
+ while ( BBTest( bb_target ) )
{
to = LastOne( bb_target );
utemp = To2Move(to);
}
-unsigned int *
+unsigned int * CONV
w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove )
{
bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
XorDiag2( sq_wk, OCCUPIED_DIAG2 );
XorDiag1( sq_wk, OCCUPIED_DIAG1 );
- BBNot( bb_desti, BB_WOCCUPY );
- BBAnd( bb_desti, bb_desti, abb_king_attacks[sq_wk] );
+ BBNotAnd( bb_desti, abb_king_attacks[sq_wk], BB_WOCCUPY );
utemp = From2Move(sq_wk) | Piece2Move(king);
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
if ( ! is_white_attacked( ptree, to ) )
XorDiag2( sq_wk, OCCUPIED_DIAG2 );
XorDiag1( sq_wk, OCCUPIED_DIAG1 );
- bb_checker = attacks_to_piece( ptree, sq_wk );
- BBAnd( bb_checker, bb_checker, BB_BOCCUPY );
+ bb_checker = b_attacks_to_piece( ptree, sq_wk );
nchecker = PopuCount( bb_checker );
if ( nchecker == 2 ) { return pmove; }
BBOr( bb_target, bb_inter, bb_checker );
BBAnd( bb_desti, bb_target, BB_WPAWN_ATK );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_WLANCE;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
bb_desti = AttackFile( from );
BBAnd( bb_desti, bb_desti, abb_plus_rays[from] );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
}
bb_piece = BB_WKNIGHT;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_target, abb_w_knight_attacks[from] );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
| Cap2Move(BOARD[to]) );
if ( to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
if ( to <= I3 ) { *pmove++ = utemp; }
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_WSILVER;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_target, abb_w_silver_attacks[from] );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
| Cap2Move(BOARD[to]) );
if ( from > I4 || to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
*pmove++ = utemp;
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_WTGOLD;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_target, abb_w_gold_attacks[from] );
- if ( ! BBToU(bb_desti) ) { continue; }
+ if ( ! BBTest(bb_desti) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
*pmove++ = ( To2Move(to) | From2Move(from)
| Piece2Move(-BOARD[from])
| Cap2Move(BOARD[to]) );
- } while( BBToU( bb_desti ) );
+ } while( BBTest( bb_desti ) );
}
bb_piece = BB_WBISHOP;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
AttackBishop( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
| Cap2Move(BOARD[to]) );
if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
*pmove++ = utemp;
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_WROOK;
- while ( BBToU( bb_piece ) )
+ while ( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
AttackRook( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU( bb_desti ) ) { continue; }
+ if ( ! BBTest( bb_desti ) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
do {
| Cap2Move(BOARD[to]) );
if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
*pmove++ = utemp;
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_WHORSE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
AttackHorse( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU(bb_desti) ) { continue; }
+ if ( ! BBTest(bb_desti) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
Xor( to, bb_desti);
*pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
| Cap2Move(BOARD[to]) );
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
bb_piece = BB_WDRAGON;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
AttackDragon( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_target );
- if ( ! BBToU(bb_desti) ) { continue; }
+ if ( ! BBTest(bb_desti) ) { continue; }
idirec = (int)adirec[sq_wk][from];
if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
Xor( to, bb_desti );
*pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
| Cap2Move(BOARD[to]) );
- } while ( BBToU( bb_desti ) );
+ } while ( BBTest( bb_desti ) );
}
if ( ! HAND_W ) { return pmove; }
- if ( ! BBToU(bb_inter) ) { return pmove; }
+ if ( ! BBTest(bb_inter) ) { return pmove; }
/* drop */
bb_target = bb_inter;
ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
- while ( BBToU( bb_target ) )
+ while ( BBTest( bb_target ) )
{
to = FirstOne( bb_target );
utemp = To2Move(to);
}
}
else {
- while ( BBToU( bb_target ) )
+ while ( BBTest( bb_target ) )
{
to = FirstOne( bb_target );
utemp = To2Move(to);
return pmove;
}
+
+
+int CONV b_have_evasion( tree_t * restrict ptree )
+{
+ bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
+ unsigned int ubb_pawn_cmp;
+ unsigned int ais_pawn[nfile];
+ int nchecker, sq_bk, to, sq_check, idirec, flag, from;
+
+ /* move the king */
+ flag = 0;
+ sq_bk = SQ_BKING;
+
+ Xor( sq_bk, BB_BOCCUPY );
+ XorFile( sq_bk, OCCUPIED_FILE );
+ XorDiag2( sq_bk, OCCUPIED_DIAG2 );
+ XorDiag1( sq_bk, OCCUPIED_DIAG1 );
+
+ BBNotAnd( bb_desti, abb_king_attacks[sq_bk], BB_BOCCUPY );
+
+ while ( BBTest( bb_desti ) )
+ {
+ to = LastOne( bb_desti );
+ Xor( to, bb_desti );
+
+ if ( ! is_black_attacked( ptree, to ) )
+ {
+ flag = 1;
+ break;
+ }
+ }
+
+ Xor( sq_bk, BB_BOCCUPY );
+ XorFile( sq_bk, OCCUPIED_FILE );
+ XorDiag2( sq_bk, OCCUPIED_DIAG2 );
+ XorDiag1( sq_bk, OCCUPIED_DIAG1 );
+
+ if ( flag ) { return 1; }
+
+
+ bb_checker = w_attacks_to_piece( ptree, sq_bk );
+ nchecker = PopuCount( bb_checker );
+ if ( nchecker == 2 ) { return 0; }
+
+ sq_check = LastOne( bb_checker );
+ bb_inter = abb_obstacle[sq_bk][sq_check];
+
+ /* move other pieces */
+ BBOr( bb_target, bb_inter, bb_checker );
+
+ BBAnd( bb_desti, bb_target, BB_BPAWN_ATK );
+ while ( BBTest( bb_desti ) )
+ {
+ to = LastOne( bb_desti );
+ Xor( to, bb_desti );
+
+ from = to + 9;
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BLANCE;
+ while ( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_desti = AttackFile( from );
+ BBAnd( bb_desti, bb_desti, abb_minus_rays[from] );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BKNIGHT;
+ while ( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBAnd( bb_desti, bb_target, abb_b_knight_attacks[from] );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BSILVER;
+ while ( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBAnd( bb_desti, bb_target, abb_b_silver_attacks[from] );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBAnd( bb_desti, bb_target, abb_b_gold_attacks[from] );
+ if ( ! BBTest(bb_desti) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BBISHOP;
+ while ( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackBishop( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BROOK;
+ while ( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackRook( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest(bb_desti) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_BDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest(bb_desti) ) { continue; }
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( ! idirec
+ || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ /* drops */
+ if ( ! BBTest(bb_inter) ) { return 0; }
+
+ if ( IsHandSGBR(HAND_B) ) { return 1; }
+
+ bb_inter.p[0] &= 0x003ffffU;
+ if ( ! BBTest(bb_inter) ) { return 0; }
+
+ if ( IsHandLance(HAND_B) ) { return 1; }
+
+ if ( IsHandKnight(HAND_B) )
+ {
+ bb_target = bb_inter;
+ bb_target.p[0] &= 0x00001ffU;
+ if ( BBTest(bb_target) ) { return 1; }
+ }
+
+ if ( IsHandPawn(HAND_B) )
+ {
+ bb_target = bb_inter;
+ ubb_pawn_cmp= BBToU( BB_BPAWN_ATK );
+ ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
+ ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
+ ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
+ ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
+ ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
+ ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
+ ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
+ ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
+ ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
+
+ while ( BBTest( bb_target ) )
+ {
+ to = LastOne( bb_target );
+ Xor( to, bb_target );
+
+ if ( ! ais_pawn[aifile[to]]
+ && ! IsMateBPawnDrop( ptree, to ) ) { return 1; }
+ }
+ }
+
+ return 0;
+}
+
+
+int CONV w_have_evasion( tree_t * restrict ptree )
+{
+ bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
+ unsigned int ubb_pawn_cmp;
+ unsigned int ais_pawn[nfile];
+ int nchecker, sq_wk, to, sq_check, idirec, flag, from;
+
+ /* move the king */
+ flag = 0;
+ sq_wk = SQ_WKING;
+
+ Xor( sq_wk, BB_WOCCUPY );
+ XorFile( sq_wk, OCCUPIED_FILE );
+ XorDiag2( sq_wk, OCCUPIED_DIAG2 );
+ XorDiag1( sq_wk, OCCUPIED_DIAG1 );
+
+ BBNotAnd( bb_desti, abb_king_attacks[sq_wk], BB_WOCCUPY );
+ while ( BBTest( bb_desti ) )
+ {
+ to = FirstOne( bb_desti );
+ Xor( to, bb_desti );
+
+ if ( ! is_white_attacked( ptree, to ) )
+ {
+ flag = 1;
+ break;
+ }
+ }
+
+ Xor( sq_wk, BB_WOCCUPY );
+ XorFile( sq_wk, OCCUPIED_FILE );
+ XorDiag2( sq_wk, OCCUPIED_DIAG2 );
+ XorDiag1( sq_wk, OCCUPIED_DIAG1 );
+
+ if ( flag ) { return 1; }
+
+
+ bb_checker = b_attacks_to_piece( ptree, sq_wk );
+ nchecker = PopuCount( bb_checker );
+ if ( nchecker == 2 ) { return 0; }
+
+ sq_check = FirstOne( bb_checker );
+ bb_inter = abb_obstacle[sq_wk][sq_check];
+
+ /* move other pieces */
+ BBOr( bb_target, bb_inter, bb_checker );
+
+ BBAnd( bb_desti, bb_target, BB_WPAWN_ATK );
+ while ( BBTest( bb_desti ) )
+ {
+ to = FirstOne( bb_desti );
+ Xor( to, bb_desti );
+
+ from = to - 9;
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WLANCE;
+ while ( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_desti = AttackFile( from );
+ BBAnd( bb_desti, bb_desti, abb_plus_rays[from] );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WKNIGHT;
+ while ( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBAnd( bb_desti, bb_target, abb_w_knight_attacks[from] );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WSILVER;
+ while ( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBAnd( bb_desti, bb_target, abb_w_silver_attacks[from] );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBAnd( bb_desti, bb_target, abb_w_gold_attacks[from] );
+ if ( ! BBTest(bb_desti) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WBISHOP;
+ while ( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackBishop( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WROOK;
+ while ( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackRook( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest( bb_desti ) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest(bb_desti) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ bb_piece = BB_WDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_desti, bb_desti, bb_target );
+ if ( ! BBTest(bb_desti) ) { continue; }
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( ! idirec
+ || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
+ }
+
+ /* drop */
+ if ( ! BBTest(bb_inter) ) { return 0; }
+
+ if ( IsHandSGBR(HAND_W) ) { return 1; }
+
+ bb_inter.p[2] &= 0x7fffe00U;
+ if ( ! BBTest(bb_inter) ) { return 0; }
+
+ if ( IsHandLance(HAND_W) ) { return 1; }
+
+ if ( IsHandKnight(HAND_W) )
+ {
+ bb_target = bb_inter;
+ bb_target.p[2] &= 0x7fc0000U;
+ if ( BBTest(bb_target) ) { return 1; }
+ }
+
+ if ( IsHandPawn(HAND_W) )
+ {
+ bb_target = bb_inter;
+ ubb_pawn_cmp= BBToU( BB_WPAWN_ATK );
+ ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
+ ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
+ ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
+ ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
+ ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
+ ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
+ ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
+ ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
+ ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
+
+ while ( BBTest( bb_target ) )
+ {
+ to = FirstOne( bb_target );
+ Xor( to, bb_target );
+
+ if ( ! ais_pawn[aifile[to]]
+ && ! IsMateWPawnDrop( ptree, to ) ) { return 1; }
+ }
+ }
+
+ return 0;
+}
#include "shogi.h"
-unsigned int *
+unsigned int * CONV
b_gen_nocaptures( const tree_t * restrict ptree,
unsigned int * restrict pmove )
{
}
bb_piece = BB_BSILVER;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_empty, abb_b_silver_attacks[from] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_BTGOLD;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_empty, abb_b_gold_attacks[from] );
utemp = From2Move( from ) | Piece2Move( BOARD[from] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
from = SQ_BKING;
BBAnd( bb_desti, bb_empty, abb_king_attacks[from] );
utemp = From2Move( from ) | Piece2Move( king );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_BHORSE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
AttackHorse( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_empty );
utemp = From2Move( from ) | Piece2Move( horse );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_BDRAGON;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
AttackDragon( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_empty );
utemp = From2Move( from ) | Piece2Move( dragon );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
bb_empty.p[0] &= 0x1ffU;
bb_piece = BB_BLANCE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_desti, bb_empty );
utemp = From2Move( from ) | Piece2Move( lance );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_BKNIGHT;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_empty, abb_b_knight_attacks[from] );
utemp = From2Move( from ) | Piece2Move( knight );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = LastOne( bb_desti );
Xor( to, bb_desti );
}
-unsigned int *
+unsigned int * CONV
w_gen_nocaptures( const tree_t * restrict ptree,
unsigned int * restrict pmove )
{
}
bb_piece = BB_WSILVER;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_empty, abb_w_silver_attacks[from] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_WTGOLD;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_empty, abb_w_gold_attacks[from] );
utemp = From2Move( from ) | Piece2Move( -BOARD[from] );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
from = SQ_WKING;
BBAnd( bb_desti, bb_empty, abb_king_attacks[from] );
utemp = From2Move( from ) | Piece2Move( king );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_WHORSE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
AttackHorse( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_empty );
utemp = From2Move( from ) | Piece2Move( horse );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_WDRAGON;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
AttackDragon( bb_desti, from );
BBAnd( bb_desti, bb_desti, bb_empty );
utemp = From2Move( from ) | Piece2Move( dragon );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
bb_empty.p[2] &= 0x7fc0000U;
bb_piece = BB_WLANCE;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_desti, bb_empty );
utemp = From2Move( from ) | Piece2Move( lance );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
}
bb_piece = BB_WKNIGHT;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
Xor( from, bb_piece );
BBAnd( bb_desti, bb_empty, abb_w_knight_attacks[from] );
utemp = From2Move( from ) | Piece2Move( knight );
- while ( BBToU( bb_desti ) )
+ while ( BBTest( bb_desti ) )
{
to = FirstOne( bb_desti );
Xor( to, bb_desti );
#include <assert.h>
#include "shogi.h"
-static int eval_supe( unsigned int hand_current, unsigned int hand_hash,
- int turn_current, int turn_hash,
- int * restrict pvalue_hash, int * restrict ptype_hash );
+static int CONV eval_supe( unsigned int hand_current, unsigned int hand_hash,
+ int turn_current, int turn_hash,
+ int * restrict pvalue_hash,
+ int * restrict ptype_hash );
-int
+int CONV
ini_trans_table( void )
{
size_t size;
#define Foo( PIECE, piece ) bb = BB_B ## PIECE; \
- while( BBToU(bb) ) { \
+ while( BBTest(bb) ) { \
sq = FirstOne( bb ); \
Xor( sq, bb ); \
key ^= ( b_ ## piece ## _rand )[sq]; \
} \
bb = BB_W ## PIECE; \
- while( BBToU(bb) ) { \
+ while( BBTest(bb) ) { \
sq = FirstOne( bb ); \
Xor( sq, bb ); \
key ^= ( w_ ## piece ## _rand )[sq]; \
}
-uint64_t
+uint64_t CONV
hash_func( const tree_t * restrict ptree )
{
uint64_t key = 0;
age 3 0
*/
-void
+void CONV
hash_store( const tree_t * restrict ptree, int ply, int depth, int turn,
int value_type, int value, unsigned int move,
unsigned int state_node )
}
-void
+void CONV
hash_store_pv( const tree_t * restrict ptree, unsigned int move, int turn )
{
uint64_t key_turn_pv, word1, word2;
}
-trans_entry_t
-hash_learn_store( const tree_t * restrict ptree, int depth, int value,
- unsigned int move )
-{
- trans_entry_t ret;
-
- assert( 0 <= depth && depth <= 0xff );
-
- ret.word2 = ( (HASH_KEY&(~(uint64_t)0x7fU))
- | (uint64_t)( (root_turn<<6)
- | (value_exact<<3) | trans_table_age ) );
- ret.word1 = ( ( (uint64_t)( depth<<16 | (value+32768) ) << 40 )
- | ( (uint64_t)( move & 0x7ffffU ) << 21 )
- | HAND_B );
-
- return ret;
-}
-
-
-int
-all_hash_learn_store( void )
-{
- uint64_t aword[2];
- unsigned int u32key, unext, u, index;
-
- if ( pf_hash == NULL ) { return 0; }
-
- if ( fseek( pf_hash, sizeof(unsigned int), SEEK_SET ) == EOF
- || fread( &unext, sizeof(unsigned int), 1, pf_hash ) != 1 )
- {
- str_error = str_io_error;
- return -2;
- }
- if ( ++unext == 0x10000U ) { unext = 0x1U; }
- if ( fseek( pf_hash, (long)( 20U * unext ), SEEK_SET ) == EOF )
- {
- str_error = str_io_error;
- return -2;
- }
- for ( u = 0;; u++ )
- {
- if ( fread( &u32key, sizeof(unsigned int), 1, pf_hash ) != 1
- || fread( aword, sizeof(uint64_t), 2, pf_hash ) != 2 )
- {
- str_error = str_io_error;
- return -2;
- }
- index = u32key & hash_mask;
- aword[1] |= (uint64_t)trans_table_age;
- SignKey( aword[1], aword[0] );
- ptrans_table[index].prefer.word1 = aword[0];
- ptrans_table[index].prefer.word2 = aword[1];
- if ( u == 0xfffeU ) { break; }
- if ( ++unext == 0x10000U )
- {
- unext = 0x1U;
- if ( fseek( pf_hash, 20, SEEK_SET ) == EOF )
- {
- str_error = str_io_error;
- return -2;
- }
- }
- }
-
- return 1;
-}
-
-
-unsigned int
+unsigned int CONV
hash_probe( tree_t * restrict ptree, int ply, int depth_current,
- int turn_current, int alpha, int beta, unsigned int state_node )
+ int turn_current, int alpha, int beta, unsigned int *pstate_node )
{
uint64_t word1, word2, key_current, key_hash;
- unsigned int hand_hash, move_hash, move_infe, move_supe, slot, utemp;
+ unsigned int hand_hash, move_hash, move_supe, slot, utemp;
unsigned int state_node_hash, index;
int null_depth, value_hash, ifrom;
int turn_hash, depth_hash, type_hash, is_superior;
ptree->ntrans_probe++;
move_supe = 0;
- move_infe = 0;
if ( depth_current < 0 ) { depth_current = 0; }
null_depth = NullDepth( depth_current );
{
if ( value_hash > 0 ) { value_hash -= ply-1; }
else { value_hash += ply-1; }
+
#if ! defined(MINIMUM)
if ( abs(value_hash) > score_mate1ply )
{
}
#endif
}
-
- if ( move_hash )
+
+ if ( RecursionThreshold <= depth_current
+ && depth_hash < RecursionDepth(depth_current) ) { move_hash = 0; }
+ else if ( move_hash )
{
move_hash |= turn_current ? Cap2Move( BOARD[I2To(move_hash)])
: Cap2Move(-BOARD[I2To(move_hash)]);
assert( ! move_hash || is_move_valid( ptree, move_hash, turn_current ) );
ptree->amove_hash[ply] = move_hash;
+ *pstate_node |= state_node_hash;
+
+ if ( value_hash <= score_max_eval ) { *pstate_node &= ~node_do_mate; }
+
+ if ( ( type_hash & flag_value_up_exact )
+ && value_hash < beta
+ && null_depth <= depth_hash )
+ {
+ *pstate_node &= ~node_do_null;
+ }
+
+ if ( ( type_hash & flag_value_up_exact )
+ && value_hash <= alpha
+ && RecursionDepth(depth_current) <= depth_hash )
+ {
+ *pstate_node &= ~node_do_recursion;
+ }
+
if ( type_hash == value_lower
- && value_hash >= beta
+ && beta <= value_hash
&& ( depth_hash >= depth_current || value_hash > score_max_eval ) )
{
HASH_VALUE = value_hash;
return value_lower;
}
- state_node |= state_node_hash;
-
- if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate; }
-
- if ( ( type_hash & flag_value_up_exact )
- && value_hash < beta
- && null_depth <= depth_hash )
- {
- state_node &= ~node_do_null;
- }
-
} else {
is_superior = eval_supe( HAND_B, hand_hash, turn_current, turn_hash,
|| score_max_eval < value_hash
|| ( turn_current != turn_hash
&& depth_hash >= null_depth
- && ( state_node & node_do_null ) ) ) )
+ && ( *pstate_node & node_do_null ) ) ) )
{
HASH_VALUE = value_hash;
ptree->ntrans_superior_hit++;
}
}
- } else {
-
- if ( turn_hash == turn_current ) { move_infe = move_hash; }
+ } else if ( is_superior == -1 ) {
- if ( is_superior == -1 ) {
-
- state_node |= state_node_hash;
-
- if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate; }
-
- if ( type_hash & flag_value_up_exact )
- {
- if ( value_hash <= alpha
- && ( depth_current <= depth_hash
- || value_hash < -score_max_eval ) )
- {
- HASH_VALUE = value_hash;
- ptree->ntrans_inferior_hit++;
- return value_upper;
- }
- if ( value_hash < beta && null_depth <= depth_hash )
- {
- state_node &= ~node_do_null;
- }
- }
- }
+ *pstate_node |= state_node_hash;
+
+ if ( value_hash <= score_max_eval )
+ {
+ *pstate_node &= ~node_do_mate;
+ }
+
+ if ( ( type_hash & flag_value_up_exact )
+ && value_hash <= alpha
+ && RecursionDepth(depth_current) <= depth_hash )
+ {
+ *pstate_node &= ~node_do_recursion;
+ }
+
+ if ( type_hash & flag_value_up_exact )
+ {
+ if ( value_hash < beta && null_depth <= depth_hash )
+ {
+ *pstate_node &= ~node_do_null;
+ }
+ if ( value_hash <= alpha
+ && ( depth_current <= depth_hash
+ || value_hash < -score_max_eval ) )
+ {
+ HASH_VALUE = value_hash;
+ ptree->ntrans_inferior_hit++;
+ return value_upper;
+ }
+ }
}
}
}
{
if ( value_hash > 0 ) { value_hash -= ply-1; }
else { value_hash += ply-1; }
+
#if ! defined(MINIMUM)
if ( abs(value_hash) > score_mate1ply )
{
#endif
}
- if ( move_hash )
+ if ( RecursionThreshold <= depth_current
+ && depth_hash < RecursionDepth(depth_current) ) { move_hash = 0; }
+ else if ( move_hash )
{
move_hash |= turn_current ? Cap2Move( BOARD[I2To(move_hash)])
: Cap2Move(-BOARD[I2To(move_hash)]);
ptree->amove_hash[ply] = move_hash;
}
+ *pstate_node |= state_node_hash;
+
+ if ( value_hash <= score_max_eval ) { *pstate_node &= ~node_do_mate; }
+
+ if ( ( type_hash & flag_value_up_exact )
+ && value_hash <= alpha
+ && RecursionDepth(depth_current) <= depth_hash )
+ {
+ *pstate_node &= ~node_do_recursion;
+ }
+
+ if ( ( type_hash & flag_value_up_exact )
+ && value_hash < beta
+ && null_depth <= depth_hash )
+ {
+ *pstate_node &= ~node_do_null;
+ }
+
if ( type_hash == value_lower
&& value_hash >= beta
&& ( depth_hash >= depth_current || value_hash > score_max_eval ) )
return value_lower;
}
- state_node |= state_node_hash;
-
- if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate; }
-
- if ( ( type_hash & flag_value_up_exact )
- && value_hash < beta
- && null_depth <= depth_hash )
- {
- state_node &= ~node_do_null;
- }
-
} else {
is_superior = eval_supe( HAND_B, hand_hash, turn_current, turn_hash,
|| score_max_eval < value_hash
|| ( turn_current != turn_hash
&& depth_hash >= null_depth
- && ( state_node & node_do_null ) ) ) )
+ && ( *pstate_node & node_do_null ) ) ) )
{
HASH_VALUE = value_hash;
ptree->ntrans_superior_hit++;
}
}
- } else {
+ } else if ( is_superior == -1 ) {
- if ( ! move_infe && turn_hash == turn_current )
+ *pstate_node |= state_node_hash;
+
+ if ( value_hash <= score_max_eval )
{
- move_infe = move_hash;
+ *pstate_node &= ~node_do_mate;
+ }
+
+ if ( ( type_hash & flag_value_up_exact )
+ && value_hash <= alpha
+ && RecursionDepth(depth_current) <= depth_hash )
+ {
+ *pstate_node &= ~node_do_recursion;
+ }
+
+ if ( type_hash & flag_value_up_exact )
+ {
+ if ( value_hash < beta && null_depth <= depth_hash )
+ {
+ *pstate_node &= ~node_do_null;
+ }
+ if ( value_hash <= alpha
+ && ( depth_hash >= depth_current
+ || value_hash < -score_max_eval ) )
+ {
+ HASH_VALUE = value_hash;
+ ptree->ntrans_inferior_hit++;
+ return value_upper;
+ }
}
-
- if ( is_superior == -1 ) {
-
- state_node |= state_node_hash;
-
- if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate;}
-
- if ( type_hash & flag_value_up_exact )
- {
- if ( value_hash <= alpha
- && ( depth_hash >= depth_current
- || value_hash < -score_max_eval ) )
- {
- HASH_VALUE = value_hash;
- ptree->ntrans_inferior_hit++;
- return value_upper;
- }
- if ( value_hash < beta && null_depth <= depth_hash )
- {
- state_node &= ~node_do_null;
- }
- }
- }
}
}
}
assert( is_move_valid( ptree, move_supe, turn_current ) );
ptree->amove_hash[ply] = move_supe;
}
- else if ( move_infe )
- {
- ifrom = (int)I2From(move_infe);
- if ( ifrom >= nsquare )
- {
- unsigned int hand = turn_current ? HAND_W : HAND_B;
- switch( From2Drop(ifrom) )
- {
- case pawn: if ( ! IsHandPawn(hand) ) { goto esc; } break;
- case lance: if ( ! IsHandLance(hand) ) { goto esc; } break;
- case knight: if ( ! IsHandKnight(hand) ) { goto esc; } break;
- case silver: if ( ! IsHandSilver(hand) ) { goto esc; } break;
- case gold: if ( ! IsHandGold(hand) ) { goto esc; } break;
- case bishop: if ( ! IsHandBishop(hand) ) { goto esc; } break;
- case rook: if ( ! IsHandRook(hand) ) { goto esc; } break;
- }
- }
- assert( is_move_valid( ptree, move_infe, turn_current ) );
- ptree->amove_hash[ply] = move_infe;
- }
- }
-
- esc:
- return state_node;
-}
-
-
-int
-hash_learn_on( void )
-{
- int iret = file_close( pf_hash );
- if ( iret < 0 ) { return iret; }
-
- pf_hash = file_open( str_hash, "rb+" );
- if ( pf_hash == NULL ) { return -2; }
-
- return 1;
-}
-
-
-int
-hash_learn_off( void )
-{
- int iret = file_close( pf_hash );
- if ( iret < 0 ) { return iret; }
-
- pf_hash = NULL;
-
- return 1;
-}
-
-#if !defined(MINIMUM)
-int
-hash_learn_create( void )
-{
- uint64_t au64[2];
- unsigned int u;
- int iret, i;
-
- iret = hash_learn_off();
- if ( iret < 0 ) { return iret; }
-
- pf_hash = file_open( str_hash, "wb" );
- if ( pf_hash == NULL ) { return -2; }
-
- for ( i = 0; i < 5; i++ )
- {
- u = 0;
- if ( fwrite( &u, sizeof(unsigned int), 1, pf_hash ) != 1 )
- {
- str_error = str_io_error;
- return -2;
- }
- }
-
- u = 0;
- au64[0] = au64[1] = 0;
- for ( i = 1; i < 0x10000; i++ )
- if ( fwrite( &u, sizeof(unsigned int), 1, pf_hash ) != 1
- || fwrite( au64, sizeof(uint64_t), 2, pf_hash ) != 2 )
- {
- str_error = str_io_error;
- return -2;
- }
-
- return hash_learn_on();
-}
-#endif
-
-int
-hash_learn( const tree_t * restrict ptree, unsigned int move, int value,
- int depth )
-{
- trans_entry_t trans_entry;
- unsigned int unum, unext, u;
- int pre_value, ply;
-
- ply = record_game.moves;
- if ( ply >= HASH_REG_HIST_LEN ) { return 1; }
- if ( pf_hash == NULL ) { return 1; }
- if ( abs(value) > score_max_eval ) { return 1; }
- if ( ply < 2 ) { return 1; }
- if ( depth < 2 ) { return 1; }
-
- if ( history_book_learn[ply].key_probed == (unsigned int)HASH_KEY
- && history_book_learn[ply].hand_probed == HAND_B
- && history_book_learn[ply].move_probed == move ) { return 1; }
-
- if ( history_book_learn[ply-2].key_responsible
- != history_book_learn[ply-2].key_played ) { return 1; }
- if ( history_book_learn[ply-2].hand_responsible
- != history_book_learn[ply-2].hand_played ) { return 1; }
- if ( history_book_learn[ply-2].move_responsible
- != history_book_learn[ply-2].move_played ) { return 1; }
-
- if ( ( history_book_learn[ply-2].key_probed
- == history_book_learn[ply-2].key_played )
- && ( history_book_learn[ply-2].hand_probed
- == history_book_learn[ply-2].hand_played )
- && ( history_book_learn[ply-2].move_probed
- == history_book_learn[ply-2].move_played ) ) { return 1; }
-
- pre_value = (int)( history_book_learn[ply-2].data & 0xffffU ) - 32768;
-
- if ( pre_value < value + HASH_REG_MINDIFF ) { return 1; }
- if ( pre_value < -HASH_REG_THRESHOLD ) { return 1; }
- if ( pre_value == score_inferior ) { return 1; }
-
- Out( "save hash value of the position\n\n" );
- if ( fseek( pf_hash, 0, SEEK_SET ) == EOF
- || fread( &unum, sizeof(unsigned int), 1, pf_hash ) != 1
- || fread( &unext, sizeof(unsigned int), 1, pf_hash ) != 1 )
- {
- str_error = str_io_error;
- return -2;
- }
- if ( ++unum == 0x10000U ) { unum = 0xffffU; }
- if ( ++unext == 0x10000U ) { unext = 0x0001U; }
-
- if ( fseek( pf_hash, 0, SEEK_SET ) == EOF
- || fwrite( &unum, sizeof(unsigned int), 1, pf_hash ) != 1
- || fwrite( &unext, sizeof(unsigned int), 1, pf_hash ) != 1 )
- {
- str_error = str_io_error;
- return -2;
- }
- trans_entry
- = hash_learn_store( ptree, depth * PLY_INC + PLY_INC/2, value, move );
- u = (unsigned int)HASH_KEY;
- if ( fseek( pf_hash, (long)( 20 * unext ), SEEK_SET ) == EOF
- || fwrite( &u, sizeof(unsigned int), 1, pf_hash ) != 1
- || fwrite( &trans_entry.word1, sizeof(uint64_t), 1, pf_hash ) != 1
- || fwrite( &trans_entry.word2, sizeof(uint64_t), 1, pf_hash ) != 1
- || fflush( pf_hash ) == EOF )
- {
- str_error = str_io_error;
- return -2;
}
- return 1;
+ return value_null;
}
-static int
+static int CONV
eval_supe( unsigned int hand_current, unsigned int hand_hash,
int turn_current, int turn_hash,
int * restrict pvalue_hash, int * restrict ptype_hash )
}
-int
+int CONV
clear_trans_table( void )
{
unsigned int elapsed_start, elapsed_end;
return 1;
}
-
-
-void
-add_rejections_root( tree_t * restrict ptree, unsigned int move_made )
-{
- uint64_t hash_value;
- unsigned int * restrict pmove;
- unsigned int *pmove_last;
- unsigned int hash_key, hand_ply_turn;
- int tt;
- unsigned char hash_parent;
-
- tt = Flip( root_turn );
- UnMakeMove( tt, move_made, 1 );
- hash_parent = (unsigned char)(HASH_KEY >> 32);
-
- pmove = ptree->amove;
- pmove_last = GenCaptures( tt, pmove );
- pmove_last = GenNoCaptures( tt, pmove_last );
- pmove_last = GenCapNoProEx2( tt, pmove_last );
- pmove_last = GenNoCapNoProEx2( tt, pmove_last );
- pmove_last = GenDrop( tt, pmove_last );
-
- while ( pmove != pmove_last )
- {
- if ( *pmove != move_made )
- {
- MakeMove( tt, *pmove, 1 );
- if ( ! InCheck( tt ) )
- {
- hash_key = (unsigned int)HASH_KEY & REJEC_MASK;
- hand_ply_turn = ( HAND_B << 6 ) | 2U | (unsigned int)tt;
- hash_value = ( ( HASH_KEY & ~(uint64_t)0x7ffffffU )
- | (uint64_t)hand_ply_turn );
- hash_rejections[hash_key].root = hash_value;
- hash_rejections_parent[hash_key] = hash_parent;
- }
- UnMakeMove( tt, *pmove, 1 );
- }
- pmove++;
- }
-
- MakeMove( tt, move_made, 1 );
-}
-
-
-void
-sub_rejections_root( tree_t * restrict ptree, unsigned int move_made )
-{
- unsigned int * restrict pmove;
- unsigned int *pmove_last;
- unsigned int hash_key;
-
- pmove = ptree->amove;
- pmove_last = GenCaptures( root_turn, pmove );
- pmove_last = GenNoCaptures( root_turn, pmove_last );
- pmove_last = GenCapNoProEx2( root_turn, pmove_last );
- pmove_last = GenNoCapNoProEx2( root_turn, pmove_last );
- pmove_last = GenDrop( root_turn, pmove_last );
-
- while ( pmove != pmove_last )
- {
- if ( *pmove != move_made )
- {
- MakeMove( root_turn, *pmove, 1 );
- if ( ! InCheck( root_turn ) )
- {
- hash_key = (unsigned int)HASH_KEY & REJEC_MASK;
-
- hash_rejections[hash_key].root = 0;
- hash_rejections_parent[hash_key] = 0;
- }
- UnMakeMove( root_turn, *pmove, 1 );
- }
- pmove++;
- }
-}
-
-
-void
-add_rejections( tree_t * restrict ptree, int turn, int ply )
-{
- uint64_t hash_value;
- unsigned int * restrict pmove;
- unsigned int * restrict pmove_last;
- unsigned int hash_key, hand_ply_turn;
-
-#if ! defined(MINIMUM)
- if ( game_status & flag_learning ) { return; }
-#endif
-
- pmove = ptree->move_last[ply-1];
- pmove_last = GenCaptures( turn, pmove );
- pmove_last = GenNoCaptures( turn, pmove_last );
- pmove_last = GenCapNoProEx2( turn, pmove_last );
- pmove_last = GenNoCapNoProEx2( turn, pmove_last );
- pmove_last = GenDrop( turn, pmove_last );
-
- while ( pmove != pmove_last )
- {
- MakeMove( turn, *pmove, ply );
- if ( ! InCheck( turn ) )
- {
- hash_key = (unsigned int)HASH_KEY & REJEC_MASK;
- if ( ! (unsigned int)hash_rejections[hash_key].sibling )
- {
- hand_ply_turn = ( ( HAND_B << 6 ) | ( (unsigned int)ply << 1 )
- | (unsigned int)turn );
- hash_value = ( ( HASH_KEY & ~(uint64_t)0x7ffffffU )
- | (uint64_t)hand_ply_turn );
- hash_rejections[hash_key].sibling = hash_value;
-#if defined(TLP)
- tlp_rejections_slot[hash_key] = (unsigned short)
- ( ptree->tlp_slot ^ (unsigned short)( hash_value >> 32 ) );
-#endif
- }
- }
- UnMakeMove( turn, *pmove, ply );
- pmove++;
- }
-}
-
-
-void
-sub_rejections( tree_t * restrict ptree, int turn, int ply )
-{
- uint64_t hash_value;
- unsigned int * restrict pmove;
- unsigned int * restrict pmove_last;
- unsigned int hash_key, hand_ply_turn;
-
-#if ! defined(MINIMUM)
- if ( game_status & flag_learning ) { return; }
-#endif
-
- pmove = ptree->move_last[ply-1];
- pmove_last = GenCaptures( turn, pmove );
- pmove_last = GenNoCaptures( turn, pmove_last );
- pmove_last = GenCapNoProEx2( turn, pmove_last );
- pmove_last = GenNoCapNoProEx2( turn, pmove_last );
- pmove_last = GenDrop( turn, pmove_last );
-
- while ( pmove != pmove_last )
- {
- MakeMove( turn, *pmove, ply );
- if ( ! InCheck( turn ) )
- {
- hash_key = (unsigned int)HASH_KEY & REJEC_MASK;
- hand_ply_turn = ( ( HAND_B << 6 )
- | ( (unsigned int)ply << 1 )
- | (unsigned int)turn );
- hash_value = ( ( HASH_KEY & ~(uint64_t)0x7ffffffU )
- | (uint64_t)hand_ply_turn );
-
- if ( hash_rejections[hash_key].sibling == hash_value )
- {
- hash_rejections[hash_key].sibling = 0;
- }
- }
- UnMakeMove( turn, *pmove, ply );
- pmove++;
- }
-}
-
-
-int
-rejections_probe( tree_t * restrict ptree, int turn, int ply )
-{
- uint64_t value_turn, value_turn_current, value;
- unsigned int hand_hash, hand_current, key_current;
- int nrep, value_ply;
- unsigned char parent_hash, parent_current;
-
- turn = Flip(turn);
- hand_current = HAND_B;
- key_current = (unsigned int)HASH_KEY & REJEC_MASK;
- value_turn_current = ( HASH_KEY & ~(uint64_t)0x7ffffffU ) | (uint64_t)turn;
-
- value = hash_rejections[key_current].root;
- value_turn = value & ~(uint64_t)0x7fffffeU;
- if ( value_turn == value_turn_current )
- {
- hand_hash = ( (unsigned int)value & 0x7ffffffU ) >> 6;
- if ( ( turn && is_hand_eq_supe( hand_current, hand_hash ) )
- || ( ! turn && is_hand_eq_supe( hand_hash, hand_current ) ) )
- {
- nrep = root_nrep + ply - 2;
- parent_current = (unsigned char)(ptree->rep_board_list[nrep] >> 32);
- parent_hash = hash_rejections_parent[key_current];
- if ( parent_hash != parent_current ) { return 1; }
- }
- }
-
- value = hash_rejections[key_current].sibling;
- value_ply = ( (int)value & 0x3eU ) >> 1;
- if ( value_ply + 2 < ply )
- {
- value_turn = value & ~(uint64_t)0x7fffffeU;
- if ( value_turn == value_turn_current )
- {
- hand_hash = ( (unsigned int)value & 0x7ffffffU ) >> 6;
- if ( ( turn && is_hand_eq_supe( hand_current, hand_hash ) )
- || ( ! turn && is_hand_eq_supe( hand_hash, hand_current ) ) )
- {
-#if defined(TLP)
- int slot_hash;
- slot_hash = (int)( tlp_rejections_slot[key_current]
- ^ (unsigned short)( value >> 32 ) );
- if ( tlp_is_descendant( ptree, slot_hash ) )
-
-#endif
- return 1;
- }
- }
- }
-
- return 0;
-}
static void ini_check_table( void );
static bitboard_t bb_set_mask( int isquare );
-static int load_fv( void );
static void set_attacks( int irank, int ifilea, bitboard_t *pbb );
static void ini_is_same( void );
static void ini_tables( void );
static void ini_random_table( void );
-static int
-load_fv( void )
+int CONV load_fv( void )
{
FILE *pf;
size_t size;
return 1;
}
-/*
-static int
-ini_fv( void )
-{
- FILE *pf;
- size_t size, i;
-
- pf = file_open( str_fv, "wb" );
- if ( pf == NULL ) { return -2; }
-
- size = nsquare * pos_n;
- for ( i = 0; i < size; i++ ) { pc_on_sq[0][i] = 0; }
- if ( fwrite( pc_on_sq, sizeof(short), size, pf ) != size )
- {
- str_error = str_io_error;
- return -2;
- }
-
- size = nsquare * nsquare * kkp_end;
- for ( i = 0; i < size; i++ ) { kkp[0][0][i] = 0; }
- if ( fwrite( kkp, sizeof(short), size, pf ) != size )
- {
- str_error = str_io_error;
- return -2;
- }
-
- return file_close( pf );
-}
-*/
int
ini( tree_t * restrict ptree )
for ( i = 0; i < 31; i++ ) { p_value[i] = 0; }
for ( i = 0; i < 31; i++ ) { p_value_ex[i] = 0; }
- for ( i = 0; i < 15; i++ ) { benefit2promo[i] = 0; }
+ for ( i = 0; i < 15; i++ ) { p_value_pm[i] = 0; }
p_value[15+pawn] = DPawn;
p_value[15+lance] = DLance;
p_value[15+knight] = DKnight;
ptrans_table_orig = NULL;
record_game.pf = NULL;
node_per_second = TIME_CHECK_MIN_NODE;
+ resign_threshold = RESIGN_THRESHOLD;
node_limit = UINT64_MAX;
time_response = TIME_RESPONSE;
sec_limit = 0;
sec_limit_depth = UINT_MAX;
depth_limit = PLY_MAX;
log2_ntrans_table = 20;
-
+ record_num = -1;
+
pf_book = NULL;
- pf_hash = NULL;
+
+ for ( i = 0; i < NUM_UNMAKE; i++ )
+ {
+ amove_save[i] = MOVE_NA;
+ amaterial_save[i] = 0;
+ ansuc_check_save[i] = 0;
+ alast_root_value_save[i] = 0;
+ alast_pv_save[i].a[0] = 0;
+ alast_pv_save[i].a[1] = 0;
+ alast_pv_save[i].depth = 0;
+ alast_pv_save[i].length = 0;
+ alast_pv_save[i].type = no_rep;
+ }
#if defined(TLP)
tlp_max = 1;
tlp_atree_work[i].tlp_used = 0;
if ( lock_init( &tlp_atree_work[i].tlp_lock ) < 0 ) { return -1; }
}
-# if defined(_WIN32)
-# else
+#endif
+
+#if ! defined(_WIN32) && ( defined(DFPN_CLIENT) || defined(TLP) )
if ( pthread_attr_init( &pthread_attr )
|| pthread_attr_setdetachstate( &pthread_attr,
PTHREAD_CREATE_DETACHED ) )
str_error = "pthread_attr_init() failed.";
return -1;
}
-# endif
#endif
+
#if defined(CSA_LAN)
sckt_csa = SCKT_NULL;
time_last_send = 0U;
#endif
+#if defined(MNJ_LAN) || defined(USI)
+ moves_ignore[0] = MOVE_NA;
+#endif
+
#if defined(MNJ_LAN)
- for ( i = 1; i < MNJ_MASK + 1; i++ ) { mnj_tbl[i] = 0; }
- sckt_mnj = SCKT_NULL;
- mnj_posi_id = 0;
- mnj_move_last = 0;
- time_last_send = 0U;
+ sckt_mnj = SCKT_NULL;
+ mnj_posi_id = 0;
+ time_last_send = 0U;
+#endif
+
+#if defined(TLP) || defined(DFPN_CLIENT)
+ if ( lock_init( &io_lock ) < 0 ) { return -1; }
+#endif
+
+#if defined(DFPN_CLIENT)
+ if ( lock_init( &dfpn_client_lock ) < 0 ) { return -1; }
+ dfpn_client_str_move[0] = '\0';
+ dfpn_client_str_addr[0] = '\0';
+ dfpn_client_signature[0] = '\0';
+ dfpn_client_rresult = dfpn_client_na;
+ dfpn_client_num_cresult = 0;
+ dfpn_client_flag_read = 0;
+ dfpn_client_sckt = SCKT_NULL;
+#endif
+
+#if defined(USI)
+ usi_byoyomi = 0;
+ if ( usi_mode != usi_off )
+ {
+ game_status |= flag_noprompt;
+ game_status |= flag_nostdout;
+ game_status |= flag_noponder;
+ game_status |= flag_nobeep;
+ resign_threshold = 65535;
+ }
#endif
#if defined(_WIN32)
-# if defined(DEKUNOBOU)
- dek_ngame = 0;
-# endif
#else
clk_tck = (clock_t)sysconf(_SC_CLK_TCK);
#endif
}
#endif
- for ( i = 0; i < HASH_REG_HIST_LEN; i++ )
- {
- history_book_learn[i].move_responsible = 0;
- history_book_learn[i].move_probed = 0;
- history_book_learn[i].move_played = 0;
- }
-
ini_rand( 5489U );
ini_is_same();
ini_tables();
if ( ini_trans_table() < 0 ) { return -1; }
+#if defined(DFPN)
+ dfpn_sckt = SCKT_NULL;
+ dfpn_hash_log2 = 20;
+ if ( dfpn_ini_hash() < 0 ) { return -1; }
+#endif
+
if ( book_on() < 0 ) { out_warning( "%s", str_error );}
else { Out( "%s found\n", str_book );}
- if ( hash_learn_on() < 0 ) { out_warning( "%s", str_error );}
- else { Out( "%s found\n", str_hash );}
-
if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
ini_rand( time_turn_start );
Out( "rand seed = %x\n", time_turn_start );
- resign_threshold = RESIGN_THRESHOLD;
-
#if defined(MPV)
mpv_num = 1;
mpv_width = 2 * MT_CAP_PAWN;
#endif
+#if defined(INANIWA_SHIFT)
+ inaniwa_flag = 0;
+#endif
+
return 1;
}
memory_free( (void *)ptrans_table_orig );
+#if defined(TLP) || defined(DFPN_CLIENT)
+ if ( lock_free( &io_lock ) < 0 ) { return -1; }
+#endif
+
+#if defined(DFPN_CLIENT)
+ if ( lock_free( & dfpn_client_lock ) < 0 ) { return -1; }
+#endif
+
#if defined(TLP)
tlp_abort = 1;
while ( tlp_num ) { tlp_yield(); }
{
if ( lock_free( &tlp_atree_work[i].tlp_lock ) < 0 ) { return -1; }
}
-# if defined(_WIN32)
-# else
+#endif
+
+#if ! defined(_WIN32) && ( defined(DFPN_CLIENT) || defined(TLP) )
if ( pthread_attr_destroy( &pthread_attr ) )
{
str_error = "pthread_attr_destroy() failed.";
return -1;
}
-# endif
#endif
if ( book_off() < 0 ) { return -1; }
if ( file_close( pf_log ) < 0 ) { return -1; }
#endif
+ ShutdownAll();
return 1;
}
p_value_ex[15+horse] = p_value[15+horse] + p_value[15+bishop];
p_value_ex[15+dragon] = p_value[15+dragon] + p_value[15+rook];
- benefit2promo[7+pawn] = p_value[15+pro_pawn] - p_value[15+pawn];
- benefit2promo[7+lance] = p_value[15+pro_lance] - p_value[15+lance];
- benefit2promo[7+knight] = p_value[15+pro_knight] - p_value[15+knight];
- benefit2promo[7+silver] = p_value[15+pro_silver] - p_value[15+silver];
- benefit2promo[7+bishop] = p_value[15+horse] - p_value[15+bishop];
- benefit2promo[7+rook] = p_value[15+dragon] - p_value[15+rook];
+ p_value_pm[7+pawn] = p_value[15+pro_pawn] - p_value[15+pawn];
+ p_value_pm[7+lance] = p_value[15+pro_lance] - p_value[15+lance];
+ p_value_pm[7+knight] = p_value[15+pro_knight] - p_value[15+knight];
+ p_value_pm[7+silver] = p_value[15+pro_silver] - p_value[15+silver];
+ p_value_pm[7+bishop] = p_value[15+horse] - p_value[15+bishop];
+ p_value_pm[7+rook] = p_value[15+dragon] - p_value[15+rook];
p_value[15-pawn] = p_value[15+pawn];
p_value[15-lance] = p_value[15+lance];
p_value_ex[15-horse] = p_value_ex[15+horse];
p_value_ex[15-dragon] = p_value_ex[15+dragon];
- benefit2promo[7-pawn] = benefit2promo[7+pawn];
- benefit2promo[7-lance] = benefit2promo[7+lance];
- benefit2promo[7-knight] = benefit2promo[7+knight];
- benefit2promo[7-silver] = benefit2promo[7+silver];
- benefit2promo[7-bishop] = benefit2promo[7+bishop];
- benefit2promo[7-rook] = benefit2promo[7+rook];
+ p_value_pm[7-pawn] = p_value_pm[7+pawn];
+ p_value_pm[7-lance] = p_value_pm[7+lance];
+ p_value_pm[7-knight] = p_value_pm[7+knight];
+ p_value_pm[7-silver] = p_value_pm[7+silver];
+ p_value_pm[7-bishop] = p_value_pm[7+bishop];
+ p_value_pm[7-rook] = p_value_pm[7+rook];
}
}
BBOr( bb, abb_plus1dir[ifrom], abb_minus1dir[ifrom] );
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
ito = FirstOne( bb );
adirec[ifrom][ito] = (unsigned char)direc_rank;
Xor( ito, bb );
}
BBOr( bb, abb_plus8dir[ifrom], abb_minus8dir[ifrom] );
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
ito = FirstOne( bb );
adirec[ifrom][ito] = (unsigned char)direc_diag1;
Xor( ito, bb );
}
BBOr( bb, abb_plus9dir[ifrom], abb_minus9dir[ifrom] );
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
ito = FirstOne( bb );
adirec[ifrom][ito] = (unsigned char)direc_file;
Xor(ito,bb);
}
BBOr( bb, abb_plus10dir[ifrom], abb_minus10dir[ifrom] );
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
ito = FirstOne( bb );
adirec[ifrom][ito] = (unsigned char)direc_diag2;
int irank, ifile, pcs, i;
bitboard_t bb;
+ for ( i = 0; i < nsquare; i++ ) {
+
+ aslide[i].ir0 = (unsigned char)(i/27);
+ aslide[i].sr0 = (unsigned char)((2-(i/9)%3)*9+1);
+ aslide[i].irl90 = (unsigned char)(2-(i%9)/3);
+ aslide[i].srl90 = (unsigned char)(((i%9)%3)*9+1);
+ }
+
for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nfile; ifile++ )
- {
+ for ( ifile = 0; ifile < nfile; ifile++ ) {
+
+ BBIni(bb);
+ set_attacks( irank-1, ifile-1, &bb );
+ set_attacks( irank-1, ifile+1, &bb );
+ set_attacks( irank+1, ifile-1, &bb );
+ set_attacks( irank+1, ifile+1, &bb );
+ set_attacks( irank-1, ifile, &bb );
+ abb_b_silver_attacks[ irank*nfile + ifile ] = bb;
+
+ BBIni(bb);
+ set_attacks( irank-1, ifile-1, &bb );
+ set_attacks( irank-1, ifile+1, &bb );
+ set_attacks( irank+1, ifile-1, &bb );
+ set_attacks( irank+1, ifile+1, &bb );
+ set_attacks( irank+1, ifile, &bb );
+ abb_w_silver_attacks[ irank*nfile + ifile ] = bb;
+
+ BBIni(bb);
+ set_attacks( irank-1, ifile-1, &bb );
+ set_attacks( irank-1, ifile+1, &bb );
+ set_attacks( irank-1, ifile, &bb );
+ set_attacks( irank+1, ifile, &bb );
+ set_attacks( irank, ifile-1, &bb );
+ set_attacks( irank, ifile+1, &bb );
+ abb_b_gold_attacks[ irank*nfile + ifile ] = bb;
+
+ BBIni(bb);
+ set_attacks( irank+1, ifile-1, &bb );
+ set_attacks( irank+1, ifile+1, &bb );
+ set_attacks( irank+1, ifile, &bb );
+ set_attacks( irank-1, ifile, &bb );
+ set_attacks( irank, ifile-1, &bb );
+ set_attacks( irank, ifile+1, &bb );
+ abb_w_gold_attacks[ irank*nfile + ifile ] = bb;
+
+ BBIni(bb);
+ set_attacks( irank+1, ifile-1, &bb );
+ set_attacks( irank+1, ifile+1, &bb );
+ set_attacks( irank+1, ifile, &bb );
+ set_attacks( irank-1, ifile-1, &bb );
+ set_attacks( irank-1, ifile+1, &bb );
+ set_attacks( irank-1, ifile, &bb );
+ set_attacks( irank, ifile-1, &bb );
+ set_attacks( irank, ifile+1, &bb );
+ abb_king_attacks[ irank*nfile + ifile ] = bb;
+
+ BBIni(bb);
+ set_attacks( irank-2, ifile-1, &bb );
+ set_attacks( irank-2, ifile+1, &bb );
+ abb_b_knight_attacks[ irank*nfile + ifile ] = bb;
+
+ BBIni(bb);
+ set_attacks( irank+2, ifile-1, &bb );
+ set_attacks( irank+2, ifile+1, &bb );
+ abb_w_knight_attacks[ irank*nfile + ifile ] = bb;
+
+
+ for ( pcs = 0; pcs < 128; pcs++ ) {
+
BBIni(bb);
- set_attacks( irank-1, ifile-1, &bb );
- set_attacks( irank-1, ifile+1, &bb );
- set_attacks( irank+1, ifile-1, &bb );
- set_attacks( irank+1, ifile+1, &bb );
- set_attacks( irank-1, ifile, &bb );
- abb_b_silver_attacks[ irank*nfile + ifile ] = bb;
-
+ for ( i = -1; irank+i >= 0; i-- ) {
+ set_attacks( irank+i, ifile, &bb );
+ if ( (pcs<<1) & (1 << (8-irank-i)) ) { break; }
+ }
+ for ( i = 1; irank+i <= 8; i++ ) {
+ set_attacks( irank+i, ifile, &bb );
+ if ( (pcs<<1) & (1 << (8-irank-i)) ) { break; }
+ }
+ abb_file_attacks[irank*nfile+ifile][pcs] = bb;
+
BBIni(bb);
- set_attacks( irank-1, ifile-1, &bb );
- set_attacks( irank-1, ifile+1, &bb );
- set_attacks( irank+1, ifile-1, &bb );
- set_attacks( irank+1, ifile+1, &bb );
- set_attacks( irank+1, ifile, &bb );
- abb_w_silver_attacks[ irank*nfile + ifile ] = bb;
-
+ for ( i = -1; ifile+i >= 0; i-- ) {
+ set_attacks( irank, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ }
+ for ( i = 1; ifile+i <= 8; i++ ) {
+ set_attacks( irank, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ }
+ abb_rank_attacks[irank*nfile+ifile][pcs] = bb;
+
BBIni(bb);
- set_attacks( irank-1, ifile-1, &bb );
- set_attacks( irank-1, ifile+1, &bb );
- set_attacks( irank-1, ifile, &bb );
- set_attacks( irank+1, ifile, &bb );
- set_attacks( irank, ifile-1, &bb );
- set_attacks( irank, ifile+1, &bb );
- abb_b_gold_attacks[ irank*nfile + ifile ] = bb;
+ if ( ifile <= irank ) {
- BBIni(bb);
- set_attacks( irank+1, ifile-1, &bb );
- set_attacks( irank+1, ifile+1, &bb );
- set_attacks( irank+1, ifile, &bb );
- set_attacks( irank-1, ifile, &bb );
- set_attacks( irank, ifile-1, &bb );
- set_attacks( irank, ifile+1, &bb );
- abb_w_gold_attacks[ irank*nfile + ifile ] = bb;
+ for ( i = -1; ifile+i >= 0; i-- ) {
+ set_attacks( irank+i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ }
+ for ( i = 1; irank+i <= 8; i++ ) {
+ set_attacks( irank+i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ }
- BBIni(bb);
- set_attacks( irank+1, ifile-1, &bb );
- set_attacks( irank+1, ifile+1, &bb );
- set_attacks( irank+1, ifile, &bb );
- set_attacks( irank-1, ifile-1, &bb );
- set_attacks( irank-1, ifile+1, &bb );
- set_attacks( irank-1, ifile, &bb );
- set_attacks( irank, ifile-1, &bb );
- set_attacks( irank, ifile+1, &bb );
- abb_king_attacks[ irank*nfile + ifile ] = bb;
- }
+ } else {
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nfile; ifile++ )
- {
- BBIni(bb);
- set_attacks( irank-2, ifile-1, &bb );
- set_attacks( irank-2, ifile+1, &bb );
- abb_b_knight_attacks[ irank*nfile + ifile ] = bb;
- }
+ for ( i = -1; irank+i >= 0; i-- ) {
+ set_attacks( irank+i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ }
+ for ( i = 1; ifile+i <= 8; i++ ) {
+ set_attacks( irank+i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ }
+ }
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nfile; ifile++ )
- {
+ abb_bishop_attacks_rl45[irank*nfile+ifile][pcs] = bb;
+
BBIni(bb);
- set_attacks( irank+2, ifile-1, &bb );
- set_attacks( irank+2, ifile+1, &bb );
- abb_w_knight_attacks[ irank*nfile + ifile ] = bb;
- }
-
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nrank; ifile++ )
- for ( pcs = 0; pcs < 128; pcs++ )
- {
- BBIni(bb);
- for ( i = -1; irank+i >= 0; i-- )
- {
- set_attacks( irank+i, ifile, &bb );
- if ( (pcs<<1) & (1 << (8-irank-i)) ) { break; }
- }
- for ( i = 1; irank+i <= 8; i++ )
- {
- set_attacks( irank+i, ifile, &bb );
- if ( (pcs<<1) & (1 << (8-irank-i)) ) { break; }
- }
- abb_file_attacks[irank*nfile+ifile][pcs] = bb;
- }
+ if ( ifile+irank >= 8 ) {
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nrank; ifile++ )
- for ( pcs = 0; pcs < 128; pcs++ )
- {
- BBIni(bb);
- for ( i = -1; ifile+i >= 0; i-- )
- {
- set_attacks( irank, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ for ( i = -1; irank-i <= 8; i-- ) {
+ set_attacks( irank-i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
}
- for ( i = 1; ifile+i <= 8; i++ )
- {
- set_attacks( irank, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
+ for ( i = 1; ifile+i <= 8; i++ ) {
+ set_attacks( irank-i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
}
- ai_rook_attacks_r0[irank*nfile+ifile][pcs] = bb.p[irank/3];
- }
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nrank; ifile++ )
- for ( pcs = 0; pcs < 128; pcs++ )
- {
- BBIni(bb);
- if ( ifile <= irank )
- {
- for ( i = -1; ifile+i >= 0; i-- )
- {
- set_attacks( irank+i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
- }
- for ( i = 1; irank+i <= 8; i++ )
- {
- set_attacks( irank+i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
- }
- }
- else {
- for ( i = -1; irank+i >= 0; i-- )
- {
- set_attacks( irank+i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
- }
- for ( i = 1; ifile+i <= 8; i++ )
- {
- set_attacks( irank+i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (8-ifile-i)) ) { break; }
- }
- }
- abb_bishop_attacks_rl45[irank*nfile+ifile][pcs] = bb;
- }
+ } else {
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nrank; ifile++ )
- for ( pcs = 0; pcs < 128; pcs++ )
- {
- BBIni(bb);
- if ( ifile+irank >= 8 )
- {
- for ( i = -1; irank-i <= 8; i-- )
- {
- set_attacks( irank-i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
- }
- for ( i = 1; ifile+i <= 8; i++ )
- {
- set_attacks( irank-i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
- }
- }
- else {
- for ( i = -1; ifile+i >= 0; i-- )
- {
- set_attacks( irank-i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
- }
- for ( i = 1; irank-i >= 0; i++ )
- {
- set_attacks( irank-i, ifile+i, &bb );
- if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
- }
+ for ( i = -1; ifile+i >= 0; i-- ) {
+ set_attacks( irank-i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
}
- abb_bishop_attacks_rr45[irank*nfile+ifile][pcs] = bb;
- }
-
- for ( i = 0; i < nsquare; i++ )
- {
- aslide[i].ir0 = (unsigned char)(i/27);
- aslide[i].sr0 = (unsigned char)((2-(i/9)%3)*9+1);
- aslide[i].irl90 = (unsigned char)(2-(i%9)/3);
- aslide[i].srl90 = (unsigned char)(((i%9)%3)*9+1);
- }
-
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nfile; ifile++ )
- {
- if ( irank >= ifile )
- {
- aslide[ irank*nfile+ifile ].irl45
- = (unsigned char)((irank-ifile)/3);
- aslide[ irank*nfile+ifile ].srl45
- = (unsigned char)((2-((irank-ifile)%3))*9+1);
+ for ( i = 1; irank-i >= 0; i++ ) {
+ set_attacks( irank-i, ifile+i, &bb );
+ if ( (pcs<<1) & (1 << (irank-i)) ) { break; }
}
- else {
- aslide[ irank*nfile+ifile ].irl45
- = (unsigned char)((9+irank-ifile)/3);
- aslide[ irank*nfile+ifile ].srl45
- = (unsigned char)((2-((9+irank-ifile)%3))*9+1);
}
+ abb_bishop_attacks_rr45[irank*nfile+ifile][pcs] = bb;
}
-
- for ( irank = 0; irank < nrank; irank++ )
- for ( ifile = 0; ifile < nfile; ifile++ )
- {
- if ( ifile+irank >= 8 )
- {
- aslide[ irank*nfile+ifile ].irr45
- = (unsigned char)((irank+ifile-8)/3);
- aslide[ irank*nfile+ifile ].srr45
- = (unsigned char)((2-((irank+ifile-8)%3))*9+1);
- }
- else {
- aslide[ irank*nfile+ifile ].irr45
- = (unsigned char)((irank+ifile+1)/3);
- aslide[ irank*nfile+ifile ].srr45
- = (unsigned char)((2-((irank+ifile+1)%3))*9+1);
- }
+
+ if ( irank >= ifile ) {
+ aslide[irank*nfile+ifile].irl45 = (unsigned char)((irank-ifile)/3);
+ aslide[irank*nfile+ifile].srl45
+ = (unsigned char)((2-((irank-ifile)%3))*9+1);
+ } else {
+ aslide[irank*nfile+ifile].irl45 = (unsigned char)((9+irank-ifile)/3);
+ aslide[irank*nfile+ifile].srl45
+ = (unsigned char)((2-((9+irank-ifile)%3))*9+1);
+ }
+
+ if ( ifile+irank >= 8 ) {
+ aslide[irank*nfile+ifile].irr45 = (unsigned char)((irank+ifile-8)/3);
+ aslide[irank*nfile+ifile].srr45
+ = (unsigned char)((2-((irank+ifile-8)%3))*9+1);
+ } else {
+ aslide[irank*nfile+ifile].irr45 = (unsigned char)((irank+ifile+1)/3);
+ aslide[irank*nfile+ifile].srr45
+ = (unsigned char)((2-((irank+ifile+1)%3))*9+1);
}
+ }
}
static bitboard_t
-bb_set_mask( int isquare )
+bb_set_mask( int sq )
{
bitboard_t bb;
- if ( isquare > 53 )
- {
- bb.p[0] = bb.p[1] = 0;
- bb.p[2] = 1U << (80-isquare);
- }
- else if ( isquare > 26 )
- {
- bb.p[0] = bb.p[2] = 0;
- bb.p[1] = 1U << (53-isquare);
- }
- else {
- bb.p[1] = bb.p[2] = 0;
- bb.p[0] = 1U << (26-isquare);
- }
-
+ BBIni(bb);
+ if ( sq > 53 ) { bb.p[2] = 1U << ( 80 - sq ); }
+ else if ( sq > 26 ) { bb.p[1] = 1U << ( 53 - sq ); }
+ else { bb.p[0] = 1U << ( 26 - sq ); }
+
return bb;
}
ini_check_table( void )
{
bitboard_t bb_check, bb;
- int iking, icheck;
-
- for ( iking = 0; iking < nsquare; iking++ )
- {
- /* black gold */
- BBIni( b_chk_tbl[iking].gold );
- bb_check = abb_w_gold_attacks[iking];
- while ( BBToU(bb_check) )
- {
- icheck = LastOne( bb_check );
- BBOr( b_chk_tbl[iking].gold, b_chk_tbl[iking].gold,
- abb_w_gold_attacks[icheck] );
- Xor( icheck, bb_check );
- }
- BBOr( bb, abb_mask[iking], abb_w_gold_attacks[iking] );
- BBNot( bb, bb );
- BBAnd( b_chk_tbl[iking].gold, b_chk_tbl[iking].gold, bb );
-
- /* black silver */
- BBIni( b_chk_tbl[iking].silver );
- bb_check = abb_w_silver_attacks[iking];
- while ( BBToU(bb_check) )
- {
- icheck = LastOne( bb_check );
- BBOr( b_chk_tbl[iking].silver, b_chk_tbl[iking].silver,
- abb_w_silver_attacks[icheck] );
- Xor( icheck, bb_check );
- }
- bb_check.p[0] = abb_w_gold_attacks[iking].p[0];
- while ( bb_check.p[0] )
- {
- icheck = last_one0( bb_check.p[0] );
- BBOr( b_chk_tbl[iking].silver, b_chk_tbl[iking].silver,
- abb_w_silver_attacks[icheck] );
- bb_check.p[0] ^= abb_mask[icheck].p[0];
- }
- bb_check.p[1] = abb_w_gold_attacks[iking].p[1];
- while ( bb_check.p[1] )
- {
- icheck = last_one1( bb_check.p[1] );
- b_chk_tbl[iking].silver.p[0]
- |= abb_w_silver_attacks[icheck].p[0];
- bb_check.p[1] ^= abb_mask[icheck].p[1];
- }
- BBOr( bb, abb_mask[iking], abb_w_silver_attacks[iking] );
- BBNot( bb, bb );
- BBAnd( b_chk_tbl[iking].silver, b_chk_tbl[iking].silver, bb );
-
- /* black knight */
- BBIni( b_chk_tbl[iking].knight );
- bb_check = abb_w_knight_attacks[iking];
- while ( BBToU(bb_check) )
- {
- icheck = LastOne( bb_check );
- BBOr( b_chk_tbl[iking].knight, b_chk_tbl[iking].knight,
- abb_w_knight_attacks[icheck] );
- Xor( icheck, bb_check );
- }
- bb_check.p[0] = abb_w_gold_attacks[iking].p[0];
- while ( bb_check.p[0] )
- {
- icheck = last_one0( bb_check.p[0] );
- BBOr( b_chk_tbl[iking].knight, b_chk_tbl[iking].knight,
- abb_w_knight_attacks[icheck] );
- bb_check.p[0] ^= abb_mask[icheck].p[0];
- }
-
- /* black lance */
- if ( iking <= I3 ) {
- BBAnd( b_chk_tbl[iking].lance, abb_plus_rays[iking+nfile],
- abb_file_attacks[iking][0] );
- if ( iking <= I7 && iking != A9 && iking != A8 && iking != A7 ) {
- BBAnd( bb, abb_plus_rays[iking-1], abb_file_attacks[iking-1][0] );
- BBOr( b_chk_tbl[iking].lance, b_chk_tbl[iking].lance, bb );
- }
- if ( iking <= I7 && iking != I9 && iking != I8 && iking != I7 ) {
- BBAnd( bb, abb_plus_rays[iking+1], abb_file_attacks[iking+1][0] );
- BBOr( b_chk_tbl[iking].lance, b_chk_tbl[iking].lance, bb );
- }
- } else { BBIni( b_chk_tbl[iking].lance ); }
-
- /* white gold */
- BBIni( w_chk_tbl[iking].gold );
- bb_check = abb_b_gold_attacks[iking];
- while ( BBToU(bb_check) )
- {
- icheck = LastOne( bb_check );
- BBOr( w_chk_tbl[iking].gold, w_chk_tbl[iking].gold,
- abb_b_gold_attacks[icheck] );
- Xor( icheck, bb_check );
- }
- BBOr( bb, abb_mask[iking], abb_b_gold_attacks[iking] );
- BBNot( bb, bb );
- BBAnd( w_chk_tbl[iking].gold, w_chk_tbl[iking].gold, bb );
-
- /* white silver */
- BBIni( w_chk_tbl[iking].silver );
- bb_check = abb_b_silver_attacks[iking];
- while ( BBToU(bb_check) )
- {
- icheck = LastOne( bb_check );
- BBOr( w_chk_tbl[iking].silver, w_chk_tbl[iking].silver,
- abb_b_silver_attacks[icheck] );
- Xor( icheck, bb_check );
- }
- bb_check.p[2] = abb_b_gold_attacks[iking].p[2];
- while ( bb_check.p[2] )
- {
- icheck = first_one2( bb_check.p[2] );
- BBOr( w_chk_tbl[iking].silver, w_chk_tbl[iking].silver,
- abb_b_silver_attacks[icheck] );
- bb_check.p[2] ^= abb_mask[icheck].p[2];
- }
- bb_check.p[1] = abb_b_gold_attacks[iking].p[1];
- while ( bb_check.p[1] )
- {
- icheck = first_one1( bb_check.p[1] );
- w_chk_tbl[iking].silver.p[2]
- |= abb_b_silver_attacks[icheck].p[2];
- bb_check.p[1] ^= abb_mask[icheck].p[1];
- }
- BBOr( bb, abb_mask[iking], abb_b_silver_attacks[iking] );
- BBNot( bb, bb );
- BBAnd( w_chk_tbl[iking].silver, w_chk_tbl[iking].silver, bb );
-
- /* white knight */
- BBIni( w_chk_tbl[iking].knight );
- bb_check = abb_b_knight_attacks[iking];
- while ( BBToU(bb_check) )
- {
- icheck = LastOne( bb_check );
- BBOr( w_chk_tbl[iking].knight, w_chk_tbl[iking].knight,
- abb_b_knight_attacks[icheck] );
- Xor( icheck, bb_check );
- }
- bb_check.p[2] = abb_b_gold_attacks[iking].p[2];
- while ( bb_check.p[2] )
- {
- icheck = first_one2( bb_check.p[2] );
- BBOr( w_chk_tbl[iking].knight, w_chk_tbl[iking].knight,
- abb_b_knight_attacks[icheck] );
- bb_check.p[2] ^= abb_mask[icheck].p[2];
- }
-
- /* white lance */
- if ( iking >= A7 ) {
- BBAnd( w_chk_tbl[iking].lance, abb_minus_rays[iking-nfile],
- abb_file_attacks[iking][0] );
- if ( iking >= A3 && iking != A3 && iking != A2 && iking != A1 ) {
- BBAnd( bb, abb_minus_rays[iking-1], abb_file_attacks[iking-1][0] );
- BBOr( w_chk_tbl[iking].lance, w_chk_tbl[iking].lance, bb );
- }
- if ( iking >= A3 && iking != I3 && iking != I2 && iking != I1 ) {
- BBAnd( bb, abb_minus_rays[iking+1], abb_file_attacks[iking+1][0] );
- BBOr( w_chk_tbl[iking].lance, w_chk_tbl[iking].lance, bb );
- }
- } else { BBIni( w_chk_tbl[iking].lance ); }
- }
+ int iking, sq_chk;
+
+ for ( iking = 0; iking < nsquare; iking++ ) {
+
+ /* black gold */
+ BBIni( b_chk_tbl[iking].gold );
+ bb_check = abb_w_gold_attacks[iking];
+ while ( BBTest(bb_check) )
+ {
+ sq_chk = LastOne( bb_check );
+ BBOr( b_chk_tbl[iking].gold, b_chk_tbl[iking].gold,
+ abb_w_gold_attacks[sq_chk] );
+ Xor( sq_chk, bb_check );
+ }
+ BBOr( bb, abb_mask[iking], abb_w_gold_attacks[iking] );
+ BBNotAnd( b_chk_tbl[iking].gold, b_chk_tbl[iking].gold, bb );
+
+ /* black silver */
+ BBIni( b_chk_tbl[iking].silver );
+ bb_check = abb_w_silver_attacks[iking];
+ while ( BBTest(bb_check) )
+ {
+ sq_chk = LastOne( bb_check );
+ BBOr( b_chk_tbl[iking].silver, b_chk_tbl[iking].silver,
+ abb_w_silver_attacks[sq_chk] );
+ Xor( sq_chk, bb_check );
+ }
+ bb_check.p[0] = abb_w_gold_attacks[iking].p[0];
+ while ( bb_check.p[0] )
+ {
+ sq_chk = last_one0( bb_check.p[0] );
+ BBOr( b_chk_tbl[iking].silver, b_chk_tbl[iking].silver,
+ abb_w_silver_attacks[sq_chk] );
+ bb_check.p[0] ^= abb_mask[sq_chk].p[0];
+ }
+ bb_check.p[1] = abb_w_gold_attacks[iking].p[1];
+ while ( bb_check.p[1] )
+ {
+ sq_chk = last_one1( bb_check.p[1] );
+ b_chk_tbl[iking].silver.p[0]
+ |= abb_w_silver_attacks[sq_chk].p[0];
+ bb_check.p[1] ^= abb_mask[sq_chk].p[1];
+ }
+ BBOr( bb, abb_mask[iking], abb_w_silver_attacks[iking] );
+ BBNotAnd( b_chk_tbl[iking].silver, b_chk_tbl[iking].silver, bb );
+
+ /* black knight */
+ BBIni( b_chk_tbl[iking].knight );
+ bb_check = abb_w_knight_attacks[iking];
+ while ( BBTest(bb_check) )
+ {
+ sq_chk = LastOne( bb_check );
+ BBOr( b_chk_tbl[iking].knight, b_chk_tbl[iking].knight,
+ abb_w_knight_attacks[sq_chk] );
+ Xor( sq_chk, bb_check );
+ }
+ bb_check.p[0] = abb_w_gold_attacks[iking].p[0];
+ while ( bb_check.p[0] )
+ {
+ sq_chk = last_one0( bb_check.p[0] );
+ BBOr( b_chk_tbl[iking].knight, b_chk_tbl[iking].knight,
+ abb_w_knight_attacks[sq_chk] );
+ bb_check.p[0] ^= abb_mask[sq_chk].p[0];
+ }
+
+ /* black lance */
+ if ( iking <= I3 ) {
+ BBAnd( b_chk_tbl[iking].lance, abb_plus_rays[iking+nfile],
+ abb_file_attacks[iking][0] );
+ if ( iking <= I7 && iking != A9 && iking != A8 && iking != A7 ) {
+ BBAnd( bb, abb_plus_rays[iking-1], abb_file_attacks[iking-1][0] );
+ BBOr( b_chk_tbl[iking].lance, b_chk_tbl[iking].lance, bb );
+ }
+ if ( iking <= I7 && iking != I9 && iking != I8 && iking != I7 ) {
+ BBAnd( bb, abb_plus_rays[iking+1], abb_file_attacks[iking+1][0] );
+ BBOr( b_chk_tbl[iking].lance, b_chk_tbl[iking].lance, bb );
+ }
+ } else { BBIni( b_chk_tbl[iking].lance ); }
+
+ /* white gold */
+ BBIni( w_chk_tbl[iking].gold );
+ bb_check = abb_b_gold_attacks[iking];
+ while ( BBTest(bb_check) )
+ {
+ sq_chk = LastOne( bb_check );
+ BBOr( w_chk_tbl[iking].gold, w_chk_tbl[iking].gold,
+ abb_b_gold_attacks[sq_chk] );
+ Xor( sq_chk, bb_check );
+ }
+ BBOr( bb, abb_mask[iking], abb_b_gold_attacks[iking] );
+ BBNotAnd( w_chk_tbl[iking].gold, w_chk_tbl[iking].gold, bb );
+
+ /* white silver */
+ BBIni( w_chk_tbl[iking].silver );
+ bb_check = abb_b_silver_attacks[iking];
+ while ( BBTest(bb_check) )
+ {
+ sq_chk = LastOne( bb_check );
+ BBOr( w_chk_tbl[iking].silver, w_chk_tbl[iking].silver,
+ abb_b_silver_attacks[sq_chk] );
+ Xor( sq_chk, bb_check );
+ }
+ bb_check.p[2] = abb_b_gold_attacks[iking].p[2];
+ while ( bb_check.p[2] )
+ {
+ sq_chk = first_one2( bb_check.p[2] );
+ BBOr( w_chk_tbl[iking].silver, w_chk_tbl[iking].silver,
+ abb_b_silver_attacks[sq_chk] );
+ bb_check.p[2] ^= abb_mask[sq_chk].p[2];
+ }
+ bb_check.p[1] = abb_b_gold_attacks[iking].p[1];
+ while ( bb_check.p[1] )
+ {
+ sq_chk = first_one1( bb_check.p[1] );
+ w_chk_tbl[iking].silver.p[2]
+ |= abb_b_silver_attacks[sq_chk].p[2];
+ bb_check.p[1] ^= abb_mask[sq_chk].p[1];
+ }
+ BBOr( bb, abb_mask[iking], abb_b_silver_attacks[iking] );
+ BBNotAnd( w_chk_tbl[iking].silver, w_chk_tbl[iking].silver, bb );
+
+ /* white knight */
+ BBIni( w_chk_tbl[iking].knight );
+ bb_check = abb_b_knight_attacks[iking];
+ while ( BBTest( bb_check ) )
+ {
+ sq_chk = LastOne( bb_check );
+ BBOr( w_chk_tbl[iking].knight, w_chk_tbl[iking].knight,
+ abb_b_knight_attacks[sq_chk] );
+ Xor( sq_chk, bb_check );
+ }
+ bb_check.p[2] = abb_b_gold_attacks[iking].p[2];
+ while ( bb_check.p[2] )
+ {
+ sq_chk = first_one2( bb_check.p[2] );
+ BBOr( w_chk_tbl[iking].knight, w_chk_tbl[iking].knight,
+ abb_b_knight_attacks[sq_chk] );
+ bb_check.p[2] ^= abb_mask[sq_chk].p[2];
+ }
+
+ /* white lance */
+ if ( iking >= A7 ) {
+ BBAnd( w_chk_tbl[iking].lance, abb_minus_rays[iking-nfile],
+ abb_file_attacks[iking][0] );
+ if ( iking >= A3 && iking != A3 && iking != A2 && iking != A1 ) {
+ BBAnd( bb, abb_minus_rays[iking-1], abb_file_attacks[iking-1][0] );
+ BBOr( w_chk_tbl[iking].lance, w_chk_tbl[iking].lance, bb );
+ }
+ if ( iking >= A3 && iking != I3 && iking != I2 && iking != I1 ) {
+ BBAnd( bb, abb_minus_rays[iking+1], abb_file_attacks[iking+1][0] );
+ BBOr( w_chk_tbl[iking].lance, w_chk_tbl[iking].lance, bb );
+ }
+ } else { BBIni( w_chk_tbl[iking].lance ); }
+ }
}
first_one00( int pcs )
{
int i;
-
+
for ( i = 0; i < 9; i++ ) { if ( pcs & (1<<(8-i)) ) { break; } }
return i;
}
last_one00( int pcs )
{
int i;
-
+
for ( i = 8; i >= 0; i-- ) { if ( pcs & (1<<(8-i)) ) { break; } }
return i;
}
# define OutBoard0(a,b,c,d,e,f) out_board0(a,b,c,d,e,f)
#endif
-static int check_input_buffer( void );
-static int read_command( char **pstr_line_end );
-static void out_hand( FILE *pf, unsigned int hand, const char *str_prefix );
-static void out_hand0( FILE *pf, int n, const char *str_prefix,
- const char *str );
+static void CONV out_file( FILE *pf, const char *format, ... );
+static int CONV check_input_buffer( void );
+static int CONV read_command( char **pstr_line_end );
+static void CONV out_hand( FILE *pf, unsigned int hand,
+ const char *str_prefix );
+static void CONV out_hand0( FILE *pf, int n, const char *str_prefix,
+ const char *str );
#if ! ( defined(NO_STDOUT) && defined(NO_LOGGING) )
void
out( const char *format, ... )
{
va_list arg;
- if ( game_status & flag_quiet ) { return; }
# if ! defined(NO_STDOUT)
+ if ( !( game_status & flag_nostdout ) )
+ {
+ va_start( arg, format );
+ vprintf( format, arg );
+ va_end( arg );
+ fflush( stdout );
+ }
+# endif
+
+# if ! defined(NO_LOGGING)
+ if ( ( strchr( format, '\n' ) != NULL || strchr( format, '\r' ) == NULL )
+ && pf_log != NULL )
+ {
+ va_start( arg, format );
+ vfprintf( pf_log, format, arg );
+ va_end( arg );
+ fflush( pf_log );
+ }
+# endif
+}
+#endif
+
+
+#if defined(USI)
+void CONV
+usi_out( const char *format, ... )
+{
+ va_list arg;
+
va_start( arg, format );
vprintf( format, arg );
va_end( arg );
fflush( stdout );
-# endif
# if ! defined(NO_LOGGING)
if ( ( strchr( format, '\n' ) != NULL || strchr( format, '\r' ) == NULL )
&& pf_log != NULL )
{
+ fprintf( pf_log, "OUT: " );
va_start( arg, format );
vfprintf( pf_log, format, arg );
va_end( arg );
void
-out_file( FILE *pf, const char *format, ... )
+out_warning( const char *format, ... )
{
va_list arg;
- if ( pf != NULL )
+#if defined(TLP) || defined(DFPN_CLIENT)
+ lock( &io_lock );
+#endif
+
+ if ( !( game_status & flag_nostdout ) )
{
+ fprintf( stderr, "\n%s", str_warning );
va_start( arg, format );
- vfprintf( pf, format, arg );
+ vfprintf( stderr, format, arg );
va_end( arg );
- fflush( pf );
+ fprintf( stderr, "\n\n" );
+ fflush( stderr );
}
-
+
#if ! defined(NO_LOGGING)
if ( pf_log != NULL )
{
+ fprintf( pf_log, "\n%s", str_warning );
va_start( arg, format );
vfprintf( pf_log, format, arg );
va_end( arg );
+ fprintf( pf_log, "\n\n" );
fflush( pf_log );
}
#endif
+#if defined(TLP) || defined(DFPN_CLIENT)
+ unlock( &io_lock );
+#endif
}
void
-out_warning( const char *format, ... )
+out_error( const char *format, ... )
{
va_list arg;
- fprintf( stderr, "\n%s", str_warning );
- va_start( arg, format );
- vfprintf( stderr, format, arg );
- va_end( arg );
- fprintf( stderr, "\n\n" );
- fflush( stderr );
-
-#if ! defined(NO_LOGGING)
- if ( pf_log != NULL )
+ if ( !( game_status & flag_nostdout ) )
{
- fprintf( pf_log, "\n%s", str_warning );
+ fprintf( stderr, "\nERROR: " );
va_start( arg, format );
- vfprintf( pf_log, format, arg );
+ vfprintf( stderr, format, arg );
va_end( arg );
- fprintf( pf_log, "\n\n" );
- fflush( pf_log );
+ fprintf( stderr, "\n\n" );
+ fflush( stderr );
}
-#endif
-
-}
-
-void
-out_error( const char *format, ... )
-{
- va_list arg;
-
- fprintf( stderr, "\nERROR: " );
- va_start( arg, format );
- vfprintf( stderr, format, arg );
- va_end( arg );
- fprintf( stderr, "\n\n" );
- fflush( stderr );
-
#if ! defined(NO_LOGGING)
if ( pf_log != NULL )
{
{
if ( game_status & flag_noprompt ) { return; }
-#if defined(DEKUNOBOU)
- if ( dek_ngame )
- {
- Out( "Won=%3d Lost=%3d Total=%4d/", dek_win, dek_lost, dek_ngame-1 );
- }
-#endif
-
if ( game_status & flag_drawn ) { Out( "Drawn> " ); }
else if ( game_status & flag_mated )
{
iret = record_close( &record_game );
if ( iret < 0 ) { return -1; }
- strncpy( str_file, "game.csa", SIZE_FILENAME-1 );
- iret = record_open( &record_game, str_file, mode_read_write,
+ iret = record_open( &record_game, "game.csa", mode_read_write,
str_name1, str_name2 );
if ( iret < 0 ) { return -1; }
return 1;
}
- iret = file_close( pf_log );
- if ( iret < 0 ) { return -1; }
-
- iret = record_close( &record_game );
- if ( iret < 0 ) { return -1; }
-
- for ( i = 0; i < 999; i++ )
+ if ( ( ( game_status & flag_nonewlog )
+# if defined(USI)
+ || usi_mode != usi_off
+# endif
+ ) && 0 <= record_num )
+ {
+ iret = record_close( &record_game );
+ if ( iret < 0 ) { return -1; }
+
+ snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
+ str_dir_logs, record_num );
+ iret = record_open( &record_game, str_file, mode_read_write,
+ str_name1, str_name2 );
+ if ( iret < 0 ) { return -1; }
+ }
+ else
{
+ iret = file_close( pf_log );
+ if ( iret < 0 ) { return -1; }
+
+ iret = record_close( &record_game );
+ if ( iret < 0 ) { return -1; }
+
+ for ( i = 0; i < 999; i++ )
+ {
+ snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
+ str_dir_logs, i );
+ pf = file_open( str_file, "r" );
+ if ( pf == NULL ) { break; }
+ iret = file_close( pf );
+ if ( iret < 0 ) { return -1; }
+ }
+ record_num = i;
+
+ snprintf( str_file, SIZE_FILENAME, "%s/n%03d.log",
+ str_dir_logs, i );
+ pf_log = file_open( str_file, "w" );
+ if ( pf_log == NULL ) { return -1; }
+
snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
- str_dir_logs, i );
- pf = file_open( str_file, "r" );
- if ( pf == NULL ) { break; }
- iret = file_close( pf );
+ str_dir_logs, i );
+ iret = record_open( &record_game, str_file, mode_read_write,
+ str_name1, str_name2 );
if ( iret < 0 ) { return -1; }
}
- irecord_game = i;
-
- snprintf( str_file, SIZE_FILENAME, "%s/n%03d.log",
- str_dir_logs, i );
- pf_log = file_open( str_file, "w" );
- if ( pf_log == NULL ) { return -1; }
-
- snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
- str_dir_logs, i );
- iret = record_open( &record_game, str_file, mode_read_write,
- str_name1, str_name2 );
- if ( iret < 0 ) { return -1; }
-
+
return 1;
#endif
}
int is_promote;
#endif
+ if ( game_status & flag_nostdout ) { return 1; }
+
if ( ! is_strict && move )
{
ito = I2To( move );
}
}
else {
-#if defined(DEKUNOBOU)
- if ( dek_ngame )
- {
- iret = dek_check();
- goto tag;
- }
-#endif
-
-#if defined(CSA_LAN)
- if ( sckt_csa != SCKT_NULL )
- {
- iret = sckt_check( sckt_csa );
- goto tag;
- }
-#endif
-
-#if defined(MNJ_LAN)
- if ( sckt_mnj != SCKT_NULL )
- {
- iret = sckt_check( sckt_mnj );
- goto tag;
- }
-#endif
iret = check_input_buffer();
-
-#if defined(DEKUNOBOU) || defined(CSA_LAN) || defined(MNJ_LAN)
- tag:
-#endif
if ( iret <= 0 ) { return iret; }
iret = read_command( & str_line_end );
memcpy( str_cmdline, str_buffer_cmdline, size );
*( str_cmdline + size ) = '\0';
-#if defined(DEKUNOBOU)
- if ( dek_ngame )
- {
- iret = dek_parse( str_cmdline, SIZE_CMDLINE );
- if ( iret < 0 )
- {
- memmove( str_buffer_cmdline, str_line_end + 1,
- strlen( str_line_end + 1 ) + 1 );
- return iret;
- }
- }
-#endif
-
if ( is_wait )
{
out_file( NULL, "%s\n", str_cmdline );
#endif /* no NO_STDOUT and no WIN32_PIPE */
-static void
+static void CONV
out_hand( FILE *pf, unsigned int hand, const char *str_prefix )
{
out_hand0( pf, (int)I2HandPawn(hand), str_prefix, "00FU" );
}
-static void
+static void CONV
out_hand0( FILE *pf, int n, const char *str_prefix, const char *str )
{
int i;
}
-static int
+static int CONV
read_command( char ** pstr_line_end )
{
char *str_end;
count_cmdbuff = (int)strlen( str_buffer_cmdline );
str_end = str_buffer_cmdline + count_cmdbuff;
-#if defined(DEKUNOBOU)
- if ( dek_ngame )
- {
- count_byte = dek_in( str_end, SIZE_CMDLINE-1-count_cmdbuff );
- if ( count_byte < 0 ) { return count_byte; }
- goto tag;
- }
-#endif
-
#if defined(CSA_LAN)
if ( sckt_csa != SCKT_NULL )
{
}
#endif
+#if defined(DFPN)
+ if ( dfpn_sckt != SCKT_NULL )
+ {
+ count_byte = sckt_in( dfpn_sckt, str_end, SIZE_CMDLINE-1-count_cmdbuff );
+ if ( count_byte < 0 ) { return count_byte; }
+ goto tag;
+ }
+#endif
+
do { count_byte = (int)read( 0, str_end, SIZE_CMDBUFFER-1-count_cmdbuff ); }
while ( count_byte < 0 && errno == EINTR );
}
*( str_end + count_byte ) = '\0';
-#if defined(DEKUNOBOU) || defined(CSA_LAN) || defined(MNJ_LAN)
+#if defined(CSA_LAN) || defined(MNJ_LAN) || defined(DFPN)
tag:
#endif
+#if defined(USI)
+ if ( usi_mode != usi_off ) { Out( "IN: %s[END]\n", str_end );}
+#endif
*pstr_line_end = strchr( str_buffer_cmdline, '\n' );
if ( *pstr_line_end == NULL
return count_byte;
}
-#if defined(_WIN32)
-static int
+static int CONV
check_input_buffer( void )
{
-# if defined(WIN32_PIPE)
- BOOL bSuccess;
- HANDLE hHandle;
- DWORD dwBytesRead, dwTotalBytesAvail, dwBytesLeftThisMessage;
- char buf[1];
+#if defined(CSA_LAN)
+ if ( sckt_csa != SCKT_NULL ) { return sckt_check( sckt_csa ); }
+#endif
+
+#if defined(MNJ_LAN)
+ if ( sckt_mnj != SCKT_NULL ) { return sckt_check( sckt_mnj ); }
+#endif
- hHandle = GetStdHandle( STD_INPUT_HANDLE );
- if ( hHandle == INVALID_HANDLE_VALUE )
- {
- str_error = "GetStdHandle() faild.";
- return -1;
- }
- bSuccess = PeekNamedPipe( hHandle, buf, 1, &dwBytesRead, &dwTotalBytesAvail,
- &dwBytesLeftThisMessage );
- if ( ! bSuccess )
- {
- str_error = "PeekNamedPipe() faild.";
- return -1;
- }
- if ( dwBytesRead ) { return 1; }
- return 0;
-# else
- return _kbhit();
+#if defined(DFPN)
+ if ( dfpn_sckt != SCKT_NULL ) { return sckt_check( dfpn_sckt ); }
+#endif
+
+ {
+#if defined(_WIN32) && defined(WIN32_PIPE)
+ BOOL bSuccess;
+ HANDLE hHandle;
+ DWORD dwBytesRead, dwTotalBytesAvail, dwBytesLeftThisMessage;
+ char buf[1];
+
+ hHandle = GetStdHandle( STD_INPUT_HANDLE );
+ if ( hHandle == INVALID_HANDLE_VALUE )
+ {
+ str_error = "GetStdHandle() faild.";
+ return -1;
+ }
+ bSuccess = PeekNamedPipe( hHandle, buf, 1, &dwBytesRead,
+ &dwTotalBytesAvail, &dwBytesLeftThisMessage );
+ if ( ! bSuccess )
+ {
+ str_error = "PeekNamedPipe() faild.";
+ return -1;
+ }
+ if ( dwBytesRead ) { return 1; }
+ return 0;
+
+#elif defined(_WIN32)
+
+ return _kbhit();
+
+#else
+
+ fd_set readfds;
+ struct timeval tv;
+ int iret;
+
+# if defined(__ICC)
+# pragma warning(disable:279)
+# pragma warning(disable:593)
+# pragma warning(disable:1469)
+# endif
+
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ iret = select( 1, &readfds, NULL, NULL, &tv );
+ if ( iret == -1 )
+ {
+ str_error = "select() faild.";
+ return -1;
+ }
+ return iret;
+
+# if defined(__ICC)
+# pragma warning(default:279)
+# pragma warning(default:593)
+# pragma warning(default:1469)
# endif
+#endif /* no _WIN32 */
+ }
}
-#else /* no _WIN32 */
-static int
-check_input_buffer( void )
+static void CONV
+out_file( FILE *pf, const char *format, ... )
{
- fd_set readfds;
- struct timeval tv;
- int iret;
-
-#if defined(__ICC)
-# pragma warning(disable:279)
-# pragma warning(disable:593)
-# pragma warning(disable:1469)
-#endif
+ va_list arg;
- FD_ZERO(&readfds);
- FD_SET(0, &readfds);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- iret = select( 1, &readfds, NULL, NULL, &tv );
- if ( iret == -1 )
+ if ( pf != NULL )
{
- str_error = "select() faild.";
- return -1;
+ va_start( arg, format );
+ vfprintf( pf, format, arg );
+ va_end( arg );
+ fflush( pf );
+ }
+
+#if ! defined(NO_LOGGING)
+ if ( pf_log != NULL )
+ {
+ va_start( arg, format );
+ vfprintf( pf_log, format, arg );
+ va_end( arg );
+ fflush( pf_log );
}
- return iret;
-
-#if defined(__ICC)
-# pragma warning(default:279)
-# pragma warning(default:593)
-# pragma warning(default:1469)
#endif
-}
-#endif /* no _WIN32 */
+}
#include <stdlib.h>
#include "shogi.h"
-static void adjust_fmg( void );
-static int ini_hash( void );
-static int set_root_alpha( int nfail_low, int root_alpha_old );
-static int set_root_beta( int nfail_high, int root_beta_old );
-static int is_answer_right( unsigned int move );
-static const char *str_fail_high( int turn, int nfail_high );
+static void CONV adjust_fmg( void );
+static int CONV set_root_alpha( int nfail_low, int root_alpha_old );
+static int CONV set_root_beta( int nfail_high, int root_beta_old );
+static int CONV is_answer_right( unsigned int move );
+static int CONV rep_book_prob( tree_t * restrict ptree );
+static const char * CONV str_fail_high( int turn, int nfail_high );
-static int rep_book_prob( tree_t * restrict ptree )
+int CONV
+iterate( tree_t * restrict ptree )
{
- int i;
-
- for ( i = root_nrep - 2; i >= 0; i -= 2 )
- if ( ptree->rep_board_list[i] == HASH_KEY
- && ptree->rep_hand_list[i] == HAND_B )
- {
- Out( "- book is ignored due to a repetition.\n" );
- return 1;
- }
-
- return 0;
-}
-
-
-int
-iterate( tree_t * restrict ptree, int flag )
-{
- int value, iret, ply, is_hash_learn_stored;
+ int value, iret, ply;
unsigned int cpu_start;
int right_answer_made;
/* probe the opening book */
- if ( pf_book != NULL && n_nobook_move < 7 && ! rep_book_prob( ptree ) )
+ if ( pf_book != NULL
+#if defined(USI) || defined(MNJ_LAN)
+ && moves_ignore[0] == MOVE_NA
+#endif
+ && ! rep_book_prob( ptree ) )
{
int is_book_hit, i;
unsigned int elapsed;
-
+
is_book_hit = book_probe( ptree );
if ( is_book_hit < 0 ) { return is_book_hit; }
-
+
iret = get_elapsed( &elapsed );
if ( iret < 0 ) { return iret; }
pv_close( ptree, 2, book_hit );
last_pv = ptree->pv[1];
last_root_value = 0;
- n_nobook_move = 0;
if ( ! ( game_status & flag_puzzling ) )
{
- for ( i = 0; i < HIST_SIZE; i++ )
+ for ( i = 0; i < (int)HIST_SIZE; i++ )
{
ptree->hist_good[i] /= 256U;
ptree->hist_tried[i] /= 256U;
}
}
+ MnjOut( "pid=%d move=%s n=0 v=0e final%s\n",
+ mnj_posi_id, str_CSA_move(ptree->pv[1].a[1]),
+ ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+
- MnjOut( "pid=%d move=%s v=0b n=0 confident\n", mnj_posi_id,
- str_CSA_move(ptree->pv[1].a[1]) );
+#if defined(USI)
+ if ( usi_mode != usi_off )
+ {
+ char str_usi[6];
+ csa2usi( ptree, str_CSA_move(ptree->pv[1].a[1]), str_usi );
+ USIOut( "info depth 1 score cp 0 nodes 0 pv %s\n", str_usi );
+ }
+#endif
return 1;
}
- if ( ! ( game_status & ( flag_puzzling | flag_pondering ) ) )
+ }
+
+ /* detect inaniwa tactics */
+#if defined(INANIWA_SHIFT)
+ if ( ! inaniwa_flag && 19 < ptree->nrep )
+ {
+ if ( root_turn == white
+ && ( BOARD[A7]==-pawn || BOARD[A6]==-pawn || BOARD[A5]==-pawn )
+ && BOARD[B7] == -pawn && BOARD[C7] == -pawn
+ && BOARD[D7] == -pawn && BOARD[E7] == -pawn
+ && BOARD[F7] == -pawn && BOARD[G7] == -pawn
+ && BOARD[H7] == -pawn
+ && ( BOARD[I7]==-pawn || BOARD[I6]==-pawn || BOARD[I5]==-pawn ) )
+ {
+ Out( "\nINANIWA SHIFT TURNED ON (BLACK)\n\n" );
+ inaniwa_flag = 1;
+ ehash_clear();
+ if ( ini_trans_table() < 0 ) { return -1; }
+ }
+
+ if ( root_turn == black
+ && ( BOARD[A3]==pawn || BOARD[A4]==pawn || BOARD[A5] == pawn )
+ && BOARD[B3] == pawn && BOARD[C3] == pawn
+ && BOARD[D3] == pawn && BOARD[E3] == pawn
+ && BOARD[F3] == pawn && BOARD[G3] == pawn
+ && BOARD[H3] == pawn
+ && ( BOARD[I3]==pawn || BOARD[I4]==pawn || BOARD[I5]==pawn ) )
{
- n_nobook_move += 1;
+ Out( "\nINANIWA SHIFT TURNED ON (WHITE)\n\n" );
+ inaniwa_flag = 2;
+ ehash_clear();
+ if ( ini_trans_table() < 0 ) { return -1; }
}
}
+#endif
+
/* initialize variables */
if ( get_cputime( &cpu_start ) < 0 ) { return -1; }
ptree->node_searched = 0;
- ptree->nreject_done = 0;
- ptree->nreject_tried = 0;
ptree->null_pruning_done = 0;
ptree->null_pruning_tried = 0;
ptree->check_extension_done = 0;
ptree->fail_high = 0;
ptree->fail_high_first = 0;
ptree->current_move[0] = 0;
+ ptree->save_eval[0] = INT_MAX;
+ ptree->save_eval[1] = INT_MAX;
ptree->pv[0].a[0] = 0;
ptree->pv[0].a[1] = 0;
ptree->pv[0].depth = 0;
easy_value = 0;
easy_abs = 0;
right_answer_made = 0;
- is_hash_learn_stored = 0;
root_abort = 0;
root_nmove = 0;
root_value = -score_bound;
root_alpha = -score_bound;
root_beta = score_bound;
- root_move_cap = 0;
+ root_index = 0;
+ root_move_list[0].status = flag_first;
node_last_check = 0;
- time_last_eff_search = time_start;
time_last_check = time_start;
game_status &= ~( flag_move_now | flag_suspend
| flag_quit_ponder | flag_search_error );
easy_move = 0;
#endif
+#if defined(USI)
+ usi_time_out_last = time_start;
+#endif
+
#if defined(TLP)
ptree->tlp_abort = 0;
tlp_nsplit = 0;
else { root_mpv = 0; }
#endif
+#if defined(DFPN_CLIENT)
+ dfpn_client_rresult_unlocked = dfpn_client_na;
+ dfpn_client_move_unlocked = MOVE_NA;
+ dfpn_client_best_move = MOVE_NA;
+ dfpn_client_cresult_index = 0;
+#endif
for ( ply = 0; ply < PLY_MAX; ply++ )
{
set_search_limit_time( root_turn );
adjust_fmg();
+ Out( "nsuc_check: [0]=%d [1]=%d\n",
+ (int)ptree->nsuc_check[0], (int)ptree->nsuc_check[1] );
+
/* look up last pv. */
if ( last_pv.length )
{
Out( "- a pv was found in the previous search result.\n" );
- iteration_depth = last_pv.depth;
+ iteration_depth = ( iteration_depth < 1 ) ? 0 : last_pv.depth - 1;
ptree->pv[0] = last_pv;
ptree->pv[0].type = prev_solution;
root_value = root_turn ? -last_root_value : last_root_value;
#endif
)
{
- unsigned int value_type;
+ unsigned int value_type, dummy;
int alpha, beta;
- iret = ini_hash();
- if ( iret < 0 ) { return iret; }
- is_hash_learn_stored = 1;
-
value = INT_MIN;
for ( ply = 1; ply < PLY_MAX - 10; ply++ )
{
+ dummy = 0;
alpha = -score_bound;
beta = score_bound;
value_type = hash_probe( ptree, 1, ply*PLY_INC+PLY_INC/2,
- root_turn, alpha, beta, 0 );
+ root_turn, alpha, beta, &dummy );
if ( value_type != value_exact ) { break; }
value = HASH_VALUE;
}
if ( ! ptree->pv[0].length )
{
- iteration_depth = 0;
+ iteration_depth = 0;
ptree->pv[0].depth = 0;
- root_value = -score_bound;
+ root_value = -score_bound;
#if ! defined(MINIMUM)
out_warning( "PEEK FAILED!!!" );
#endif
unsigned int elapsed;
Out( "- root move generation" );
- value = make_root_move_list( ptree, flag );
- if ( game_status & flag_search_error ) { return -1; }
- if ( game_status & ( flag_quit | flag_quit_ponder | flag_suspend ) )
- {
- return 1;
- }
+ value = make_root_move_list( ptree );
if ( ! root_nmove )
{
- str_error = "No legal moves to search";
+#if defined(MNJ_LAN) || defined(USI)
+ if ( moves_ignore[0] != MOVE_NA )
+ {
+ MnjOut( "pid=%d move=%%TORYO v=%de n=0 final%s\n",
+ mnj_posi_id, -score_bound,
+ ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+
+ return 1;
+ }
+#endif
+ str_error = str_no_legal_move;
return -2;
}
ptree->pv[0].depth = 1;
ptree->pv[0].type = no_rep;
root_value = value;
+ root_index = 0;
}
#if defined(MPV)
}
+#if defined(DFPN_CLIENT)
+ /* probe results from DFPN searver */
+ dfpn_client_check_results();
+ if ( dfpn_client_move_unlocked != MOVE_NA )
+ {
+ ptree->pv[0].a[1] = dfpn_client_move_unlocked;
+ ptree->pv[0].length = 1;
+ ptree->pv[0].depth = 0;
+ ptree->pv[0].type = no_rep;
+ root_value = score_matelong;
+ }
+#endif
+
+
/* save preliminary result */
assert( root_value != -score_bound );
last_root_value = root_turn ? -root_value : root_value;
last_pv = ptree->pv[0];
-#if defined(MNJ_LAN)
- if ( sckt_mnj != SCKT_NULL )
+
+#if defined(DFPN_CLIENT)
+ /* send the best move to DFPN server */
+ if ( dfpn_client_sckt != SCKT_NULL
+ && dfpn_client_best_move != ptree->pv[0].a[1] )
{
- const char *str = ( root_nmove == 1 ) ? "confident" : "";
+ dfpn_client_best_move = ptree->pv[0].a[1];
+ lock( &dfpn_client_lock );
+ dfpn_client_out( "BEST MOVE %s\n", str_CSA_move(dfpn_client_best_move) );
+ unlock( &dfpn_client_lock );
+ }
+#endif
+
+
+#if 0 && defined(MNJ_LAN)
+ /* send the best move to parallel server */
+ if ( sckt_mnj != SCKT_NULL ) {
- MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 " %s\n",
+ if ( moves_ignore[0] == MOVE_NA && root_nmove == 1 ) {
+ /* only one replay */
+ MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 " final%s\n",
mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
- ptree->node_searched, str );
+ ptree->node_searched,
+ ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+
+ return 1;
}
+
+ MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "\n",
+ mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
+ ptree->node_searched );
+ }
#endif
+ MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "\n",
+ mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
+ ptree->node_searched );
+
+#if defined(USI)
+ if ( usi_mode != usi_off )
+ {
+ char str_usi[6];
+ csa2usi( ptree, str_CSA_move(ptree->pv[0].a[1]), str_usi );
+ USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv %s\n",
+ iteration_depth, root_value, ptree->node_searched, str_usi );
+ }
+#endif
+
/* return, if previous pv is long enough */
if ( abs(root_value) > score_max_eval
return 1;
}
- if ( ! is_hash_learn_stored )
- {
- iret = ini_hash();
- if ( iret < 0 ) { return iret; }
- }
/* iterative deepening search */
#if defined(TLP)
root_beta = set_root_beta( 0, root_value );
root_alpha = set_root_alpha( 0, root_value );
root_value = root_alpha;
- add_rejections( ptree, root_turn, 1 );
+
Out( "- drive an iterative deepening search starting from depth %d\n",
iteration_depth );
for ( ; iteration_depth < 30/*PLY_MAX-10*/; iteration_depth++ ) {
- MnjOut( "pid=%d d=%d\n", mnj_posi_id, iteration_depth );
-
-
if ( get_elapsed( &time_last_search ) < 0 ) { return -1; }
#if defined(MPV)
double dvalue;
root_move_list[0].status &= ~flag_searched;
- root_move_list[0].status |= flag_failhigh;
dvalue = (double)( root_turn ? -root_beta : root_beta );
do { root_beta = set_root_beta( ++root_nfail_high, root_beta ); }
while ( value >= root_beta );
+#if defined(DFPN_CLIENT)
+ if ( dfpn_client_sckt != SCKT_NULL
+ && 4 < iteration_depth
+ && dfpn_client_best_move != ptree->pv[1].a[1] )
+ {
+ dfpn_client_best_move = ptree->pv[1].a[1];
+ lock( &dfpn_client_lock );
+ dfpn_client_out( "BEST MOVE %s\n",
+ str_CSA_move(dfpn_client_best_move) );
+ unlock( &dfpn_client_lock );
+ }
+#endif
+ MnjOut( "pid=%d move=%s v=%dl n=%" PRIu64 "%s\n",
+ mnj_posi_id, str_CSA_move(ptree->pv[1].a[1]),
+ root_beta, ptree->node_searched,
+ ( mnj_depth_stable <= iteration_depth ) ? " stable" : "" );
+
+#if defined(USI)
+ if ( usi_mode != usi_off )
+ {
+ char str_usi[6];
+ csa2usi( ptree, str_CSA_move(ptree->pv[1].a[1]), str_usi );
+ USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv %s\n",
+ iteration_depth, root_beta, ptree->node_searched,
+ str_usi );
+ }
+#endif
+
str = str_time_symple( time_last_result - time_start );
if ( root_move_list[0].status & flag_first )
{
}
else { Out( " %6s %7.2f ", str, dvalue / 100.0 ); }
- str = str_fail_high( root_turn, root_nfail_high );
-
- MnjOut( "pid=%d move=%s v=%dl n=%" PRIu64 "\n", mnj_posi_id,
- str_CSA_move(ptree->pv[1].a[1]), root_beta,
- ptree->node_searched );
-
- str_move = str_CSA_move_plus( ptree, ptree->pv[1].a[1], 1,
- root_turn );
+ str = str_fail_high( root_turn, root_nfail_high );
+ str_move = str_CSA_move(ptree->pv[1].a[1]);
Out( " 1.%c%s [%s!]\n", ach_turn[root_turn], str_move, str );
}
root_move_list[0].status &= ~flag_searched;
- root_move_list[0].status |= flag_faillow;
dvalue = (double)( root_turn ? -root_alpha : root_alpha );
if ( get_elapsed( &time_elapsed ) < 0 ) { return -1; }
Out( "(%2d)%6s %7.2f ", iteration_depth, str, dvalue / 100.0 );
str = str_fail_high( Flip(root_turn), root_nfail_low );
- str_move = str_CSA_move_plus( ptree, root_move_list[0].move, 1,
- root_turn );
+ str_move = str_CSA_move(root_move_list[0].move);
Out( " 1.%c%s [%s?]\n", ach_turn[root_turn], str_move, str );
if ( game_status & flag_pondering )
{
else { break; }
}
- /* the trial of search ended */
+ /* the trial of search is finished */
if ( root_alpha < root_value && root_value < root_beta )
{
last_root_value = root_turn ? - root_value : root_value;
}
}
- /* iteration ended */
- sub_rejections( ptree, root_turn, 1 );
-
+ /* iteration finished */
if ( game_status & flag_problem )
{
if ( is_answer_right( ptree->pv[0].a[1] ) )
{
int i;
- for ( i = 0; i < HIST_SIZE; i++ )
+ for ( i = 0; i < (int)HIST_SIZE; i++ )
{
ptree->hist_good[i] /= 256U;
ptree->hist_tried[i] /= 256U;
}
/* prunings and extentions-statistics */
{
- double drep, dreject, dhash, dnull, dfh1st;
+ double drep, dhash, dnull, dfh1st;
drep = (double)ptree->nperpetual_check;
drep += (double)ptree->nfour_fold_rep;
drep += (double)ptree->nsuperior_rep;
drep *= 100.0 / (double)( ptree->nrep_tried + 1 );
- dreject = 100.0 * (double)ptree->nreject_done;
- dreject /= (double)( ptree->nreject_tried + 1 );
-
dhash = (double)ptree->ntrans_exact;
dhash += (double)ptree->ntrans_inferior_hit;
dhash += (double)ptree->ntrans_superior_hit;
dfh1st = 100.0 * (double)ptree->fail_high_first;
dfh1st /= (double)( ptree->fail_high + 1 );
- Out( " pruning -> rep=%4.2f%% reject=%4.2f%%\n", drep, dreject );
-
- Out( " pruning -> hash=%2.0f%% null=%2.0f%% fh1st=%4.1f%%\n",
- dhash, dnull, dfh1st );
+ Out( " pruning -> rep=%4.3f%% hash=%2.0f%% null=%2.0f%%"
+ " fh1st=%4.1f%%\n", drep, dhash, dnull, dfh1st );
Out( " extension-> chk=%u recap=%u 1rep=%u\n",
ptree->check_extension_done, ptree->recap_extension_done,
}
#endif
+#if defined(DFPN_CLIENT)
+ if ( dfpn_client_sckt != SCKT_NULL )
+ {
+ int asum[4] = { 0, 0, 0, 0 };
+ int i, n;
+
+ n = root_nmove;
+ for ( i = 0; i < n; i += 1 )
+ {
+ asum[ root_move_list[i].dfpn_cresult ] += 1;
+ }
+
+ switch ( dfpn_client_rresult_unlocked )
+ {
+ case dfpn_client_na:
+ Out( " dfpn -> n/a " );
+ break;
+
+ case dfpn_client_win:
+ if ( dfpn_client_move_unlocked != MOVE_NA )
+ {
+ Out( " dfpn -> win %s ",
+ str_CSA_move(dfpn_client_move_unlocked) );
+ }
+ else { Out( " dfpn -> win ignore " ); }
+ break;
+
+ case dfpn_client_lose:
+ Out( " dfpn -> lose " );
+ break;
+
+ default:
+ assert( dfpn_client_misc == dfpn_client_rresult_unlocked );
+ Out( " dfpn -> misc " );
+ break;
+ }
+
+ Out( "(children win %d, lose %d, misc %d, n/a %d)\n",
+ asum[dfpn_client_win], asum[dfpn_client_lose],
+ asum[dfpn_client_misc], asum[dfpn_client_na] );
+ }
+ if ( dfpn_client_move_unlocked )
+ {
+ last_root_value = root_turn ? -score_matelong : score_matelong;
+ last_pv.a[1] = dfpn_client_move_unlocked;
+ last_pv.length = 1;
+ last_pv.depth = 0;
+ last_pv.type = no_rep;
+ MnjOut( "pid=%d move=%s n=0 v=%de final%s\n", mnj_posi_id,
+ str_CSA_move(last_pv.a[1]), score_matelong,
+ ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+ }
+#endif
+
{
double dcpu_percent, dnps, dmat;
unsigned int cpu, elapsed;
node_per_second = (unsigned int)( dnps + 0.5 );
#endif
- dmat = (double)MATERIAL;
- dmat /= (double)MT_CAP_PAWN;
+ dmat = (double)MATERIAL;
+ dmat /= (double)MT_CAP_PAWN;
OutCsaShogi( " cpu=%.0f nps=%.2f\n", dcpu_percent, dnps / 1e3 );
Out( " time=%s ", str_time_symple( elapsed ) );
- Out( "cpu=%3.0f%% mat=%.1f nps=%.2fK", dcpu_percent, dmat, dnps / 1e3 );
- Out( " time_eff=%s\n\n",
- str_time_symple( time_last_eff_search - time_start ) );
+ Out( "cpu=%3.0f%% mat=%.1f nps=%.2fK\n", dcpu_percent, dmat, dnps/1e3 );
}
if ( ( game_status & flag_problem ) && ! right_answer_made ) { iret = 0; }
}
-static int
-ini_hash( void )
+#if defined(USI)
+int CONV
+usi_root_list( tree_t * restrict ptree )
{
+#define SIZE_STR ( MAX_LEGAL_MOVES * 6 + 200 )
+ char str[ SIZE_STR ];
+ char str_usi[6];
unsigned int elapsed;
- int iret;
+ int i, istr;
- if ( time_limit < 150U ) { return 1; }
-
- iret = all_hash_learn_store();
- if ( iret < 0 ) { return iret; }
- if ( iret )
+ ptree->node_searched = 0;
+ ptree->current_move[0] = MOVE_NA;
+ ptree->save_eval[0] = INT_MAX;
+ ptree->save_eval[1] = INT_MAX;
+ ptree->pv[0].a[0] = 0;
+ ptree->pv[0].a[1] = 0;
+ ptree->pv[0].depth = 0;
+ ptree->pv[0].length = 0;
+ easy_value = 0;
+ easy_abs = 0;
+ root_abort = 0;
+ root_nmove = 0;
+ root_value = -score_bound;
+ root_alpha = -score_bound;
+ root_beta = score_bound;
+ node_last_check = 0;
+ game_status &= ~( flag_move_now | flag_suspend
+ | flag_quit_ponder | flag_search_error );
+
+ Out( "- root move generation" );
+ make_root_move_list( ptree );
+
+ if ( game_status & flag_search_error ) { return -1; }
+ if ( game_status & ( flag_quit | flag_quit_ponder | flag_suspend ) )
{
- if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
- Out( "- load learnt hash values (%ss)\n",
- str_time_symple( elapsed - time_start ) );
+ return 1;
+ }
+
+ if ( ! root_nmove )
+ {
+ str_error = "No legal moves to search";
+ return -1;
+ }
+
+ if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
+ Out( " ... done (%d moves, %ss)\n",
+ root_nmove, str_time_symple( elapsed - time_start ) );
+
+ istr = snprintf( str, SIZE_STR, "genmove_probability" );
+ for ( i = 0; i < root_nmove; i++ )
+ {
+ csa2usi( ptree, str_CSA_move(root_move_list[i].move), str_usi );
+ istr += snprintf( str + istr, SIZE_STR - istr, " %s %d",
+ str_usi, i + 1 );
+ }
+
+ USIOut( "%s\n", str );
+ return 1;
+}
+
+
+int CONV
+usi_book( tree_t * restrict ptree )
+{
+ char str_usi[6];
+ int is_book_hit;
+
+ if ( pf_book == NULL || rep_book_prob( ptree ) )
+ {
+ USIOut( "bestmove pass\n" );
+ return 1;
+ }
+
+ is_book_hit = book_probe( ptree );
+ if ( is_book_hit < 0 ) { return is_book_hit; }
+
+ if ( ! is_book_hit )
+ {
+ USIOut( "bestmove pass\n" );
+ return 1;
}
+ csa2usi( ptree, str_CSA_move(ptree->current_move[1]), str_usi );
+ USIOut( "bestmove %s\n", str_usi );
return 1;
}
+#endif
+
+
+#if defined(DFPN_CLIENT)
+void CONV
+dfpn_client_check_results( void )
+{
+ int i, n, index, num;
+
+ n = root_nmove;
+ lock( &dfpn_client_lock );
+
+ if ( dfpn_client_rresult_unlocked == dfpn_client_na )
+ {
+ dfpn_client_rresult_unlocked = dfpn_client_rresult;
+ if ( dfpn_client_rresult == dfpn_client_win
+ && dfpn_client_move_unlocked == MOVE_NA )
+ {
+ for ( i = 0; i < n; i += 1 )
+ if ( ! strcmp( (const char *)dfpn_client_str_move,
+ str_CSA_move(root_move_list[i].move) ) )
+ {
+ dfpn_client_move_unlocked = root_move_list[i].move;
+ break;
+ }
+ }
+ }
+
+ num = dfpn_client_num_cresult;
+ for ( index = dfpn_client_cresult_index; index < num; index += 1 )
+ {
+ for ( i = 0; i < n; i += 1 ) {
+
+ if ( root_move_list[i].dfpn_cresult != dfpn_client_na ) { continue; }
+
+ if ( ! strcmp( (const char *)dfpn_client_cresult[index].str_move,
+ str_CSA_move(root_move_list[i].move) ) ) {
+
+ root_move_list[i].dfpn_cresult
+ = (int)dfpn_client_cresult[index].result;
+ break;
+ }
+ }
+ }
+
+ dfpn_client_cresult_index = index;
+ dfpn_client_flag_read = 0;
+ unlock( &dfpn_client_lock );
+}
+#endif
+
+
+static int CONV rep_book_prob( tree_t * restrict ptree )
+{
+ int i;
+
+ for ( i = ptree->nrep - 2; i >= 0; i -= 2 )
+ if ( ptree->rep_board_list[i] == HASH_KEY
+ && ptree->rep_hand_list[i] == HAND_B )
+ {
+ Out( "- book is ignored due to a repetition.\n" );
+ return 1;
+ }
+
+ return 0;
+}
-static void
-adjust_fmg( void )
+static void CONV adjust_fmg( void )
{
int misc, cap, drop, mt, misc_king, cap_king;
}
-static int
-set_root_beta( int nfail_high, int root_beta_old )
+static int CONV set_root_beta( int nfail_high, int root_beta_old )
{
int aspiration_hwdth, aspiration_fail1;
}
-static int
-set_root_alpha( int nfail_low, int root_alpha_old )
+static int CONV set_root_alpha( int nfail_low, int root_alpha_old )
{
int aspiration_hwdth, aspiration_fail1;
}
-static const char *
-str_fail_high( int turn, int nfail_high )
+static const char * CONV str_fail_high( int turn, int nfail_high )
{
const char *str;
}
-static int
-is_answer_right( unsigned int move )
+static int CONV is_answer_right( unsigned int move )
{
const char *str_anser;
const char *str_move;
}
#if defined(TLP)
+ tlp_num = nworker;
for ( id = 1; id < nworker; id++ )
{
# if defined(_WIN32)
Out( " Illegal Moves : %u\n", pdata[0]->illegal_moves );
Out( " Nodes Searched : %"PRIu64"\n",pdata[0]->num_nodes );
Out( " Max pos_buf : %x\n", pdata[0]->max_pos_buf );
- Out( " Move Prediction :" );
+ Out( " Prediction (%) :" );
for ( i = 0, dtemp = 0.0; i < NUM_RESULT; i++ )
{
dtemp += (double)pdata[0]->result[i] * 100.0;
- Out( " %4.1f%%", dtemp / (double)pdata[0]->result_norm );
+ Out( " %4.2f", dtemp / (double)pdata[0]->result_norm );
}
Out( "\n" );
unsigned int record_move;
int i, imove, iret;
- iret = 0;
- pdata = (parse1_data_t *)arg;
- ptree = pdata->ptree;
-
-#if defined(TLP)
- if ( pdata->nworker > 1 )
- {
- lock( &tlp_lock );
- tlp_num += 1;
- if ( pdata->id ) { Out( "hi from thread #%d\n", pdata->id ); }
- unlock( &tlp_lock );
- while ( tlp_num < pdata->nworker ) { tlp_yield(); }
- }
-#endif
+ iret = 0;
+ pdata = (parse1_data_t *)arg;
+ ptree = pdata->ptree;
for ( i = 0; i < NUM_RESULT; i++ ) { pdata->result[i] = 0; }
pdata->num_moves_counted = 0;
pdata->target_out_window = 0.0;
for ( ;; ) {
- /* make results */
+ /* make pv */
pdata->pos_buf = 2U;
for ( imove = 0; imove < (int)pdata->record_length; imove++ )
{
}
#if defined(TLP)
- if ( pdata->nworker > 1 ) { lock( &tlp_lock ); }
+ lock( &tlp_lock );
#endif
- /* save results */
+ /* save pv */
if ( pdata->record_length )
{
if ( pdata->pos_buf > pdata->max_pos_buf )
}
#if defined(TLP)
- if ( pdata->nworker > 1 ) { unlock( &tlp_lock ); }
+ unlock( &tlp_lock );
#endif
if ( iret < 0 ) { break; }
}
#if defined(TLP)
- if ( pdata->nworker > 1 )
- {
- lock( &tlp_lock );
- tlp_num -= 1;
- unlock( &tlp_lock );
- }
+ lock( &tlp_lock );
+ tlp_num -= 1;
+ unlock( &tlp_lock );
#endif
pdata->info = iret;
unsigned int *pmove;
unsigned int move, pos_buf;
int i, imove, record_value, nth, nc, nmove_legal;
- int value, alpha, beta, depth, ply, tt;
+ int value, alpha, beta, depth, ply, tt, new_depth;
record_value = INT_MIN;
nc = 0;
pos_buf = pdata->pos_buf;
ptree = pdata->ptree;
ptree->node_searched = 0;
+ ptree->save_eval[0] = INT_MAX;
+ ptree->save_eval[1] = INT_MAX;
#if defined(TLP)
ptree->tlp_abort = 0;
#endif
for ( ply = 0; ply < PLY_MAX; ply++ )
{
ptree->amove_killer[ply].no1 = ptree->amove_killer[ply].no2 = 0U;
- ptree->killers[ply].no1 = ptree->killers[ply].no2 = 0U;
+ ptree->killers[ply].no1 = ptree->killers[ply].no2 = 0U;
}
- for ( i = 0; i < HIST_SIZE; i++ )
+ for ( i = 0; i < (int)HIST_SIZE; i++ )
{
ptree->hist_good[i] /= 256U;
ptree->hist_tried[i] /= 256U;
}
-
+ evaluate( ptree, 1, pdata->root_turn );
+
pmove = GenCaptures ( pdata->root_turn, pdata->amove_legal );
pmove = GenNoCaptures ( pdata->root_turn, pmove );
pmove = GenDrop ( pdata->root_turn, pmove );
move = pdata->amove_legal[0];
pdata->amove_legal[0] = pdata->amove_legal[i];
pdata->amove_legal[i] = move;
-
+
for ( imove = 0; imove < nmove_legal; imove++ ) {
+
move = pdata->amove_legal[imove];
+ ptree->current_move[1] = move;
if ( imove )
{
alpha = record_value - FV_WINDOW;
if ( InCheck(tt) )
{
- ptree->nsuc_check[2]
- = (unsigned char)( ptree->nsuc_check[0] + 1U );
- } else { ptree->nsuc_check[2] = 0; }
+ new_depth = depth + PLY_INC;
+ ptree->nsuc_check[2] = (unsigned char)( ptree->nsuc_check[0] + 1U );
+ }
+ else {
+ new_depth = depth;
+ ptree->nsuc_check[2] = 0;
+ }
ptree->current_move[1] = move;
ptree->pv[1].type = no_rep;
- value = -search( ptree, -beta, -alpha, tt, depth, 2,
+ value = -search( ptree, -beta, -alpha, tt, new_depth, 2,
node_do_mate | node_do_null | node_do_futile
- | node_do_recap );
+ | node_do_recap | node_do_recursion | node_do_hashcut );
UnMakeMove( pdata->root_turn, move, 1 );
}
else { pdata->record_moves[ imove ] = record_move; }
- iret = make_move_root( ptree, record_move, flag_rejections );
+ iret = make_move_root( ptree, record_move, 0 );
if ( iret < 0 ) { return iret; }
}
for ( ;; ) {
#if defined(TLP)
+ tlp_num = nworker;
for ( id = 1; id < nworker; id++ )
{
# if defined(_WIN32)
target = ( pdata[0]->target + target_out_window ) / obj_norm;
objective_function = target + penalty;
Out( " Moves Counted : %d\n", pdata[0]->num_moves_counted );
- Out( " Objective Func. : %f %f %f\n",
+ Out( " Objective Func. : %.8f %.8f %.8f\n",
objective_function, target, penalty );
Out( " Steps " );
}
pdata = (parse2_data_t *)arg;
ptree = pdata->ptree;
-#if defined(TLP)
- if ( pdata->nworker > 1 )
- {
- lock( &tlp_lock );
- tlp_num += 1;
- unlock( &tlp_lock );
- while ( tlp_num < pdata->nworker ) { tlp_yield(); }
- }
-#endif
-
pdata->num_moves_counted = 0;
pdata->info = 0;
pdata->target = 0.0;
for ( ;; ) {
#if defined(TLP)
- if ( pdata->nworker > 1 ) { lock( &tlp_lock ); }
+ lock( &tlp_lock );
#endif
iret = read_buf( pdata->buf, pdata->pf_tmp );
#if defined(TLP)
- if ( pdata->nworker > 1 ) { unlock( &tlp_lock ); }
+ unlock( &tlp_lock );
#endif
if ( iret <= 0 ) { break; } /* 0: eof, -2: error */
turn = Flip( turn );
ptree->move_last[1] = ptree->move_last[0];
ptree->nsuc_check[0] = 0;
- ptree->nsuc_check[1]
- = (unsigned char)( InCheck( turn ) ? 1U : 0 );
+ ptree->nsuc_check[1] = (unsigned char)( InCheck( turn ) ? 1U : 0 );
}
}
#if defined(TLP)
- if ( pdata->nworker > 1 )
- {
- lock( &tlp_lock );
- tlp_num -= 1;
- unlock( &tlp_lock );
- }
+ lock( &tlp_lock );
+ tlp_num -= 1;
+ unlock( &tlp_lock );
#endif
pdata->info = iret;
{
int n, i, imin;
- n = root_nrep + ply - 1;
+ n = ptree->nrep + ply - 1;
imin = n - REP_MAX_PLY;
if ( imin < 0 ) { imin = 0; }
n2 = 0;
bb = BB_BPAWN;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WPAWN;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BLANCE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WLANCE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BKNIGHT;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WKNIGHT;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BSILVER;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WSILVER;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BTGOLD;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WTGOLD;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BBISHOP;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WBISHOP;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BROOK;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WROOK;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
-/*
- BUG LIST
-
- - detection of repetitions can be wrong due to collision of hash keys and
- limitation of history table size.
-
- - detection of mates fails if all of pseudo-legal evasions are perpetual
- checks. Father more, inferior evasions, such as unpromotion of
- bishop, rook, and lance at 8th rank, are not counted for the mate
- detection.
-
- - detection of perpetual checks fails if one of those inferior
- evasions makes a position that occurred four times.
-*/
-/*
- TODO:
- - idirec && is_pinned_on_black_king();
- - aifile and airank
- - incheck at quies
- - max legal moves
- - tactical macro
- - out_warning( "A node returns a value lower than mate." ); is obsolate.
- - do_mate in hash
- - pv store to hash
- - no threat
- - use IsDiscover macro
- - change hash_store_pv()
- - dek.c is obsolate.
- - limit time ? ? num
- - hash.bin
- - SHARE to all transition table
- */
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int main_child( tree_t * restrict ptree );
-int CONV_CDECL
-#if defined(CSASHOGI)
+int
+#if defined(CSASHOGI) || defined(USI)
main( int argc, char *argv[] )
#else
main()
#endif
#if defined(CSASHOGI) && defined(_WIN32)
- FreeConsole();
if ( argc != 2 || strcmp( argv[1], "csa_shogi" ) )
{
MessageBox( NULL,
}
#endif
+#if defined(USI)
+ if ( argc == 2 && ! strcmp( argv[1], "usi" ) ) { usi_mode = usi_on; }
+ else { usi_mode = usi_off; }
+#endif
+
if ( ini( ptree ) < 0 )
{
out_error( "%s", str_error );
if ( iret == -1 )
{
out_error( "%s", str_error );
- ShutdownClient;
+ ShutdownAll();
break;
}
else if ( iret == -2 )
{
out_warning( "%s", str_error );
- ShutdownClient;
+ ShutdownAll();
continue;
}
else if ( iret == -3 ) { break; }
{
int iret;
-#if defined(DEKUNOBOU)
- if ( dek_ngame && ( game_status & mask_game_end ) )
- {
- TlpEnd();
- if ( dek_next_game( ptree ) < 0 )
- {
- out_error( "%s", str_error );
- return -3;
- }
- }
-#endif
-
/* ponder a move */
ponder_move = 0;
iret = ponder( ptree );
+#include <limits.h>
#include <assert.h>
#include <string.h>
#include "shogi.h"
BOARD[to] = - piece
-void
+void CONV
make_move_b( tree_t * restrict ptree, unsigned int move, int ply )
{
const int from = (int)I2From(move);
const int to = (int)I2To(move);
- const int nrep = root_nrep + ply - 1;
+ const int nrep = ptree->nrep + ply - 1;
assert( UToCap(move) != king );
assert( move );
ptree->rep_board_list[nrep] = HASH_KEY;
ptree->rep_hand_list[nrep] = HAND_B;
ptree->save_material[ply] = (short)MATERIAL;
- ptree->stand_pat[ply+1] = score_bound;
+ ptree->save_eval[ply+1] = INT_MAX;
if ( from >= nsquare )
{
}
-void
+void CONV
make_move_w( tree_t * restrict ptree, unsigned int move, int ply )
{
const int from = (int)I2From(move);
const int to = (int)I2To(move);
- const int nrep = root_nrep + ply - 1;
+ const int nrep = ptree->nrep + ply - 1;
assert( UToCap(move) != king );
assert( move );
ptree->rep_board_list[nrep] = HASH_KEY;
ptree->rep_hand_list[nrep] = HAND_B;
ptree->save_material[ply] = (short)MATERIAL;
- ptree->stand_pat[ply+1] = score_bound;
+ ptree->save_eval[ply+1] = INT_MAX;
if ( from >= nsquare )
{
* flag_time
* flag_nomake_move
* flag_history
- * flag_rejections
*/
-int
+int CONV
make_move_root( tree_t * restrict ptree, unsigned int move, int flag )
{
int check, drawn, iret, i, n;
- ptree->save_material[0] = (short)MATERIAL;
MakeMove( root_turn, move, 1 );
/* detect hang-king */
if ( drawn ) { game_status |= flag_drawn; }
- /* renovate time */
+ /* update time */
if ( flag & flag_time )
{
- iret = renovate_time( root_turn );
- if ( iret < 0 ) { return iret; }
+ iret = update_time( root_turn );
+ if ( iret < 0 ) { return -1; }
}
root_turn = Flip( root_turn );
if ( check && is_mate( ptree, 1 ) ) { game_status |= flag_mated; }
/* save history */
- if ( flag & flag_history )
- {
- /* save history for book learning */
- if ( record_game.moves < HASH_REG_HIST_LEN )
- {
- history_book_learn[ record_game.moves ].move_played = move;
- history_book_learn[ record_game.moves ].hand_played
- = ptree->rep_hand_list[ root_nrep ];
- history_book_learn[ record_game.moves ].key_played
- = (unsigned int)ptree->rep_board_list[ root_nrep ];
- }
-
- out_CSA( ptree, &record_game, move );
- }
-
- /* add rejections */
- if ( flag & flag_rejections ) { add_rejections_root( ptree, move ); }
+ if ( flag & flag_history ) { out_CSA( ptree, &record_game, move ); }
/* renew repetition table */
- n = root_nrep;
+ n = ptree->nrep;
if ( n >= REP_HIST_LEN - PLY_MAX -1 )
{
for ( i = 0; i < n; i++ )
ptree->rep_hand_list[i] = ptree->rep_hand_list[i+1];
}
}
- else { root_nrep++; }
+ else { ptree->nrep++; }
- ptree->nsuc_check[PLY_MAX] = ptree->nsuc_check[0];
- ptree->nsuc_check[0] = ptree->nsuc_check[1];
- ptree->nsuc_check[1] = ptree->nsuc_check[2];
+ for ( i = 1; i < NUM_UNMAKE; i += 1 )
+ {
+ amove_save[i-1] = amove_save[i];
+ amaterial_save[i-1] = amaterial_save[i];
+ ansuc_check_save[i-1] = ansuc_check_save[i];
+ alast_root_value_save[i-1] = alast_root_value_save[i];
+ alast_pv_save[i-1] = alast_pv_save[i];
+ }
+ amove_save [NUM_UNMAKE-1] = move;
+ amaterial_save [NUM_UNMAKE-1] = ptree->save_material[1];
+ ansuc_check_save[NUM_UNMAKE-1] = ptree->nsuc_check[0];
+ ptree->nsuc_check[0] = ptree->nsuc_check[1];
+ ptree->nsuc_check[1] = ptree->nsuc_check[2];
+
+ /* update pv */
+ alast_root_value_save[NUM_UNMAKE-1] = last_root_value;
+ alast_pv_save[NUM_UNMAKE-1] = last_pv;
- /* renovate pv */
- last_root_value_save = last_root_value;
- last_pv_save = last_pv;
if ( last_pv.a[1] == move && last_pv.length >= 2 )
{
if ( last_pv.depth )
last_root_value = 0;
}
+#if defined(DFPN_CLIENT)
+ lock( &dfpn_client_lock );
+ snprintf( (char *)dfpn_client_signature, DFPN_CLIENT_SIZE_SIGNATURE,
+ "%" PRIx64 "_%x_%x_%x", HASH_KEY, HAND_B, HAND_W, root_turn );
+ dfpn_client_signature[DFPN_CLIENT_SIZE_SIGNATURE-1] = '\0';
+ dfpn_client_rresult = dfpn_client_na;
+ dfpn_client_num_cresult = 0;
+ dfpn_client_flag_read = 0;
+ dfpn_client_out( "%s %s\n", str_CSA_move(move), dfpn_client_signature );
+ unlock( &dfpn_client_lock );
+#endif
+
return 1;
}
-void
-unmake_move_root( tree_t * restrict ptree, unsigned int move )
+int CONV unmake_move_root( tree_t * restrict ptree )
{
- last_root_value = last_root_value_save;
- last_pv = last_pv_save;
+ unsigned int move;
+ int i;
- ptree->nsuc_check[1] = ptree->nsuc_check[0];
- ptree->nsuc_check[0] = ptree->nsuc_check[PLY_MAX];
-
- root_nrep -= 1;
+ if ( ptree->nrep == 0 || amove_save[NUM_UNMAKE-1] == MOVE_NA )
+ {
+ str_error = "no more undo infomation at root";
+ return -1;
+ }
+
+ ptree->nsuc_check[1] = ptree->nsuc_check[0];
+ ptree->nsuc_check[0] = ansuc_check_save[NUM_UNMAKE-1];
+ ptree->save_material[1] = (short)amaterial_save[NUM_UNMAKE-1];
+ move = amove_save[NUM_UNMAKE-1];
+ last_root_value = alast_root_value_save[NUM_UNMAKE-1];
+ last_pv = alast_pv_save[NUM_UNMAKE-1];
+
+ ptree->nrep -= 1;
game_status &= ~( flag_drawn | flag_mated );
- root_turn = Flip(root_turn);
+ root_turn = Flip(root_turn);
+
+ for ( i = NUM_UNMAKE-1; i > 0; i -= 1 )
+ {
+ amove_save[i] = amove_save[i-1];
+ amaterial_save[i] = amaterial_save[i-1];
+ ansuc_check_save[i] = ansuc_check_save[i-1];
+ alast_root_value_save[i] = alast_root_value_save[i-1];
+ alast_pv_save[i] = alast_pv_save[i-1];
+ }
+ amove_save[0] = MOVE_NA;
+ amaterial_save[0] = 0;
+ ansuc_check_save[0] = 0;
+ alast_root_value_save[0] = 0;
+ alast_pv_save[0].a[0] = 0;
+ alast_pv_save[0].a[1] = 0;
+ alast_pv_save[0].depth = 0;
+ alast_pv_save[0].length = 0;
- ptree->save_material[1] = ptree->save_material[0];
UnMakeMove( root_turn, move, 1 );
- sub_rejections_root( ptree, move );
+#if defined(DFPN_CLIENT)
+ lock( &dfpn_client_lock );
+ snprintf( (char *)dfpn_client_signature, DFPN_CLIENT_SIZE_SIGNATURE,
+ "%" PRIx64 "_%x_%x_%x", HASH_KEY, HAND_B, HAND_W, root_turn );
+ dfpn_client_signature[DFPN_CLIENT_SIZE_SIGNATURE-1] = '\0';
+ dfpn_client_rresult = dfpn_client_na;
+ dfpn_client_flag_read = 0;
+ dfpn_client_num_cresult = 0;
+ dfpn_client_out( "unmake\n" );
+ unlock( &dfpn_client_lock );
+#endif
+
+ return 1;
}
#define DebugOut { static int count = 0; \
if ( count++ < 16 ) { out_CSA_posi( ptree, stdout, 0 ); } }
-static int can_w_king_escape( tree_t * restrict ptree, int to, bitboard_t bb );
-static int can_b_king_escape( tree_t * restrict ptree, int to, bitboard_t bb );
-static int can_w_piece_capture( const tree_t * restrict ptree, int to );
-static int can_b_piece_capture( const tree_t * restrict ptree, int to );
+static int CONV can_w_king_escape( tree_t * restrict ptree, int to,
+ const bitboard_t * restrict pbb );
+static int CONV can_b_king_escape( tree_t * restrict ptree, int to,
+ const bitboard_t * restrict pbb );
+static int CONV can_w_piece_capture( const tree_t * restrict ptree, int to );
+static int CONV can_b_piece_capture( const tree_t * restrict ptree, int to );
-unsigned int
+unsigned int CONV
is_b_mate_in_1ply( tree_t * restrict ptree )
{
bitboard_t bb, bb_temp, bb_check, bb_check_pro, bb_attacks, bb_drop, bb_move;
if ( IsHandRook(HAND_B) ) {
- BBAnd( bb, abb_w_gold_attacks[SQ_WKING],
- abb_b_gold_attacks[SQ_WKING] );
+ BBAnd( bb, abb_w_gold_attacks[SQ_WKING], abb_b_gold_attacks[SQ_WKING] );
BBAnd( bb, bb, bb_drop );
- while( BBToU(bb) )
+ while( BBTest(bb) )
{
to = FirstOne( bb );
Xor( to, bb );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ BBOr( bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0] );
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_w_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(rook);
}
if ( ! BOARD[to] && is_white_attacked( ptree, to ) )
{
bb_attacks = abb_file_attacks[to][0];
- if ( ! can_w_king_escape( ptree, to, bb_attacks )
+ if ( ! can_w_king_escape( ptree, to, &bb_attacks )
&& ! can_w_piece_capture( ptree, to ) )
{
return To2Move(to) | Drop2Move(lance);
BBAnd( bb, abb_w_silver_attacks[SQ_WKING],
abb_b_silver_attacks[SQ_WKING] );
BBAnd( bb, bb, bb_drop );
- while( BBToU(bb) )
+ while( BBTest(bb) )
{
to = FirstOne( bb );
Xor( to, bb );
BBOr( bb_attacks, abb_bishop_attacks_rr45[to][0],
abb_bishop_attacks_rl45[to][0] );
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_w_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(bishop);
}
}
{
BBAnd( bb, abb_b_gold_attacks[SQ_WKING],
abb_b_silver_attacks[SQ_WKING] );
- BBNot( bb, bb );
- BBAnd( bb, bb, bb_drop );
+ BBNotAnd( bb, bb_drop, bb );
BBAnd( bb, bb, abb_w_gold_attacks[SQ_WKING] );
}
else { BBAnd( bb, bb_drop, abb_w_gold_attacks[SQ_WKING] ); }
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
to = FirstOne( bb );
Xor( to, bb );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_gold_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_w_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(gold);
}
}
if ( IsHandGold(HAND_B) )
{
if ( IsHandBishop(HAND_B) ) { goto b_silver_drop_end; }
- BBNot( bb, abb_w_gold_attacks[SQ_WKING] );
- BBAnd( bb, bb, abb_w_silver_attacks[SQ_WKING] );
+ BBNotAnd( bb,
+ abb_w_silver_attacks[SQ_WKING],
+ abb_w_gold_attacks[SQ_WKING] );
BBAnd( bb, bb, bb_drop );
}
else {
}
}
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
to = FirstOne( bb );
Xor( to, bb );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_silver_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_w_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(silver);
}
}
if ( IsHandKnight(HAND_B) ) {
BBAnd( bb, bb_drop, abb_w_knight_attacks[SQ_WKING] );
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
to = FirstOne( bb );
Xor( to, bb );
BBIni( bb_attacks );
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_w_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(knight);
}
}
BBNot( bb_move, BB_BOCCUPY );
bb = BB_BDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = FirstOne( bb );
Xor( from, bb );
AttackDragon( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_WKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
Xor( from, BB_B_HDK );
Xor( from, BB_B_RD );
if ( (int)adirec[SQ_WKING][to] & flag_cross )
{
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr( bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
}
else { AttackDragon( bb_attacks, to ); }
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
Xor( from, BB_B_HDK );
return ( To2Move(to) | From2Move(from)
| Cap2Move(-BOARD[to]) | Piece2Move(dragon) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
AttackRook( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_WKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_B_RD.p[0] ^= abb_mask[from].p[0];
BB_BOCCUPY.p[0] ^= abb_mask[from].p[0];
if ( (int)adirec[SQ_WKING][to] & flag_cross )
{
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr( bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
}
else { AttackDragon( bb_attacks, to ); }
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BB_B_RD.p[0] ^= abb_mask[from].p[0];
return ( To2Move(to) | From2Move(from) | FLAG_PROMO
| Cap2Move(-BOARD[to]) | Piece2Move(rook) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
bb_check.p[2] &= abb_b_gold_attacks[SQ_WKING].p[2];
bb_check.p[1] &= abb_w_gold_attacks[SQ_WKING].p[1];
bb_check.p[2] &= abb_w_gold_attacks[SQ_WKING].p[2];
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_B_RD.p[1] ^= abb_mask[from].p[1];
BB_B_RD.p[2] ^= abb_mask[from].p[2];
if ( to <= I7 ) {
if ( (int)adirec[SQ_WKING][to] & flag_cross )
{
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr(bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0]);
bb_attacks.p[0] |= abb_king_attacks[to].p[0];
bb_attacks.p[1] |= abb_king_attacks[to].p[1];
}
else { AttackDragon( bb_attacks, to ); }
} else {
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr( bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0] );
}
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
return ( To2Move(to) | From2Move(from)
| ( (to < A6) ? FLAG_PROMO : 0 )
| Cap2Move(-BOARD[to]) | Piece2Move(rook) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
bb = BB_BHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = FirstOne( bb );
Xor( from, bb );
AttackHorse( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_WKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
Xor( from, BB_B_HDK );
Xor( from, BB_B_BH );
BBOr( bb_attacks, abb_bishop_attacks_rr45[to][0],
abb_bishop_attacks_rl45[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
Xor( from, BB_B_HDK );
return ( To2Move(to) | From2Move(from)
| Cap2Move(-BOARD[to]) | Piece2Move(horse) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
AttackBishop( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_WKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_B_BH.p[0] ^= abb_mask[from].p[0];
BB_BOCCUPY.p[0] ^= abb_mask[from].p[0];
BBOr( bb_attacks, abb_bishop_attacks_rr45[to][0],
abb_bishop_attacks_rl45[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BB_B_BH.p[0] ^= abb_mask[from].p[0];
return ( To2Move(to) | From2Move(from) | FLAG_PROMO
| Cap2Move(-BOARD[to]) | Piece2Move(bishop) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
bb_check.p[2] &= abb_b_silver_attacks[SQ_WKING].p[2];
bb_check.p[1] &= abb_w_silver_attacks[SQ_WKING].p[1];
bb_check.p[2] &= abb_w_silver_attacks[SQ_WKING].p[2];
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_B_BH.p[1] ^= abb_mask[from].p[1];
BB_B_BH.p[2] ^= abb_mask[from].p[2];
bb_attacks.p[0] |= abb_king_attacks[to].p[0];
bb_attacks.p[1] |= abb_king_attacks[to].p[1];
}
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
return ( To2Move(to) | From2Move(from)
| ( (to < A6) ? FLAG_PROMO : 0 )
| Cap2Move(-BOARD[to]) | Piece2Move(bishop) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
BBAnd( bb, BB_BTGOLD, b_chk_tbl[SQ_WKING].gold );
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = FirstOne( bb );
Xor( from, bb );
BBAnd( bb_check, bb_move, abb_b_gold_attacks[from] );
BBAnd( bb_check, bb_check, abb_w_gold_attacks[SQ_WKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
Xor( from, BB_BTGOLD );
Xor( from, BB_BOCCUPY );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_gold_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
Xor( from, BB_BTGOLD );
return ( To2Move(to) | From2Move(from)
| Cap2Move(-BOARD[to]) | Piece2Move(BOARD[from]) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_gold_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_silver_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_gold_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_silver_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_silver_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
BBAnd( bb, BB_BKNIGHT, b_chk_tbl[SQ_WKING].knight );
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = FirstOne( bb );
Xor( from, bb );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_gold_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BBAnd( bb_check, bb_move, abb_b_knight_attacks[from] );
BBAnd( bb_check, bb_check, abb_w_knight_attacks[SQ_WKING] );
- if ( BBToU(bb_check) ) {
+ if ( BBTest(bb_check) ) {
BB_BKNIGHT.p[1] ^= abb_mask[from].p[1];
BB_BKNIGHT.p[2] ^= abb_mask[from].p[2];
BB_BOCCUPY.p[1] ^= abb_mask[from].p[1];
Xor( to, bb_check );
BBIni( bb_attacks );
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BB_BKNIGHT.p[2] ^= abb_mask[from].p[2];
return ( To2Move(to) | From2Move(from)
| Cap2Move(-BOARD[to]) | Piece2Move(knight) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
BBAnd( bb, BB_BLANCE, b_chk_tbl[SQ_WKING].lance );
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = FirstOne( bb );
Xor( from, bb );
XorDiag1( from, OCCUPIED_DIAG1 );
bb_check.p[0] &= 0x1ffU;
- if ( BBToU(bb_check) ) {
+ if ( BBTest(bb_check) ) {
to = SQ_WKING+nfile;
if ( ! is_white_attacked( ptree, to ) ) {
goto b_lance_next;
}
bb_temp = abb_file_attacks[to][0];
- if ( can_w_king_escape( ptree, to, bb_temp ) ) { goto b_lance_next; }
+ if ( can_w_king_escape( ptree, to, &bb_temp ) ) { goto b_lance_next; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { goto b_lance_next; }
- if ( IsDiscoverBK( from, to ) ) { goto b_lance_next; }
+ else if ( can_w_piece_capture( ptree, to ) ) { goto b_lance_next; }
+ if ( IsDiscoverBK( from, to ) ) { goto b_lance_next; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_white_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_b_gold_attacks[to];
- if ( can_w_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_w_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverBK( from, to ) ) { continue; }
+ else if ( can_w_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverBK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag1( from, OCCUPIED_DIAG1 );
- if ( ! is_white_attacked( ptree, to ) ) { goto b_pawn_pro_next; }
+ if ( ! is_white_attacked( ptree, to ) ) { goto b_pawn_pro_next; }
bb_attacks = abb_b_gold_attacks[to];
- if ( can_w_king_escape( ptree,to,bb_attacks ) ) { goto b_pawn_pro_next; }
+ if ( can_w_king_escape( ptree,to,&bb_attacks ) ) { goto b_pawn_pro_next; }
if ( IsDiscoverWK( from, to ) );
- else if ( can_w_piece_capture( ptree, to ) ) { goto b_pawn_pro_next; }
- if ( IsDiscoverBK( from, to ) ) { goto b_pawn_pro_next; }
+ else if ( can_w_piece_capture( ptree, to ) ) { goto b_pawn_pro_next; }
+ if ( IsDiscoverBK( from, to ) ) { goto b_pawn_pro_next; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag1( from, OCCUPIED_DIAG1 );
- if ( ! is_white_attacked( ptree, to ) ) { goto b_pawn_end; }
+ if ( ! is_white_attacked( ptree, to ) ) { goto b_pawn_end; }
BBIni( bb_attacks );
- if ( can_w_king_escape( ptree,to,bb_attacks ) ) { goto b_pawn_end; }
- if ( can_w_piece_capture( ptree, to ) ) { goto b_pawn_end; }
- if ( IsDiscoverBK( from, to ) ) { goto b_pawn_end; }
+ if ( can_w_king_escape( ptree,to,&bb_attacks ) ) { goto b_pawn_end; }
+ if ( can_w_piece_capture( ptree, to ) ) { goto b_pawn_end; }
+ if ( IsDiscoverBK( from, to ) ) { goto b_pawn_end; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
-unsigned int
+unsigned int CONV
is_w_mate_in_1ply( tree_t * restrict ptree )
{
bitboard_t bb, bb_temp, bb_check, bb_check_pro, bb_attacks, bb_drop, bb_move;
BBAnd( bb, abb_w_gold_attacks[SQ_BKING],
abb_b_gold_attacks[SQ_BKING] );
BBAnd( bb, bb, bb_drop );
- while( BBToU(bb) )
+ while( BBTest(bb) )
{
to = LastOne( bb );
Xor( to, bb );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ BBOr( bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0] );
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_b_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(rook);
}
if ( ( ! BOARD[to] ) && is_black_attacked( ptree, to ) )
{
bb_attacks = abb_file_attacks[to][0];
- if ( ( ! can_b_king_escape( ptree, to, bb_attacks ) )
+ if ( ( ! can_b_king_escape( ptree, to, &bb_attacks ) )
&& ( ! can_b_piece_capture( ptree, to ) ) )
{
return To2Move(to) | Drop2Move(lance);
BBAnd( bb, abb_w_silver_attacks[SQ_BKING],
abb_b_silver_attacks[SQ_BKING] );
BBAnd( bb, bb, bb_drop );
- while( BBToU(bb) )
+ while( BBTest(bb) )
{
to = LastOne( bb );
Xor( to, bb );
BBOr( bb_attacks, abb_bishop_attacks_rr45[to][0],
abb_bishop_attacks_rl45[to][0] );
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_b_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(bishop);
}
}
{
BBAnd( bb, abb_w_gold_attacks[SQ_BKING],
abb_w_silver_attacks[SQ_BKING] );
- BBNot( bb, bb );
- BBAnd( bb, bb, bb_drop );
+ BBNotAnd( bb, bb_drop, bb );
BBAnd( bb, bb, abb_b_gold_attacks[SQ_BKING] );
}
else { BBAnd( bb, bb_drop, abb_b_gold_attacks[SQ_BKING] ); }
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
to = LastOne( bb );
Xor( to, bb );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_gold_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_b_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(gold);
}
}
if ( IsHandGold(HAND_W) )
{
if ( IsHandBishop(HAND_W) ) { goto w_silver_drop_end; }
- BBNot( bb, abb_b_gold_attacks[SQ_BKING] );
- BBAnd( bb, bb, abb_b_silver_attacks[SQ_BKING] );
+ BBNotAnd( bb,
+ abb_b_silver_attacks[SQ_BKING],
+ abb_b_gold_attacks[SQ_BKING] );
BBAnd( bb, bb, bb_drop );
}
else {
}
}
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
to = LastOne( bb );
Xor( to, bb );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_silver_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_b_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(silver);
}
}
if ( IsHandKnight(HAND_W) ) {
BBAnd( bb, bb_drop, abb_b_knight_attacks[SQ_BKING] );
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
to = LastOne( bb );
Xor( to, bb );
BBIni( bb_attacks );
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
- if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
+ if ( can_b_piece_capture( ptree, to ) ) { continue; }
return To2Move(to) | Drop2Move(knight);
}
}
BBNot( bb_move, BB_WOCCUPY );
bb = BB_WDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = LastOne( bb );
Xor( from, bb );
AttackDragon( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_BKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
Xor( from, BB_W_HDK );
Xor( from, BB_W_RD );
if ( (int)adirec[SQ_BKING][to] & flag_cross )
{
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr( bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
}
else { AttackDragon( bb_attacks, to ); }
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
Xor( from, BB_W_HDK );
return ( To2Move(to) | From2Move(from)
| Cap2Move(BOARD[to]) | Piece2Move(dragon) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
AttackRook( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_BKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_W_RD.p[2] ^= abb_mask[from].p[2];
BB_WOCCUPY.p[2] ^= abb_mask[from].p[2];
if ( (int)adirec[SQ_BKING][to] & flag_cross )
{
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr( bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
}
else { AttackDragon( bb_attacks, to ); }
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BB_W_RD.p[2] ^= abb_mask[from].p[2];
return ( To2Move(to) | From2Move(from) | FLAG_PROMO
| Cap2Move(BOARD[to]) | Piece2Move(rook) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
bb_check.p[0] &= abb_w_gold_attacks[SQ_BKING].p[0];
bb_check.p[1] &= abb_w_gold_attacks[SQ_BKING].p[1];
bb_check.p[2] &= abb_king_attacks[SQ_BKING].p[2];
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_W_RD.p[0] ^= abb_mask[from].p[0];
BB_W_RD.p[1] ^= abb_mask[from].p[1];
if ( to >= A3 ) {
if ( (int)adirec[SQ_BKING][to] & flag_cross )
{
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr(bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0]);
bb_attacks.p[1] |= abb_king_attacks[to].p[1];
bb_attacks.p[2] |= abb_king_attacks[to].p[2];
}
else { AttackDragon( bb_attacks, to ); }
} else {
- bb_attacks = abb_file_attacks[to][0];
- bb_attacks.p[aslide[to].ir0] |= ai_rook_attacks_r0[to][0];
+ BBOr(bb_attacks, abb_file_attacks[to][0], abb_rank_attacks[to][0]);
}
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
return ( To2Move(to) | From2Move(from)
| ( (to > I4) ? FLAG_PROMO : 0 )
| Cap2Move(BOARD[to]) | Piece2Move(rook) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
bb = BB_WHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = LastOne( bb );
Xor( from, bb );
AttackHorse( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_BKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
Xor( from, BB_W_HDK );
Xor( from, BB_W_BH );
BBOr( bb_attacks, abb_bishop_attacks_rr45[to][0],
abb_bishop_attacks_rl45[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
Xor( from, BB_W_HDK );
return ( To2Move(to) | From2Move(from)
| Cap2Move(BOARD[to]) | Piece2Move(horse) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
AttackBishop( bb_attacks, from );
BBAnd( bb_check, bb_move, bb_attacks );
BBAnd( bb_check, bb_check, abb_king_attacks[SQ_BKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_W_BH.p[2] ^= abb_mask[from].p[2];
BB_WOCCUPY.p[2] ^= abb_mask[from].p[2];
BBOr( bb_attacks, abb_bishop_attacks_rr45[to][0],
abb_bishop_attacks_rl45[to][0] );
BBOr( bb_attacks, bb_attacks, abb_king_attacks[to] );
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BB_W_BH.p[2] ^= abb_mask[from].p[2];
return ( To2Move(to) | From2Move(from) | FLAG_PROMO
| Cap2Move(BOARD[to]) | Piece2Move(bishop) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
bb_check.p[0] &= abb_w_silver_attacks[SQ_BKING].p[0];
bb_check.p[1] &= abb_w_silver_attacks[SQ_BKING].p[1];
bb_check.p[2] &= abb_king_attacks[SQ_BKING].p[2];
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
BB_W_BH.p[0] ^= abb_mask[from].p[0];
BB_W_BH.p[1] ^= abb_mask[from].p[1];
bb_attacks.p[1] |= abb_king_attacks[to].p[1];
bb_attacks.p[2] |= abb_king_attacks[to].p[2];
}
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
return ( To2Move(to) | From2Move(from)
| ( (to > I4) ? FLAG_PROMO : 0 )
| Cap2Move(BOARD[to]) | Piece2Move(bishop) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
BBAnd( bb, BB_WTGOLD, w_chk_tbl[SQ_BKING].gold );
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = LastOne( bb );
Xor( from, bb );
BBAnd( bb_check, bb_move, abb_w_gold_attacks[from] );
BBAnd( bb_check, bb_check, abb_b_gold_attacks[SQ_BKING] );
- if ( ! BBToU(bb_check) ) { continue; }
+ if ( ! BBTest(bb_check) ) { continue; }
Xor( from, BB_WTGOLD );
Xor( from, BB_WOCCUPY );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_gold_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
Xor( from, BB_WTGOLD );
return ( To2Move(to) | From2Move(from)
| Cap2Move(BOARD[to]) | Piece2Move(-BOARD[from]) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_gold_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_silver_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_gold_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_silver_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_silver_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
BBAnd( bb, BB_WKNIGHT, w_chk_tbl[SQ_BKING].knight );
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = LastOne( bb );
Xor( from, bb );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_gold_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BBAnd( bb_check, bb_move, abb_w_knight_attacks[from] );
BBAnd( bb_check, bb_check, abb_b_knight_attacks[SQ_BKING] );
- if ( BBToU(bb_check) ) {
+ if ( BBTest(bb_check) ) {
BB_WKNIGHT.p[0] ^= abb_mask[from].p[0];
BB_WKNIGHT.p[1] ^= abb_mask[from].p[1];
BB_WOCCUPY.p[0] ^= abb_mask[from].p[0];
Xor( to, bb_check );
BBIni( bb_attacks );
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
BB_WKNIGHT.p[1] ^= abb_mask[from].p[1];
return ( To2Move(to) | From2Move(from)
| Cap2Move(BOARD[to]) | Piece2Move(knight) );
- } while ( BBToU(bb_check) );
+ } while ( BBTest(bb_check) );
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
BBAnd( bb, BB_WLANCE, w_chk_tbl[SQ_BKING].lance );
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
from = LastOne( bb );
Xor( from, bb );
XorDiag1( from, OCCUPIED_DIAG1 );
bb_check.p[2] &= 0x7fc0000U;
- if ( BBToU(bb_check) ) {
+ if ( BBTest(bb_check) ) {
to = SQ_BKING-nfile;
if ( ! is_black_attacked( ptree, to ) ) {
goto w_lance_next;
}
bb_temp = abb_file_attacks[to][0];
- if ( can_b_king_escape( ptree, to, bb_temp ) ) { goto w_lance_next; }
+ if ( can_b_king_escape( ptree, to, &bb_temp ) ) { goto w_lance_next; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { goto w_lance_next; }
- if ( IsDiscoverWK( from, to ) ) { goto w_lance_next; }
+ else if ( can_b_piece_capture( ptree, to ) ) { goto w_lance_next; }
+ if ( IsDiscoverWK( from, to ) ) { goto w_lance_next; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
if ( ! is_black_attacked( ptree, to ) ) { continue; }
bb_attacks = abb_w_gold_attacks[to];
- if ( can_b_king_escape( ptree, to, bb_attacks ) ) { continue; }
+ if ( can_b_king_escape( ptree, to, &bb_attacks ) ) { continue; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { continue; }
- if ( IsDiscoverWK( from, to ) ) { continue; }
+ else if ( can_b_piece_capture( ptree, to ) ) { continue; }
+ if ( IsDiscoverWK( from, to ) ) { continue; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag1( from, OCCUPIED_DIAG1 );
- if ( ! is_black_attacked( ptree, to ) ) { goto w_pawn_pro_next; }
+ if ( ! is_black_attacked( ptree, to ) ) { goto w_pawn_pro_next; }
bb_attacks = abb_w_gold_attacks[to];
- if ( can_b_king_escape( ptree,to,bb_attacks ) ) { goto w_pawn_pro_next; }
+ if ( can_b_king_escape( ptree,to,&bb_attacks ) ) { goto w_pawn_pro_next; }
if ( IsDiscoverBK( from, to ) );
- else if ( can_b_piece_capture( ptree, to ) ) { goto w_pawn_pro_next; }
- if ( IsDiscoverWK( from, to ) ) { goto w_pawn_pro_next; }
+ else if ( can_b_piece_capture( ptree, to ) ) { goto w_pawn_pro_next; }
+ if ( IsDiscoverWK( from, to ) ) { goto w_pawn_pro_next; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag2( from, OCCUPIED_DIAG2 );
XorDiag1( from, OCCUPIED_DIAG1 );
- if ( ! is_black_attacked( ptree, to ) ) { goto w_pawn_end; }
+ if ( ! is_black_attacked( ptree, to ) ) { goto w_pawn_end; }
BBIni( bb_attacks );
- if ( can_b_king_escape( ptree,to,bb_attacks ) ) { goto w_pawn_end; }
- if ( can_b_piece_capture( ptree, to ) ) { goto w_pawn_end; }
- if ( IsDiscoverWK( from, to ) ) { goto w_pawn_end; }
+ if ( can_b_king_escape( ptree,to,&bb_attacks ) ) { goto w_pawn_end; }
+ if ( can_b_piece_capture( ptree, to ) ) { goto w_pawn_end; }
+ if ( IsDiscoverWK( from, to ) ) { goto w_pawn_end; }
XorFile( from, OCCUPIED_FILE );
XorDiag2( from, OCCUPIED_DIAG2 );
}
-static int
+static int CONV
can_w_piece_capture( const tree_t * restrict ptree, int to )
{
bitboard_t bb_sum, bb, bb_attacks;
BBAnd( bb_sum, BB_WKNIGHT, abb_b_knight_attacks[to] );
- BBAnd( bb, BB_WSILVER, abb_b_silver_attacks[to] );
- BBOr( bb_sum, bb, bb_sum );
-
- BBAnd( bb, BB_WTGOLD, abb_b_gold_attacks[to] );
- BBOr( bb_sum, bb, bb_sum );
+ BBAndOr( bb_sum, BB_WSILVER, abb_b_silver_attacks[to] );
+ BBAndOr( bb_sum, BB_WTGOLD, abb_b_gold_attacks[to] );
BBOr( bb, BB_WHORSE, BB_WDRAGON );
- BBAnd( bb, bb, abb_king_attacks[to] );
- BBOr( bb_sum, bb, bb_sum );
+ BBAndOr( bb_sum, bb, abb_king_attacks[to] );
AttackBishop( bb, to );
- BBAnd( bb, BB_W_BH, bb );
- BBOr( bb_sum, bb, bb_sum );
+ BBAndOr( bb_sum, BB_W_BH, bb );
- bb_sum.p[aslide[to].ir0] |= BB_W_RD.p[aslide[to].ir0] & AttackRank(to);
-
- BBAnd( bb, BB_WLANCE, abb_minus_rays[to] );
- BBOr( bb, bb, BB_W_RD );
+ BBAndOr( bb_sum, BB_W_RD, AttackRank(to) );
+ bb = BB_W_RD;
+ BBAndOr( bb, BB_WLANCE, abb_minus_rays[to] );
bb_attacks = AttackFile( to );
- BBAnd( bb, bb, bb_attacks );
- BBOr( bb_sum, bb_sum, bb );
+ BBAndOr( bb_sum, bb, bb_attacks );
- while ( BBToU( bb_sum ) )
+ while ( BBTest( bb_sum ) )
{
from = FirstOne( bb_sum );
Xor( from, bb_sum );
}
-static int
+static int CONV
can_b_piece_capture( const tree_t * restrict ptree, int to )
{
- bitboard_t bb_sum, bb, bb_attacks;
+ bitboard_t bb_sum, bb;
int idirec, from;
from = to+nfile;
BBAnd( bb_sum, BB_BKNIGHT, abb_w_knight_attacks[to] );
- BBAnd( bb, BB_BSILVER, abb_w_silver_attacks[to] );
- BBOr( bb_sum, bb_sum, bb );
-
- BBAnd( bb, BB_BTGOLD, abb_w_gold_attacks[to] );
- BBOr( bb_sum, bb_sum, bb );
+ BBAndOr( bb_sum, BB_BSILVER, abb_w_silver_attacks[to] );
+ BBAndOr( bb_sum, BB_BTGOLD, abb_w_gold_attacks[to] );
BBOr( bb, BB_BHORSE, BB_BDRAGON );
- BBAnd( bb, bb, abb_king_attacks[to] );
- BBOr( bb_sum, bb_sum, bb );
+ BBAndOr( bb_sum, bb, abb_king_attacks[to] );
AttackBishop( bb, to );
- BBAnd( bb, bb, BB_B_BH );
- BBOr( bb_sum, bb_sum, bb );
+ BBAndOr( bb_sum, bb, BB_B_BH );
+ BBAndOr( bb_sum, BB_B_RD, AttackRank(to) );
- bb_sum.p[aslide[to].ir0] |= BB_B_RD.p[aslide[to].ir0] & AttackRank(to);
-
- BBAnd( bb, BB_BLANCE, abb_plus_rays[to] );
- BBOr( bb, bb, BB_B_RD );
- bb_attacks = AttackFile( to );
- BBAnd( bb, bb, bb_attacks );
- BBOr( bb_sum, bb_sum, bb );
+ bb = BB_B_RD;
+ BBAndOr( bb, BB_BLANCE, abb_plus_rays[to] );
+ BBAndOr( bb_sum, bb, AttackFile( to ) );
- while ( BBToU( bb_sum ) )
+ while ( BBTest( bb_sum ) )
{
from = LastOne( bb_sum );
Xor( from, bb_sum );
}
-static int
-can_w_king_escape( tree_t * restrict ptree, int to, bitboard_t bb )
+static int CONV
+can_w_king_escape( tree_t * restrict ptree, int to,
+ const bitboard_t * restrict pbb )
{
+ bitboard_t bb = *pbb;
int iret = 0, iescape;
if ( !BOARD[to] )
BBOr( bb, bb, abb_mask[to] );
BBOr( bb, bb, BB_WOCCUPY );
- BBNot( bb, bb );
- BBAnd( bb, bb, abb_king_attacks[SQ_WKING] );
+ BBNotAnd( bb, abb_king_attacks[SQ_WKING], bb );
- while( BBToU(bb) )
+ while( BBTest(bb) )
{
iescape = FirstOne( bb );
if ( ! is_white_attacked( ptree, iescape ) )
}
-static int
-can_b_king_escape( tree_t * restrict ptree, int to, bitboard_t bb )
+static int CONV
+can_b_king_escape( tree_t * restrict ptree, int to,
+ const bitboard_t * restrict pbb )
{
+ bitboard_t bb = *pbb;
int iret = 0, iescape;
if ( !BOARD[to] )
BBOr( bb, bb, abb_mask[to] );
BBOr( bb, bb, BB_BOCCUPY );
- BBNot( bb, bb );
- BBAnd( bb, bb, abb_king_attacks[SQ_BKING] );
+ BBNotAnd( bb, abb_king_attacks[SQ_BKING], bb );
- while( BBToU(bb) )
+ while( BBTest(bb) )
{
iescape = LastOne( bb );
if ( ! is_black_attacked( ptree, iescape ) )
mate_intercept_weak_move,
mate_intercept_drop_sup };
-static int mate3_and( tree_t * restrict ptree, int turn, int ply, int flag );
-static void checker( const tree_t * restrict ptree, char *psq, int turn );
-static unsigned int gen_king_cap_checker( const tree_t * restrict ptree,
- int to, int turn );
-static int mate_weak_or( tree_t * restrict ptree, int turn, int ply,
- int from, int to );
-static unsigned int *gen_move_to( const tree_t * restrict ptree, int sq,
- int turn, unsigned int * restrict pmove );
-static unsigned int *gen_king_move( const tree_t * restrict ptree,
- const char *psq, int turn, int is_capture,
- unsigned int * restrict pmove );
-static unsigned int *gen_intercept( tree_t * restrict __ptree__,
- int sq_checker, int ply, int turn,
- int * restrict premaining,
- unsigned int * restrict pmove, int flag );
-static int gen_next_evasion_mate( tree_t * restrict ptree, const char *psq,
- int ply, int turn, int flag );
-
-unsigned int
+static int CONV mate3_and( tree_t * restrict ptree, int turn, int ply,
+ int flag );
+static void CONV checker( const tree_t * restrict ptree, char *psq, int turn );
+static unsigned int CONV gen_king_cap_checker( const tree_t * restrict ptree,
+ int to, int turn );
+static int CONV mate_weak_or( tree_t * restrict ptree, int turn, int ply,
+ int from, int to );
+static unsigned int * CONV gen_move_to( const tree_t * restrict ptree, int sq,
+ int turn,
+ unsigned int * restrict pmove );
+static unsigned int * CONV gen_king_move( const tree_t * restrict ptree,
+ const char *psq, int turn,
+ int is_capture,
+ unsigned int * restrict pmove );
+static unsigned int * CONV gen_intercept( tree_t * restrict __ptree__,
+ int sq_checker, int ply, int turn,
+ int * restrict premaining,
+ unsigned int * restrict pmove,
+ int flag );
+static int CONV gen_next_evasion_mate( tree_t * restrict ptree,
+ const char *psq, int ply, int turn,
+ int flag );
+
+static uint64_t mate3_hash_tbl[ MATE3_MASK + 1 ] = {0};
+
+static int CONV
+mhash_probe( tree_t * restrict ptree, int turn, int ply )
+{
+ uint64_t key_current, key, word;
+ unsigned int move;
+
+ word = mate3_hash_tbl[ (unsigned int)HASH_KEY & MATE3_MASK ];
+#if ! defined(__x86_64__)
+ word ^= word << 32;
+#endif
+
+ key = word & ~(uint64_t)0x7ffffU;
+ key_current = HASH_KEY & ~(uint64_t)0x7ffffU;
+ key_current ^= (uint64_t)HAND_B << 42;
+ key_current ^= (uint64_t)turn << 63;
+
+ if ( key != key_current ) { return 0; }
+
+ move = (unsigned int)word & 0x7ffffU;
+ if ( move != MOVE_NA )
+ {
+ move |= turn ? Cap2Move( BOARD[I2To(move)])
+ : Cap2Move(-BOARD[I2To(move)]);
+ }
+
+ MOVE_CURR = move;
+
+ return 1;
+}
+
+
+static void CONV
+mhash_store( const tree_t * restrict ptree, int turn, unsigned int move )
+{
+ uint64_t word;
+
+ word = HASH_KEY & ~(uint64_t)0x7ffffU;
+ word |= (uint64_t)( move & 0x7ffffU );
+ word ^= (uint64_t)HAND_B << 42;
+ word ^= (uint64_t)turn << 63;
+
+#if ! defined(__x86_64__)
+ word ^= word << 32;
+#endif
+ mate3_hash_tbl[ (unsigned int)HASH_KEY & MATE3_MASK ] = word;
+}
+
+
+unsigned int CONV
is_mate_in3ply( tree_t * restrict ptree, int turn, int ply )
{
int value, flag_skip;
+ if ( mhash_probe( ptree, turn, ply ) )
+ {
+ if ( MOVE_CURR == MOVE_NA ) { return 0; }
+ else { return 1; }
+ }
+
if ( ply >= PLY_MAX-2 ) { return 0; }
flag_skip = 0;
UnMakeMove( turn, MOVE_CURR, ply );
- if ( value ) { return 1; }
+ if ( value )
+ {
+ mhash_store( ptree, turn, MOVE_CURR );
+ return 1;
+ }
if ( ( MOVE_CURR & MOVE_CHK_SET )
&& I2To(MOVE_CURR) != I2To(ptree->current_move[ply+1]) )
}
}
+ mhash_store( ptree, turn, MOVE_NA );
return 0;
}
-static int
+static int CONV
mate3_and( tree_t * restrict ptree, int turn, int ply, int flag )
{
unsigned int move;
}
-static int
+static int CONV
mate_weak_or( tree_t * restrict ptree, int turn, int ply, int from,
int to )
{
}
-static int
+static int CONV
gen_next_evasion_mate( tree_t * restrict ptree, const char *psq, int ply,
int turn, int flag )
{
}
-static void
+static void CONV
checker( const tree_t * restrict ptree, char *psq, int turn )
{
- bitboard_t bb, bb_checkers;
+ bitboard_t bb;
int n, sq0, sq1, sq_king;
if ( turn )
{
- sq_king = SQ_WKING;
- bb_checkers = BB_BOCCUPY;
+ sq_king = SQ_WKING;
+ bb = b_attacks_to_piece( ptree, sq_king );
}
else {
- sq_king = SQ_BKING;
- bb_checkers = BB_WOCCUPY;
+ sq_king = SQ_BKING;
+ bb = w_attacks_to_piece( ptree, sq_king );
}
- bb = attacks_to_piece( ptree, sq_king );
- BBAnd( bb, bb, bb_checkers );
- assert( BBToU(bb) );
+
+ assert( BBTest(bb) );
sq0 = LastOne( bb );
sq1 = nsquare;
Xor( sq0, bb );
- if ( BBToU( bb ) )
+ if ( BBTest( bb ) )
{
sq1 = LastOne( bb );
if ( BBContract( abb_king_attacks[sq_king], abb_mask[sq1] ) )
}
-static unsigned int
+static unsigned int CONV
gen_king_cap_checker( const tree_t * restrict ptree, int to, int turn )
{
unsigned int move;
}
-static unsigned int *
+static unsigned int * CONV
gen_move_to( const tree_t * restrict ptree, int to, int turn,
unsigned int * restrict pmove )
{
bitboard_t bb;
int direc, from, pc, flag_promo, flag_unpromo;
- bb = attacks_to_piece( ptree, to );
if ( turn )
{
- BBAnd( bb, bb, BB_WOCCUPY );
- BBNotAnd( bb, abb_mask[SQ_WKING] );
- while ( BBToU(bb) )
+ bb = w_attacks_to_piece( ptree, to );
+ BBNotAnd( bb, bb, abb_mask[SQ_WKING] );
+ while ( BBTest(bb) )
{
from = LastOne( bb );
Xor( from, bb );
}
}
else {
- BBAnd( bb, bb, BB_BOCCUPY );
- BBNotAnd( bb, abb_mask[SQ_BKING] );
- while ( BBToU(bb) )
+ bb = b_attacks_to_piece( ptree, to );
+ BBNotAnd( bb, bb, abb_mask[SQ_BKING] );
+ while ( BBTest(bb) )
{
from = FirstOne( bb );
Xor( from, bb );
}
-static unsigned int *
+static unsigned int * CONV
gen_king_move( const tree_t * restrict ptree, const char *psq, int turn,
int is_capture, unsigned int * restrict pmove )
{
if ( turn )
{
from = SQ_WKING;
- bb = abb_king_attacks[from];
+ bb = abb_king_attacks[from];
if ( is_capture )
{
BBAnd( bb, bb, BB_BOCCUPY );
- BBNotAnd( bb, abb_mask[(int)psq[0]] );
+ BBNotAnd( bb, bb, abb_mask[(int)psq[0]] );
}
- else { BBNotAnd( bb, BB_BOCCUPY ); }
- BBNotAnd( bb, BB_WOCCUPY );
+ else { BBNotAnd( bb, bb, BB_BOCCUPY ); }
+ BBNotAnd( bb, bb, BB_WOCCUPY );
}
else {
from = SQ_BKING;
- bb = abb_king_attacks[from];
+ bb = abb_king_attacks[from];
if ( is_capture )
{
BBAnd( bb, bb, BB_WOCCUPY );
- BBNotAnd( bb, abb_mask[(int)psq[0]] );
+ BBNotAnd( bb, bb, abb_mask[(int)psq[0]] );
}
- else { BBNotAnd( bb, BB_WOCCUPY ); }
- BBNotAnd( bb, BB_BOCCUPY );
+ else { BBNotAnd( bb, bb, BB_WOCCUPY ); }
+ BBNotAnd( bb, bb, BB_BOCCUPY );
}
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
to = LastOne( bb );
Xor( to, bb );
}
-static unsigned int *
+static unsigned int * CONV
gen_intercept( tree_t * restrict __ptree__, int sq_checker, int ply, int turn,
int * restrict premaining, unsigned int * restrict pmove,
int flag )
{
sq_k = SQ_WKING;
bb_defender = BB_WOCCUPY;
- BBNotAnd( bb_defender, abb_mask[sq_k] );
+ BBNotAnd( bb_defender, bb_defender, abb_mask[sq_k] );
}
else {
sq_k = SQ_BKING;
bb_defender = BB_BOCCUPY;
- BBNotAnd( bb_defender, abb_mask[sq_k] );
+ BBNotAnd( bb_defender, bb_defender, abb_mask[sq_k] );
}
switch ( adirec[sq_k][sq_checker] )
nmove = 0;
bb_atk = attacks_to_piece( ptree, to );
BBAnd( bb, bb_defender, bb_atk );
- while ( BBToU(bb) )
+ while ( BBTest(bb) )
{
from = LastOne( bb );
Xor( from, bb );
/* -tentative assumption- */
/* no intercept-drop at non-supported square. */
- if ( I2To(MOVE_LAST) == sq_checker && dist > min_chuai ) { continue; }
+ if ( (int)I2To(MOVE_LAST) == sq_checker
+ && dist > min_chuai ) { continue; }
}
nmove = 0;
#define BAddMoveCap(piece) \
utemp = From2Move(from) | Piece2Move(piece); \
- while ( BBToU( bb_move ) ) { \
+ while ( BBTest( bb_move ) ) { \
to = LastOne( bb_move ); \
*pmove++ = To2Move(to) | Cap2Move(-BOARD[to]) | utemp; \
Xor( to, bb_move ); }
-#define BAddMove(piece) utemp = From2Move(from) | Piece2Move(piece); \
- while ( BBToU( bb_move ) ) { \
- to = LastOne( bb_move ); \
- *pmove++ = To2Move(to) | utemp; \
+#define BAddMove(piece) utemp = From2Move(from) | Piece2Move(piece); \
+ while ( BBTest( bb_move ) ) { \
+ to = LastOne( bb_move ); \
+ *pmove++ = To2Move(to) | utemp; \
Xor( to, bb_move ); }
-#define WAddMoveCap(piece) \
- utemp = From2Move(from) | Piece2Move(piece); \
- while ( BBToU( bb_move ) ) { \
- to = FirstOne( bb_move ); \
- *pmove++ = To2Move(to) | Cap2Move(BOARD[to]) | utemp; \
+#define WAddMoveCap(piece) \
+ utemp = From2Move(from) | Piece2Move(piece); \
+ while ( BBTest( bb_move ) ) { \
+ to = FirstOne( bb_move ); \
+ *pmove++ = To2Move(to) | Cap2Move(BOARD[to]) | utemp; \
Xor( to, bb_move ); }
-#define WAddMove(piece) utemp = From2Move(from) | Piece2Move(piece); \
- while ( BBToU( bb_move ) ) { \
- to = FirstOne( bb_move ); \
- *pmove++ = To2Move(to) | utemp; \
+#define WAddMove(piece) utemp = From2Move(from) | Piece2Move(piece); \
+ while ( BBTest( bb_move ) ) { \
+ to = FirstOne( bb_move ); \
+ *pmove++ = To2Move(to) | utemp; \
Xor( to, bb_move ); }
-unsigned int *
+unsigned int * CONV
b_gen_cap_nopro_ex2( const tree_t * restrict ptree,
unsigned int * restrict pmove )
{
bb_piece = BB_BLANCE;
bb_target.p[0] &= 0x3fe00;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
ubb_move0 = AttackFile(from).p[0]
}
-unsigned int *
+unsigned int * CONV
b_gen_nocap_nopro_ex2( const tree_t * restrict ptree,
unsigned int * restrict pmove )
{
bb_piece = BB_BLANCE;
ubb_target0 = bb_target.p[0] & 0x3fe00;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = LastOne( bb_piece );
ubb_move0 = AttackFile(from).p[0]
}
-unsigned int *
+unsigned int * CONV
w_gen_cap_nopro_ex2( const tree_t * restrict ptree,
unsigned int * restrict pmove )
{
bb_piece = BB_WLANCE;
bb_target.p[2] &= 0x3fe00;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
ubb_move2 = AttackFile(from).p[2]
}
-unsigned int *
+unsigned int * CONV
w_gen_nocap_nopro_ex2( const tree_t * restrict ptree,
unsigned int * restrict pmove )
{
bb_piece = BB_WLANCE;
ubb_target2 = bb_target.p[2] & 0x3fe00;
- while( BBToU( bb_piece ) )
+ while( BBTest( bb_piece ) )
{
from = FirstOne( bb_piece );
ubb_move2 = AttackFile(from).p[2]
#include <limits.h>
#include "shogi.h"
-int
+int CONV
gen_next_move( tree_t * restrict ptree, int ply, int turn )
{
switch ( ptree->anext_move[ply].next_phase )
ibest = -1;
ptree->move_last[ply] = GenNoCaptures( turn, ptree->move_last[ply] );
ptree->move_last[ply] = GenDrop( turn, ptree->move_last[ply] );
+
n = (int)( ptree->move_last[ply] - ptree->anext_move[ply].move_last );
pmove = ptree->anext_move[ply].move_last;
for ( i = 0; i < n; i++ )
}
-int
+int CONV
gen_next_evasion( tree_t * restrict ptree, int ply, int turn )
{
switch ( ptree->anext_move[ply].next_phase )
{
if ( *( ptree->anext_move[ply].move_last ) )
{
- ptree->current_move[ply] = *(ptree->anext_move[ply].move_last++);
+ MOVE_CURR = *(ptree->anext_move[ply].move_last++);
return 1;
}
ptree->anext_move[ply].move_last++;
#define DPawn 87 /* 174 */
-#define DLance 235 /* 470 */
-#define DKnight 254 /* 508 */
-#define DProPawn 530 /* 617 */
-#define DProLance 482 /* 717 */
-#define DSilver 371 /* 742 */
-#define DProKnight 500 /* 754 */
-#define DProSilver 489 /* 860 */
-#define DGold 447 /* 894 */
-#define DBishop 571 /* 1142 */
-#define DRook 647 /* 1294 */
-#define DHorse 832 /* 1403 */
-#define DDragon 955 /* 1602 */
+#define DLance 232 /* 464 */
+#define DKnight 257 /* 514 */
+#define DProPawn 534 /* 621 */
+#define DProLance 489 /* 721 */
+#define DSilver 369 /* 738 */
+#define DProKnight 510 /* 767 */
+#define DProSilver 495 /* 864 */
+#define DGold 444 /* 888 */
+#define DBishop 569 /* 1138 */
+#define DRook 642 /* 1284 */
+#define DHorse 827 /* 1396 */
+#define DDragon 945 /* 1587 */
#define DKing 15000
-#include "shogi.h"\r
-\r
-static unsigned short tab[] = {\r
-5866,14081,15663,4534,14969,3034,8274,7570,\r
-14571,15428,2921,37,2534,4727,660,249,\r
-8308,3662,15794,10079,13857,13019,6070,9141,\r
-3942,14629,6891,11561,12156,4793,11132,12989,\r
-10044,16304,9389,2228,5053,3789,5988,4479,\r
-8719,13901,15524,3098,7570,12949,1074,0,\r
-10079,16233,7531,14642,13600,8087,0,11690,\r
-8579,15413,6522,1076,2677,6914,10881,13803,\r
-13806,15789,14642,2135,15427,14023,14079,7708,\r
-3602,0,4976,10910,4821,4543,5455,9368,\r
-4201,9970,10647,15130,10079,15020,5558,15902,\r
-7858,2962,10386,2155,14641,12308,8021,8170,\r
-2490,10528,15427,14629,10528,15136,999,1883,\r
-14912,10788,6360,3677,14960,12257,2294,12614,\r
-8698,12433,9867,12663,16016,11332,8568,8348,\r
-0,3228,8594,11249,6674,3098,9297,10077,\r
-10340,5803,5420,6070,660,5676,1,9497,\r
-8700,14264,5846,12433,16282,12561,12032,13732,\r
-8239,10731,7236,10286,2678,7321,13368,6594,\r
-9047,5291,8293,2809,3268,6485,10509,2277,\r
-10471,595,8887,15919,14413,15881,8827,13726,\r
-13975,14092,7634,1652,8753,6801,6568,15853,\r
-1022,5664,0,9303,15719,6128,6674,7433,\r
-157,9360,6555,12432,9593,9660,14081,13927,\r
-8702,13702,8663,5629,3691,16298,1573,902,\r
-1272,2376,1084,14447,14666,1692,15316,15129,\r
-3833,920,8348,15839,15902,15635,10340,6603,\r
-1764,9634,3833,2470,4704,9646,385,13200,\r
-3009,1562,6846,6598,15861,8924,11762,3766,\r
-9095,431,6599,1987,15902,11064,4972,12175,\r
-14642,13857,6130,5833,13857,12112,8170,9867,\r
-2569,9648,1883,10205,12365,6801,5222,14506,\r
-1819,5142,2172,5291,15542,12112,2092,5560,\r
-4538,5461,15059,11773,15884,2099,6876,11914,\r
-3833,4972,8164,6240,12487,1341,10731,11762,\r
-14548,4471,5044,7576,2392,16129,8175,7559,\r
-12559,15861,6396,2926,7618,8417,15759,0,\r
-9095,3510,7247,1712,16345,2209,8055,0,\r
-319,12209,13144,15159,8238,7822,5014,10077,\r
-2284,7177,6555,15861,14479,2510,8170,11806,\r
-12149,12440,14185,11762,11552,8260,11864,11728,\r
-15046,11561,4707,13420,3615,2233,2277,10668,\r
-2228,8016,1813,2677,5240,6594,6636,9911,\r
-1737,4396,12500,9682,7176,2027,12500,5244,\r
-12112,1768,14571,12663,6729,3662,8170,15641,\r
-15316,9648,5373,5475,6522,14571,3662,15902,\r
-1652,9648,2228,8348,902,5988,9150,13250,\r
-13411,4675,431,5507,10616,13987,15316,1378,\r
-13832,13356,10087,9543,9093,8065,10497,8228,\r
-11762,616,12968,5411,9648,12487,9463,15597,\r
-11292,13985,14482,14600,1705,4678,12020,8828,\r
-6210,9481,14980,5738,5990,14447,1569,8618,\r
-2273,8543,1819,16158,12447,12470,10160,4725,\r
-10778,1412,8040,4300,9550,568,7394,592,\r
-9481,15680,3476,16128,7660,1214,359,6181,\r
-8618,4067,14699,13368,514,11355,8914,3801,\r
-14520,8885,10434,8274,7709,4312,7243,12633,\r
-4867,5981,4538,2490,3034,5558,6801,7512,\r
-14971,4315,4905,11682,8845,3732,1475,11661,\r
-10189,1741,11667,5605,2656,9573,10898,2796,\r
-1817,15216,11152,470,5988,6164,4972,10386,\r
-13128,7247,3268,6729,4300,13101,8568,12663,\r
-13849,3600,9718,11203,10528,13732,5251,14148,\r
-8568,13128,10205,11332,1712,12821,9557,12753,\r
-10505,5276,109,10394,10122,9809,3513,16093,\r
-2490,9943,14798,15084,4598,5174,15648,13109,\r
-0,6971,15426,14500,14571,6831,2623,6801,\r
-6522,15388,3228,11053,0,2902,4285,13853,\r
-14830,5373,15137,10087,3268,2569,6284,2902,\r
-1483,3838,12159,4764,15130,6846,6957,12499,\r
-4604,2739,14629,996,4867,13420,7791,5263,\r
-8119,10088,4128,7950,11875,16244,1147,3473,\r
-3268,15869,12821,11152,9922,1987,8238,15271,\r
-852,6921,4155,7857,11187,2275,14224,15725,\r
-9967,4479,6522,11152,2457,5962,13732,10088,\r
-11226,11359,5053,13420,3727,12487,3823,13412,\r
-13732,5962,11005,11173,8719,4354,6821,11421,\r
-15640,4769,14868,9369,215,8176,2363,1930,\r
-4124,11338,5373,2135,5253,10648,6220,5853,\r
-2741,12020,14070,14571,7476,9011,11415,1306,\r
-5318,13418,7293,15364,8898,3402,11976,9325,\r
-1562,7366,3395,10762,7144,2336,13458,4538,\r
-1159,1987,11652,12964,13513,541,13792,9741,\r
-10840,16129,10917,4534,13600,5462,2357,3890,\r
-6299,11315,13376,13820,13369,4450,14282,3510,\r
-10008,2381,9301,10165,4832,13042,3789,11751,\r
-8021,14286,9341,436,9171,8623,12745,12738,\r
-567,13996,3654,9495,844,8260,15108,2851,\r
-10351,2756,8572,3694,8851,5833,4280,12168,\r
-9550,9095,1652,6594,2534,3662,12009,6827,\r
-7447,2228,6555,15919,2294,6522,6674,0,\r
-13128,15478,3098,14571,1573,13117,16336,3422,\r
-12751,4635,9808,13171,11875,14148,14759,15680,\r
-610,780,14127,15067,12717,11768,2223,4745,\r
-2111,4363,6821,12230,13200,16093,410,15205,\r
-3838,15020,12230,3473,7951,2926,981,13414,\r
-3034,9835,3875,7247,15776,11053,10533,6393,\r
-6729,1712,12233,10088,5152,1378,6043,3871,\r
-6043,12487,15527,11769,12308,5962,11864,10804,\r
-3268,14005,13662,10647,4972,15137,14485,7784,\r
-7275,410,6555,2470,7074,359,12751,12054,\r
-8851,2993,9487,13270,9267,2370,8119,14112,\r
-6639,157,10245,16121,9967,14912,10307,8011,\r
-12094,2470,10322,3570,6154,1453,15084,14801,\r
-3823,7259,780,4972,13047,14500,2569,5833,\r
-56,14601,2690,5036,788,46,2738,9922,\r
-11332,10619,8011,13128,3268,431,13412,8851,\r
-14748,5036,12185,13042,10030,11716,100,16205,\r
-7951,5738,8417,10757,6463,7114,1183,14798,\r
-10205,9721,15359,10074,8727,4587,11875,14615,\r
-10340,9171,9171,4686,7731,4269,13042,8574,\r
-16298,7024,10309,2858,4904,7223,8238,7512,\r
-4556,3532,15222,2161,1162,6476,3221,10290,\r
-11229,15137,14921,1319,4925,1991,7817,7427,\r
-15089,9366,920,3875,4641,11787,14255,4915,\r
-7588,15555,13106,16014,12882,10324,341,1331,\r
-10685,7950,12292,10230,15336,7431,7576,6158,\r
-5058,12149,2777,13434,5263,15769,9877,2704,\r
-10300,867,1443,5285,2155,4474,935,12586,\r
-12601,158,16191,8119,3726,3554,10398,13418,\r
-8170,4867,14642,15478,1712,10136,6674,0,\r
-46,9867,3766,12433,6057,3972,2156,852,\r
-2144,9856,14761,11491,46,363,10561,4484,\r
-999,9557,2902,7323,15084,8274,16087,6679,\r
-6867,6971,2914,586,6240,5988,10386,8304,\r
-3662,10088,5988,12821,7409,8308,15931,14376,\r
-14700,15998,4484,1766,15794,3833,2464,4342,\r
-1358,319,10099,15776,15839,1530,8538,7800,\r
-3641,5569,7469,2104,8314,8976,5962,11857,\r
-10330,8293,12356,1399,1991,5415,10497,15478,\r
-15931,8308,11608,10167,4185,9369,1658,6193,\r
-5962,5132,12322,319,7802,4707,3034,11308,\r
-9559,10788,2228,8339,13513,5222,1712,3098,\r
-1987,2719,1548,15427,13361,13736,5139,1255,\r
-11064,8011,985,6135,788,2761,6522,5362,\r
-13128,3476,6164,12032,2902,15881,11053,14538,\r
-12964,14730,3751,12890,396,1132,6164,7938,\r
-3165,7677,12218,7007,4824,6266,4198,9127,\r
-12821,6463,199,6522,5462,1084,7232,15717,\r
-3354,2788,6294,11857,14174,2235,6135,7808,\r
-15931,10377,1168,9162,7176,3595,10046,1960,\r
-3726,1723,6779,10955,11201,4721,661,7247,\r
-5988,11291,9095,8555,7017,5975,14500,15822,\r
-10887,7999,9648,15908,2938,8293,14629,4233,\r
-8419,5141,12427,9360,2948,9321,13473,1134,\r
-87,4180,2284,8822,3893,15653,15668,12175,\r
-7951,12668,13119,7839,4793,4686,914,9481,\r
-11912,13196,4235,15293,5704,9063,1605,15640,\r
-13270,1192,9967,8698,5576,3059,4067,11809,\r
-5420,7691,16087,764,12487,2273,14224,13412,\r
-5373,12663,788,12433,8870,15902,14019,3966,\r
-1104,11153,13117,8913,46,9922,15240,8260,\r
-9874,1712,9096,7708,4544,15601,0,10529,\r
-7419,9404,653,4067,10717,4901,10009,7229,\r
-9867,7620,1412,14284,9931,8845,13975,8238,\r
-10941,10205,678,11308,14985,12099,3268,11120,\r
-14148,7900,5934,10099,12903,6274,9648,2851,\r
-972,5149,9506,12102,723,15873,14497,5447,\r
-13505,13658,13128,4699,11152,0,0,7808,\r
-2623,6674,9557,7920,10004,14081,0,15478,\r
-12498,7162,13662,14438,6939,10841,6599,7074,\r
-2129,9303,3614,5121,13626,14806,13096,5275,\r
-12032,11431,12265,242,12651,6465,11153,15635,\r
-6154,7864,3263,7708,13216,9466,4929,4763,\r
-16121,12949,6801,14244,6289,3766,8913,3228,\r
-10099,4198,11895,286,13119,10778,12230,7238,\r
-3614,14081,7323,4050,6846,14629,13420,9427,\r
-5460,5130,10528,15705,6369,8361,1212,8866,\r
-12821,15427,7323,2777,9648,8744,5386,8241,\r
-11875,14112,14770,15369,9813,6750,13732,6594,\r
-2464,11682,2031,15129,3532,12112,4831,4354,\r
-2275,10376,11226,11611,8313,9590,14500,8598,\r
-13403,4316,15388,13458,961,208,5995,1225,\r
-6455,5932,11987,2902,13128,1224,1003,7409,\r
-3028,650,13436,8485,6653,911,9425,11421,\r
-9554,10993,15293,514,6670,14578,4972,9874,\r
-8483,2534,14969,1934,14154,8926,11830,8784,\r
-2987,9634,6670,13501,13957,4260,5761,15347,\r
-7991,13414,7159,7233,14206,11665,6715,11079,\r
-3545,5185,15639,14307,9338,8971,15994,5645,\r
-3098,14081,788,8170,10188,8016,5988,15919,\r
-12788,14960,10214,12606,11152,2470,13420,2927,\r
-5240,7370,9648,10099,2039,4846,10610,11823,\r
-13270,14761,5962,7512,10079,4867,8260,2135,\r
-1052,10823,5729,10395,14361,13382,12200,8162,\r
-5117,7531,13361,14520,10602,8685,3654,9777,\r
-16263,6135,6389,11745,10383,8550,12618,10340,\r
-4128,15459,7062,5135,9047,9346,5897,15479,\r
-7268,5576,0,14937,12736,5545,10079,6507,\r
-3238,3204,9865,5843,12487,198,8251,13195,\r
-158,8913,6598,4373,15991,13857,3615,11106,\r
-3244,10654,6394,6183,11633,3098,12257,15427,\r
-1768,7209,11987,963,13857,7247,16046,7239,\r
-13200,11773,2914,12927,11669,13011,1905,9089,\r
-16176,3743,158,5222,12717,5825,16087,9519,\r
-9227,15563,1712,8511,11005,4867,13200,13106,\r
-10788,3606,8680,3447,5833,3709,4526,10847,\r
-2871,6000,2204,15769,2969,7617,15976,7618,\r
-4067,10757,15316,6476,10509,8772,9095,0,\r
-8996,410,14742,7239,10532,9406,7419,15903,\r
-5437,5560,12608,9141,3986,14358,7409,3992,\r
-3221,6170,11821,508,6434,1442,4260,3813,\r
-8308,6456,3534,431,4538,3406,12435,5643,\r
-7144,8870,9186,3775,1817,9905,7951,4336,\r
-2273,12264,6513,2993,16270,5541,5077,6263,\r
-1259,2559,1675,16218,1790,12804,15098,4445,\r
-10336,15216,12144,8618,4573,13679,15000,10189,\r
-2209,4583,5353,13784,2623,7720,5833,11064,\r
-10088,10077,10610,6786,10939,10867,1768,8119,\r
-7394,12056,3789,1074,15413,10527,7247,12487,\r
-8568,10136,2228,13412,4840,1652,6740,11322,\r
-5037,2910,5174,10340,2135,8011,11895,11895,\r
-109,11957,14336,13234,8225,14343,9063,9819,\r
-13517,11635,13549,14936,988,3809,5833,7857,\r
-13462,297,7668,14482,4316,10848,2569,13931,\r
-5593,12056,11103,14170,448,902,1768,11552,\r
-6043,0,0,8646,10391,0,15316,3737,\r
-10594,11026,13280,14667,5713,4057,2787,4191,\r
-3838,7247,8772,14185,15641,8772,0,14081,\r
-0,9429,17,613,7428,15131,15651,14350,\r
-4365,15856,9521,3228,7950,3395,0,6594,\r
-11078,14975,6889,10768,4288,6707,7175,2235,\r
-10896,911,7707,7592,12916,15570,15644,6997,\r
-12523,14757,11895,7109,16279,12969,11690,0,\r
-8854,16304,8568,11334,15641,15478,2275,6193,\r
-7323,5230,9835,12821,1652,12477,5044,359,\r
-12487,13881,10731,8246,14642,14885,6555,15919,\r
-13857,1982,7646,12528,12009,7310,12310,3193,\r
-359,1483,5322,10476,46,3751,3766,6729,\r
-4512,13853,5558,12736,1733,2718,9956,7857,\r
-6519,2187,12964,12949,750,8877,15136,3742,\r
-4495,13851,3811,906,11592,9943,920,10806,\r
-10442,12561,5035,988,15861,8024,10272,16372,\r
-13353,15946,7330,4834,9414,8267,1668,12498,\r
-4530,9162,8648,3883,9451,3900,2028,12427,\r
-11203,3071,5645,10228,11875,8198,4563,215,\r
-3614,5717,11332,1617,11382,13987,12626,11857,\r
-12156,6513,13496,6997,16158,9093,6725,13737,\r
-5890,10008,14447,5475,12215,141,16192,10200,\r
-4450,6688,11090,16109,12256,9027,15355,3422,\r
-10079,14571,13101,9967,12296,3460,8348,15413,\r
-5222,11762,3823,13412,6729,6599,10528,9922,\r
-11152,9171,5362,5373,750,8969,1652,6220,\r
-5373,2569,3742,15119,10340,999,10088,10731,\r
-1028,3228,7369,15256,11822,12904,8121,11641,\r
-11158,5016,10725,8412,1183,9674,11806,12112,\r
-2623,15516,4226,10021,13316,12075,792,4972,\r
-8506,8921,6133,14718,567,4349,13420,5953,\r
-2265,11902,10019,16265,16312,0,9922,3009,\r
-8170,3473,10757,3567,2825,6915,5174,4299,\r
-0,8274,6292,295,6522,1475,359,4538,\r
-5358,5174,3008,6317,12688,4165,752,12052,\r
-10008,3912,7431,13364,9894,13524,284,16013,\r
-9820,11295,1144,2845,3538,10678,13806,1469,\r
-14210,7870,3766,10528,13642,10823,4200,8031,\r
-4671,14093,5541,1214,4115,3286,8217,8018 };\r
-\r
-\r
-unsigned int phash( unsigned int move, int turn )\r
-{\r
- unsigned int a, b;\r
- \r
- move |= ( (unsigned int)turn << 31 );\r
- move += 0x69fe378e;\r
- move ^= ( move >> 16 );\r
- move += ( move << 8 );\r
- move ^= ( move >> 4 );\r
- b = ( move >> 7 ) & 0x7ff;\r
- a = move >> 18;\r
- \r
- return a ^ tab[b];\r
-}\r
+#include "shogi.h"
+
+static unsigned short tab[] = {
+5866,14081,15663,4534,14969,3034,8274,7570,
+14571,15428,2921,37,2534,4727,660,249,
+8308,3662,15794,10079,13857,13019,6070,9141,
+3942,14629,6891,11561,12156,4793,11132,12989,
+10044,16304,9389,2228,5053,3789,5988,4479,
+8719,13901,15524,3098,7570,12949,1074,0,
+10079,16233,7531,14642,13600,8087,0,11690,
+8579,15413,6522,1076,2677,6914,10881,13803,
+13806,15789,14642,2135,15427,14023,14079,7708,
+3602,0,4976,10910,4821,4543,5455,9368,
+4201,9970,10647,15130,10079,15020,5558,15902,
+7858,2962,10386,2155,14641,12308,8021,8170,
+2490,10528,15427,14629,10528,15136,999,1883,
+14912,10788,6360,3677,14960,12257,2294,12614,
+8698,12433,9867,12663,16016,11332,8568,8348,
+0,3228,8594,11249,6674,3098,9297,10077,
+10340,5803,5420,6070,660,5676,1,9497,
+8700,14264,5846,12433,16282,12561,12032,13732,
+8239,10731,7236,10286,2678,7321,13368,6594,
+9047,5291,8293,2809,3268,6485,10509,2277,
+10471,595,8887,15919,14413,15881,8827,13726,
+13975,14092,7634,1652,8753,6801,6568,15853,
+1022,5664,0,9303,15719,6128,6674,7433,
+157,9360,6555,12432,9593,9660,14081,13927,
+8702,13702,8663,5629,3691,16298,1573,902,
+1272,2376,1084,14447,14666,1692,15316,15129,
+3833,920,8348,15839,15902,15635,10340,6603,
+1764,9634,3833,2470,4704,9646,385,13200,
+3009,1562,6846,6598,15861,8924,11762,3766,
+9095,431,6599,1987,15902,11064,4972,12175,
+14642,13857,6130,5833,13857,12112,8170,9867,
+2569,9648,1883,10205,12365,6801,5222,14506,
+1819,5142,2172,5291,15542,12112,2092,5560,
+4538,5461,15059,11773,15884,2099,6876,11914,
+3833,4972,8164,6240,12487,1341,10731,11762,
+14548,4471,5044,7576,2392,16129,8175,7559,
+12559,15861,6396,2926,7618,8417,15759,0,
+9095,3510,7247,1712,16345,2209,8055,0,
+319,12209,13144,15159,8238,7822,5014,10077,
+2284,7177,6555,15861,14479,2510,8170,11806,
+12149,12440,14185,11762,11552,8260,11864,11728,
+15046,11561,4707,13420,3615,2233,2277,10668,
+2228,8016,1813,2677,5240,6594,6636,9911,
+1737,4396,12500,9682,7176,2027,12500,5244,
+12112,1768,14571,12663,6729,3662,8170,15641,
+15316,9648,5373,5475,6522,14571,3662,15902,
+1652,9648,2228,8348,902,5988,9150,13250,
+13411,4675,431,5507,10616,13987,15316,1378,
+13832,13356,10087,9543,9093,8065,10497,8228,
+11762,616,12968,5411,9648,12487,9463,15597,
+11292,13985,14482,14600,1705,4678,12020,8828,
+6210,9481,14980,5738,5990,14447,1569,8618,
+2273,8543,1819,16158,12447,12470,10160,4725,
+10778,1412,8040,4300,9550,568,7394,592,
+9481,15680,3476,16128,7660,1214,359,6181,
+8618,4067,14699,13368,514,11355,8914,3801,
+14520,8885,10434,8274,7709,4312,7243,12633,
+4867,5981,4538,2490,3034,5558,6801,7512,
+14971,4315,4905,11682,8845,3732,1475,11661,
+10189,1741,11667,5605,2656,9573,10898,2796,
+1817,15216,11152,470,5988,6164,4972,10386,
+13128,7247,3268,6729,4300,13101,8568,12663,
+13849,3600,9718,11203,10528,13732,5251,14148,
+8568,13128,10205,11332,1712,12821,9557,12753,
+10505,5276,109,10394,10122,9809,3513,16093,
+2490,9943,14798,15084,4598,5174,15648,13109,
+0,6971,15426,14500,14571,6831,2623,6801,
+6522,15388,3228,11053,0,2902,4285,13853,
+14830,5373,15137,10087,3268,2569,6284,2902,
+1483,3838,12159,4764,15130,6846,6957,12499,
+4604,2739,14629,996,4867,13420,7791,5263,
+8119,10088,4128,7950,11875,16244,1147,3473,
+3268,15869,12821,11152,9922,1987,8238,15271,
+852,6921,4155,7857,11187,2275,14224,15725,
+9967,4479,6522,11152,2457,5962,13732,10088,
+11226,11359,5053,13420,3727,12487,3823,13412,
+13732,5962,11005,11173,8719,4354,6821,11421,
+15640,4769,14868,9369,215,8176,2363,1930,
+4124,11338,5373,2135,5253,10648,6220,5853,
+2741,12020,14070,14571,7476,9011,11415,1306,
+5318,13418,7293,15364,8898,3402,11976,9325,
+1562,7366,3395,10762,7144,2336,13458,4538,
+1159,1987,11652,12964,13513,541,13792,9741,
+10840,16129,10917,4534,13600,5462,2357,3890,
+6299,11315,13376,13820,13369,4450,14282,3510,
+10008,2381,9301,10165,4832,13042,3789,11751,
+8021,14286,9341,436,9171,8623,12745,12738,
+567,13996,3654,9495,844,8260,15108,2851,
+10351,2756,8572,3694,8851,5833,4280,12168,
+9550,9095,1652,6594,2534,3662,12009,6827,
+7447,2228,6555,15919,2294,6522,6674,0,
+13128,15478,3098,14571,1573,13117,16336,3422,
+12751,4635,9808,13171,11875,14148,14759,15680,
+610,780,14127,15067,12717,11768,2223,4745,
+2111,4363,6821,12230,13200,16093,410,15205,
+3838,15020,12230,3473,7951,2926,981,13414,
+3034,9835,3875,7247,15776,11053,10533,6393,
+6729,1712,12233,10088,5152,1378,6043,3871,
+6043,12487,15527,11769,12308,5962,11864,10804,
+3268,14005,13662,10647,4972,15137,14485,7784,
+7275,410,6555,2470,7074,359,12751,12054,
+8851,2993,9487,13270,9267,2370,8119,14112,
+6639,157,10245,16121,9967,14912,10307,8011,
+12094,2470,10322,3570,6154,1453,15084,14801,
+3823,7259,780,4972,13047,14500,2569,5833,
+56,14601,2690,5036,788,46,2738,9922,
+11332,10619,8011,13128,3268,431,13412,8851,
+14748,5036,12185,13042,10030,11716,100,16205,
+7951,5738,8417,10757,6463,7114,1183,14798,
+10205,9721,15359,10074,8727,4587,11875,14615,
+10340,9171,9171,4686,7731,4269,13042,8574,
+16298,7024,10309,2858,4904,7223,8238,7512,
+4556,3532,15222,2161,1162,6476,3221,10290,
+11229,15137,14921,1319,4925,1991,7817,7427,
+15089,9366,920,3875,4641,11787,14255,4915,
+7588,15555,13106,16014,12882,10324,341,1331,
+10685,7950,12292,10230,15336,7431,7576,6158,
+5058,12149,2777,13434,5263,15769,9877,2704,
+10300,867,1443,5285,2155,4474,935,12586,
+12601,158,16191,8119,3726,3554,10398,13418,
+8170,4867,14642,15478,1712,10136,6674,0,
+46,9867,3766,12433,6057,3972,2156,852,
+2144,9856,14761,11491,46,363,10561,4484,
+999,9557,2902,7323,15084,8274,16087,6679,
+6867,6971,2914,586,6240,5988,10386,8304,
+3662,10088,5988,12821,7409,8308,15931,14376,
+14700,15998,4484,1766,15794,3833,2464,4342,
+1358,319,10099,15776,15839,1530,8538,7800,
+3641,5569,7469,2104,8314,8976,5962,11857,
+10330,8293,12356,1399,1991,5415,10497,15478,
+15931,8308,11608,10167,4185,9369,1658,6193,
+5962,5132,12322,319,7802,4707,3034,11308,
+9559,10788,2228,8339,13513,5222,1712,3098,
+1987,2719,1548,15427,13361,13736,5139,1255,
+11064,8011,985,6135,788,2761,6522,5362,
+13128,3476,6164,12032,2902,15881,11053,14538,
+12964,14730,3751,12890,396,1132,6164,7938,
+3165,7677,12218,7007,4824,6266,4198,9127,
+12821,6463,199,6522,5462,1084,7232,15717,
+3354,2788,6294,11857,14174,2235,6135,7808,
+15931,10377,1168,9162,7176,3595,10046,1960,
+3726,1723,6779,10955,11201,4721,661,7247,
+5988,11291,9095,8555,7017,5975,14500,15822,
+10887,7999,9648,15908,2938,8293,14629,4233,
+8419,5141,12427,9360,2948,9321,13473,1134,
+87,4180,2284,8822,3893,15653,15668,12175,
+7951,12668,13119,7839,4793,4686,914,9481,
+11912,13196,4235,15293,5704,9063,1605,15640,
+13270,1192,9967,8698,5576,3059,4067,11809,
+5420,7691,16087,764,12487,2273,14224,13412,
+5373,12663,788,12433,8870,15902,14019,3966,
+1104,11153,13117,8913,46,9922,15240,8260,
+9874,1712,9096,7708,4544,15601,0,10529,
+7419,9404,653,4067,10717,4901,10009,7229,
+9867,7620,1412,14284,9931,8845,13975,8238,
+10941,10205,678,11308,14985,12099,3268,11120,
+14148,7900,5934,10099,12903,6274,9648,2851,
+972,5149,9506,12102,723,15873,14497,5447,
+13505,13658,13128,4699,11152,0,0,7808,
+2623,6674,9557,7920,10004,14081,0,15478,
+12498,7162,13662,14438,6939,10841,6599,7074,
+2129,9303,3614,5121,13626,14806,13096,5275,
+12032,11431,12265,242,12651,6465,11153,15635,
+6154,7864,3263,7708,13216,9466,4929,4763,
+16121,12949,6801,14244,6289,3766,8913,3228,
+10099,4198,11895,286,13119,10778,12230,7238,
+3614,14081,7323,4050,6846,14629,13420,9427,
+5460,5130,10528,15705,6369,8361,1212,8866,
+12821,15427,7323,2777,9648,8744,5386,8241,
+11875,14112,14770,15369,9813,6750,13732,6594,
+2464,11682,2031,15129,3532,12112,4831,4354,
+2275,10376,11226,11611,8313,9590,14500,8598,
+13403,4316,15388,13458,961,208,5995,1225,
+6455,5932,11987,2902,13128,1224,1003,7409,
+3028,650,13436,8485,6653,911,9425,11421,
+9554,10993,15293,514,6670,14578,4972,9874,
+8483,2534,14969,1934,14154,8926,11830,8784,
+2987,9634,6670,13501,13957,4260,5761,15347,
+7991,13414,7159,7233,14206,11665,6715,11079,
+3545,5185,15639,14307,9338,8971,15994,5645,
+3098,14081,788,8170,10188,8016,5988,15919,
+12788,14960,10214,12606,11152,2470,13420,2927,
+5240,7370,9648,10099,2039,4846,10610,11823,
+13270,14761,5962,7512,10079,4867,8260,2135,
+1052,10823,5729,10395,14361,13382,12200,8162,
+5117,7531,13361,14520,10602,8685,3654,9777,
+16263,6135,6389,11745,10383,8550,12618,10340,
+4128,15459,7062,5135,9047,9346,5897,15479,
+7268,5576,0,14937,12736,5545,10079,6507,
+3238,3204,9865,5843,12487,198,8251,13195,
+158,8913,6598,4373,15991,13857,3615,11106,
+3244,10654,6394,6183,11633,3098,12257,15427,
+1768,7209,11987,963,13857,7247,16046,7239,
+13200,11773,2914,12927,11669,13011,1905,9089,
+16176,3743,158,5222,12717,5825,16087,9519,
+9227,15563,1712,8511,11005,4867,13200,13106,
+10788,3606,8680,3447,5833,3709,4526,10847,
+2871,6000,2204,15769,2969,7617,15976,7618,
+4067,10757,15316,6476,10509,8772,9095,0,
+8996,410,14742,7239,10532,9406,7419,15903,
+5437,5560,12608,9141,3986,14358,7409,3992,
+3221,6170,11821,508,6434,1442,4260,3813,
+8308,6456,3534,431,4538,3406,12435,5643,
+7144,8870,9186,3775,1817,9905,7951,4336,
+2273,12264,6513,2993,16270,5541,5077,6263,
+1259,2559,1675,16218,1790,12804,15098,4445,
+10336,15216,12144,8618,4573,13679,15000,10189,
+2209,4583,5353,13784,2623,7720,5833,11064,
+10088,10077,10610,6786,10939,10867,1768,8119,
+7394,12056,3789,1074,15413,10527,7247,12487,
+8568,10136,2228,13412,4840,1652,6740,11322,
+5037,2910,5174,10340,2135,8011,11895,11895,
+109,11957,14336,13234,8225,14343,9063,9819,
+13517,11635,13549,14936,988,3809,5833,7857,
+13462,297,7668,14482,4316,10848,2569,13931,
+5593,12056,11103,14170,448,902,1768,11552,
+6043,0,0,8646,10391,0,15316,3737,
+10594,11026,13280,14667,5713,4057,2787,4191,
+3838,7247,8772,14185,15641,8772,0,14081,
+0,9429,17,613,7428,15131,15651,14350,
+4365,15856,9521,3228,7950,3395,0,6594,
+11078,14975,6889,10768,4288,6707,7175,2235,
+10896,911,7707,7592,12916,15570,15644,6997,
+12523,14757,11895,7109,16279,12969,11690,0,
+8854,16304,8568,11334,15641,15478,2275,6193,
+7323,5230,9835,12821,1652,12477,5044,359,
+12487,13881,10731,8246,14642,14885,6555,15919,
+13857,1982,7646,12528,12009,7310,12310,3193,
+359,1483,5322,10476,46,3751,3766,6729,
+4512,13853,5558,12736,1733,2718,9956,7857,
+6519,2187,12964,12949,750,8877,15136,3742,
+4495,13851,3811,906,11592,9943,920,10806,
+10442,12561,5035,988,15861,8024,10272,16372,
+13353,15946,7330,4834,9414,8267,1668,12498,
+4530,9162,8648,3883,9451,3900,2028,12427,
+11203,3071,5645,10228,11875,8198,4563,215,
+3614,5717,11332,1617,11382,13987,12626,11857,
+12156,6513,13496,6997,16158,9093,6725,13737,
+5890,10008,14447,5475,12215,141,16192,10200,
+4450,6688,11090,16109,12256,9027,15355,3422,
+10079,14571,13101,9967,12296,3460,8348,15413,
+5222,11762,3823,13412,6729,6599,10528,9922,
+11152,9171,5362,5373,750,8969,1652,6220,
+5373,2569,3742,15119,10340,999,10088,10731,
+1028,3228,7369,15256,11822,12904,8121,11641,
+11158,5016,10725,8412,1183,9674,11806,12112,
+2623,15516,4226,10021,13316,12075,792,4972,
+8506,8921,6133,14718,567,4349,13420,5953,
+2265,11902,10019,16265,16312,0,9922,3009,
+8170,3473,10757,3567,2825,6915,5174,4299,
+0,8274,6292,295,6522,1475,359,4538,
+5358,5174,3008,6317,12688,4165,752,12052,
+10008,3912,7431,13364,9894,13524,284,16013,
+9820,11295,1144,2845,3538,10678,13806,1469,
+14210,7870,3766,10528,13642,10823,4200,8031,
+4671,14093,5541,1214,4115,3286,8217,8018 };
+
+
+unsigned int CONV phash( unsigned int move, int turn )
+{
+ unsigned int a, b;
+
+ move |= ( (unsigned int)turn << 31 );
+ move += 0x69fe378e;
+ move ^= ( move >> 16 );
+ move += ( move << 8 );
+ move ^= ( move >> 4 );
+ b = ( move >> 7 ) & 0x7ff;
+ a = move >> 18;
+
+ return a ^ tab[b];
+}
|| ! record_game.moves
|| sec_limit_up == UINT_MAX ) { return 1; }
- ponder_nmove = gen_legal_moves( ptree, ponder_move_list );
+ ponder_nmove = gen_legal_moves( ptree, ponder_move_list, 1 );
if ( get_elapsed( &time_start ) < 0 ) { return -1; }
OutCsaShogi( "info ponder start\n" );
game_status |= flag_puzzling;
- iret = iterate( ptree, 0 );
+ iret = iterate( ptree );
game_status &= ~flag_puzzling;
if ( iret < 0 ) { return iret; }
Out( "\nPonder on %c%s (%+.2f)\n\n",
ach_turn[root_turn], str, (double)last_root_value / 100.0 );
- iret = make_move_root( ptree, move, ( flag_rep | flag_rejections ) );
+ iret = make_move_root( ptree, move, flag_rep );
if ( iret < 0 )
{
OutCsaShogi( "info ponder end\n" );
if ( game_status & mask_game_end )
{
OutCsaShogi( "info ponder end\n" );
- unmake_move_root( ptree, move );
- return 1;
+ return unmake_move_root( ptree );
}
if ( get_elapsed( &time_start ) < 0 ) { return -1; }
game_status |= flag_pondering;
- iret = iterate( ptree, 0 );
+ iret = iterate( ptree );
if ( game_status & flag_thinking )
{
game_status &= ~flag_thinking;
}
OutCsaShogi( "info ponder end\n" );
game_status &= ~flag_pondering;
- unmake_move_root( ptree, move );
-
- return iret;
+ return unmake_move_root( ptree );
}
-#if defined(MNJ_LAN)
+#if defined(MNJ_LAN) || defined(USI)
int
analyze( tree_t * restrict ptree )
{
int iret;
- if ( game_status & mask_game_end ) { return 1; }
+#if defined(MNJ_LAN)
+ if ( game_status & mask_game_end )
+ {
+ MnjOut( "pid=%d move=%%TORYO v=%de n=0 final%s\n",
+ mnj_posi_id, -score_bound,
+ ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+ return 1;
+ }
+#endif
iret = get_elapsed( &time_start );
if ( iret < 0 ) { return iret; }
- game_status |= flag_pondering;
- iret = iterate( ptree, 0 );
+ game_status |= flag_pondering;
+ iret = iterate( ptree );
game_status &= ~flag_pondering;
if ( abs(last_root_value) > score_max_eval )
{
- MnjOut( "pid=%d confident\n", mnj_posi_id );
+ MnjOut( "pid=%d final%s\n", mnj_posi_id,
+ ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
}
return iret;
+#include <math.h>
+#include <limits.h>
#include "shogi.h"
-int
+int CONV
solve_problems( tree_t * restrict ptree, unsigned int nposition )
{
const char *str_move;
for ( uposition = 0; uposition < nposition; uposition++ )
{
istatus = in_CSA( ptree, &record_problems, NULL,
- ( flag_nomake_move | flag_detect_hang
- | flag_rejections ) );
+ ( flag_nomake_move | flag_detect_hang ) );
if ( istatus < 0 ) { return istatus; }
if ( istatus > record_next )
game_status_save = game_status;
game_status |= flag_problem | flag_nopeek | flag_thinking;
- iresult = iterate( ptree, 0 );
+ iresult = iterate( ptree );
game_status = game_status_save;
if ( iresult < 0 ) { return iresult; }
return 1;
}
+
+
+#if defined(DFPN)
+int CONV
+solve_mate_problems( tree_t * restrict ptree, unsigned int nposition )
+{
+ unsigned int uposition;
+ int iret;
+
+ for ( uposition = 0; uposition < nposition; uposition++ )
+ {
+ int imove, istatus;
+ unsigned int record_move;
+
+ for ( imove = 0; ; imove++ )
+ {
+ istatus = in_CSA( ptree, &record_problems, &record_move,
+ ( flag_nomake_move | flag_detect_hang
+ | flag_nofmargin ) );
+ if ( istatus < 0 )
+ {
+ str_error = str_illegal_move;
+ return -1;
+ }
+
+ if ( istatus >= record_eof ) { break; }
+
+ iret = make_move_root( ptree, record_move, 0 );
+ if ( iret < 0 ) { return iret; }
+ }
+
+ Out( "Problem #%d %s\n",
+ uposition, ptree->nsuc_check[1] ? "(in check)" : "" );
+
+ iret = dfpn( ptree, root_turn, 1 );
+ if ( iret < 0 ) { return iret; }
+
+ if ( istatus == record_eof ) { break; }
+ if ( istatus == record_misc )
+ {
+ iret = record_wind( &record_problems );
+ if ( iret < 0 ) { return iret; }
+ if ( iret == record_eof ) { break; }
+ }
+ }
+
+ return 1;
+}
+#endif
#if defined(MINIMUM)
# define CmdBook(x,y) cmd_book(y);
-static int cmd_book( char **lasts );
+static int CONV cmd_book( char **lasts );
#else
# define CmdBook(x,y) cmd_book(x,y);
-static int cmd_learn( tree_t * restrict ptree, char **lasts );
-static int cmd_book( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_learn( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_book( tree_t * restrict ptree, char **lasts );
#endif
#if ! defined(NO_STDOUT)
-static int cmd_stress( char **lasts );
-#endif
-
-#if defined(DEKUNOBOU)
-static int cmd_dek( char **lasts );
+static int CONV cmd_stress( char **lasts );
#endif
#if defined(CSA_LAN)
-static int proce_csalan( tree_t * restrict ptree );
-static int cmd_connect( tree_t * restrict ptree, char **lasts );
+static int CONV proce_csalan( tree_t * restrict ptree );
+static int CONV cmd_connect( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_sendpv( char **lasts );
#endif
#if defined(MNJ_LAN)
-static int proce_mnj( tree_t * restrict ptree );
-static int cmd_mnj( tree_t * restrict ptree, char **lasts );
-static int cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter );
+static int CONV proce_mnj( tree_t * restrict ptree );
+static int CONV cmd_mnjignore( tree_t *restrict ptree, char **lasts );
+static int CONV cmd_mnj( char **lasts );
+static int CONV cmd_mnjmove( tree_t * restrict ptree, char **lasts,
+ int num_alter );
+#endif
+
+#if defined(USI)
+static int CONV proce_usi( tree_t * restrict ptree );
+static int CONV usi_posi( tree_t * restrict ptree, char **lasts );
+static int CONV usi_go( tree_t * restrict ptree, char **lasts );
+static int CONV usi_ignore( tree_t * restrict ptree, char **lasts );
#endif
#if defined(TLP)
-static int cmd_thread( char **lasts );
+static int CONV cmd_thread( char **lasts );
#endif
#if defined(MPV)
-static int cmd_mpv( char **lasts );
+static int CONV cmd_mpv( char **lasts );
+#endif
+
+#if defined(DFPN)
+static int CONV cmd_dfpn( tree_t * restrict ptree, char **lasts );
+#endif
+
+#if defined(DFPN_CLIENT)
+static int CONV cmd_dfpn_client( tree_t * restrict ptree, char **lasts );
#endif
-static int proce_cui( tree_t * restrict ptree );
-static int cmd_usrmove( tree_t * restrict ptree, const char *str_move,
- char **last );
-static int cmd_move_now( void );
-static int cmd_ponder( char **lasts );
-static int cmd_limit( char **lasts );
-static int cmd_quit( void );
-static int cmd_beep( char **lasts );
-static int cmd_peek( char **lasts );
-static int cmd_hash( char **lasts );
-static int cmd_ping( void );
-static int cmd_suspend( void );
-static int cmd_problem( tree_t * restrict ptree, char **lasts );
-static int cmd_display( tree_t * restrict ptree, char **lasts );
-static int cmd_move( tree_t * restrict ptree, char **lasts );
-static int cmd_new( tree_t * restrict ptree, char **lasts );
-static int cmd_read( tree_t * restrict ptree, char **lasts );
-static int cmd_resign( tree_t * restrict ptree, char **lasts );
-static int cmd_time( char **lasts );
-static int is_move( const char *str );
-
-
-int
+static int CONV proce_cui( tree_t * restrict ptree );
+static int CONV cmd_usrmove( tree_t * restrict ptree, const char *str_move,
+ char **last );
+static int CONV cmd_outmove( tree_t * restrict ptree );
+static int CONV cmd_move_now( void );
+static int CONV cmd_ponder( char **lasts );
+static int CONV cmd_limit( char **lasts );
+static int CONV cmd_quit( void );
+static int CONV cmd_beep( char **lasts );
+static int CONV cmd_peek( char **lasts );
+static int CONV cmd_stdout( char **lasts );
+static int CONV cmd_newlog( char **lasts );
+static int CONV cmd_hash( char **lasts );
+static int CONV cmd_ping( void );
+static int CONV cmd_suspend( void );
+static int CONV cmd_problem( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_display( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_move( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_new( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_read( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_resign( tree_t * restrict ptree, char **lasts );
+static int CONV cmd_time( char **lasts );
+
+
+int CONV is_move( const char *str )
+{
+ if ( isdigit( (int)str[0] ) && isdigit( (int)str[1] )
+ && isdigit( (int)str[2] ) && isdigit( (int)str[3] )
+ && isupper( (int)str[4] ) && isupper( (int)str[5] )
+ && str[6] == '\0' ) { return 1; }
+
+ return 0;
+}
+
+
+int CONV
procedure( tree_t * restrict ptree )
{
#if defined(CSA_LAN)
if ( sckt_csa != SCKT_NULL ) { return proce_csalan( ptree ); }
#endif
+
#if defined(MNJ_LAN)
if ( sckt_mnj != SCKT_NULL ) { return proce_mnj( ptree ); }
#endif
+#if defined(USI)
+ if ( usi_mode != usi_off ) { return proce_usi( ptree ); }
+#endif
+
return proce_cui( ptree );
}
-static int
-proce_cui( tree_t * restrict ptree )
+static int CONV proce_cui( tree_t * restrict ptree )
{
const char *token;
char *last;
if ( ! strcmp( token, "limit" ) ) { return cmd_limit( &last ); }
if ( ! strcmp( token, "move" ) ) { return cmd_move( ptree, &last ); }
if ( ! strcmp( token, "new" ) ) { return cmd_new( ptree, &last ); }
+ if ( ! strcmp( token, "outmove" ) ) { return cmd_outmove( ptree ); }
if ( ! strcmp( token, "peek" ) ) { return cmd_peek( &last ); }
+ if ( ! strcmp( token, "stdout" ) ) { return cmd_stdout( &last ); }
if ( ! strcmp( token, "ping" ) ) { return cmd_ping(); }
if ( ! strcmp( token, "ponder" ) ) { return cmd_ponder( &last ); }
if ( ! strcmp( token, "problem" ) ) { return cmd_problem( ptree, &last ); }
if ( ! strcmp( token, "resign" ) ) { return cmd_resign( ptree, &last ); }
if ( ! strcmp( token, "suspend" ) ) { return cmd_suspend(); }
if ( ! strcmp( token, "time" ) ) { return cmd_time( &last ); }
+ if ( ! strcmp( token, "newlog" ) ) { return cmd_newlog( &last ); }
#if defined(CSA_LAN)
if ( ! strcmp( token, "connect" ) ) { return cmd_connect( ptree, &last ); }
+ if ( ! strcmp( token, "sendpv" ) ) { return cmd_sendpv( &last ); }
#endif
#if defined(MNJ_LAN)
- if ( ! strcmp( token, "mnj" ) ) { return cmd_mnj( ptree, &last ); }
-#endif
-#if defined(DEKUNOBOU)
- if ( ! strcmp( token, "dekunobou" ) ) { return cmd_dek( &last ); }
+ if ( ! strcmp( token, "mnj" ) ) { return cmd_mnj( &last ); }
#endif
#if defined(MPV)
if ( ! strcmp( token, "mpv" ) ) { return cmd_mpv( &last ); }
#endif
+#if defined(DFPN)
+ if ( ! strcmp( token, "dfpn" ) ) { return cmd_dfpn( ptree, &last ); }
+#endif
+#if defined(DFPN_CLIENT)
+ if ( ! strcmp( token, "dfpn_client")) { return cmd_dfpn_client( ptree,
+ &last ); }
+#endif
#if defined(TLP)
if ( ! strcmp( token, "tlp" ) ) { return cmd_thread( &last ); }
#endif
#if defined(CSA_LAN)
-static int
-proce_csalan( tree_t * restrict ptree )
+static int CONV proce_csalan( tree_t * restrict ptree )
{
const char *token;
char *last;
game_status |= flag_suspend;
return 2;
}
-
- ShutdownClient;
+
+ if ( sckt_out( sckt_csa, "LOGOUT\n" ) < 0 ) { return -1; }
+ if ( sckt_recv_all( sckt_csa ) < 0 ) { return -1; }
+
+ ShutdownAll();
if ( client_ngame == client_max_game ) { return cmd_quit(); }
#if defined(MNJ_LAN)
-static int
-proce_mnj( tree_t * restrict ptree )
+static int CONV proce_mnj( tree_t * restrict ptree )
{
const char *token;
char *last;
iret = cmd_new( ptree, &last );
if ( iret < 0 ) { return iret; }
+ moves_ignore[0] = MOVE_NA;
return analyze( ptree );
}
- if ( ! strcmp( token, "idle" ) ) { return cmd_suspend(); }
- if ( ! strcmp( token, "alter" ) ) { return cmd_mnjmove( ptree, &last, 1 ); }
+ if ( ! strcmp( token, "ignore" ) ) { return cmd_mnjignore( ptree, &last ); }
+ if ( ! strcmp( token, "idle" ) ) { return cmd_suspend(); }
+ if ( ! strcmp( token, "alter" ) ) { return cmd_mnjmove( ptree, &last, 1 ); }
+ if ( ! strcmp( token, "retract" ) )
+ {
+ long l;
+ char *ptr;
+ const char *str = strtok_r( NULL, str_delimiters, &last );
+ if ( str == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+ l = strtol( str, &ptr, 0 );
+ if ( ptr == str || (long)NUM_UNMAKE < l )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+
+ return cmd_mnjmove( ptree, &last, (int)l );
+ }
if ( ! strcmp( token, "move" ) ) { return cmd_mnjmove( ptree, &last, 0 ); }
str_error = str_bad_cmdline;
}
-static int
-cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter )
+static int CONV
+cmd_mnjignore( tree_t *restrict ptree, char **lasts )
+{
+ const char *token;
+ char *ptr;
+ int i;
+ unsigned int move;
+ long lid;
+
+
+ token = strtok_r( NULL, str_delimiters, lasts );
+ if ( token == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+ lid = strtol( token, &ptr, 0 );
+ if ( ptr == token || lid == LONG_MAX || lid < 1 )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+
+ AbortDifficultCommand;
+
+ for ( i = 0; ; i += 1 )
+ {
+ token = strtok_r( NULL, str_delimiters, lasts );
+ if ( token == NULL ) { break; }
+
+ if ( interpret_CSA_move( ptree, &move, token ) < 0 ) { return -1; }
+
+ moves_ignore[i] = move;
+ }
+ if ( i == 0 )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+ mnj_posi_id = (int)lid;
+ moves_ignore[i] = MOVE_NA;
+
+ return analyze( ptree );
+}
+
+
+static int CONV
+cmd_mnjmove( tree_t * restrict ptree, char **lasts, int num_alter )
{
const char *str1 = strtok_r( NULL, str_delimiters, lasts );
const char *str2 = strtok_r( NULL, str_delimiters, lasts );
AbortDifficultCommand;
- if ( is_alter ) { unmake_move_root( ptree, mnj_move_last ); };
+ while ( num_alter )
+ {
+ iret = unmake_move_root( ptree );
+ if ( iret < 0 ) { return iret; }
+
+ num_alter -= 1;
+ }
iret = interpret_CSA_move( ptree, &move, str1 );
if ( iret < 0 ) { return iret; }
iret = get_elapsed( &time_turn_start );
if ( iret < 0 ) { return iret; }
- mnj_posi_id = (int)lid;
- mnj_move_last = move;
+ mnj_posi_id = (int)lid;
- iret = make_move_root( ptree, move, ( flag_history | flag_time | flag_rep
- | flag_detect_hang
- | flag_rejections ) );
+ iret = make_move_root( ptree, move, ( flag_time | flag_rep
+ | flag_detect_hang ) );
if ( iret < 0 ) { return iret; }
# if ! defined(NO_STDOUT)
if ( iret < 0 ) { return iret; }
# endif
+ moves_ignore[0] = MOVE_NA;
return analyze( ptree );
}
#endif
-static int
-is_move( const char *str )
+#if defined(USI)
+static int CONV proce_usi( tree_t * restrict ptree )
{
- if ( isdigit( (int)str[0] ) && isdigit( (int)str[1] )
- && isdigit( (int)str[2] ) && isdigit( (int)str[3] )
- && isupper( (int)str[4] ) && isupper( (int)str[5] )
- && str[6] == '\0' ) { return 1; }
+ const char *token;
+ char *lasts;
+ int iret;
- return 0;
+ token = strtok_r( str_cmdline, str_delimiters, &lasts );
+ if ( token == NULL ) { return 1; }
+
+ if ( ! strcmp( token, "usi" ) )
+ {
+ USIOut( "id name %s\n", str_myname );
+ USIOut( "id author Kunihito Hoki\n" );
+ USIOut( "usiok\n" );
+ return 1;
+ }
+
+ if ( ! strcmp( token, "isready" ) )
+ {
+ USIOut( "readyok\n", str_myname );
+ return 1;
+ }
+
+ if ( ! strcmp( token, "echo" ) )
+ {
+ USIOut( "%s\n", lasts );
+ return 1;
+ }
+
+ if ( ! strcmp( token, "ignore_moves" ) )
+ {
+ return usi_ignore( ptree, &lasts );
+ }
+
+ if ( ! strcmp( token, "genmove_probability" ) )
+ {
+ if ( get_elapsed( &time_start ) < 0 ) { return -1; }
+ return usi_root_list( ptree );
+ }
+
+ if ( ! strcmp( token, "go" ) )
+ {
+ iret = usi_go( ptree, &lasts );
+ moves_ignore[0] = MOVE_NA;
+ return iret;
+ }
+
+ if ( ! strcmp( token, "stop" ) ) { return cmd_move_now(); }
+ if ( ! strcmp( token, "position" ) ) { return usi_posi( ptree, &lasts ); }
+ if ( ! strcmp( token, "quit" ) ) { return cmd_quit(); }
+
+ str_error = str_bad_cmdline;
+ return -1;
+}
+
+
+static int CONV
+usi_ignore( tree_t * restrict ptree, char **lasts )
+{
+ const char *token;
+ char str_buf[7];
+ int i;
+ unsigned int move;
+
+ AbortDifficultCommand;
+
+ for ( i = 0; ; i += 1 )
+ {
+ token = strtok_r( NULL, str_delimiters, lasts );
+ if ( token == NULL ) { break; }
+
+ if ( usi2csa( ptree, token, str_buf ) < 0 ) { return -1; }
+ if ( interpret_CSA_move( ptree, &move, str_buf ) < 0 ) { return -1; }
+
+ moves_ignore[i] = move;
+ }
+
+ moves_ignore[i] = MOVE_NA;
+
+ return 1;
+}
+
+
+static int CONV
+usi_go( tree_t * restrict ptree, char **lasts )
+{
+ const char *token;
+ char *ptr;
+ int iret;
+ long l;
+
+ AbortDifficultCommand;
+
+ if ( game_status & mask_game_end )
+ {
+ str_error = str_game_ended;
+ return -1;
+ }
+
+ token = strtok_r( NULL, str_delimiters, lasts );
+
+ if ( ! strcmp( token, "book" ) )
+ {
+ AbortDifficultCommand;
+ if ( usi_book( ptree ) < 0 ) { return -1; }
+
+ return 1;
+ }
+
+
+ if ( ! strcmp( token, "infinite" ) )
+ {
+ usi_byoyomi = UINT_MAX;
+ depth_limit = PLY_MAX;
+ node_limit = UINT64_MAX;
+ sec_limit_depth = UINT_MAX;
+ }
+ else if ( ! strcmp( token, "byoyomi" ) )
+ {
+ token = strtok_r( NULL, str_delimiters, lasts );
+ if ( token == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+
+ l = strtol( token, &ptr, 0 );
+ if ( ptr == token || l > UINT_MAX || l < 1 )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+
+ usi_byoyomi = (unsigned int)l;
+ depth_limit = PLY_MAX;
+ node_limit = UINT64_MAX;
+ sec_limit_depth = UINT_MAX;
+ }
+ else {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+
+
+ if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
+
+ iret = com_turn_start( ptree, 0 );
+ if ( iret < 0 ) {
+ if ( str_error == str_no_legal_move ) { USIOut( "bestmove resign\n" ); }
+ else { return -1; }
+ }
+
+ return 1;
+}
+
+
+static int CONV
+usi_posi( tree_t * restrict ptree, char **lasts )
+{
+ const char *token;
+ char str_buf[7];
+ unsigned int move;
+
+ AbortDifficultCommand;
+
+ moves_ignore[0] = MOVE_NA;
+
+ token = strtok_r( NULL, str_delimiters, lasts );
+ if ( strcmp( token, "startpos" ) )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+
+ if ( ini_game( ptree, &min_posi_no_handicap,
+ flag_history, NULL, NULL ) < 0 ) { return -1; }
+
+ token = strtok_r( NULL, str_delimiters, lasts );
+ if ( token == NULL ) { return 1; }
+
+ if ( strcmp( token, "moves" ) )
+ {
+ str_error = str_bad_cmdline;
+ return -1;
+ }
+
+ for ( ;; ) {
+
+ token = strtok_r( NULL, str_delimiters, lasts );
+ if ( token == NULL ) { break; }
+
+ if ( usi2csa( ptree, token, str_buf ) < 0 ) { return -1; }
+ if ( interpret_CSA_move( ptree, &move, str_buf ) < 0 ) { return -1; }
+ if ( make_move_root( ptree, move, ( flag_history | flag_time
+ | flag_rep
+ | flag_detect_hang ) ) < 0 )
+ {
+ return -1;
+ }
+ }
+
+ if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
+ return 1;
}
+#endif
+
-static int
-cmd_move_now( void )
+static int CONV cmd_move_now( void )
{
if ( game_status & flag_thinking ) { game_status |= flag_move_now; }
}
-static int
+static int CONV
cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts )
{
const char *str;
if ( sckt_csa != SCKT_NULL ) { AbortDifficultCommand; }
#endif
-#if defined(DEKUNOBOU)
- if ( dek_ngame ) { AbortDifficultCommand; }
-#endif
-
#if defined(CSASHOGI)
AbortDifficultCommand;
#else
return 2;
}
else {
- iret = renovate_time( Flip(root_turn) );
+ iret = update_time( Flip(root_turn) );
if ( iret < 0 ) { return iret; }
if ( lelapsed )
{
adjust_time( (unsigned int)lelapsed, Flip(root_turn) );
}
- history_book_learn[ record_game.moves ].move_played = ponder_move;
- history_book_learn[ record_game.moves ].hand_played
- = ptree->rep_hand_list[ root_nrep-1 ];
- history_book_learn[ record_game.moves ].key_played
- = (unsigned int)ptree->rep_board_list[ root_nrep-1 ];
-
out_CSA( ptree, &record_game, ponder_move );
game_status &= ~flag_pondering;
game_status |= flag_thinking;
- n_nobook_move += 1;
set_search_limit_time( root_turn );
OutCsaShogi( "info ponder end\n" );
if ( iret < 0 ) { return iret; }
move_evasion_pchk = 0;
iret = make_move_root( ptree, move, ( flag_rep | flag_history | flag_time
- | flag_rejections
| flag_detect_hang ) );
if ( iret < 0 )
{
}
#endif
-#if defined(DEKUNOBOU)
- if ( dek_ngame )
- {
- if ( move_evasion_pchk )
- {
- dek_win += 1;
- OutDek( "%%TORYO\n" );
- }
- return cmd_suspend();
- }
-#endif
-
if ( move_evasion_pchk )
{
str = str_CSA_move( move_evasion_pchk );
}
#endif
-#if defined(DEKUNOBOU)
- if ( dek_ngame && ( game_status & flag_drawn ) ) { OutDek( "%%TORYO\n" ); }
-#endif
-
if ( ! ( game_status & mask_game_end ) )
{
iret = com_turn_start( ptree, 0 );
}
-static int
-cmd_beep( char **lasts )
+static int CONV cmd_beep( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
if ( str == NULL )
}
-static int
-cmd_peek( char **lasts )
+static int CONV cmd_peek( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
}
-static int
-cmd_ponder( char **lasts )
+static int CONV cmd_stdout( char **lasts )
+{
+ const char *str = strtok_r( NULL, str_delimiters, lasts );
+
+ if ( str == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_nostdout; }
+ else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nostdout; }
+ else {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ return 1;
+}
+
+
+static int CONV cmd_newlog( char **lasts )
+{
+ const char *str = strtok_r( NULL, str_delimiters, lasts );
+
+ if ( str == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_nonewlog; }
+ else if ( ! strcmp( str, str_off ) ) { game_status |= flag_nonewlog; }
+ else {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ return 1;
+}
+
+
+static int CONV cmd_ponder( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
return -2;
}
- if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_noponder; }
+ if ( ! strcmp( str, str_on ) ) { game_status &= ~flag_noponder; }
else if ( ! strcmp( str, str_off ) )
{
if ( game_status & ( flag_pondering | flag_puzzling ) )
#if ! defined(NO_STDOUT)
-static int
-cmd_stress( char **lasts )
+static int CONV cmd_stress( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
#endif
-static int
+static int CONV
#if defined(MINIMUM)
cmd_book( char **lasts )
#else
}
-static int
-cmd_display( tree_t * restrict ptree, char **lasts )
+static int CONV cmd_display( tree_t * restrict ptree, char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
char *ptr;
}
-static int
-cmd_ping( void )
+static int CONV cmd_ping( void )
{
OutCsaShogi( "pong\n" );
Out( "pong\n" );
}
-static int
-cmd_hash( char **lasts )
+static int CONV cmd_hash( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
char *ptr;
return -2;
}
- if ( ! strcmp( str, "learn" ) )
- {
- str = strtok_r( NULL, str_delimiters, lasts );
- if ( str != NULL && ! strcmp( str, str_on ) )
- {
- return hash_learn_on();
- }
- else if ( str != NULL && ! strcmp( str, str_off ) )
- {
- return hash_learn_off();
- }
-#if ! defined(MINIMUM)
- else if ( str != NULL && ! strcmp( str, "create" ) )
- {
- return hash_learn_create();
- }
-#endif
- else {
- str_error = str_bad_cmdline;
- return -2;
- }
- }
-
l = strtol( str, &ptr, 0 );
if ( ptr == str || l == LONG_MAX || l < 1 || l > 31 )
{
}
-static int
-cmd_limit( char **lasts )
+static int CONV cmd_limit( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
char *ptr;
}
-static int
+static int CONV
cmd_read( tree_t * restrict ptree, char **lasts )
{
const char *str1 = strtok_r( NULL, str_delimiters, lasts );
long l;
int iret, flag, c;
- flag = flag_history | flag_rep | flag_detect_hang | flag_rejections;
+ flag = flag_history | flag_rep | flag_detect_hang;
moves = UINT_MAX;
str_tmp = NULL;
strncpy( str_file, "game.csa", SIZE_FILENAME-1 );
#else
snprintf( str_file, SIZE_FILENAME, "%s/game%03d.csa",
- str_dir_logs, irecord_game );
+ str_dir_logs, record_num );
#endif
pf_dest = file_open( str_tmp, "w" );
if ( pf_dest == NULL ) { return -2; }
}
-static int
-cmd_resign( tree_t * restrict ptree, char **lasts )
+static int CONV cmd_resign( tree_t * restrict ptree, char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
char *ptr;
if ( game_status & mask_game_end ) { return 1; }
-#if defined(DEKUNOBOU)
- if ( dek_ngame && record_game.moves < 2 )
- {
- str_error = "ignore resignation";
- return -2;
- }
-#endif
-
game_status |= flag_resigned;
- renovate_time( root_turn );
+ update_time( root_turn );
out_CSA( ptree, &record_game, MOVE_RESIGN );
}
else {
}
-static int
-cmd_move( tree_t * restrict ptree, char **lasts )
+static int CONV cmd_move( tree_t * restrict ptree, char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
+ char *ptr;
+ long l;
unsigned int move;
- int iret;
+ int iret, i;
if ( game_status & mask_game_end )
{
iret = get_elapsed( &time_turn_start );
if ( iret < 0 ) { return iret; }
- iret = com_turn_start( ptree, 0 );
- if ( iret < 0 ) { return iret; }
+ return com_turn_start( ptree, 0 );
}
- else if ( ! strcmp( str, "restraint" ) )
+
+ l = strtol( str, &ptr, 0 );
+ if ( str != ptr && l != LONG_MAX && l >= 1 && *ptr == '\0' )
{
- iret = get_elapsed( &time_turn_start );
- if ( iret < 0 ) { return iret; }
-
- iret = com_turn_start( ptree, flag_refer_rest );
- if ( iret < 0 ) { return iret; }
+ for ( i = 0; i < l; i += 1 )
+ {
+ if ( game_status & ( flag_move_now | mask_game_end ) ) { break; }
+
+ iret = get_elapsed( &time_turn_start );
+ if ( iret < 0 ) { return iret; }
+
+ iret = com_turn_start( ptree, 0 );
+ if ( iret < 0 ) { return iret; }
+ }
+
+ return 1;
}
- else {
+ do {
iret = interpret_CSA_move( ptree, &move, str );
if ( iret < 0 ) { return iret; }
iret = get_elapsed( &time_turn_start );
if ( iret < 0 ) { return iret; }
-#if defined(MNJ_LAN)
- if ( sckt_mnj != SCKT_NULL )
- {
- const char *str2 = strtok_r( NULL, str_delimiters, lasts );
- char *ptr;
- long l;
- if ( str2 ) { l = strtol( str2, &ptr, 0 ); }
- if ( ! str2 || ptr == str || l == LONG_MAX || l < 1 )
- {
- str_error = str_bad_cmdline;
- return -2;
- }
- mnj_posi_id = (int)l;
- mnj_move_last = move;
- }
-#endif
-
- iret = make_move_root( ptree, move, ( flag_history | flag_time | flag_rep
- | flag_detect_hang
- | flag_rejections ) );
+ iret = make_move_root( ptree, move,
+ ( flag_history | flag_time | flag_rep
+ | flag_detect_hang ) );
if ( iret < 0 ) { return iret; }
- }
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+
+ } while ( str != NULL );
return 1;
}
-static int
-cmd_new( tree_t * restrict ptree, char **lasts )
+static int CONV cmd_new( tree_t * restrict ptree, char **lasts )
{
const char *str1 = strtok_r( NULL, str_delimiters, lasts );
const char *str2 = strtok_r( NULL, str_delimiters, lasts );
}
-static int
-cmd_problem( tree_t * restrict ptree, char **lasts )
+static int CONV cmd_outmove( tree_t * restrict ptree )
+{
+ const char *str_move;
+ char buffer[256];
+ unsigned int move_list[ MAX_LEGAL_MOVES ];
+ int i, c, n;
+
+ AbortDifficultCommand;
+
+ if ( game_status & mask_game_end )
+ {
+ Out( "NO LEGAL MOVE\n" );
+ DFPNOut( "NO LEGAL MOVE\n" );
+ return 1;
+ }
+
+ n = gen_legal_moves( ptree, move_list, 0 );
+
+ buffer[0]='\0';
+ for ( c = i = 0; i < n; i += 1 )
+ {
+ str_move = str_CSA_move(move_list[i]);
+
+ if ( i && ( i % 10 ) == 0 )
+ {
+ Out( "%s\n", buffer );
+ DFPNOut( "%s ", buffer );
+ memcpy( buffer, str_move, 6 );
+ c = 6;
+ }
+ else if ( i )
+ {
+ buffer[c] = ' ';
+ memcpy( buffer + c + 1, str_move, 6 );
+ c += 7;
+ }
+ else {
+ memcpy( buffer + c, str_move, 6 );
+ c += 6;
+ }
+ buffer[c] = '\0';
+ }
+ Out( "%s\n", buffer );
+ DFPNOut( "%s\n", buffer );
+
+ return 1;
+}
+
+
+static int CONV cmd_problem( tree_t * restrict ptree, char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
char *ptr;
long l;
unsigned int nposition;
int iret;
+#if defined(DFPN)
+ int is_mate;
+#endif
+
+ AbortDifficultCommand;
+
+
+#if defined(DFPN)
+ is_mate = 0;
+ if ( str != NULL && ! strcmp( str, "mate" ) )
+ {
+ is_mate = 1;
+ str = strtok_r( NULL, str_delimiters, lasts );
+ }
+#endif
if ( str != NULL )
{
}
else { nposition = UINT_MAX; }
- AbortDifficultCommand;
-
+
iret = record_open( &record_problems, "problem.csa", mode_read, NULL, NULL );
if ( iret < 0 ) { return iret; }
+#if defined(DFPN)
+ iret = is_mate ? solve_mate_problems( ptree, nposition )
+ : solve_problems( ptree, nposition );
+#else
iret = solve_problems( ptree, nposition );
+#endif
+
if ( iret < 0 )
{
record_close( &record_problems );
iret = record_close( &record_problems );
if ( iret < 0 ) { return iret; }
- iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
- if ( iret < 0 ) { return iret; }
-
return get_elapsed( &time_turn_start );
}
-static int
-cmd_quit( void )
+static int CONV cmd_quit( void )
{
game_status |= flag_quit;
return 1;
}
-static int
-cmd_suspend( void )
+static int CONV cmd_suspend( void )
{
if ( game_status & ( flag_pondering | flag_puzzling ) )
{
}
-static int
-cmd_time( char **lasts )
+static int CONV cmd_time( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
char *ptr;
#if !defined(MINIMUM)
/* learn (ini|no-ini) steps games iterations tlp1 tlp2 */
-static int
-cmd_learn( tree_t * restrict ptree, char **lasts )
+static int CONV cmd_learn( tree_t * restrict ptree, char **lasts )
{
const char *str1 = strtok_r( NULL, str_delimiters, lasts );
const char *str2 = strtok_r( NULL, str_delimiters, lasts );
#if defined(MPV)
-static int
-cmd_mpv( char **lasts )
+static int CONV cmd_mpv( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
char *ptr;
#endif
+#if defined(DFPN)
+static int CONV cmd_dfpn( tree_t * restrict ptree, char **lasts )
+{
+ const char *str = strtok_r( NULL, str_delimiters, lasts );
+
+ if ( str == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+ else if ( ! strcmp( str, "hash" ) )
+ {
+ char *ptr;
+ long l;
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( str == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+ l = strtol( str, &ptr, 0 );
+ if ( ptr == str || l == LONG_MAX || l < 1 )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ AbortDifficultCommand;
+
+ dfpn_hash_log2 = (unsigned int)l;
+ return dfpn_ini_hash();
+ }
+ else if ( ! strcmp( str, "go" ) )
+ {
+ AbortDifficultCommand;
+
+ return dfpn( ptree, root_turn, 1 );
+ }
+ else if ( ! strcmp( str, "connect" ) )
+ {
+ char str_addr[256];
+ char str_id[256];
+ char *ptr;
+ long l;
+ int port;
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( ! str || ! strcmp( str, "." ) ) { str = "127.0.0.1"; }
+ strncpy( str_addr, str, 255 );
+ str_addr[255] = '\0';
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( ! str || ! strcmp( str, "." ) ) { str = "4083"; }
+ l = strtol( str, &ptr, 0 );
+ if ( ptr == str || l == LONG_MAX || l < 0 || l > USHRT_MAX )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+ port = (int)l;
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( ! str || ! strcmp( str, "." ) ) { str = "bonanza1"; }
+ strncpy( str_id, str, 255 );
+ str_id[255] = '\0';
+
+ AbortDifficultCommand;
+
+ dfpn_sckt = sckt_connect( str_addr, port );
+ if ( dfpn_sckt == SCKT_NULL ) { return -2; }
+
+ str_buffer_cmdline[0] = '\0';
+ DFPNOut( "Worker: %s\n", str_id );
+
+ return 1;
+ }
+
+ str_error = str_bad_cmdline;
+ return -2;
+}
+#endif
+
+
#if defined(TLP)
-static int
-cmd_thread( char **lasts )
+static int CONV cmd_thread( char **lasts )
{
const char *str = strtok_r( NULL, str_delimiters, lasts );
#endif
+#if defined(DFPN_CLIENT)
+static int CONV cmd_dfpn_client( tree_t * restrict ptree, char **lasts )
+{
+ const char *str;
+ char *ptr;
+ int iret;
+
+ AbortDifficultCommand;
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( ! str || ! strcmp( str, "." ) ) { str = "127.0.0.1"; }
+ strncpy( dfpn_client_str_addr, str, 255 );
+ dfpn_client_str_addr[255] = '\0';
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( ! str || ! strcmp( str, "." ) ) { str = "4083"; }
+ dfpn_client_port = strtol( str, &ptr, 0 );
+ if ( ptr == str || dfpn_client_port == LONG_MAX || dfpn_client_port < 0
+ || dfpn_client_port > USHRT_MAX )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ Out( "DFPN Server: %s %d\n", dfpn_client_str_addr, dfpn_client_port );
+
+ iret = ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL );
+ if ( iret < 0 ) { return iret; }
+
+ if ( dfpn_client_sckt == SCKT_NULL )
+ {
+ str_error = "Check network status.";
+ return -1;
+ }
+
+ return get_elapsed( &time_turn_start );
+}
+#endif
+
+
#if defined(CSA_LAN)
-static int
-cmd_connect( tree_t * restrict ptree, char **lasts )
+static int CONV cmd_connect( tree_t * restrict ptree, char **lasts )
{
const char *str;
char *ptr;
return client_next_game( ptree, client_str_addr, (int)client_port );
}
+
+
+static int CONV cmd_sendpv( char **lasts )
+{
+ const char *str = strtok_r( NULL, str_delimiters, lasts );
+
+ if ( str == NULL )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ if ( ! strcmp( str, str_off ) ) { game_status &= ~flag_sendpv; }
+ else if ( ! strcmp( str, str_on ) ) { game_status |= flag_sendpv; }
+ else {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ return 1;
+}
#endif
#if defined(MNJ_LAN)
-static int
-cmd_mnj( tree_t * restrict ptree, char **lasts )
+/* mnj sd seed addr port name factor stable_depth */
+static int CONV cmd_mnj( char **lasts )
{
char client_str_addr[256];
char client_str_id[256];
const char *str;
char *ptr;
unsigned int seed;
- int sd;
long l;
- int client_port;
+ int client_port, sd;
+ double factor;
str = strtok_r( NULL, str_delimiters, lasts );
if ( ! str )
strncpy( client_str_id, str, 255 );
client_str_id[255] = '\0';
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( ! str || ! strcmp( str, "." ) ) { str = "1.0"; }
+ factor = strtod( str, &ptr );
+ if ( ptr == str || factor < 0.0 )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+
+ str = strtok_r( NULL, str_delimiters, lasts );
+ if ( ! str || ! strcmp( str, "." ) ) { l = -1; }
+ else {
+ l = strtol( str, &ptr, 0 );
+ if ( ptr == str || l == LONG_MAX )
+ {
+ str_error = str_bad_cmdline;
+ return -2;
+ }
+ }
+ if ( l <= 0 ) { mnj_depth_stable = INT_MAX; }
+ else { mnj_depth_stable = (int)l; }
+
AbortDifficultCommand;
resign_threshold = 65535;
str_buffer_cmdline[0] = '\0';
Out( "Sending my name %s", client_str_id );
- sckt_out( sckt_mnj, "%s\n", client_str_id );
+ MnjOut( "%s %g final%s\n", client_str_id, factor,
+ ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
- return analyze( ptree );
+ return cmd_suspend();
}
#endif
-#if defined(DEKUNOBOU)
-
-static int
-cmd_dek( char **lasts )
-{
- const char *str = strtok_r( NULL, str_delimiters, lasts );
- char *ptr;
- long l1, l2;
- int iret;
-
- if ( str == NULL )
- {
- str_error = str_bad_cmdline;
- return -2;
- }
- strncpy( str_message, str, SIZE_MESSAGE-1 );
- str_message[SIZE_MESSAGE-1] = '\0';
- dek_ul_addr = inet_addr( str );
-
- str = strtok_r( NULL, str_delimiters, lasts );
- if ( str == NULL )
- {
- str_error = str_bad_cmdline;
- return -2;
- }
- l1 = strtol( str, &ptr, 0 );
- if ( ptr == str || l1 == LONG_MAX || l1 < 0 || l1 > USHRT_MAX )
- {
- str_error = str_bad_cmdline;
- return -2;
- }
-
- str = strtok_r( NULL, str_delimiters, lasts );
- if ( str == NULL )
- {
- str_error = str_bad_cmdline;
- return -2;
- }
- l2 = strtol( str, &ptr, 0 );
- if ( ptr == str || l2 == LONG_MAX || l2 < 0 || l2 > USHRT_MAX )
- {
- str_error = str_bad_cmdline;
- return -2;
- }
-
- AbortDifficultCommand;
-
- iret = dek_start( str_message, (int)l1, (int)l2 );
- if ( iret < 0 ) { return iret; }
-
- Out( "\n- in communication with Dekunobou...\n" );
-
- str_buffer_cmdline[0] = '\0';
- dek_ngame = 1;
- dek_lost = 0;
- dek_win = 0;
- dek_turn = 1;
- game_status |= flag_resigned;
-
- return 1;
-}
-
-#endif
-
# define DOut( ... )
#endif
-static int gen_next_quies( tree_t * restrict ptree, int alpha, int turn,
- int ply, int qui_ply );
+static int CONV gen_next_quies( tree_t * restrict ptree, int alpha, int turn,
+ int ply, int qui_ply );
-int
+int CONV
search_quies( tree_t * restrict ptree, int alpha, int beta, int turn, int ply,
int qui_ply )
{
- int value, alpha_old;
+ int value, alpha_old, stand_pat;
#if defined(DBG_QSEARCH)
int dbg_flag = 0;
ptree->nquies_called += 1;
alpha_old = alpha;
- value = evaluate( ptree, ply, turn );
+ stand_pat = evaluate( ptree, ply, turn );
- if ( alpha < value )
+ if ( alpha < stand_pat )
{
- if ( beta <= value )
+ if ( beta <= stand_pat )
{
DOut( ", cut by stand-pat\n" );
MOVE_CURR = MOVE_PASS;
- return value;
+ return stand_pat;
}
- alpha = value;
+ alpha = stand_pat;
}
if ( ply >= PLY_MAX-1 )
{
if ( alpha_old != alpha ) { pv_close( ptree, ply, no_rep ); }
MOVE_CURR = MOVE_NA;
- return value;
+ return stand_pat;
}
- if ( ( qui_ply == 1 && ! ( ply == 2 && InCheck( turn ) ) )
- || ( 1 < qui_ply && qui_ply < QUIES_PLY_LIMIT && ! InCheck( turn ) ) )
+ if ( is_mate_in3ply( ptree, turn, ply ) )
{
- MOVE_CURR = IsMateIn1Ply( turn );
- if ( MOVE_CURR )
- {
- value = score_mate1ply + 1 - ply;
-
- if ( alpha < value
- && value < beta ) { pv_close( ptree, ply, mate_search ); }
-
- DOut( "mate found\n" );
+ value = score_mate1ply + 1 - ply;
+
+ if ( alpha < value
+ && value < beta ) { pv_close( ptree, ply, mate_search ); }
- assert( is_move_valid( ptree, MOVE_CURR, turn ) );
- return value;
- }
+ assert( is_move_valid( ptree, MOVE_CURR, turn ) );
+ return value;
}
if ( alpha < value )
{
- check_futile_score_quies( ptree, MOVE_CURR, ptree->stand_pat[ply],
- -ptree->stand_pat[ply+1], turn );
+ check_futile_score_quies( ptree, MOVE_CURR, ptree->save_eval[ply],
+ -ptree->save_eval[ply+1], turn );
if ( beta <= value )
{
DOut( ", beta cut (%" PRIu64 ")\n", ptree->node_searched );
DOut( "\nall searched (%" PRIu64 ")\n", ptree->node_searched );
- if ( qui_ply < QUIES_PLY_LIMIT && is_mate_in3ply( ptree, turn, ply ) )
- {
- value = score_mate1ply + 1 - ply;
-
- if ( alpha < value
- && value < beta ) { pv_close( ptree, ply, mate_search ); }
-
- assert( is_move_valid( ptree, MOVE_CURR, turn ) );
- return value;
- }
-
if ( alpha_old != alpha )
{
- if ( alpha == ptree->stand_pat[ply] ) { pv_close( ptree, ply, no_rep ); }
- else { pv_copy( ptree, ply ); }
+ if ( alpha == stand_pat ) { pv_close( ptree, ply, no_rep ); }
+ else { pv_copy( ptree, ply ); }
}
return alpha;
}
-static int
+static int CONV
gen_next_quies( tree_t * restrict ptree, int alpha, int turn, int ply,
int qui_ply )
{
}
diff = estimate_score_diff( ptree, move, turn );
- min_score = eval_max_score( ptree, move, ptree->stand_pat[ply],
+ min_score = eval_max_score( ptree, move, ptree->save_eval[ply],
turn, diff );
if ( alpha < min_score )
-----------------------------------------------------------------------
- Bonanza Feliz 0.0 - Executable Source Code
- Kunihito Hoki, 1 Apr 2010
-----------------------------------------------------------------------
-
-
-1. Introduction
-----------------
-
-Bonanza is a state-of-the art computer shogi engine which runs on
-Windows and Linux machines, and this directory contains a
-platform-independent source code.
-
-This source code is distributed with a hope that it will be useful in
-addition to the main part of the shogi engine. This program includes
-many useful functions such as manipulating a shogi board, reading and
-writing a CSA record file, speaking of a CSA protocol with a socket
-communication, and controlling time, and etc.. I believe this program
-can be a good starting point if you are interested in making shogi
-programs.
-
-One main feature of this program is that it employs a brute-force
-search method together with bitboard techniques as many chess programs
-do. Another notable feature is a machine learning of shogi evaluation
-functions. The details of the learning algorithm (aka Bonanza method)
-were already presented [1], and this source code provides an example
-of implementation of the learning method.
-
-I admit that some parts of the source code are cryptic, e.g. codes in
-"mate1ply.c". I hope that I will have some time to make a quality
-documentation and comments on the program code, or someone else could
-decrypt my program and provide a documentation.
-
-Any comments or suggestions are welcome [2].
-
-[1] K. Hoki, "Optimal control of minimax search results to learn
- positional evaluation", Game Programming Workshop, Hakone, Japan
- 2008.
-
-[2] Contact to "bonanza_query [at] hotmail.com".
-
-
-2. Legal Notices
------------------
-
-This program is protected by copyright. Without a specific
-permission, any means of commercial applications are prohibited.
-Furthermore, this program is distributed without any warranty.
-Within these limits, you can use, redistribute, and/or modify it.
-
-
-3. Change Logs
----------------
-
-Feliz 0.0
-
-- Some results from Y. Sato's experiments with Bonanza inspired me
- to use the history table in LMR in Shogi, as Fruit did in chess. By
- doing so, some improvement in performance of the tree search is
- made.
-
-- From private communications with Yaneurao, it turned out that the
- 3-ply-mate detections in 'mate3.c' can search game trees more
- efficiently by using several heuristic pruning techniques. Now
- 'mate3.c' adopts some of these techniques.
-
-- E. Ito kindly reported two bugs in the source codes. One is in
- hash_store(), and the other is in ehash_probe() and
- ehash_store(). Now these are fixed.
-
-- The structure of history table is modified from 'square-to' and
- 'square-from' method to an exact match method by using the perfect
- hash technique. The hash function of moves in 'phash.c' is generated
- by codes at http://burtleburtle.net/bob/hash/perfect.html.
-
-- A command 'mnj' is added to connect to the cluster-computing server
- in src/cluster/.
-
-- In client_next_game(), the way of dealing with REJECT message from a
- CSA Shogi server is revised. Now Bonanza connects to the server again
- when the game is rejected by an opponent.
-
-
-Version 4.1.3
-- The owner of 'LS3600 Blog Webpage' pointed out that there were two
- serious bugs. Thank you very much! According to his indication,
- is_hand_eq_supe() in 'utility.c' and read_CSA_line() in 'csa.c' are
- revised.
-- In MPV code in 'searchr.c', a test of 'root_abort' flag had been
- forgotten. Now the flag is tested after every call of search().
-- 'lan.txt' is added to 'src/executable/' directory. This is an
- example of an input sequence to connect to CSA Shogi server.
-- 'book.bin' now has smaller moves and positions than previous one does.
- Also, 'book_anti.csa' is added to 'src/executable/' directory. This
- is an example of bad moves which apear in records of human experts.
-- 'Legal Notices' in this document is corrected.
-
-Version 4.1.2
-- In 'Makefile' and 'Makefile.vs', targets which require profile-guided
- optimization are removed. Furthermore, an option, which controls
- optimization, has been reverted from the aggressive flag, -O3, to a
- moderate one, '-O2'. These modifications were necessary for avoiding
- abnormal terminations of the program.
-- In 'ini.c', the attribute of POSIX thread in a global-variable
- 'pthread_attr' is set to 'detach-state'. Because threads will never
- join with any other threads in this program, the thread should be
- created in the detached state to free system resources.
-- In 'ini.c', the default size of the transposition table is lifted
- from 12MByte to 48MByte.
-- In 'iterate.c", probing the opening book is avoided when the move
- history of a current game has repetitions.
-- In 'shogi.h', the margins of futility pruning are increased in
- accord with new positional evaluation of the feature vector in
- 'fv.bin'.
-- The quality of an opening book, 'winbin/book.bin', has been improved
- at the expense of quantity.
-
-Version 4.1.0 and 4.1.1 (26 Apr 2009)
-- In 'Makefile' and 'Makefile.vs', some options of Intel C compiler
- are modified. Here, agressive optimization '-O3' is substituted for
- the default '-O2', pthreads support '-pthread' is substituted for
- '-lpthread', and an obsolete '-static-libcxx' is removed.
-- In 'Makefile', the conformance of GNU C and Intel C compilers are
- set to GNU extensions of ISO C99 by setting '-std=gnu99' because a
- POSIX function 'strtok_r()' is not in the C99 standard library.
-- In 'Makefile', targets for GNU C with gprof and profile-guided
- optimization of GNU C are removed.
-- In 'shogi.h', inline assemblies and intrinsics are used on x86-64 as
- well as x86. To detect the targets, pre-defined macros '__i386__'
- and '__x86_64__' are examined.
-- In 'evaluate.c', the evaluation function looks up the table
- 'stand_pat[ply]' to see if the position have been evaluated since
- the previous move is made by 'make_move_[bw]()' functions. Also, the
- evaluation function probes the hash table 'ehash_tbl[]' to avoid
- re-evaluation of the same position.
-- In 'io.c', an immediate value 0 is substituted for 'fileno(stdin)'
- because the POSIX function 'fileno()' is not part of ANSI C. POSIX
- requires that the file descriptor associated with 'stdin' be 0.
-- In 'iterate.c', a criterion for aging of transposition-table, i.e.,
- increment of a global variable 'trans_table_age', is lifted from 7%
- to 9% of saturation ratio of the table.
-- In 'learn1.c', the macro 'SEARCH_DEPTH' is set to 2. The macro
- specifies the depth threashold of searches for finding all of
- principle variations of positions in a set of games.
-- In 'learn1.c', a step size of increment/decrement of feature vectors
- is fixed to 1 in 'learn_parse2()' function.
-- In 'hash.c', when a node can be pruned by using a hash value based on
- futility pruning, a return value of the node is set to beta.
-- In 'rand.c', some codes of initialization of PRNG variables are
- moved to 'ini_genrand()' from 'ini()' function.
-- In 'sckt.c', a function 'send_crlf()' is removed.
-- In 'search.c', now 'search()' calls 'search_quies()' and returns if
- a search depth reaches a threashold. So that we can call 'search()'
- function anytime, and this makes source codes simple.
-- In 'search.c', the static evaluation value is evaluated and used to
- see if the late-move reduction is applicable or not. The evaluation
- value is also used by the futility pruning.
-- In 'search.c', the futility pruning is not applied if the node is in
- check or the move is a check.
-- In 'search.c', now Bonanza sends the keep-alive command '0x0a' to
- the server in 'detect_signals()'.
-- In 'time.c', 'set_seach_limit_time()' is simplified.
-- In 'time.c', the second argument of 'gettimeofday()' is set to 'NULL'.
-
-Version 4.0.4 (2 Feb 2009)
-- An error of GCC inline assembly for spinlock in "thread.c" is fixed.
-- In Windows OS, Bonanza now opens all streams with file sharing by
- using "_SH_DENYNO" constant in "io.c".
-- GCC built-in functions are substituted for GCC inline assemblies for
- bit-scan operations in "bitop.h". Furthermore, "bitop.h" is removed,
- and some of macros in the header are integrated into "shogi.h".
-
-Version 4.0.3 (Jan 2008)
-
-
-4. Files
----------
-
-Here is a list of files you can find in this directory.
-
-C headers
-- param.h piece values
-- shogi.h main header
-
-basic C functions
-- main.c main function of C program
-- data.c definition of global variables
-- ini.c initializations
-- rand.c pseudo random number generator
-- time.c time functions
-- bitop.c bit operation
-- utility.c misc. functions
-
-I/O
-- proce.c input procedure
-- csa.c csa file format I/O
-- io.c basic I/O
-- dek.c dekunobou
-- sckt.c TCP/IP client of CSA SHOGI protocol
-
-bitboard manipulations
-- attack.c piece attacks
-- genchk.c move generation (checks)
-- genevasn.c move generation (evasions)
-- gendrop.c move generation (drops)
-- gennocap.c move generation (non-captures)
-- gencap.c move generation (captures)
-- movgenex.c move generation (inferior moves)
-- makemove.c make moves
-- unmake.c unmake move
-- mate1ply.c 1-ply mate detection
-- debug.c examine bitboard validity
-
-brute-force search
-- iterate.c iterative deepning search at root node
-- searchr.c alpha-beta search at root node
-- search.c alpha-beta search
-- next.c obtains next move
-- quiesrch.c quiescence search
-- evaluate.c static eveluation function
-- evaldiff.c easy and fast evaluation function
-- swap.c static exchange evaluation
-- hash.c transposition table
-- thread.c thread-level parallelization
-- root.c root move genelation and shallow min-max search
-- mate3.c 3-ply mate detection
-- ponder.c pondering
-- book.c creates and probes opening book
-- problem.c auto problem solver
-- valid.c examine move validity
-
-optimal control of min-max search
-- learn1.c main functions
-- learn2.c feture vector manipuration
-
-misc.
-- bonanza.txt which now you are looking at
-- Makefile makefile for gnu make.exe
-- Makefile.vs makefile for Microsoft nmake.exe
-- bonanza.ico icon file for windows
-- bonanza.rc resource-definition file for windows
-- lan.txt example of input sequence to connect CSA Shogi server
-- book_anti.csa example of a set of bad moves which apear in records
- of human exparts. This is used by 'book create' command.
-
-4. How to build Bonanza
------------------------
-
-You can build Bonanza by means of GNU Make on Linux or Microsoft NMAKE
-on Windows. Here is some examples:
-
-- GCC on Linux
-> make -f Makefile gcc
-
-- Intel C++ Compiler on Linux
-> make -f Makefile icc
-
-- Microsoft C/C++ Compiler on Windows
-> nmake -f Makefile.vs cl
-
-- Intel C++ Compiler on Windows
-> nmake -f Makefile.vs icl
-
-The C source codes are written by using ANSI C plus a small number of
-new features in ISO C99. Therefore, I think this can be easily built
-in many platforms without much effort.
-
-It may be necessary to define some macros in Makefile or
-Makefile.vs. The macros are:
-
-- NDEBUG (DEBUG) builds release (debug) version of Bonanza
-
-- MINIMUM disables some auxiliary functions that are not
- necessary to play a game, e.g., book composition
- and optimization of evaluation functions
-
-- TLP enables thread-level parallel search
-
-- MPV enables multi-PV search
-
-- CSA_LAN enables Bonanza to communicate by CSA Shogi TCP/IP
- protcol
-
-- DEKUNOBOU enables dekunobou interface (available only for
- Windows)
-
-- CSASHOGI builds an engine for CSA Shogi (available only for
- Windows)
-
-- NO_LOGGING suppresses dumping log files
-
-Bonanza is an application that does not provide graphical user
-interface. If you could build "bonanza.exe" properly without CSASHOGI
-macro, it shows a prompt "Black 1>" when you execute it at a computer
-console.
-
-Bonanza uses three binary files: a feature vector of static evaluation
-function "fv.bin", an opening book "book.bin", and a
-position-learning database "hash.bin". You can find these in "winbin/"
-directory. Without the NO_LOGGING option, Bonanza must find "log/"
-directory to dump log files.
-
-
-5. Command List
----------------
-
-- beep on
-- beep off
- These commands enable (on) or disable (off) a beep when Bonanza
- makes a move. The default is on.
-
-- book on
-- book off
- These commands enable (on) or disable (off) to probe the opening
- book, "./book.bin". The default is on.
-
-- book narrow
-- book wide
- When the command with "narrow" is used, Bonanza selects a book
- move from a small set of opening moves. The default is "wide". The
- narrowing of the opening moves is useful if you want Bonanza
- choose a common opening line.
-
-- book create
- This command creates the opening book file, "./book.bin", by using
- numerous experts' games in a single CSA record file, "./book.csa".
- It also uses another CSA record file, "book_anti.csa", where you
- can register bad moves that may appear in the experts' games at
- the last moves in the record file. Here is the example:
-
- ----------------------------------------
- PI, +, +6978KI, %TORYO
- /
- PI, +, +6978KI, -8384FU, %TORYO
- /
- PI, +, +7776FU, -4132KI, %TORYO
- /
- PI, +, +7776FU, -4132KI, +2726FU, %TORYO
- ----------------------------------------
-
- This command becomes effective when MINIMUM macro is not defined
- in the Makefile.
-
-- connect 'addr' 'port' 'id' 'passwd' ['ngame']
- This command connects Bonanza to a shogi server by using the CSA
- protocol. The first four arguments specify the network address,
- port number, user ID, and password, respectively. The last
- argument limits a number of games that will be played by Bonanza.
- This command becomes effective when CSA_LAN macro is defined in
- the Makefile.
-
-- dekunobou 'addr' 'port-dekunobou' 'port-bonanza'
- This command connects Bonanza to Dekunobou.
-
-- display ['num']
- This command prints the shogi board. If you want to flip the
- board, set 'num' to 2. If not, set it to 1.
-
-- s
- Bonanza makes a prompt reply while thinking as soon as this
- command is used.
-
-- hash 'num'
- This command is used to initialize the transposition table and
- set the size of the table to 2^'num'.
-
-- hash learn create
- This command is used to make a zero-filled position-lerning
- database, "hash.bin". This command becomes effective when MINIMUM
- macro is not defined in the Makefile.
-
-- hash learn on
-- hash learn off
- These commands enable (on) or disable (off) the position learning.
- The default is on.
-
-- learn 'str' 'steps' ['games' ['iterations' ['num1' ['num2']]]]
- This command optimizes a feature vector of the static evaluation
- function by using numorous experts' games in a single CSA record
- file, "./records.csa". If you want to use a zero-filled vector as
- an initial guess of the optimization procedure, set 'str' to
- "ini". If not, set it to "no-ini". The third argument 'games' is a
- number of games to be read from the record file. If the third
- argument is negative or omitted, all games are read from the file.
-
- The learning method iterates a set of procedures, and the number
- of iteration can be limited by the fourth argument. It continues
- as long as the argument is negative. The procedures consist of two
- parts. The first part reads the record file and creates principal
- variations by using 'num1' threads. The default value of 'num1' is
- 1. The second part renews the feature vector 'steps' times by using
- 'num2' threads in accord with the principal variations. The default
- value of 'steps' and 'num2' is 1. Note that each thread in the
- second procedure uses about 500MByte of the main memory. The two
- arguments 'num1' and 'num2' become effective when TLP macro is
- defined in the Makefile. After the procedures, the optimized
- vector is saved in "./fv.bin". This command become effective when
- MINIMUM macro is not defined in the Makefile.
-
-- limit depth 'num'
- This command is used to specify a depth, 'num', at which Bonanza
- ends the iterative deepening search.
-
-- limit nodes 'num'
- When this command is used, Bonanza stops thinking after searched
- nodes reach to 'num'.
-
-- limit time 'minute' 'second' ['depth']
- This command limits thinking time of Bonanza. It tries to make
- each move by consuming the time 'minute'. When the time is spent
- all, it makes each move in 'second'. The last argument 'depth' can
- be used if you want Bonanza to stop thinking after the iterative
- deepening searches reach sufficient depth.
-
-- limit time extendable
-- limit time strict
- The command, "limit time extendable", allows Bonanza to think
- longer than the time limited by the previous command if it wishes
- to. The default is "strict".
-
-- mnj 'sd' 'seed' 'addr' 'port' 'id'
- This command connects Bonanza to the council server in
- src/cluster/. The first two integers specify the standard
- deviation and initial seed of pseudo-random numbers which are
- added to the static evaluation function. Experiments suggested
- that an appropriate value for the standard deviation is 50. Note
- that all clients should use different seeds. The last three
- arguments are network address, port number, user ID,
- respectively. This command becomes effective when MNJ_LAN macro is
- defined in the Makefile.
-
-- move ['str']
- Bonanza makes a move of 'str'. If the argument is omitted, Bonanza
- thinks of its next move by itself.
-
-- mpv num 'nroot'
-- mpv width 'threshold'
- These commands control the number of root moves, 'nroot', to
- constitute principal variations. The default number is 1. A root
- move that yields a smaller value than the best value by 'threshold'
- is neglected. The default threshold is about 200. These commands
- become effective when MPV macro is defined in the Makefile.
-
-- new ['str']
- This command initializes the shogi board. The argument 'str'
- controls an initial configuration of the board. If you want to
- play a no-handicapped game, set 'str' to "PI" and this is the
- default value. In a handicapped game, specify squares and pieces
- to drop, e.g. "new PI82HI22KA" or "new PI19KY".
-
-- peek on
-- peek off
- The command "peek on (off)" enables (disables) peeks at a buffer
- of the standard input file while Bonanza is thinking. The default
- is on. This command is useful when you want to process a set of
- commands as "> ./bonanza.exe < infile".
-
-- ping
- Prompt Bonanza to print "pong".
-
-- ponder on
-- ponder off
- The command "ponder on (off)" enables (disables) thinks on the
- opponent's time. The default is on.
-
-- problem ['num']
- This command is used to solve problems in "./problem.csa". Here
- is an example of the problem file.
-
- -----------------------------
- $ANSWER:+0024FU
- P1-KY-KE-OU-KI * * * * -KY
- P2 * * * * * -KI * * *
- P3 * * -FU-GI-FU * -KE * -KA
- P4-FU * * -FU-GI-FU-HI * -FU
- P5 * * * * * * * -FU+KY
- P6+FU+KA+FU+FU+GI+FU+KI * *
- P7 * +FU * * +FU * * * *
- P8 * +OU+KI+GI * * +HI * *
- P9+KY+KE * * * * * +KE *
- P+00FU00FU
- P-00FU00FU00FU
- +
- /
- $ANSWER:+0087KY:+0088KY
- P1-OU-KE * * * * * +GI *
- P2-KY-KI * * * * * * *
- P3-FU-HI * -KI * * -GI * *
- P4 * * -KE * * * * * -FU
- P5 * +GI * -FU-FU-FU-FU-FU *
- P6+FU+HI-FU * * * * * *
- P7 * * * +FU * * * * +FU
- P8 * * +OU+KI+KI * * * *
- P9+KY+KE * * * * * +KE+KY
- P+00KA00GI00KY00FU00FU
- P-00KA00FU00FU00FU00FU00FU
- +
- -----------------------------
-
- The argument 'num' specifies the number of problems to solve.
-
-- quit
- The quit command and EOF character will exit Bonanza.
-
-- read 'filename' [(t|nil) ['num']]
- This command is used to read a CSA record 'filename' up to 'num'
- moves. Set the second argument to "nil" when you want to ignore
- time information in the record. The default value is "t". Bonanza
- reads all move sequence if the last argument is neglected. If
- 'filename' is ".", the command reads an ongoing game from the
- initial position.
-
-- resign
- Use this command when you resign a game.
-
-- resign 'num'
- This command specifies the threshold to resign. 'num' is a value
- of the threshold. The default is around 1000.
-
-- stress on
-- stress off
- When the command "stress on" is used, last-move shown in shogi
- board is stressed. The default is on.
-
-- time remain 'num1' 'num2'
- This command tells Bonanza the remaining time. 'num1' ('num2') is
- the remaining time of black (white) in seconds.
-
-- time response 'num'
- This command specifies a margin to control time. The time margin
- saves Bonanza from time up due to TCP/IP communication to a server
- program, sudden disc access, or imperfection of time control of
- Bonanza. 'num' is the time margin in milli-second. The default
- value is 200.
-
-- tlp 'num'
- This command controls the number of threads to be created when
- Bonana considers a move to make. The command becomes effective
- when TLP macro is defined in the Makefile. 'num' is the number of
- threads. The default value is 1.
-
-- #
- A line beginning with # causes all characters on that line
- to be ignored.
-
-- [move command]
- A move command consists of four digits followed by two
- capital alphabets, e.g. 7776FU. The first two digits
- are a starting square and the last two are a target square. The
- starting square is "OO" if the move is a dorp, e.g. 0087FU. The
- following two alphabets specify a piece type as the following,
-
- FU - pawn (Fuhyo) TO - promoted pawn (Tokin)
- KY - lance (Kyousha) NY - promoted lance (Narikyo)
- KE - knight (Keima) NK - promoted knight (Narikei)
- GI - silver general (Ginsho) NG - promoted silver (Narigin)
- KI - gold general (Kinsyo)
- KA - Bishop (Kakugyo) UM - Dragon horse (Ryuma)
- HI - Rook (Hisha) RY - Dragon king (Ryuo)
- OU - King (Osho)
-
- Here, words in parentheses are romanization of Japanese words.
+----------------------------------------------------------------------\r
+ Bonanza 6.0 - Client Source Code\r
+ Kunihito Hoki, May 2011\r
+----------------------------------------------------------------------\r
+\r
+\r
+1. Introduction\r
+----------------\r
+\r
+Bonanza is a state-of-the art computer shogi engine which runs on\r
+Windows and Linux machines, and this directory contains a\r
+platform-independent source code.\r
+\r
+This source code is distributed with a hope that it will be useful in\r
+addition to the main part of the shogi engine. This program includes\r
+many useful functions such as manipulating a shogi board, reading and\r
+writing a CSA record file, speaking of a CSA protocol with a socket\r
+communication, and controlling time, and etc.. I believe this program\r
+can be a good starting point if you are interested in making shogi\r
+programs.\r
+\r
+One main feature of this program is that it employs a brute-force\r
+search method together with bitboard techniques as many chess programs\r
+do. Another notable feature is a machine learning of shogi evaluation\r
+functions. The details of the learning algorithm (aka Bonanza method)\r
+were already presented [1], and this source code provides an example\r
+of implementation of the learning method.\r
+\r
+I admit that some parts of the source code are cryptic, e.g. codes in\r
+"mate1ply.c". I hope that I will have some time to make a quality\r
+documentation and comments on the program code, or someone else could\r
+decrypt my program and provide a documentation.\r
+\r
+Any comments or suggestions are welcome [2].\r
+\r
+[1] K. Hoki, "Optimal control of minimax search results to learn\r
+ positional evaluation", Game Programming Workshop, Hakone, Japan\r
+ 2008.\r
+\r
+[2] Contact to "bonanza_query [at] hotmail.com".\r
+\r
+\r
+2. Legal Notices\r
+-----------------\r
+\r
+This program is protected by copyright. Without a specific \r
+permission, any means of commercial applications are prohibited.\r
+Furthermore, this program is distributed without any warranty.\r
+Within these limits, you can use, redistribute, and/or modify it.\r
+\r
+\r
+3. Change Logs\r
+---------------\r
+\r
+Version 6.0\r
+\r
+Search() function is modified to ignore moves which receive negative\r
+values from Static Exchange Evaluation (SEE) at frontier and\r
+pre-frontier nodes. Self-play experiments showed that this modification\r
+makes Bonanza slightly stronger. Similar results were also observed in\r
+experiments using a shogi program YSS,\r
+http://www32.ocn.ne.jp/~yss/horizon.txt. Moreover, the branch cut by\r
+means of SEE at frontier nodes can also be found in a chess program,\r
+Stockfish.\r
+\r
+Now Bonanza does Late Move Reduction (LMR) at root nodes, and recursive\r
+iterative deepening more often. Self-play experiments showed that these\r
+modifications make Bonanza slightly stronger.\r
+\r
+DFPN searcher is added to the set of Bonanza source codes (dfpn.c,\r
+dfpn.h, and dfpnhash.c). You can use the searcher by using 'dfpn'\r
+command with a compile option -DDFPN turned on. To make use of the DFPN\r
+searcher in ordinary search, use 'dfpn_client' command with a compile\r
+option -DDFPN_CLIENT turned on. To provide a proper service to the DFPN\r
+client, you also need to use a server script 'src/server/dfpn_server.pl'\r
+with one or more DFPN worker(s) connected with 'dfpn connect' command.\r
+I am thankful to Dr. A. Nagai for his kind and fruitful advice.\r
+\r
+Now Bonanza can be a client of parallel searches using cluster computing\r
+environment with mnj command. 'src/server/parallel_server.pl' is a\r
+server script of root-node parallelizations, and the server can be a\r
+client of majority voting cluster computation.\r
+\r
+Some techniques which increase computational efficiency of Bonanza are\r
+reported by E. Ito, http://aleag.cocolog-nifty.com/. In his website,\r
+two ideas are shown, i.e., (i) speed up of the computation of the static\r
+evaluation function, and (2) use of SSE instructions of Intel processors\r
+for bitboard operations. By adopting his ideas to Bonanza, NPS value\r
+nearly doubled. This is amazing. To use SSE instructions, specify -DSSE2\r
+or -DSSE4 compiler option. I am thankful to Mr. E. Ito for his kind and\r
+fruitful advice.\r
+\r
+-DINANIWA_SHIFT compilation flag is supplied to enable an Inaniwa-strategy detection\r
+\r
+There are many other modifications and bug fixes.\r
+\r
+\r
+Feliz 0.0\r
+\r
+- Some results from Y. Sato's experiments with Bonanza inspired me\r
+ to use the history table in LMR in Shogi, as Fruit did in chess. By\r
+ doing so, some improvement in performance of the tree search is\r
+ made.\r
+\r
+- From private communications with Yaneurao, it turned out that the\r
+ 3-ply-mate detections in 'mate3.c' can search game trees more\r
+ efficiently by using several heuristic pruning techniques. Now\r
+ 'mate3.c' adopts some of these techniques.\r
+\r
+- E. Ito kindly reported two bugs in the source codes. One is in\r
+ hash_store(), and the other is in ehash_probe() and\r
+ ehash_store(). Now these are fixed.\r
+\r
+- The structure of history table is modified from 'square-to' and\r
+ 'square-from' method to an exact match method by using the perfect\r
+ hash technique. The hash function of moves in 'phash.c' is generated\r
+ by codes at http://burtleburtle.net/bob/hash/perfect.html.\r
+\r
+- A command 'mnj' is added to connect to the cluster-computing server\r
+ in src/cluster/.\r
+\r
+- In client_next_game(), the way of dealing with REJECT message from a\r
+ CSA Shogi server is revised. Now Bonanza connects to the server again\r
+ when the game is rejected by an opponent.\r
+\r
+\r
+Version 4.1.3\r
+- The owner of 'LS3600 Blog Webpage' pointed out that there were two\r
+ serious bugs. Thank you very much! According to his indication,\r
+ is_hand_eq_supe() in 'utility.c' and read_CSA_line() in 'csa.c' are\r
+ revised.\r
+- In MPV code in 'searchr.c', a test of 'root_abort' flag had been\r
+ forgotten. Now the flag is tested after every call of search().\r
+- 'lan.txt' is added to 'src/executable/' directory. This is an\r
+ example of an input sequence to connect to CSA Shogi server.\r
+- 'book.bin' now has smaller moves and positions than previous one does.\r
+ Also, 'book_anti.csa' is added to 'src/executable/' directory. This\r
+ is an example of bad moves which apear in records of human experts.\r
+- 'Legal Notices' in this document is corrected.\r
+\r
+Version 4.1.2\r
+- In 'Makefile' and 'Makefile.vs', targets which require profile-guided\r
+ optimization are removed. Furthermore, an option, which controls\r
+ optimization, has been reverted from the aggressive flag, -O3, to a\r
+ moderate one, '-O2'. These modifications were necessary for avoiding\r
+ abnormal terminations of the program.\r
+- In 'ini.c', the attribute of POSIX thread in a global-variable\r
+ 'pthread_attr' is set to 'detach-state'. Because threads will never\r
+ join with any other threads in this program, the thread should be\r
+ created in the detached state to free system resources.\r
+- In 'ini.c', the default size of the transposition table is lifted\r
+ from 12MByte to 48MByte.\r
+- In 'iterate.c", probing the opening book is avoided when the move\r
+ history of a current game has repetitions.\r
+- In 'shogi.h', the margins of futility pruning are increased in\r
+ accord with new positional evaluation of the feature vector in\r
+ 'fv.bin'.\r
+- The quality of an opening book, 'winbin/book.bin', has been improved\r
+ at the expense of quantity.\r
+\r
+Version 4.1.0 and 4.1.1 (26 Apr 2009)\r
+- In 'Makefile' and 'Makefile.vs', some options of Intel C compiler\r
+ are modified. Here, agressive optimization '-O3' is substituted for\r
+ the default '-O2', pthreads support '-pthread' is substituted for\r
+ '-lpthread', and an obsolete '-static-libcxx' is removed.\r
+- In 'Makefile', the conformance of GNU C and Intel C compilers are\r
+ set to GNU extensions of ISO C99 by setting '-std=gnu99' because a\r
+ POSIX function 'strtok_r()' is not in the C99 standard library.\r
+- In 'Makefile', targets for GNU C with gprof and profile-guided\r
+ optimization of GNU C are removed.\r
+- In 'shogi.h', inline assemblies and intrinsics are used on x86-64 as\r
+ well as x86. To detect the targets, pre-defined macros '__i386__'\r
+ and '__x86_64__' are examined.\r
+- In 'evaluate.c', the evaluation function looks up the table\r
+ 'stand_pat[ply]' to see if the position have been evaluated since\r
+ the previous move is made by 'make_move_[bw]()' functions. Also, the\r
+ evaluation function probes the hash table 'ehash_tbl[]' to avoid\r
+ re-evaluation of the same position.\r
+- In 'io.c', an immediate value 0 is substituted for 'fileno(stdin)'\r
+ because the POSIX function 'fileno()' is not part of ANSI C. POSIX\r
+ requires that the file descriptor associated with 'stdin' be 0.\r
+- In 'iterate.c', a criterion for aging of transposition-table, i.e.,\r
+ increment of a global variable 'trans_table_age', is lifted from 7%\r
+ to 9% of saturation ratio of the table.\r
+- In 'learn1.c', the macro 'SEARCH_DEPTH' is set to 2. The macro\r
+ specifies the depth threashold of searches for finding all of\r
+ principle variations of positions in a set of games.\r
+- In 'learn1.c', a step size of increment/decrement of feature vectors\r
+ is fixed to 1 in 'learn_parse2()' function.\r
+- In 'hash.c', when a node can be pruned by using a hash value based on\r
+ futility pruning, a return value of the node is set to beta.\r
+- In 'rand.c', some codes of initialization of PRNG variables are\r
+ moved to 'ini_genrand()' from 'ini()' function.\r
+- In 'sckt.c', a function 'send_crlf()' is removed.\r
+- In 'search.c', now 'search()' calls 'search_quies()' and returns if\r
+ a search depth reaches a threashold. So that we can call 'search()'\r
+ function anytime, and this makes source codes simple.\r
+- In 'search.c', the static evaluation value is evaluated and used to\r
+ see if the late-move reduction is applicable or not. The evaluation\r
+ value is also used by the futility pruning.\r
+- In 'search.c', the futility pruning is not applied if the node is in\r
+ check or the move is a check.\r
+- In 'search.c', now Bonanza sends the keep-alive command '0x0a' to\r
+ the server in 'detect_signals()'.\r
+- In 'time.c', 'set_seach_limit_time()' is simplified.\r
+- In 'time.c', the second argument of 'gettimeofday()' is set to 'NULL'.\r
+\r
+Version 4.0.4 (2 Feb 2009)\r
+- An error of GCC inline assembly for spinlock in "thread.c" is fixed.\r
+- In Windows OS, Bonanza now opens all streams with file sharing by\r
+ using "_SH_DENYNO" constant in "io.c".\r
+- GCC built-in functions are substituted for GCC inline assemblies for\r
+ bit-scan operations in "bitop.h". Furthermore, "bitop.h" is removed,\r
+ and some of macros in the header are integrated into "shogi.h".\r
+\r
+Version 4.0.3 (Jan 2008)\r
+\r
+\r
+4. Files\r
+---------\r
+\r
+Here is a list of files you can find in this directory.\r
+\r
+C headers\r
+- param.h piece values\r
+- shogi.h main header\r
+- bitop.h bit operations\r
+- dfpn.h header of DFPN codes\r
+\r
+basic C functions\r
+- main.c main function of C program\r
+- data.c definition of global variables\r
+- ini.c initializations\r
+- rand.c pseudo random number generator\r
+- time.c time functions\r
+- bitop.c bit operations\r
+- utility.c misc. functions\r
+\r
+I/O\r
+- proce.c input procedures\r
+- csa.c csa file format I/O\r
+- io.c basic I/O\r
+- sckt.c Socket communications\r
+\r
+bitboard manipulations\r
+- attack.c piece attacks\r
+- genchk.c move generation (checks)\r
+- genevasn.c move generation (evasions)\r
+- gendrop.c move generation (drops)\r
+- gennocap.c move generation (non-captures)\r
+- gencap.c move generation (captures)\r
+- movgenex.c move generation (inferior moves)\r
+- makemove.c make moves\r
+- unmake.c unmake move\r
+- mate1ply.c 1-ply mate detection\r
+- debug.c examine bitboard validity\r
+\r
+brute-force search\r
+- iterate.c iterative deepning search at root node\r
+- searchr.c alpha-beta search at root node\r
+- search.c alpha-beta search\r
+- next.c obtains next move\r
+- quiesrch.c quiescence search\r
+- evaluate.c static eveluation function\r
+- evaldiff.c easy and fast evaluation function\r
+- swap.c static exchange evaluation\r
+- hash.c transposition table\r
+- phash.c perfect hash function of moves\r
+- thread.c thread-level parallelization\r
+- root.c root move genelation and shallow min-max search\r
+- mate3.c 3-ply mate detection\r
+- ponder.c pondering\r
+- book.c creates and probes opening book\r
+- problem.c auto problem solver\r
+- valid.c examine move validity\r
+\r
+DFPN search\r
+- dfpn.c DFPN search\r
+- dfpnhash.c Hashing for DFPN search\r
+\r
+optimal control of min-max search\r
+- learn1.c main functions\r
+- learn2.c feture vector manipuration\r
+\r
+misc.\r
+- bonanza.txt which now you are looking at\r
+- Makefile makefile for gnu make.exe\r
+- Makefile.vs makefile for Microsoft nmake.exe\r
+- bonanza.ico icon file for windows\r
+- bonanza.rc resource-definition file for windows\r
+- lan.txt example of input sequence to connect CSA Shogi server\r
+- book_anti.csa example of a set of bad moves which apear in records\r
+ of human exparts. This is used by 'book create' command.\r
+\r
+4. How to build Bonanza\r
+-----------------------\r
+\r
+You can build Bonanza by means of GNU Make on Linux or Microsoft NMAKE\r
+on Windows. Here is some examples:\r
+\r
+- GCC on Linux\r
+> make -f Makefile gcc\r
+\r
+- Intel C++ Compiler on Linux\r
+> make -f Makefile icc\r
+\r
+- Microsoft C/C++ Compiler on Windows\r
+> nmake -f Makefile.vs cl\r
+\r
+- Intel C++ Compiler on Windows\r
+> nmake -f Makefile.vs icl\r
+\r
+The C source codes are written by using ANSI C plus a small number of\r
+new features in ISO C99. Therefore, I think this can be easily built\r
+in many platforms without much effort.\r
+\r
+It may be necessary to define some macros in Makefile or\r
+Makefile.vs. The macros are:\r
+\r
+- NDEBUG (DEBUG) builds release (debug) version of Bonanza\r
+\r
+- MINIMUM disables some auxiliary functions that are not\r
+ necessary to play a game, e.g., book composition\r
+ and optimization of evaluation functions\r
+\r
+- TLP enables thread-level parallel search\r
+\r
+- MPV enables multi-PV search\r
+\r
+- CSA_LAN enables Bonanza to communicate by CSA Shogi TCP/IP\r
+ protcol\r
+\r
+- DEKUNOBOU enables dekunobou interface (available only for\r
+ Windows)\r
+\r
+- CSASHOGI builds an engine for CSA Shogi (available only for\r
+ Windows)\r
+\r
+- NO_LOGGING suppresses dumping log files\r
+\r
+- HAVE_SSE2 use SSE2 instructions for speed\r
+\r
+- HAVE_SSE4 use SSE2 and SSE4.1 instructions for speed\r
+\r
+- MNJ_LAN enables a client-mode of cluster searches\r
+\r
+- INANIWA_SHIFT enables an Inaniwa strategy detection\r
+\r
+- DFPN build the DFPN worker of mate-problems server\r
+\r
+- DFPN_CLIENT enables the client-mode of mate-problem server\r
+\r
+\r
+Bonanza is an application that does not provide graphical user\r
+interface. If you could build "bonanza.exe" properly without CSASHOGI\r
+macro, it shows a prompt "Black 1>" when you execute it at a computer\r
+console.\r
+\r
+Bonanza uses three binary files: a feature vector of static evaluation\r
+function "fv.bin", an opening book "book.bin", and a\r
+position-learning database "hash.bin". You can find these in "winbin/"\r
+directory. Without the NO_LOGGING option, Bonanza must find "log/"\r
+directory to dump log files.\r
+\r
+\r
+5. Command List\r
+---------------\r
+\r
+- beep on\r
+- beep off\r
+ These commands enable (on) or disable (off) a beep when Bonanza\r
+ makes a move. The default is on.\r
+\r
+- book on\r
+- book off\r
+ These commands enable (on) or disable (off) to probe the opening\r
+ book, "./book.bin". The default is on.\r
+\r
+- book narrow\r
+- book wide\r
+ When the command with "narrow" is used, Bonanza selects a book\r
+ move from a small set of opening moves. The default is "wide". The\r
+ narrowing of the opening moves is useful if you want Bonanza\r
+ choose a common opening line.\r
+\r
+- book create\r
+ This command creates the opening book file, "./book.bin", by using\r
+ numerous experts' games in a single CSA record file, "./book.csa".\r
+ It also uses another CSA record file, "book_anti.csa", where you\r
+ can register bad moves that may appear in the experts' games at\r
+ the last moves in the record file. Here is the example:\r
+\r
+ ----------------------------------------\r
+ PI, +, +6978KI, %TORYO\r
+ /\r
+ PI, +, +6978KI, -8384FU, %TORYO\r
+ /\r
+ PI, +, +7776FU, -4132KI, %TORYO\r
+ /\r
+ PI, +, +7776FU, -4132KI, +2726FU, %TORYO\r
+ ----------------------------------------\r
+\r
+ This command becomes effective when MINIMUM macro is not defined\r
+ in the Makefile.\r
+\r
+- connect 'addr' 'port' 'id' 'passwd' ['ngame']\r
+ This command connects Bonanza to a shogi server by using the CSA\r
+ protocol. The first four arguments specify the network address,\r
+ port number, user ID, and password, respectively. The last\r
+ argument limits a number of games that will be played by Bonanza.\r
+ This command becomes effective when CSA_LAN macro is defined in\r
+ the Makefile.\r
+\r
+- dfpn go\r
+ Bonanza does DFPN search at a current position.\r
+\r
+- dfpn hash 'num'\r
+ This command is used to initialize the transposition table of\r
+ DFPN search and set the size of the table to 2^'num'. This\r
+ command becomes effective when DFPN macro is defined in the\r
+ Makefile.\r
+\r
+- dfpn connect 'hostname' 'port#' 'ID'\r
+ This command is used to connect to the server script\r
+ dfpn_server.pl as a worker. This command becomes effective when\r
+ DFPN macro is defined in the Makefile.\r
+\r
+- dfpn_client 'hostname' 'port#'\r
+ This command is used to connect to the server script\r
+ dfpn_server.pl as a client. With this, a root and its child\r
+ posittions are examined by the DFPN worker(s). This command\r
+ becomes effective when DFPN_CLIENT macro is defined in the\r
+ Makefile.\r
+\r
+- display ['num']\r
+ This command prints the shogi board. If you want to flip the\r
+ board, set 'num' to 2. If not, set it to 1.\r
+\r
+- s\r
+ Bonanza makes a prompt reply while thinking as soon as this\r
+ command is used.\r
+\r
+- hash 'num'\r
+ This command is used to initialize the transposition table and\r
+ set the size of the table to 2^'num'.\r
+\r
+- hash learn create\r
+ This command is used to make a zero-filled position-lerning\r
+ database, "hash.bin". This command becomes effective when MINIMUM\r
+ macro is not defined in the Makefile.\r
+\r
+- hash learn on\r
+- hash learn off\r
+ These commands enable (on) or disable (off) the position learning.\r
+ The default is on.\r
+\r
+- learn 'str' 'steps' ['games' ['iterations' ['num1' ['num2']]]]\r
+ This command optimizes a feature vector of the static evaluation\r
+ function by using numorous experts' games in a single CSA record\r
+ file, "./records.csa". If you want to use a zero-filled vector as\r
+ an initial guess of the optimization procedure, set 'str' to\r
+ "ini". If not, set it to "no-ini". The third argument 'games' is a\r
+ number of games to be read from the record file. If the third\r
+ argument is negative or omitted, all games are read from the file.\r
+\r
+ The learning method iterates a set of procedures, and the number\r
+ of iteration can be limited by the fourth argument. It continues\r
+ as long as the argument is negative. The procedures consist of two\r
+ parts. The first part reads the record file and creates principal\r
+ variations by using 'num1' threads. The default value of 'num1' is\r
+ 1. The second part renews the feature vector 'steps' times by using\r
+ 'num2' threads in accord with the principal variations. The default\r
+ value of 'steps' and 'num2' is 1. Note that each thread in the\r
+ second procedure uses about 500MByte of the main memory. The two\r
+ arguments 'num1' and 'num2' become effective when TLP macro is\r
+ defined in the Makefile. After the procedures, the optimized\r
+ vector is saved in "./fv.bin". This command become effective when\r
+ MINIMUM macro is not defined in the Makefile.\r
+\r
+- limit depth 'num'\r
+ This command is used to specify a depth, 'num', at which Bonanza\r
+ ends the iterative deepening search.\r
+\r
+- limit nodes 'num'\r
+ When this command is used, Bonanza stops thinking after searched\r
+ nodes reach to 'num'.\r
+\r
+- limit time 'minute' 'second' ['depth']\r
+ This command limits thinking time of Bonanza. It tries to make\r
+ each move by consuming the time 'minute'. When the time is spent\r
+ all, it makes each move in 'second'. The last argument 'depth' can\r
+ be used if you want Bonanza to stop thinking after the iterative\r
+ deepening searches reach sufficient depth.\r
+\r
+- limit time extendable\r
+- limit time strict\r
+ The command, "limit time extendable", allows Bonanza to think\r
+ longer than the time limited by the previous command if it wishes\r
+ to. The default is "strict".\r
+\r
+- mnj 'sd' 'seed' 'addr' 'port' 'id' 'factor' 'stable_depth'\r
+ This command connects Bonanza to the majority or parallel server in\r
+ src/server/. The first two integers specify the standard\r
+ deviation and initial seed of pseudo-random numbers which are\r
+ added to the static evaluation function. Experiments suggested\r
+ that an appropriate value for the standard deviation is 15. Note\r
+ that all clients should use different seeds. The following three\r
+ arguments are network address, port number, user ID,\r
+ respectively. You can specify factor as a voting weight. Also\r
+ stable_depth is useful to detect opening positions. Here, when\r
+ Bonanza reaches the specified depth, then this is reported to the\r
+ server to reduce thinking time. This command becomes effective\r
+ when MNJ_LAN macro is defined in the Makefile.\r
+\r
+- move ['str']\r
+ Bonanza makes a move of 'str'. If the argument is omitted, Bonanza\r
+ thinks of its next move by itself.\r
+\r
+- mpv num 'nroot'\r
+- mpv width 'threshold'\r
+ These commands control the number of root moves, 'nroot', to\r
+ constitute principal variations. The default number is 1. A root\r
+ move that yields a smaller value than the best value by 'threshold'\r
+ is neglected. The default threshold is about 200. These commands\r
+ become effective when MPV macro is defined in the Makefile.\r
+\r
+- new ['str']\r
+ This command initializes the shogi board. The argument 'str'\r
+ controls an initial configuration of the board. If you want to\r
+ play a no-handicapped game, set 'str' to "PI" and this is the\r
+ default value. In a handicapped game, specify squares and pieces\r
+ to drop, e.g. "new PI82HI22KA" or "new PI19KY".\r
+\r
+- peek on\r
+- peek off\r
+ The command "peek on (off)" enables (disables) peeks at a buffer\r
+ of the standard input file while Bonanza is thinking. The default\r
+ is on. This command is useful when you want to process a set of\r
+ commands as "> ./bonanza.exe < infile".\r
+\r
+- ping\r
+ Prompt Bonanza to print "pong".\r
+\r
+- ponder on\r
+- ponder off\r
+ The command "ponder on (off)" enables (disables) thinks on the\r
+ opponent's time. The default is on.\r
+\r
+- problem ['num']\r
+ This command is used to solve problems in "./problem.csa". Here\r
+ is an example of the problem file.\r
+\r
+ -----------------------------\r
+ $ANSWER:+0024FU\r
+ P1-KY-KE-OU-KI * * * * -KY\r
+ P2 * * * * * -KI * * * \r
+ P3 * * -FU-GI-FU * -KE * -KA\r
+ P4-FU * * -FU-GI-FU-HI * -FU\r
+ P5 * * * * * * * -FU+KY\r
+ P6+FU+KA+FU+FU+GI+FU+KI * * \r
+ P7 * +FU * * +FU * * * * \r
+ P8 * +OU+KI+GI * * +HI * * \r
+ P9+KY+KE * * * * * +KE * \r
+ P+00FU00FU\r
+ P-00FU00FU00FU\r
+ +\r
+ /\r
+ $ANSWER:+0087KY:+0088KY\r
+ P1-OU-KE * * * * * +GI * \r
+ P2-KY-KI * * * * * * * \r
+ P3-FU-HI * -KI * * -GI * * \r
+ P4 * * -KE * * * * * -FU\r
+ P5 * +GI * -FU-FU-FU-FU-FU * \r
+ P6+FU+HI-FU * * * * * * \r
+ P7 * * * +FU * * * * +FU\r
+ P8 * * +OU+KI+KI * * * * \r
+ P9+KY+KE * * * * * +KE+KY\r
+ P+00KA00GI00KY00FU00FU\r
+ P-00KA00FU00FU00FU00FU00FU\r
+ +\r
+ -----------------------------\r
+\r
+ The argument 'num' specifies the number of problems to solve.\r
+\r
+- quit\r
+ The quit command and EOF character will exit Bonanza.\r
+\r
+- read 'filename' [(t|nil) ['num']]\r
+ This command is used to read a CSA record 'filename' up to 'num'\r
+ moves. Set the second argument to "nil" when you want to ignore\r
+ time information in the record. The default value is "t". Bonanza\r
+ reads all move sequence if the last argument is neglected. If\r
+ 'filename' is ".", the command reads an ongoing game from the\r
+ initial position.\r
+\r
+- resign\r
+ Use this command when you resign a game.\r
+\r
+- resign 'num'\r
+ This command specifies the threshold to resign. 'num' is a value\r
+ of the threshold. The default is around 1000.\r
+\r
+- stress on\r
+- stress off\r
+ When the command "stress on" is used, last-move shown in shogi\r
+ board is stressed. The default is on.\r
+\r
+- time remain 'num1' 'num2'\r
+ This command tells Bonanza the remaining time. 'num1' ('num2') is\r
+ the remaining time of black (white) in seconds.\r
+\r
+- time response 'num'\r
+ This command specifies a margin to control time. The time margin\r
+ saves Bonanza from time up due to TCP/IP communication to a server\r
+ program, sudden disc access, or imperfection of time control of\r
+ Bonanza. 'num' is the time margin in milli-second. The default\r
+ value is 200.\r
+\r
+- tlp 'num'\r
+ This command controls the number of threads to be created when\r
+ Bonana considers a move to make. The command becomes effective\r
+ when TLP macro is defined in the Makefile. 'num' is the number of\r
+ threads. The default value is 1.\r
+\r
+- #\r
+ A line beginning with # causes all characters on that line\r
+ to be ignored.\r
+\r
+- [move command]\r
+ A move command consists of four digits followed by two\r
+ capital alphabets, e.g. 7776FU. The first two digits\r
+ are a starting square and the last two are a target square. The\r
+ starting square is "OO" if the move is a dorp, e.g. 0087FU. The\r
+ following two alphabets specify a piece type as the following,\r
+\r
+ FU - pawn (Fuhyo) TO - promoted pawn (Tokin)\r
+ KY - lance (Kyousha) NY - promoted lance (Narikyo)\r
+ KE - knight (Keima) NK - promoted knight (Narikei)\r
+ GI - silver general (Ginsho) NG - promoted silver (Narigin)\r
+ KI - gold general (Kinsyo)\r
+ KA - Bishop (Kakugyo) UM - Dragon horse (Ryuma)\r
+ HI - Rook (Hisha) RY - Dragon king (Ryuo)\r
+ OU - King (Osho)\r
+\r
+ Here, words in parentheses are romanization of Japanese words.\r
#include <limits.h>
#include "shogi.h"
-static int read_rest_list( tree_t * restrict ptree,
- unsigned int * restrict pmove_list );
-
-static int is_move_rest( unsigned int move,
- const unsigned int * restrict pmove_restraint );
+#if defined(USI) || defined(MNJ_LAN)
+static int is_move_ignore( unsigned int move );
+#endif
int
-make_root_move_list( tree_t * restrict ptree, int flag )
+make_root_move_list( tree_t * restrict ptree )
{
unsigned int * restrict pmove;
- unsigned int arestraint_list[ MAX_LEGAL_MOVES ];
int asort[ MAX_LEGAL_MOVES ];
- unsigned int move, move_best;
+ unsigned int move;
int i, j, k, h, value, num_root_move, iret, value_pre_pv;
int value_best;
- if ( flag & flag_refer_rest ) { read_rest_list( ptree, arestraint_list ); }
- else { arestraint_list[0] = 0; }
-
pmove = ptree->move_last[0];
ptree->move_last[1] = GenCaptures( root_turn, pmove );
ptree->move_last[1] = GenNoCaptures( root_turn, ptree->move_last[1] );
num_root_move = (int)( ptree->move_last[1] - pmove );
value_pre_pv = INT_MIN;
- move_best = 0;
value_best = 0;
for ( i = 0; i < num_root_move; i++ )
{
- if ( ! ( game_status & flag_nopeek )
- && ( game_status & ( flag_puzzling | flag_pondering ) )
- && i != 0
- && ( i % 8 ) == 0 )
- {
- iret = next_cmdline( 0 );
- if ( iret == -1 )
- {
- game_status |= flag_search_error;
- return 1;
- }
- else if ( iret == -2 )
- {
- out_warning( "%s", str_error );
- ShutdownClient;
- }
- else if ( game_status & flag_quit ) { return 1; }
- else if ( iret )
- {
- iret = procedure( ptree );
- if ( iret == -1 )
- {
- game_status |= flag_search_error;
- next_cmdline( 1 );
- return 1;
- }
- else if ( iret == -2 )
- {
- out_warning( "%s", str_error );
- next_cmdline( 1 );
- ShutdownClient;
- }
- else if ( iret == 1 ) { next_cmdline( 1 ); }
-
- if ( game_status & ( flag_quit | flag_quit_ponder
- | flag_suspend ) )
- {
- return 1;
- }
- }
- }
-
value = INT_MIN;
move = pmove[i];
MakeMove( root_turn, move, 1 );
if ( ! InCheck( root_turn )
- && ! is_move_rest( move, arestraint_list ) )
+#if defined(USI) || defined(MNJ_LAN)
+ && ! is_move_ignore( move )
+#endif
+ )
{
iret = no_rep;
if ( InCheck(Flip(root_turn)) )
ptree->current_move[1] = move;
value = -search_quies( ptree, -score_bound, score_bound,
Flip(root_turn), 2, 1 );
- if ( value > value_best )
- {
- value_best = value;
- move_best = move;
- }
+
+ if ( value > value_best ) { value_best = value; }
if ( I2IsPromote(move) ) { value++; }
if ( move == ptree->pv[0].a[1] )
{
UnMakeMove( root_turn, move, 1 );
asort[i] = value;
}
- if ( UToCap(move_best) ) { root_move_cap = 1; }
/* shell sort */
for ( k = SHELL_H_LEN - 1; k >= 0; k-- )
root_move_list[i].move = pmove[i];
root_move_list[i].nodes = 0;
root_move_list[i].status = 0;
+#if defined(DFPN_CLIENT)
+ root_move_list[i].dfpn_cresult = dfpn_client_na;
+#endif
}
if ( value_pre_pv != INT_MIN ) { asort[0] = value_pre_pv; }
root_nmove = num_root_move;
}
-static int
-read_rest_list( tree_t * restrict ptree, unsigned int * restrict pmove_list )
+#if defined(USI) || defined(MNJ_LAN)
+static int CONV
+is_move_ignore( unsigned int move )
{
- FILE *pf;
- int iret, imove;
- char a[65536];
+ int i;
- pf = file_open( "restraint.dat", "r" );
- if ( pf == NULL ) { return -2; }
-
- for ( imove = 0; imove < MAX_LEGAL_MOVES; imove++ )
+ for ( i = 0; moves_ignore[i] != MOVE_NA; i += 1 )
{
-#if defined(_MSC_VER)
- iret = fscanf_s( pf, "%s\n", a, 65536 );
-#else
- iret = fscanf( pf, "%s\n", a );
-#endif
- if ( iret != 1 ) { break; }
- iret = interpret_CSA_move( ptree, pmove_list+imove, a );
- if ( iret < 0 )
- {
- file_close( pf );
- return iret;
- }
+ if ( move == moves_ignore[i] ) { return 1; }
}
-
- pmove_list[imove] = 0;
-
- return file_close( pf );
-}
-
-
-static int
-is_move_rest( unsigned int move,
- const unsigned int * restrict pmove_restraint )
-{
- while ( *pmove_restraint )
- {
- if ( move == *pmove_restraint++ ) { return 1; }
- }
-
+
return 0;
}
+#endif
#endif
#include "shogi.h"
-#if defined(CSA_LAN) || defined(DEKUNOBOU) || defined(MNJ_LAN)
+#if defined(CSA_LAN) || defined(MNJ_LAN) || defined(DFPN)
+void CONV shutdown_all( void )
+{
+# if defined(MNJ_LAN)
+ sckt_shutdown( sckt_mnj );
+ sckt_mnj = SCKT_NULL;
+# endif
+
+# if defined(CSA_LAN)
+ sckt_shutdown( sckt_csa );
+ sckt_csa = SCKT_NULL;
+# endif
+
+# if defined(DFPN)
+ sckt_shutdown( dfpn_sckt );
+ dfpn_sckt = SCKT_NULL;
+# endif
+}
+#endif
+
+
+#if defined(CSA_LAN) || defined(MNJ_LAN) || defined(DFPN_CLIENT)||defined(DFPN)
const char *
str_WSAError( const char *str )
{
#if defined(CSA_LAN)
-int
+int CONV
client_next_game( tree_t * restrict ptree, const char *str_addr, int iport )
{
int iret;
str_buffer_cmdline[0] = '\0';
sckt_csa = sckt_connect( str_addr, iport );
if ( sckt_csa == SCKT_NULL ) { return -2; }
-
+
str_name1 = str_name2 = NULL;
iret = sckt_out( sckt_csa, "LOGIN %s %s\n",
client_str_id, client_str_pwd );
if ( ! memcmp( str_cmdline, "REJECT:", 7 ) )
{
- ShutdownClient;
+ ShutdownAll();
continue;
}
else if ( ! memcmp( str_cmdline, "START:", 6 ) ) { break; }
#endif
-#if defined(CSA_LAN) || defined(MNJ_LAN)
-sckt_t
+#if defined(CSA_LAN)||defined(MNJ_LAN)|| defined(DFPN_CLIENT)|| defined(DFPN)
+sckt_t CONV
sckt_connect( const char *str_addr, int iport )
{
struct hostent *phe;
struct sockaddr_in sin;
sckt_t sd;
u_long ul_addr;
+ int count;
#if defined(_WIN32)
{
return SCKT_NULL;
}
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = ul_addr;
- sin.sin_port = htons( (u_short)iport );
- if ( connect( sd, (struct sockaddr *)&sin, sizeof(sin) ) == SOCKET_ERROR )
- {
- str_error = str_WSAError( "connect() faild." );
-#if defined(_WIN32)
- WSACleanup();
-#endif
- return SCKT_NULL;
- }
+ for ( count = 0;; count += 1 ) {
+
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = ul_addr;
+ sin.sin_port = htons( (u_short)iport );
+ if ( connect( sd, (struct sockaddr *)&sin, sizeof(sin) ) != SOCKET_ERROR )
+ {
+ break;
+ }
+
+ if ( ! count ) { Out( "connect() failed. try again " ); }
+ else { Out( "." ); }
+# if defined(_WIN32)
+ Sleep( 10000 );
+# else
+ sleep( 10 );
+# endif
+ }
+ if ( count ) { Out( "\n" ); }
return sd;
}
-int
+int CONV
sckt_shutdown( sckt_t sd )
{
int iret;
if ( sd == SCKT_NULL ) { return 1; }
- Out( "shut down connection\n" );
+ out_warning( "shut down connection" );
# if defined(_WIN32)
if ( shutdown( sd, SD_SEND ) == SOCKET_ERROR )
{
- str_error = str_WSAError( "shutdown() faild." );
+ str_error = str_WSAError( "shutdown() faild:" );
WSACleanup();
return -2;
}
iret = recv( sd, str_message, SIZE_MESSAGE, 0 );
if ( iret == SOCKET_ERROR )
{
- str_error = str_WSAError( "recv() failed." );
+ str_error = str_WSAError( "recv() failed:" );
WSACleanup();
return -2;
}
if ( closesocket( sd ) == SOCKET_ERROR )
{
- str_error = str_WSAError( "closesocket() failed." );
+ str_error = str_WSAError( "closesocket() failed:" );
WSACleanup();
return -2;
}
if ( WSACleanup() == SOCKET_ERROR )
{
- str_error = str_WSAError( "WSACleanup() faild." );
+ str_error = str_WSAError( "WSACleanup() faild:" );
return -2;
}
return 1;
# else
+
if ( shutdown( sd, SHUT_RD ) == -1 )
{
str_error = "shutdown() faild.";
}
-int
+int CONV sckt_recv_all( sckt_t sd )
+{
+ int iret;
+
+ for ( ;; )
+ {
+# if defined(_WIN32)
+ iret = recv( sd, str_message, SIZE_MESSAGE, 0 );
+ if ( iret == SOCKET_ERROR || ! iret ) { break; }
+# else
+ iret = (int)recv( sd, str_message, SIZE_MESSAGE, 0 );
+ if ( iret == -1 || ! iret ) { break; }
+# endif
+ }
+
+ return 1;
+}
+
+
+int CONV
sckt_check( sckt_t sd )
{
struct timeval tv;
iret = select( (int)sd+1, &readfds, NULL, NULL, &tv );
if ( iret == SOCKET_ERROR )
{
- str_error = str_WSAError( "select() with a socket connected failed." );
+ str_error = str_WSAError( "select() with a socket connected failed:" );
return -2;
}
}
-int
+int CONV
sckt_in( sckt_t sd, char *str, int n )
{
struct timeval tv;
if ( sckt_out( sd, "\n" ) == SOCKET_ERROR )
{
- str_error = str_WSAError( "send() failed." );
+ str_error = str_WSAError( "send() failed:" );
return -1;
}
}
iret = recv( sd, str, n-1, 0 );
if ( iret == SOCKET_ERROR )
{
- str_error = str_WSAError( "recv() failed." );
+ str_error = str_WSAError( "recv() failed:" );
return -1;
}
*( str + iret ) = '\0';
}
-int
+int CONV
sckt_out( sckt_t sd, const char *fmt, ... )
{
int nch;
if ( send( sd, buf, nch, 0 ) == SOCKET_ERROR )
{
- str_error = str_WSAError( "send() failed." );
+ str_error = str_WSAError( "send() failed:" );
return -1;
}
return get_elapsed( &time_last_send );
}
-#endif /* CSA_LAN || MNJ_LAN */
+#endif /* CSA_LAN || MNJ_LAN || DFPN_CLIENT || DFPN */
+
+#if defined(DFPN_CLIENT)
+int CONV
+dfpn_client_out( const char *fmt, ... )
+{
+ int nch, iret;
+ char buf[256];
+ va_list arg;
+
+ if ( dfpn_client_sckt == SCKT_NULL ) { return 1; }
+
+ va_start( arg, fmt );
+ nch = vsnprintf( buf, 256, fmt, arg );
+ va_end( arg );
+
+ if ( nch >= 256 || nch < 0 )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "A connection to DFPN server is down." );
+ return -1;
+ }
+
+ Out( "- send to DFPN server: %s", buf );
+
+ iret = send( dfpn_client_sckt, buf, nch, 0 );
+ if ( iret == SOCKET_ERROR )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "A connection to DFPN server is down." );
+ return -1;
+ }
+
+ return 1;
+}
+#endif /* DFPN_CLIENT */
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <assert.h>
#include "shogi.h"
-static void hist_add( tree_t * restrict ptree, int ply );
-static void hist_good( tree_t * restrict ptree, unsigned int move, int ply,
- int depth, int turn );
-static int detect_signals( tree_t * restrict ptree );
-static int detect_rep( tree_t * restrict ptree, int ply, int turn );
-static int rep_type( const tree_t * restrict ptree, int n, int i, int ply,
- int turn );
+static void CONV hist_add( tree_t * restrict ptree, int ply );
+static void CONV hist_good( tree_t * restrict ptree, unsigned int move,
+ int ply, int depth, int turn );
+static int CONV detect_rep( tree_t * restrict ptree, int ply, int turn );
+static int CONV rep_type( const tree_t * restrict ptree, int n, int i, int ply,
+ int turn );
/* #define DBG_SEARCH */
#if defined(DBG_SEARCH)
# define DOut( ... )
#endif
-int
+int CONV
search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
int ply, unsigned int state_node )
{
int value, alpha_old;
- if ( ! ptree->nsuc_check[ply] && depth < PLY_INC )
+ if ( ! ptree->nsuc_check[ply] && depth < PLY_INC )
{
return search_quies( ptree, alpha, beta, turn, ply, 1 );
}
}
break;
}
-
- ptree->nreject_tried++;
- if ( rejections_probe( ptree, turn, ply ) )
- {
- ptree->nreject_done++;
- if ( alpha < score_inferior && score_inferior < beta )
- {
- pv_close( ptree, ply, turn ? white_superi_rep:black_superi_rep );
- }
- MOVE_CURR = MOVE_NA;
- return score_inferior;
- }
}
/*
if ( value <= alpha ) { return value; }
}
-#if defined(NO_NULL_PRUNE)
- state_node &= ~node_do_null;
-#endif
-
ptree->amove_hash[ply] = 0;
+
#if ! defined(MINIMUM)
if ( ! ( game_status & flag_learning ) )
#endif
{
/* probe the transposition table */
- int tv = hash_probe( ptree, ply, depth, turn, alpha, beta, state_node );
- switch ( tv )
+ switch ( hash_probe( ptree, ply, depth, turn, alpha, beta,
+ &state_node ) )
{
case value_exact:
- if ( alpha < HASH_VALUE )
+ MOVE_CURR = ptree->amove_hash[ply];
+ assert( ! IsMove(MOVE_CURR)
+ || is_move_valid( ptree, MOVE_CURR, turn ) );
+ if ( ( state_node & node_do_hashcut ) && beta == alpha_old + 1 )
{
- if ( HASH_VALUE < beta ) { pv_close( ptree, ply, hash_hit ); }
- else {
- MOVE_CURR = ptree->amove_hash[ply];
- assert( is_move_valid( ptree, MOVE_CURR, turn ) );
- }
+ if ( alpha < HASH_VALUE
+ && HASH_VALUE < beta ) { pv_close( ptree, ply, hash_hit ); }
+ return HASH_VALUE;
}
- return HASH_VALUE;
-
+ break;
+
case value_lower:
MOVE_CURR = ptree->amove_hash[ply];
assert( beta <= HASH_VALUE );
assert( ! IsMove(MOVE_CURR)
|| is_move_valid( ptree, MOVE_CURR, turn ) );
- if ( beta == alpha_old + 1 ) { return HASH_VALUE; }
+ if ( ( state_node & node_do_hashcut )
+ && beta == alpha_old + 1 ) { return HASH_VALUE; }
break;
case value_upper:
assert( HASH_VALUE <= alpha );
- if ( beta == alpha_old + 1 ) { return HASH_VALUE; }
+ if ( ( state_node & node_do_hashcut )
+ && beta == alpha_old + 1 ) { return HASH_VALUE; }
break;
-
- default:
- state_node = tv;
}
}
DOut( "\nhash cut passed" );
- if ( depth >= REJEC_MIN_DEPTH ) { add_rejections( ptree, turn, ply ); }
-
if ( ! ptree->nsuc_check[ply] )
{
if ( alpha < value
&& value < beta ) { pv_close( ptree, ply, mate_search ); }
- if ( depth >= REJEC_MIN_DEPTH )
- {
- sub_rejections( ptree, turn, ply );
- }
assert( is_move_valid( ptree, MOVE_CURR, turn ) );
return value;
}
int null_depth, nrep;
null_depth = NullDepth(depth);
- nrep = root_nrep + ply - 1;
+ nrep = ptree->nrep + ply - 1;
MOVE_CURR = MOVE_PASS;
ptree->move_last[ply] = ptree->move_last[ply-1];
- ptree->stand_pat[ply+1] = (short)( - ptree->stand_pat[ply] );
+ ptree->save_eval[ply+1] = - ptree->save_eval[ply];
ptree->nsuc_check[ply+1] = 0;
ptree->rep_board_list[nrep] = HASH_KEY;
ptree->rep_hand_list[nrep] = HAND_B;
ptree->null_pruning_tried++;
value = -search( ptree, -beta, 1-beta, Flip(turn), null_depth, ply+1,
- node_do_mate | node_do_recap | node_do_futile );
- if ( SEARCH_ABORT )
- {
- if ( depth >= REJEC_MIN_DEPTH )
- {
- sub_rejections( ptree, turn, ply );
- }
- return 0;
- }
+ node_do_mate | node_do_recap | node_do_futile
+ | node_do_recursion | node_do_hashcut );
+ if ( SEARCH_ABORT ) { return 0; }
if ( beta <= value )
{
hash_store( ptree, ply, depth, turn, value_lower,
value, MOVE_NA, state_node );
}
- if ( depth >= REJEC_MIN_DEPTH )
- {
- sub_rejections( ptree, turn, ply );
- }
DOut( "\nnull move cut!\n" );
}
}
- /* recursive iterative-deepening for pv nodes */
- if ( ! ptree->amove_hash[ply]
- && depth >= 3*PLY_INC
- && ( ( alpha == root_alpha && beta == root_beta )
- || ( alpha == -root_beta && beta == -root_alpha ) ) )
+ /* recursive iterative-deepening */
+ if ( ! ptree->amove_hash[ply] && RecursionThreshold <= depth
+ && ( state_node & node_do_recursion ) )
{
- if ( depth >= REJEC_MIN_DEPTH ) { sub_rejections( ptree, turn, ply ); }
- value = search( ptree, -score_bound, beta, turn, depth-2*PLY_INC, ply,
- node_do_mate | node_do_recap );
+ int new_depth = RecursionDepth(depth);
+ int state_node_new = state_node & ~( node_do_mate | node_do_null
+ | node_do_hashcut );
+
+ value = search( ptree, alpha, beta, turn, new_depth, ply,
+ state_node_new );
if ( SEARCH_ABORT ) { return 0; }
- if ( beta <= value && IsMove(MOVE_CURR) )
- {
- ptree->amove_hash[ply] = MOVE_CURR;
- }
- else if ( value < beta && ply <= (int)ptree->pv[ply-1].length )
+ if ( beta <= value ) { ptree->amove_hash[ply] = MOVE_CURR; }
+ else if ( alpha < value )
{
+ assert( ply <= (int)ptree->pv[ply-1].length );
assert( -score_bound < value );
ptree->amove_hash[ply] = ptree->pv[ply-1].a[ply];
}
+
assert( ! ptree->amove_hash[ply]
|| is_move_valid( ptree, ptree->amove_hash[ply], turn ) );
- if ( depth >= REJEC_MIN_DEPTH ) { add_rejections( ptree, turn, ply ); }
}
{
ptree->nsuc_check[ply+1] = 0U;
state_node_new = ( node_do_mate | node_do_recap | node_do_null
- | node_do_futile );
+ | node_do_futile | node_do_recursion
+ | node_do_hashcut );
extension = 0;
depth_reduced = 0;
hist_add( ptree, ply );
/* decision of extensions */
- if ( turn ? is_move_check_w( ptree, MOVE_CURR )
- : is_move_check_b( ptree, MOVE_CURR ) )
+ if ( IsMoveCheck( ptree, turn, MOVE_CURR ) )
{
ptree->check_extension_done++;
ptree->nsuc_check[ply+1]
&& I2PieceMove(MOVE_LAST) != silver ) ) )
{
ptree->recap_extension_done++;
- state_node_new = node_do_null | node_do_mate | node_do_futile;
+ state_node_new = ( node_do_null | node_do_mate | node_do_futile
+ | node_do_recursion | node_do_hashcut );
if ( ! I2IsPromote(MOVE_CURR)
&& I2PieceMove(MOVE_LAST) == UToCap(MOVE_LAST) )
{
/* reductions */
if ( PLY_INC <= new_depth
+ && first_move_expanded
&& ! ( state_node & node_mate_threat )
&& ! ptree->nsuc_check[ply]
&& ! UToCap(MOVE_CURR)
unsigned int triedx8 = ( ptree->hist_tried[key] + 2 ) * 8U;
if ( beta != alpha_old + 1 ) {
-
- if ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
- else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
- else if ( good * 34U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
+
+ if ( good *160U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
+ else if ( good * 50U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
else if ( good * 19U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
-
+
} else {
- if ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
+ if ( good * 75U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
else if ( good * 30U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
else if ( good * 12U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
new_depth -= depth_reduced;
}
-
+
/* futility pruning */
if ( ! ptree->nsuc_check[ply+1]
&& ! ptree->nsuc_check[ply]
if ( 2*PLY_INC <= new_depth ) { bound -= EFUTIL_MG2; }
else if ( 1*PLY_INC <= new_depth ) { bound -= EFUTIL_MG1; }
- if ( eval_max_score( ptree, MOVE_CURR, ptree->stand_pat[ply],
+ if ( eval_max_score( ptree, MOVE_CURR, ptree->save_eval[ply],
turn, diff ) <= bound )
{
first_move_expanded += 1;
DOut( ", futil passed" );
+ if ( new_depth < 2*PLY_INC
+ && ! ptree->nsuc_check[ply]
+ && ! ptree->nsuc_check[ply+1]
+ && ! UToCap(MOVE_CURR)
+ && ! ( I2IsPromote(MOVE_CURR)
+ && I2PieceMove(MOVE_CURR) != silver )
+ && ptree->amove_hash[ply] != MOVE_CURR
+ && ptree->killers[ply].no1 != MOVE_CURR
+ && ptree->killers[ply].no2 != MOVE_CURR
+ && beta == alpha_old + 1
+ && swap( ptree, MOVE_CURR, -1, 0, turn ) <= -1 )
+ {
+ first_move_expanded += 1;
+ continue;
+ }
+
MakeMove( turn, MOVE_CURR, ply );
if ( I2From(MOVE_CURR) < nsquare
&& ! ptree->nsuc_check[ply]
if ( ! ptree->nsuc_check[ply+1] && ! ptree->nsuc_check[ply] )
{
- evaluate( ptree, ply+1, Flip(turn) );
- assert( ptree->stand_pat[ply] != score_bound );
+ int score = -evaluate( ptree, ply+1, Flip(turn) );
+ assert( ptree->save_eval[ply] != INT_MAX );
/* futility pruning */
- if ( ( new_depth < PLY_INC && - ptree->stand_pat[ply+1] <= alpha )
- || ( new_depth < 2*PLY_INC
- && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG1 )
- || ( new_depth < 3*PLY_INC
- && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG2 ) )
+ if ( ( new_depth < PLY_INC && score <= alpha )
+ || ( new_depth < 2*PLY_INC && score <= alpha - EFUTIL_MG1 )
+ || ( new_depth < 3*PLY_INC && score <= alpha - EFUTIL_MG2 ) )
{
first_move_expanded += 1;
UnMakeMove( turn, MOVE_CURR, ply );
}
}
- if ( depth_reduced )
- {
- value = -search( ptree, -alpha-1, -alpha, Flip(turn), new_depth,
- ply + 1, state_node_new );
- if ( ! SEARCH_ABORT && alpha < value )
- {
- new_depth += depth_reduced;
- value = -search( ptree, -beta, -alpha, Flip(turn), new_depth,
- ply+1, state_node_new );
- }
- }
- else if ( ! first_move_expanded )
+ if ( ! first_move_expanded )
{
value = -search( ptree, -beta, -alpha, Flip(turn), new_depth, ply+1,
state_node_new );
else {
value = -search( ptree, -alpha-1, -alpha, Flip(turn), new_depth,
ply + 1, state_node_new );
+ if ( ! SEARCH_ABORT && alpha < value && depth_reduced )
+ {
+ new_depth += depth_reduced;
+ value = -search( ptree, -alpha-1, -alpha, Flip(turn), new_depth,
+ ply+1, state_node_new );
+ }
if ( ! SEARCH_ABORT && alpha < value && beta != alpha+1 )
{
value = -search( ptree, -beta, -alpha, Flip(turn), new_depth,
ply + 1, state_node_new );
}
}
-
if ( SEARCH_ABORT )
{
UnMakeMove( turn, MOVE_CURR, ply );
- if ( depth >= REJEC_MIN_DEPTH )
- {
- sub_rejections( ptree, turn, ply );
- }
return 0;
}
{
if ( new_depth < PLY_INC
&& ! ptree->nsuc_check[ply+1]
- && ptree->stand_pat[ply] != score_bound )
+ && ptree->save_eval[ply] != INT_MAX )
{
check_futile_score_quies( ptree, MOVE_CURR,
- ptree->stand_pat[ply],
- -ptree->stand_pat[ply+1], turn );
+ ptree->save_eval[ply],
+ -ptree->save_eval[ply+1], turn );
}
if ( beta <= value )
ptree->fail_high++;
if ( ! first_move_expanded ) { ptree->fail_high_first++; }
- if ( depth >= REJEC_MIN_DEPTH )
- {
- sub_rejections( ptree, turn, ply );
- }
-
assert( is_move_valid( ptree, MOVE_CURR, turn ) );
return value;
}
{
if ( beta <= value )
{
- if ( depth >= REJEC_MIN_DEPTH )
- {
- sub_rejections( ptree, turn, ply );
- }
-
hash_store( ptree, ply, depth, turn, value_lower,
value, MOVE_CURR, state_node );
DOut( "\nall searched (%" PRIu64 ")\n", ptree->node_searched );
- if ( depth >= REJEC_MIN_DEPTH ) { sub_rejections( ptree, turn, ply ); }
-
if ( ! first_move_expanded )
{
#if ! defined(MINIMUM)
#if defined(TLP)
-int
+int CONV
tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
int depth, int ply, unsigned int state_node )
{
for ( ;; ) {
lock( & ptree->tlp_ptree_parent->tlp_lock );
+ if ( ptree->tlp_abort )
+ {
+ unlock( & ptree->tlp_ptree_parent->tlp_lock );
+ return 0;
+ }
if ( ptree->nsuc_check[ply] )
{
iret = gen_next_evasion( ptree->tlp_ptree_parent, ply, turn );
}
else { iret = gen_next_move( ptree->tlp_ptree_parent, ply, turn ); }
+
MOVE_CURR = ptree->tlp_ptree_parent->current_move[ply];
hist_add( ptree->tlp_ptree_parent, ply );
unlock( & ptree->tlp_ptree_parent->tlp_lock );
ptree->nsuc_check[ply+1] = 0U;
state_node_new = ( node_do_mate | node_do_recap | node_do_null
- | node_do_futile );
+ | node_do_futile | node_do_recursion
+ | node_do_hashcut );
extension = 0;
depth_reduced = 0;
- if ( turn ? is_move_check_w( ptree, MOVE_CURR )
- : is_move_check_b( ptree, MOVE_CURR ) )
+ if ( IsMoveCheck( ptree, turn, MOVE_CURR ) )
{
ptree->check_extension_done++;
ptree->nsuc_check[ply+1]
&& I2PieceMove(MOVE_LAST) != silver ) ) )
{
ptree->recap_extension_done++;
- state_node_new = node_do_null | node_do_mate | node_do_futile;
+ state_node_new = ( node_do_null | node_do_mate | node_do_futile
+ | node_do_recursion | node_do_hashcut );
if ( ! I2IsPromote(MOVE_CURR)
&& I2PieceMove(MOVE_LAST) == UToCap(MOVE_LAST) )
{
if ( beta != alpha_old + 1 ) {
- if ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
- else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
- else if ( good * 34U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
+ if ( good *160U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
+ else if ( good * 50U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
else if ( good * 19U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
} else {
- if ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
+ if ( good * 75U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
else if ( good * 30U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
else if ( good * 12U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
if ( 2*PLY_INC <= new_depth ) { bound -= EFUTIL_MG2; }
else if ( 1*PLY_INC <= new_depth ) { bound -= EFUTIL_MG1; }
- if ( eval_max_score( ptree, MOVE_CURR, ptree->stand_pat[ply],
+ if ( eval_max_score( ptree, MOVE_CURR, ptree->save_eval[ply],
turn, diff ) <= bound )
{
continue;
if ( ! ptree->nsuc_check[ply+1] && ! ptree->nsuc_check[ply] )
{
- evaluate( ptree, ply+1, Flip(turn) );
- assert( ptree->stand_pat[ply] != score_bound );
+ int score = -evaluate( ptree, ply+1, Flip(turn) );
+ assert( ptree->save_eval[ply] != INT_MAX );
/* futility pruning */
- if ( ( new_depth < PLY_INC && - ptree->stand_pat[ply+1] <= alpha )
- || ( new_depth < 2*PLY_INC
- && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG1 )
- || ( new_depth < 3*PLY_INC
- && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG2 ) )
+ if ( ( new_depth < PLY_INC && score <= alpha )
+ || ( new_depth < 2*PLY_INC && score <= alpha - EFUTIL_MG1 )
+ || ( new_depth < 3*PLY_INC && score <= alpha - EFUTIL_MG2 ) )
{
UnMakeMove( turn, MOVE_CURR, ply );
continue;
}
#endif /* TLP */
+void CONV
+pv_close( tree_t * restrict ptree, int ply, int type )
+{
+ ptree->pv[ply-1].a[ply-1] = (ptree)->current_move[ply-1];
+ ptree->pv[ply-1].length = (unsigned char)(ply-1);
+ ptree->pv[ply-1].type = (unsigned char)type;
+ ptree->pv[ply-1].depth = (unsigned char)iteration_depth;
+}
+
+void CONV
+pv_copy( tree_t * restrict ptree, int ply )
+{
+ memcpy( &(ptree->pv[ply-1].a[ply]), &(ptree->pv[ply].a[ply]),
+ ( ptree->pv[ply].length-ply+1 ) * sizeof(unsigned int) );
+ ptree->pv[ply-1].type = ptree->pv[ply].type;
+ ptree->pv[ply-1].length = ptree->pv[ply].length;
+ ptree->pv[ply-1].depth = ptree->pv[ply].depth;
+ ptree->pv[ply-1].a[ply-1] = ptree->current_move[ply-1];
+}
+
-static int
+int CONV
detect_signals( tree_t * restrict ptree )
{
unsigned int tnow, telapsed, tpondered, tsearched, tcount, tlimit, tmax;
- unsigned int tmax_limit_count, tlimit_count, u;
+ unsigned int tlimit_count, u;
int iret, easy_time, last_value, stable;
+#if defined(DFPN_CLIENT)
+ int is_first_move_skipped = 0;
+#endif
+
+#if defined(DFPN_CLIENT)
+ /* probe results from DFPN server */
+ if ( dfpn_client_flag_read )
+ {
+ dfpn_client_check_results();
+ if ( dfpn_client_move_unlocked != MOVE_NA ) { return 1; }
+ if ( root_move_list[root_index].dfpn_cresult == dfpn_client_win )
+ {
+ is_first_move_skipped = 1;
+ }
+ }
+#endif
+
+
if ( ! ( game_status & flag_nopeek ) )
{
/* peek input-buffer to find a command */
else if ( iret == -2 )
{
out_warning( "%s", str_error );
- ShutdownClient;
+ ShutdownAll();
}
else if ( game_status & flag_quit ) { return 1; } /* EOF */
else if ( iret )
{
out_warning( "%s", str_error );
next_cmdline( 1 );
- ShutdownClient;
+ ShutdownAll();
}
else if ( iret == 1 ) { next_cmdline( 1 ); }
}
#endif
-#if defined(MNJ_LAN)
- if ( sckt_mnj != SCKT_NULL && 500U < tnow - time_last_send )
+#if defined(USI)
+ if ( usi_mode != usi_off && 1000U + usi_time_out_last < tnow )
{
uint64_t nodes;
+ double dnps;
# if defined(TLP)
lock( &tlp_lock );
nodes = ptree->node_searched;
# endif
- if ( sckt_out( sckt_mnj, "pid=%d n=%" PRIu64 "\n", mnj_posi_id,
- nodes ) < 0 )
- {
- game_status |= flag_search_error;
- return 1;
- }
+ dnps = (double)nodes * 1000.0 / (double)( tnow - time_turn_start );
+ USIOut( "info time %u nodes %" PRIu64 " nps %d\n",
+ tnow, nodes, (unsigned int)dnps );
+
+ usi_time_out_last = tnow;
+ }
+#endif
+
+#if defined(MNJ_LAN)
+ if ( sckt_mnj != SCKT_NULL && 500U + time_last_send < tnow )
+ {
+ uint64_t nodes;
+
+# if defined(TLP)
+ lock( &tlp_lock );
+ nodes = tlp_count_node( tlp_atree_work );
+ unlock( &tlp_lock );
+# else
+ nodes = ptree->node_searched;
+# endif
+
+ MnjOut( "pid=%d n=%" PRIu64 "\n", mnj_posi_id, nodes );
}
#endif
if ( tlimit != tmax )
{
tcount = tsearched;
- tmax_limit_count = tmax;
tlimit_count = tlimit;
}
else {
tcount = telapsed;
- tmax_limit_count = tmax + tpondered;
tlimit_count = tlimit + tpondered;
}
if ( stable && tcount > tlimit ) { return 1; }
if ( stable
- && ( tmax_limit_count * 3U < ( time_last_search - time_start ) * 5U ) )
- {
-#if defined(DBG_EASY)
- if ( ! easy_move )
- {
- Out( " The search can be terminated "
- "before it reaches time-limit.\n" );
- easy_move = ptree->pv[0].a[1];
- }
-#else
- Out( " The search is terminated before it reaches time-limit.\n" );
- return 1;
-#endif
- }
-
- if ( stable
&& easy_abs > abs( last_value )
&& easy_min < last_value - easy_value
&& easy_max > last_value - easy_value )
else if ( tsearched + 500U > u ) { easy_time = 1; }
}
- /* renew node_per_second */
+ /* update node_per_second */
{
double dn, dd;
else { node_per_second = u; }
}
- /* renew node_next_signal */
+ /* update node_next_signal */
if ( ! ( game_status & flag_pondering ) && root_nmove == 1 )
{
u = 2000U - time_response;
}
else { node_next_signal = node_per_second / 32U; }
- /* renew time_last_check and node_last_check */
+ /* update time_last_check and node_last_check */
time_last_check = tnow;
node_last_check = 0;
-
- return 0;
-}
-
-int
-is_move_check_b( const tree_t * restrict ptree, unsigned int move )
-{
- const int from = (int)I2From(move);
- const int to = (int)I2To(move);
- int is_check, ipiece_move, idirec;
- bitboard_t bb;
-
- is_check = 0;
-
- if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
- else {
- ipiece_move = (int)I2PieceMove(move);
- if ( I2IsPromote(move) ) { ipiece_move += promote; }
-
- idirec = (int)adirec[SQ_WKING][from];
- if ( idirec && idirec != (int)adirec[SQ_WKING][to]
- && is_pinned_on_white_king( ptree, from, idirec ) )
- {
- is_check = 1;
- goto end;
- }
- }
-
- switch ( ipiece_move )
+#if defined(DFPN_CLIENT)
+ if ( is_first_move_skipped )
{
- case pawn:
- if ( BOARD[to-nfile] == -king ) { is_check = 1; }
- break;
-
- case lance:
- AttackBLance( bb, to );
- if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
- break;
-
- case knight:
- if ( BBContract(abb_b_knight_attacks[to],BB_WKING) ) { is_check = 1; }
- break;
-
- case silver:
- if ( BBContract(abb_b_silver_attacks[to],BB_WKING) ) { is_check = 1; }
- break;
-
- case gold: case pro_pawn:
- case pro_lance: case pro_knight:
- case pro_silver:
- if ( BBContract(abb_b_gold_attacks[to],BB_WKING) ) { is_check = 1; }
- break;
-
- case bishop:
- AttackBishop( bb, to );
- if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
- break;
-
- case rook:
- AttackRook( bb, to );
- if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
- break;
-
- case king:
- break;
-
- case horse:
- AttackHorse( bb, to );
- if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
- break;
-
- default:
- assert( ipiece_move == dragon );
- AttackDragon( bb, to );
- if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
- break;
- }
-
- end:
- return is_check;
-}
-
-
-int
-is_move_check_w( const tree_t * restrict ptree, unsigned int move )
-{
- const int from = (int)I2From(move);
- const int to = (int)I2To(move);
- int is_check, ipiece_move, idirec;
- bitboard_t bb;
-
- is_check = 0;
-
- if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
- else {
- ipiece_move = (int)I2PieceMove(move);
- if ( I2IsPromote(move) ) { ipiece_move += promote; }
-
- idirec = (int)adirec[SQ_BKING][from];
- if ( idirec && idirec != (int)adirec[SQ_BKING][to]
- && is_pinned_on_black_king( ptree, from, idirec ) )
- {
- is_check = 1;
- goto end;
- }
- }
-
- switch ( ipiece_move )
- {
- case pawn:
- if ( BOARD[to+nfile] == king ) { is_check = 1; }
- break;
-
- case lance:
- AttackWLance( bb, to );
- if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
- break;
-
- case knight:
- if ( BBContract(abb_w_knight_attacks[to],BB_BKING) ) { is_check = 1; }
- break;
-
- case silver:
- if ( BBContract(abb_w_silver_attacks[to],BB_BKING) ) { is_check = 1; }
- break;
-
- case gold: case pro_pawn:
- case pro_lance: case pro_knight:
- case pro_silver:
- if ( BBContract(abb_w_gold_attacks[to],BB_BKING) ) { is_check = 1; }
- break;
-
- case bishop:
- AttackBishop( bb, to );
- if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
- break;
-
- case rook:
- AttackRook( bb, to );
- if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
- break;
-
- case king:
- break;
-
- case horse:
- AttackHorse( bb, to );
- if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
- break;
-
- default:
- assert( ipiece_move == dragon );
- AttackDragon( bb, to );
- if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
- break;
+ game_status |= flag_skip_root_move;
+ return 1;
}
-
- end:
- return is_check;
-}
-
-
-void
-pv_close( tree_t * restrict ptree, int ply, int type )
-{
- ptree->pv[ply-1].a[ply-1] = (ptree)->current_move[ply-1];
- ptree->pv[ply-1].length = (unsigned char)(ply-1);
- ptree->pv[ply-1].type = (unsigned char)type;
- ptree->pv[ply-1].depth = (unsigned char)iteration_depth;
-}
-
-
-void
-pv_copy( tree_t * restrict ptree, int ply )
-{
- memcpy( &(ptree->pv[ply-1].a[ply]), &(ptree->pv[ply].a[ply]),
- ( ptree->pv[ply].length-ply+1 ) * sizeof(unsigned int) );
- ptree->pv[ply-1].type = ptree->pv[ply].type;
- ptree->pv[ply-1].length = ptree->pv[ply].length;
- ptree->pv[ply-1].depth = ptree->pv[ply].depth;
- ptree->pv[ply-1].a[ply-1] = ptree->current_move[ply-1];
+#endif
+
+ return 0;
}
-static int
+static int CONV
detect_rep( tree_t * restrict ptree, int ply, int turn )
{
if ( ply < 4 ) { return detect_repetition( ptree, ply, turn, 2 ); }
else {
int n, i, imin, iret;
- n = root_nrep + ply - 1;
+ n = ptree->nrep + ply - 1;
imin = n - REP_MAX_PLY;
if ( imin < 0 ) { imin = 0; }
}
-static int
+static int CONV
rep_type( const tree_t * restrict ptree, int n, int i, int ply, int turn )
{
const unsigned int hand1 = HAND_B;
}
-static void
+static void CONV
hist_add( tree_t * restrict ptree, int ply )
{
if ( ptree->nsuc_check[ply] ) { return; }
}
-static void
+static void CONV
hist_good( tree_t * restrict ptree, unsigned int move_good, int ply,
int depth, int turn )
{
#include <limits.h>
#include "shogi.h"
-static int find_root_move( unsigned int move );
-static int save_result( tree_t * restrict ptree, int value, int beta,
- int turn );
+static int CONV save_result( tree_t * restrict ptree, int value, int beta,
+ int turn );
#if defined(MPV)
-static int mpv_set_bound( int alpha );
-static int mpv_find_min( int *pnum );
-static int mpv_add_result( tree_t * restrict ptree, int value );
-static void mpv_sub_result( unsigned int move );
-static void mpv_out( tree_t * restrict ptree, int turn, unsigned int time );
+static int CONV mpv_set_bound( int alpha );
+static int CONV mpv_find_min( int *pnum );
+static int CONV mpv_add_result( tree_t * restrict ptree, int value );
+static void CONV mpv_sub_result( unsigned int move );
+static void CONV mpv_out( tree_t * restrict ptree, int turn,
+ unsigned int time );
#endif
#if defined(NO_STDOUT) && defined(NO_LOGGING)
# define NextRootMove(a,b) next_root_move(a)
-static int next_root_move( tree_t * restrict ptree );
+static int CONV next_root_move( tree_t * restrict ptree );
#else
# define NextRootMove(a,b) next_root_move(a,b)
-static int next_root_move( tree_t * restrict ptree, int turn );
+static int CONV next_root_move( tree_t * restrict ptree, int turn );
#endif
-int
+static int CONV
+search_wrapper( tree_t * restrict ptree, int alpha, int beta, int turn,
+ int depth, int ply, unsigned int state_node )
+{
+ int value;
+
+#if defined(DFPN_CLIENT)
+ /* try beta cut using results from DFPN server */
+ if ( root_move_list[root_index].dfpn_cresult == dfpn_client_win )
+ {
+ if ( ! root_index ) { Out( "- best move is proofed, skip.\n" ); }
+ ptree->pv[1].a[1] = MOVE_LAST;
+ ptree->pv[1].length = 1;
+ ptree->pv[1].depth = 0;
+ ptree->pv[1].type = no_rep;
+ MOVE_CURR = MOVE_NA;
+ return score_matelong;
+ }
+#endif
+
+ value = search( ptree, alpha, beta, turn, depth, ply, state_node );
+
+#if defined(DFPN_CLIENT)
+ /* catch a signal, i.e., the first move has to be ignored */
+ if ( game_status & flag_skip_root_move )
+ {
+ if ( root_index )
+ {
+ Out( "- %s is proofed while searching.\n", str_CSA_move(MOVE_LAST) );
+ }
+ else {
+ Out( "- %s (best move) is proofed while searching.\n",
+ str_CSA_move(MOVE_LAST) );
+ }
+
+ game_status &= ~flag_skip_root_move;
+ root_abort = 0;
+
+ ptree->pv[1].a[1] = MOVE_LAST;
+ ptree->pv[1].length = 1;
+ ptree->pv[1].depth = 0;
+ ptree->pv[1].type = no_rep;
+ MOVE_CURR = MOVE_NA;
+ return score_matelong;
+ }
+#endif
+
+ return value;
+}
+
+
+int CONV
searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth )
{
uint64_t root_nodes_start;
- int value, first_move_expanded, i;
+ int value, first_move;
int new_depth, extension, ply, state_node_new;
#if defined(MPV)
int bound = INT_MIN;
#endif
+#if defined(USI)
+ char str_usi[6];
+#endif
- first_move_expanded = 1;
+ first_move = 1;
ply = 1;
ptree->move_last[1] = ptree->move_last[0];
while( NextRootMove( ptree, turn ) )
{
root_nodes_start = ptree->node_searched;
+#if defined(USI)
+ if ( usi_mode != usi_off )
+ {
+ csa2usi( ptree, str_CSA_move(MOVE_CURR), str_usi );
+ }
+#endif
+
MakeMove( turn, MOVE_CURR, 1 );
assert( ! InCheck( turn ) );
state_node_new = ( node_do_mate | node_do_null | node_do_futile
- | node_do_recap );
+ | node_do_recap | node_do_recursion
+ | node_do_hashcut );
if ( InCheck(Flip(turn)) )
{
ptree->check_extension_done++;
ptree->nsuc_check[2] = 0;
}
- if ( first_move_expanded )
+ if ( first_move )
{
#if defined(MPV)
if ( root_mpv ) { bound = alpha; }
#endif
new_depth = depth + extension;
- value = -search( ptree, -beta, -alpha, Flip(turn), new_depth, 2,
- state_node_new );
+ value = -search_wrapper( ptree, -beta, -alpha, Flip(turn),
+ new_depth, 2, state_node_new );
if ( root_abort )
{
UnMakeMove( turn, MOVE_CURR, 1 );
return value;
}
- first_move_expanded = 0;
+ first_move = 0;
}
#if defined(MPV)
else if ( root_mpv )
{
new_depth = depth + extension;
- value = -search( ptree, -bound-1, -bound, Flip(turn), new_depth,
- 2, state_node_new );
+ value = -search_wrapper( ptree, -bound-1, -bound, Flip(turn),
+ new_depth, 2, state_node_new );
if ( ! root_abort && bound < value )
{
new_depth = depth + extension;
- value = -search( ptree, -beta, -bound, Flip(turn), new_depth,
- 2, state_node_new );
+ value = -search_wrapper( ptree, -beta, -bound, Flip(turn),
+ new_depth, 2, state_node_new );
}
if ( root_abort )
{
}
#endif /* MPV */
else {
- new_depth = depth + extension;
-
- value = -search( ptree, -alpha-1, -alpha, Flip(turn), new_depth, 2,
- state_node_new );
+ int depth_reduced = 0;
+ new_depth = depth + extension;
+
+ /* reductions */
+ if ( 2*PLY_INC <= new_depth
+ && ! ptree->nsuc_check[ply]
+ && ! UToCap(MOVE_CURR)
+ && ! ( I2IsPromote(MOVE_CURR)
+ && I2PieceMove(MOVE_CURR) != silver ) )
+ {
+ unsigned int key = phash( MOVE_CURR, turn );
+ unsigned int good = ptree->hist_good[key] + 1;
+ unsigned int triedx8 = ( ptree->hist_tried[key] + 2 ) * 8U;
+
+ if ( good *160U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
+ else if ( good * 50U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
+ else if ( good * 19U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
+
+ depth_reduced = PLY_INC;
+ new_depth -= depth_reduced;
+ }
+
+ value = -search_wrapper( ptree, -alpha-1, -alpha, Flip(turn),
+ new_depth, 2, state_node_new );
+ if ( ! root_abort && alpha < value && depth_reduced )
+ {
+ new_depth += depth_reduced;
+ value = -search_wrapper( ptree, -alpha-1, -alpha, Flip(turn),
+ new_depth, 2, state_node_new );
+ }
if ( root_abort )
{
UnMakeMove( turn, MOVE_CURR, 1 );
return 0;
}
+
if ( alpha < value )
{
- MnjOut( "pid=%d move=%s v=%dl n=% " PRIu64 " \n",
+#if defined(DFPN_CLIENT)
+ if ( dfpn_client_sckt != SCKT_NULL
+ && 4 < iteration_depth
+ && dfpn_client_best_move != MOVE_CURR )
+ {
+ dfpn_client_best_move = MOVE_CURR;
+ lock( &dfpn_client_lock );
+ dfpn_client_out( "BEST MOVE %s\n",
+ str_CSA_move(dfpn_client_best_move) );
+ unlock( &dfpn_client_lock );
+ }
+#endif
+ MnjOut( "pid=%d move=%s v=%dl n=% " PRIu64 "%s\n",
mnj_posi_id, str_CSA_move(MOVE_CURR), alpha+1,
- ptree->node_searched );
+ ptree->node_searched,
+ ( mnj_depth_stable <= iteration_depth ) ? " stable" : "" );
+
+#if defined(USI)
+ if ( usi_mode != usi_off )
+ {
+ USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv %s\n",
+ iteration_depth, alpha+1, ptree->node_searched,
+ str_usi );
+ }
+#endif
new_depth = depth + extension;
easy_abs = 0;
- value = -search( ptree, -beta, -alpha, Flip(turn), new_depth,
- 2, state_node_new );
+ value = -search_wrapper( ptree, -beta, -alpha, Flip(turn),
+ new_depth, 2, state_node_new );
if ( root_abort )
{
const char *str;
UnMakeMove( turn, MOVE_CURR, 1 );
pv_close( ptree, 2, pv_fail_high );
time_last_result = time_last_check;
- time_last_eff_search = time_last_search;
root_value = alpha+1;
ptree->pv[0] = ptree->pv[1];
if ( turn )
dvalue = alpha;
ch = '+';
}
- str = str_CSA_move_plus( ptree, MOVE_CURR, 1, turn );
+ str = str_CSA_move(MOVE_CURR);
Out( " %7.2f 1.%c%s [%c0!]\n",
dvalue / 100.0, ch, str, ch );
if ( game_status & flag_pondering )
UnMakeMove( turn, MOVE_CURR, 1 );
- i = find_root_move( MOVE_CURR );
- root_move_list[i].nodes = ptree->node_searched - root_nodes_start;
+ root_move_list[root_index].nodes
+ = ptree->node_searched - root_nodes_start;
#if defined(MPV)
if ( root_mpv && value < beta )
if ( bound < value && mpv_add_result( ptree, value ) < 0 )
{
game_status |= flag_search_error;
- return 1;
+ return 0;
}
}
#endif
if ( save_result( ptree, value, beta, turn ) < 0 )
{
game_status |= flag_search_error;
- return 1;
- }
- if ( beta <= value )
- {
- hash_store( ptree, 1, depth, turn, value_lower, value,
- MOVE_CURR, 0 );
- return value;
+ return 0;
}
+ if ( beta <= value ) { return value; }
alpha = value;
}
}
if ( root_abort ) { return 0; }
-#if ! defined(MINIMUM)
- if ( ! ( game_status & flag_learning ) )
-#endif
- {
- hash_store( ptree, 1, depth, turn, value_exact, alpha,
- ptree->pv[1].a[1], 0 );
- }
-
return alpha;
}
-void
+void CONV
out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time )
{
+#if defined(USI)
+ char str_pv[256];
+ int ipv;
+#endif
const char *str;
double dvalue;
int ply, tt, is_out;
tt = turn;
- is_out = ( iteration_depth > 3 || abs(value) > score_max_eval ) ? 1 : 0;
+ is_out = ( 4 < iteration_depth || abs(value) > score_max_eval ) ? 1 : 0;
#if defined(MPV)
if ( root_mpv ) { is_out = 0; }
#endif
+#if defined(USI)
+ if ( usi_mode != usi_off )
+ {
+ is_out = 1;
+ ipv = 0;
+ str_pv[0] = '\0';
+ }
+#endif
+
if ( is_out )
{
str = str_time_symple( time );
if ( ptree->pv[0].length )
{
- int i = find_root_move( ptree->pv[0].a[1] );
- if ( root_move_list[i].status & flag_first )
+ if ( root_move_list[root_index].status & flag_first )
{
Out( " %2d %6s %7.2f ", iteration_depth, str, dvalue );
}
{
if ( is_out )
{
- if ( ply > 1 && ! ( (ply-1) % 4 ) )
+ if ( ply > 1 && ! ( (ply-1) % 5 ) )
{
Out( "\n " );
}
- str = str_CSA_move_plus( ptree, ptree->pv[0].a[ply], ply, tt );
+ str = str_CSA_move( ptree->pv[0].a[ply] );
OutCsaShogi( " %c%s", ach_turn[tt], str );
- Out( "%2d.%c%-11s", ply, ach_turn[tt], str );
+ Out( "%2d.%c%-7s", ply, ach_turn[tt], str );
+
+#if defined(USI)
+ if ( usi_mode != usi_off && ply <= 4 )
+ {
+ char str_usi[6];
+ csa2usi( ptree, str_CSA_move(ptree->pv[0].a[ply]), str_usi );
+ ipv += snprintf( str_pv + ipv, 256 - ipv, " %s", str_usi );
+ }
+#endif
}
MakeMove( tt, ptree->pv[0].a[ply], ply );
if ( ptree->pv[0].type == hash_hit )
{
+ unsigned int dummy;
int i, value_type;
for ( ; ply < PLY_MAX; ply++ )
{
+ dummy = 0;
ptree->amove_hash[ply] = 0;
value_type = hash_probe( ptree, ply, 0, tt, -score_bound,
- score_bound, 0 );
+ score_bound, &dummy );
if ( ! ( value_type == value_exact
&& value == HASH_VALUE
&& is_move_valid( ptree, ptree->amove_hash[ply], tt ) ) )
if ( is_out )
{
- if ( ply > 1 && ! ( (ply-1) % 4 ) )
+ if ( ply > 1 && ! ( (ply-1) % 5 ) )
{
Out( "\n " );
}
- str = str_CSA_move_plus( ptree, ptree->pv[0].a[ply], ply,
- tt );
+ str = str_CSA_move(ptree->pv[0].a[ply]);
OutCsaShogi( " %c%s", ach_turn[tt], str );
- Out( "%2d:%c%-11s", ply, ach_turn[tt], str );
+ Out( "%2d:%c%-7s", ply, ach_turn[tt], str );
+
+#if defined(USI)
+ if ( usi_mode != usi_off && ply <= 4 )
+ {
+ char str_usi[6];
+ csa2usi( ptree, str_CSA_move(ptree->pv[0].a[ply]), str_usi );
+ ipv += snprintf( str_pv + ipv, 256 - ipv, " %s", str_usi );
+ }
+#endif
}
MakeMove( tt, ptree->pv[0].a[ply], ply );
if ( is_out && ptree->pv[0].type != no_rep )
{
- if ( (((ply-1) % 4) == 0) && (ply != 1) )
+ if ( (((ply-1) % 5) == 0) && (ply != 1) )
{
Out( "\n " );
}
}
for ( ply--; ply >= 1; ply-- )
{
- tt = Flip(tt);
+ tt = Flip(tt);
+ value = -value;
UnMakeMove( tt, ptree->pv[0].a[ply], ply );
}
{
OutCsaShogi( "\n" );
Out( "\n" );
+ USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv%s\n",
+ iteration_depth, value, ptree->node_searched, str_pv );
}
}
-static int
+static int CONV
save_result( tree_t * restrict ptree, int value, int beta, int turn )
{
root_move_t root_move_temp;
- int i;
+ int index;
if ( get_elapsed( &time_last_result ) < 0 ) { return -1; }
- i = find_root_move( ptree->current_move[1] );
- if ( i )
+ index = root_index;
+ if ( index )
{
- root_move_temp = root_move_list[i];
- for ( ; i > 0; i-- ) { root_move_list[i] = root_move_list[i-1]; }
+ root_move_temp = root_move_list[index];
+ for ( ; index > 0; index-- )
+ {
+ root_move_list[index] = root_move_list[index-1];
+ }
root_move_list[0] = root_move_temp;
}
-
+ root_index = 0;
if ( beta <= value ) { pv_close( ptree, 2, pv_fail_high ); }
- if ( ptree->pv[0].a[1] != ptree->pv[1].a[1] )
- {
- time_last_eff_search = time_last_search;
- }
-
ptree->pv[0] = ptree->pv[1];
root_value = value;
if ( value < beta )
{
- MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "\n", mnj_posi_id,
- str_CSA_move(ptree->pv[1].a[1]), value, ptree->node_searched );
+#if defined(DFPN_CLIENT)
+ if ( dfpn_client_sckt != SCKT_NULL
+ && 4 < iteration_depth
+ && dfpn_client_best_move != ptree->pv[1].a[1] )
+ {
+ dfpn_client_best_move = ptree->pv[1].a[1];
+ lock( &dfpn_client_lock );
+ dfpn_client_out( "BEST MOVE %s\n",
+ str_CSA_move(dfpn_client_best_move) );
+ unlock( &dfpn_client_lock );
+ }
+#endif
+ MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "%s\n",
+ mnj_posi_id, str_CSA_move(ptree->pv[1].a[1]), value,
+ ptree->node_searched,
+ ( mnj_depth_stable <= iteration_depth ) ? " stable" : "" );
+
out_pv( ptree, value, turn, time_last_result - time_start );
}
}
-static int
+static int CONV
#if defined(NO_STDOUT) && defined(NO_LOGGING)
next_root_move( tree_t * restrict ptree )
#else
if ( root_move_list[i].status & flag_searched ) { continue; }
root_move_list[i].status |= flag_searched;
ptree->current_move[1] = root_move_list[i].move;
+ root_index = i;
#if ! ( defined(NO_STDOUT) && defined(NO_LOGGING) )
if ( iteration_depth > 5 )
{
const char *str_move;
char str[9];
- /* check: does this code have small impact on performance? */
- str_move = str_CSA_move_plus( ptree, ptree->current_move[1], 1,
- turn);
+
+ str_move = str_CSA_move(ptree->current_move[1]);
snprintf( str, 9, "%d/%d", i+1, root_nmove );
if ( root_move_list[i].status & flag_first )
{
}
-static int
-find_root_move( unsigned int move )
-{
- int i, n;
-
- n = root_nmove;
- for ( i = 0; i < n; i++ )
- if ( root_move_list[i].move == move ) { break; }
-
- return i;
-}
-
-
#if defined(MPV)
-static void
+static void CONV
mpv_out( tree_t * restrict ptree, int turn, unsigned int time )
{
int mpv_out, ipv, best;
{
if ( is_out )
{
- if ( ply > 1 && ! ( (ply-1) % 4 ) )
+ if ( ply > 1 && ! ( (ply-1) % 5 ) )
{
Out( "\n " );
}
- str = str_CSA_move_plus( ptree, mpv_pv[ipv].a[ply], ply, tt );
+ str = str_CSA_move(mpv_pv[ipv].a[ply]);
OutCsaShogi( " %c%s", ach_turn[tt], str );
Out( "%2d.%c%-11s", ply, ach_turn[tt], str );
}
if ( mpv_pv[ipv].type == hash_hit )
{
+ unsigned int dummy;
int i, value_type;
for ( ; ply < PLY_MAX; ply++ )
{
+ dummy = 0;
ptree->amove_hash[ply] = 0;
value_type = hash_probe( ptree, ply, 0, tt, -score_bound,
- score_bound, 0 );
+ score_bound, &dummy );
if ( ! ( value_type == value_exact
&& value == HASH_VALUE
&& is_move_valid(ptree,ptree->amove_hash[ply],tt) ) )
if ( is_out )
{
- if ( ply > 1 && ! ( (ply-1) % 4 ) )
+ if ( ply > 1 && ! ( (ply-1) % 5 ) )
{
Out( "\n " );
}
- str = str_CSA_move_plus( ptree, mpv_pv[ipv].a[ply], ply,
- tt );
+ str = str_CSA_move(mpv_pv[ipv].a[ply]);
OutCsaShogi( " %c%s", ach_turn[tt], str );
Out( "%2d:%c%-11s", ply, ach_turn[tt], str );
}
if ( is_out && mpv_pv[ipv].type != no_rep )
{
- if ( (((ply-1) % 4) == 0) && (ply != 1) )
+ if ( (((ply-1) % 5) == 0) && (ply != 1) )
{
Out( "\n " );
}
}
-static void
+static void CONV
mpv_sub_result( unsigned int move )
{
int i;
}
-static int
+static int CONV
mpv_add_result( tree_t * restrict ptree, int value )
{
pv_t pv_tmp, pv;
}
-static int
+static int CONV
mpv_set_bound( int alpha )
{
int bound, num, value;
}
-static int
+static int CONV
mpv_find_min( int *pnum )
{
int i, num;
#define SHOGI_H
#include <stdio.h>
+#include "bitop.h"
#include "param.h"
#if defined(_WIN32)
# include <Winsock2.h>
-# define CONV_CDECL __cdecl
+# define CONV __fastcall
# define SCKT_NULL INVALID_SOCKET
typedef SOCKET sckt_t;
# include <pthread.h>
# include <sys/times.h>
-# define CONV_CDECL
+# define CONV
# define SCKT_NULL -1
# define SOCKET_ERROR -1
typedef int sckt_t;
#endif
-/* Microsoft C/C++ */
+/* Microsoft C/C++ on x86 and x86-64 */
#if defined(_MSC_VER)
# define _CRT_DISABLE_PERFCRIT_LOCKS
#else
# include <inttypes.h>
+typedef struct { unsigned int p[3]; } bitboard_t;
typedef pthread_mutex_t lock_t;
extern unsigned char aifirst_one[512];
extern unsigned char ailast_one[512];
#endif
+#define BK_TINY
/*
+ #define BK_SMALL
#define BK_ULTRA_NARROW
#define BK_COM
- #define BK_SMALL
- #define NO_NULL_PRUNE
#define NO_STDOUT
#define DBG_EASY
*/
# define SEARCH_ABORT root_abort
#endif
+#define NUM_UNMAKE 2
#define QUIES_PLY_LIMIT 7
#define SHELL_H_LEN 7
#define MAX_ANSWER 8
#define PLY_INC 8
-#define PLY_MAX 48
+#define PLY_MAX 128
#define RAND_N 624
-#define TC_NMOVE 37U
+#define TC_NMOVE 35U
#define SEC_MARGIN 15U
#define SEC_KEEP_ALIVE 180U
#define TIME_RESPONSE 200U
#define RESIGN_THRESHOLD ( ( MT_CAP_DRAGON * 5 ) / 8 )
-#define BNZ_VER "Feliz 0.0"
+#define BNZ_VER "6.0"
#define REP_MAX_PLY 32
#define REP_HIST_LEN 256
-#define EHASH_MASK 0x3fffffU /* occupies 32MB */
-
-#define MNJ_MASK 0xfffU
+#define EHASH_MASK 0x3fffffU /* occupies 32MB */
+#define MATE3_MASK 0x07ffffU /* occupies 4MB */
#define HIST_SIZE 0x4000U
#define HIST_INVALID 0xffffU
-#define HIST_MAX 0x1000U
+#define HIST_MAX 0x8000U
#define REJEC_MASK 0x0ffffU
#define REJEC_MIN_DEPTH ( ( PLY_INC * 5 ) )
#define FMG_MISC_KING ( ( MT_CAP_DRAGON * 2 ) / 8 )
#define FMG_CAP_KING ( ( MT_CAP_DRAGON * 2 ) / 8 )
-#define HASH_REG_HIST_LEN 256
-#define HASH_REG_MINDIFF ( ( MT_CAP_DRAGON * 1 ) / 8 )
-#define HASH_REG_THRESHOLD ( ( MT_CAP_DRAGON * 8 ) / 8 )
-
#define FV_WINDOW 256
#define FV_SCALE 32
#define FV_PENALTY ( 0.2 / (double)FV_SCALE )
#define SIZE_FILENAME 256
#define SIZE_PLAYERNAME 256
#define SIZE_MESSAGE 512
-#define SIZE_CMDLINE 512
#define SIZE_CSALINE 512
-#define SIZE_CMDBUFFER 512
+
+#if defined(USI)
+# define SIZE_CMDLINE ( 1024 * 16 )
+# define SIZE_CMDBUFFER ( 1024 * 16 )
+#else
+# define SIZE_CMDLINE 512
+# define SIZE_CMDBUFFER 512
+#endif
#define IsMove(move) ( (move) & 0xffffffU )
#define MOVE_NA 0x00000000U
( (d) <= PLY_INC*30/4 ? PLY_INC*14/4 \
: (d)-PLY_INC*16/4) )
+#define RecursionThreshold ( PLY_INC * 3 )
+
+#define RecursionDepth(d) ( (d) < PLY_INC*18/4 ? PLY_INC*6/4 \
+ : (d)-PLY_INC*12/4 )
+
#define LimitExtension(e,ply) if ( (e) && (ply) > 2 * iteration_depth ) { \
if ( (ply) < 4 * iteration_depth ) { \
e *= 4 * iteration_depth - (ply); \
#define IsHandGold(hand) ((hand) & 0x001c000)
#define IsHandBishop(hand) ((hand) & 0x0060000)
#define IsHandRook(hand) ((hand) & 0x0180000)
+#define IsHandSGBR(hand) ((hand) & 0x01ff800)
/*
xxxxxxxx xxxxxxxx x1111111 destination
xxxxxxxx xx111111 1xxxxxxx starting square or drop piece+nsquare-1
#define From2Drop(from) ((from)-nsquare+1)
-#define BBIni(bb) (bb).p[0] = (bb).p[1] = (bb).p[2] = 0
-#define BBToU(bb) ((bb).p[0] | (bb).p[1] | (bb).p[2])
-#define BBToUShift(bb) ((bb).p[0]<<2 | (bb).p[1]<<1 | (bb).p[2])
-#define PopuCount(bb) popu_count012( bb.p[0], bb.p[1], bb.p[2] )
-#define FirstOne(bb) first_one012( bb.p[0], bb.p[1], bb.p[2] )
-#define LastOne(bb) last_one210( bb.p[2], bb.p[1], bb.p[0] )
-
-#define BBCmp(bb1,bb2) ( (bb1).p[0] != (bb2).p[0] \
- || (bb1).p[1] != (bb2).p[1] \
- || (bb1).p[2] != (bb2).p[2] )
-
-#define BBNot(bb,bb1) (bb).p[0] = ~(bb1).p[0], \
- (bb).p[1] = ~(bb1).p[1], \
- (bb).p[2] = ~(bb1).p[2]
-
-#define BBOr(bb,bb1,bb2) (bb).p[0] = (bb1).p[0] | (bb2).p[0], \
- (bb).p[1] = (bb1).p[1] | (bb2).p[1], \
- (bb).p[2] = (bb1).p[2] | (bb2).p[2]
-
-#define BBAnd(bb,bb1,bb2) (bb).p[0] = (bb1).p[0] & (bb2).p[0], \
- (bb).p[1] = (bb1).p[1] & (bb2).p[1], \
- (bb).p[2] = (bb1).p[2] & (bb2).p[2]
-
-#define BBXor(bb,b1,b2) (bb).p[0] = (b1).p[0] ^ (b2).p[0], \
- (bb).p[1] = (b1).p[1] ^ (b2).p[1], \
- (bb).p[2] = (b1).p[2] ^ (b2).p[2]
-
-#define BBAndOr(bb,bb1,bb2) (bb).p[0] |= (bb1).p[0] & (bb2).p[0], \
- (bb).p[1] |= (bb1).p[1] & (bb2).p[1], \
- (bb).p[2] |= (bb1).p[2] & (bb2).p[2]
-
-#define BBNotAnd(bb,bb1) bb.p[0] &= ~bb1.p[0]; \
- bb.p[1] &= ~bb1.p[1]; \
- bb.p[2] &= ~bb1.p[2]
-
-#define BBContractShift(bb1,bb2) ( ( (bb1).p[0] & (bb2).p[0] ) << 2 \
- | ( (bb1).p[1] & (bb2).p[1] ) << 1 \
- | ( (bb1).p[2] & (bb2).p[2] ) )
-
-#define BBContract(bb1,bb2) ( ( (bb1).p[0] & (bb2).p[0] ) \
- | ( (bb1).p[1] & (bb2).p[1] ) \
- | ( (bb1).p[2] & (bb2).p[2] ) )
-
-#define Xor(i,bb) (bb).p[0] ^= abb_mask[i].p[0], \
- (bb).p[1] ^= abb_mask[i].p[1], \
- (bb).p[2] ^= abb_mask[i].p[2]
-
-#define XorFile(i,bb) (bb).p[0] ^= abb_mask_rl90[i].p[0], \
- (bb).p[1] ^= abb_mask_rl90[i].p[1], \
- (bb).p[2] ^= abb_mask_rl90[i].p[2]
-
-#define XorDiag1(i,bb) (bb).p[0] ^= abb_mask_rr45[i].p[0], \
- (bb).p[1] ^= abb_mask_rr45[i].p[1], \
- (bb).p[2] ^= abb_mask_rr45[i].p[2]
-
-#define XorDiag2(i,bb) (bb).p[0] ^= abb_mask_rl45[i].p[0], \
- (bb).p[1] ^= abb_mask_rl45[i].p[1], \
- (bb).p[2] ^= abb_mask_rl45[i].p[2]
-
-#define SetClear(bb) (bb).p[0] ^= (bb_set_clear.p[0]), \
- (bb).p[1] ^= (bb_set_clear.p[1]), \
- (bb).p[2] ^= (bb_set_clear.p[2])
-
-#define SetClearFile(i1,i2,bb) \
- (bb).p[0] ^= ((abb_mask_rl90[i1].p[0])|(abb_mask_rl90[i2].p[0])), \
- (bb).p[1] ^= ((abb_mask_rl90[i1].p[1])|(abb_mask_rl90[i2].p[1])), \
- (bb).p[2] ^= ((abb_mask_rl90[i1].p[2])|(abb_mask_rl90[i2].p[2]))
-
-#define SetClearDiag1(i1,i2,bb) \
- (bb).p[0] ^= ((abb_mask_rr45[i1].p[0])|(abb_mask_rr45[i2].p[0])), \
- (bb).p[1] ^= ((abb_mask_rr45[i1].p[1])|(abb_mask_rr45[i2].p[1])), \
- (bb).p[2] ^= ((abb_mask_rr45[i1].p[2])|(abb_mask_rr45[i2].p[2]))
-
-#define SetClearDiag2(i1,i2,bb) \
- (bb).p[0] ^= ((abb_mask_rl45[i1].p[0])|(abb_mask_rl45[i2].p[0])), \
- (bb).p[1] ^= ((abb_mask_rl45[i1].p[1])|(abb_mask_rl45[i2].p[1])), \
- (bb).p[2] ^= ((abb_mask_rl45[i1].p[2])|(abb_mask_rl45[i2].p[2]))
-
#define AttackFile(i) (abb_file_attacks[i] \
[((ptree->posi.occupied_rl90.p[aslide[i].irl90]) \
>> aslide[i].srl90) & 0x7f])
-#define AttackRank(i) (ai_rook_attacks_r0[i] \
+#define AttackRank(i) (abb_rank_attacks[i] \
[((ptree->posi.b_occupied.p[aslide[i].ir0] \
|ptree->posi.w_occupied.p[aslide[i].ir0]) \
>> aslide[i].sr0) & 0x7f ])
#define BishopAttack2(i) ( AttackDiag1(i).p[2] | AttackDiag2(i).p[2] )
#define AttackBLance(bb,i) BBAnd( bb, abb_minus_rays[i], AttackFile(i) )
#define AttackWLance(bb,i) BBAnd( bb, abb_plus_rays[i], AttackFile(i) )
+#define AttackBishop(bb,i) BBOr( bb, AttackDiag1(i), AttackDiag2(i) )
+#define AttackRook(bb,i) BBOr( bb, AttackFile(i), AttackRank(i) )
#define AttackHorse(bb,i) AttackBishop(bb,i); BBOr(bb,bb,abb_king_attacks[i])
#define AttackDragon(bb,i) AttackRook(bb,i); BBOr(bb,bb,abb_king_attacks[i])
enum { score_draw = 1,
score_max_eval = 30000,
+ score_matelong = 30002,
score_mate1ply = 32598,
score_inferior = 32599,
score_bound = 32600,
/* next_evasion_hash should be the same as next_move_hash */
enum { next_evasion_hash = 0, next_evasion_genall, next_evasion_misc };
+
enum { next_quies_gencap, next_quies_captures, next_quies_misc };
enum { no_rep = 0, four_fold_rep, perpetual_check, perpetual_check2,
node_do_mate = b0001 << 4,
node_mate_threat = b0010 << 4, /* <- don't change it */
node_do_futile = b0100 << 4,
+ node_do_recursion = b1000 << 4,
+ node_do_hashcut = b0001 << 8,
state_node_end };
/* note: maximum bits are 8. tlp_state_node uses type unsigned char. */
-enum { flag_from_ponder = b0001,
- flag_refer_rest = b0010 };
+enum { flag_from_ponder = b0001 };
enum { flag_time = b0001,
flag_history = b0010,
flag_rep = b0100,
flag_detect_hang = b1000,
- flag_rejections = b0001 << 4,
flag_nomake_move = b0010 << 4,
flag_nofmargin = b0100 << 4 };
/* flags represent status of root move */
enum { flag_searched = b0001,
- flag_failhigh = b0010,
- flag_faillow = b0100,
- flag_first = b1000 };
+ flag_first = b0010 };
+
enum { flag_mated = b0001,
flag_resigned = b0010,
flag_problem = b0001 << 8,
flag_move_now = b0010 << 8,
flag_quit_ponder = b0100 << 8,
+ flag_nostdout = b1000 << 8,
flag_search_error = b0001 << 12,
- flag_quiet = b0010 << 12,
+ flag_nonewlog = b0010 << 12,
flag_reverse = b0100 << 12,
flag_narrow_book = b1000 << 12,
flag_time_extendable = b0001 << 16,
flag_nostress = b1000 << 16,
flag_nopeek = b0001 << 20,
flag_noponder = b0010 << 20,
- flag_noprompt = b0100 << 20 };
+ flag_noprompt = b0100 << 20,
+ flag_sendpv = b1000 << 20,
+ flag_skip_root_move = b0001 << 24 };
enum { flag_hand_pawn = 1 << 0,
enum { pos_n = fe_end * ( fe_end + 1 ) / 2 };
-typedef struct { unsigned int p[3]; } bitboard_t;
-
typedef struct { bitboard_t gold, silver, knight, lance; } check_table_t;
#if ! defined(MINIMUM)
typedef struct { int count; unsigned int cnst[2], vec[RAND_N]; }rand_work_t;
typedef struct {
- uint64_t root;
- SHARE uint64_t sibling;
-} rejections_t;
-
-typedef struct {
int no1_value, no2_value;
unsigned int no1, no2;
} move_killer_t;
typedef struct {
uint64_t nodes;
unsigned int move, status;
+#if defined(DFPN_CLIENT)
+ volatile int dfpn_cresult;
+#endif
} root_move_t;
typedef struct {
unsigned int nperpetual_check;
unsigned int nsuperior_rep;
unsigned int nrep_tried;
- unsigned int nreject_tried;
- unsigned int nreject_done;
unsigned int ntrans_always_hit;
unsigned int ntrans_prefer_hit;
unsigned int ntrans_probe;
unsigned short hist_tried[ HIST_SIZE ];
unsigned short hist_good[ HIST_SIZE ];
short save_material[ PLY_MAX ];
- short stand_pat[ PLY_MAX+1 ];
+ int save_eval[ PLY_MAX+1 ];
unsigned char nsuc_check[ PLY_MAX+1 ];
+ int nrep;
#if defined(TLP)
struct tree *tlp_ptrees_sibling[ TLP_MAX_THREADS ];
struct tree *tlp_ptree_parent;
extern SHARE unsigned int game_status;
-extern history_book_learn_t history_book_learn[ HASH_REG_HIST_LEN ];
extern int npawn_box;
extern int nlance_box;
extern root_move_t root_move_list[ MAX_LEGAL_MOVES ];
extern SHARE int root_abort;
-extern int root_nrep;
extern int root_nmove;
+extern int root_index;
extern int root_value;
extern int root_alpha;
extern int root_beta;
extern int root_turn;
-extern int root_move_cap;
extern int root_nfail_high;
extern int root_nfail_low;
extern int resign_threshold;
-extern int n_nobook_move;
extern uint64_t node_limit;
extern unsigned int node_per_second;
extern int trans_table_age;
extern pv_t last_pv;
-extern pv_t last_pv_save;
+extern pv_t alast_pv_save[NUM_UNMAKE];
+extern int alast_root_value_save[NUM_UNMAKE];
extern int last_root_value;
-extern int last_root_value_save;
+extern int amaterial_save[NUM_UNMAKE];
+extern unsigned int amove_save[NUM_UNMAKE];
+extern unsigned char ansuc_check_save[NUM_UNMAKE];
extern SHARE trans_table_t *ptrans_table;
extern trans_table_t *ptrans_table_orig;
extern record_t record_problems;
extern record_t record_game;
extern FILE *pf_book;
-extern FILE *pf_hash;
-extern int irecord_game;
+extern int record_num;
-extern short p_value[31];
+extern int p_value_ex[31];
+extern int p_value_pm[15];
+extern int p_value[31];
extern short pc_on_sq[nsquare][fe_end*(fe_end+1)/2];
extern short kkp[nsquare][nsquare][kkp_end];
extern uint64_t ehash_tbl[ EHASH_MASK + 1 ];
-extern unsigned char hash_rejections_parent[ REJEC_MASK+1 ];
-extern rejections_t hash_rejections[ REJEC_MASK+1 ];
extern rand_work_t rand_work;
extern slide_tbl_t aslide[ nsquare ];
extern bitboard_t abb_b_knight_attacks[ nsquare ];
extern bitboard_t abb_obstacle[ nsquare ][ nsquare ];
extern bitboard_t abb_bishop_attacks_rl45[ nsquare ][ 128 ];
extern bitboard_t abb_bishop_attacks_rr45[ nsquare ][ 128 ];
+extern bitboard_t abb_rank_attacks[ nsquare ][ 128 ];
extern bitboard_t abb_file_attacks[ nsquare ][ 128 ];
extern bitboard_t abb_mask[ nsquare ];
extern bitboard_t abb_mask_rl90[ nsquare ];
extern uint64_t w_hand_gold_rand[ ngold_max ];
extern uint64_t w_hand_bishop_rand[ nbishop_max ];
extern uint64_t w_hand_rook_rand[ nrook_max ];
-extern unsigned int ai_rook_attacks_r0[ nsquare ][ 128 ];
extern unsigned int move_evasion_pchk;
-extern int p_value_ex[31];
-extern int benefit2promo[15];
extern int easy_abs;
extern int easy_min;
extern int easy_max;
extern const char *str_game_ended;
extern const char *str_io_error;
extern const char *str_spaces;
+extern const char *str_no_legal_move;
extern const char *str_king_hang;
#if defined(CSA_LAN)
extern const char *str_server_err;
extern const char *str_myname;
extern const char *str_version;
extern const min_posi_t min_posi_no_handicap;
-extern const short aipos[31];
+extern const int ashell_h[ SHELL_H_LEN ];
+extern const int aikkp[16];
+extern const int aikpp[31];
+extern const int aikkp_hand[8];
extern const char ach_turn[2];
-extern const char ashell_h[ SHELL_H_LEN ];
extern const unsigned char aifile[ nsquare ];
extern const unsigned char airank[ nsquare ];
-void pv_close( tree_t * restrict ptree, int ply, int type );
-void pv_copy( tree_t * restrict ptree, int ply );
+#if defined(DFPN_CLIENT)
+# define DFPN_CLIENT_SIZE_SIGNATURE 64
+enum { dfpn_client_na, dfpn_client_win, dfpn_client_lose, dfpn_client_misc };
+typedef struct { char str_move[7], result; } dfpn_client_cresult_t;
+extern volatile int dfpn_client_flag_read;
+extern volatile sckt_t dfpn_client_sckt;
+extern volatile unsigned int dfpn_client_move_unlocked;
+extern volatile int dfpn_client_rresult_unlocked;
+extern volatile int dfpn_client_num_cresult;
+extern volatile char dfpn_client_signature[ DFPN_CLIENT_SIZE_SIGNATURE ];
+extern volatile dfpn_client_cresult_t dfpn_client_cresult[ MAX_LEGAL_MOVES ];
+extern volatile char dfpn_client_str_move[7];
+extern volatile int dfpn_client_rresult;
+extern unsigned int dfpn_client_best_move;
+extern lock_t dfpn_client_lock;
+extern char dfpn_client_str_addr[256];
+extern int dfpn_client_port;
+extern int dfpn_client_cresult_index;
+void CONV dfpn_client_start( const tree_t * restrict ptree );
+void CONV dfpn_client_check_results( void );
+int CONV dfpn_client_out( const char *fmt, ... );
+#endif
+
+void CONV pv_close( tree_t * restrict ptree, int ply, int type );
+void CONV pv_copy( tree_t * restrict ptree, int ply );
void set_derivative_param( void );
-void set_search_limit_time( int turn );
-void ehash_clear( void );
-void hash_store_pv( const tree_t * restrict ptree, unsigned int move,
- int turn );
-void check_futile_score_quies( const tree_t * restrict ptree,
- unsigned int move, int old_val, int new_val,
- int turn );
-void out_file( FILE *pf, const char *format, ... );
+void CONV set_search_limit_time( int turn );
+void CONV ehash_clear( void );
+void CONV hash_store_pv( const tree_t * restrict ptree, unsigned int move,
+ int turn );
+void CONV check_futile_score_quies( const tree_t * restrict ptree,
+ unsigned int move, int old_val,
+ int new_val, int turn );
void out_warning( const char *format, ... );
void out_error( const char *format, ... );
void show_prompt( void );
-void make_move_w( tree_t * restrict ptree, unsigned int move, int ply );
-void make_move_b( tree_t * restrict ptree, unsigned int move, int ply );
-void unmake_move_b( tree_t * restrict ptree, unsigned int move, int ply );
-void unmake_move_w( tree_t * restrict ptree, unsigned int move, int ply );
+void CONV make_move_w( tree_t * restrict ptree, unsigned int move, int ply );
+void CONV make_move_b( tree_t * restrict ptree, unsigned int move, int ply );
+void CONV unmake_move_b( tree_t * restrict ptree, unsigned int move, int ply );
+void CONV unmake_move_w( tree_t * restrict ptree, unsigned int move, int ply );
void ini_rand( unsigned int s );
void out_CSA( tree_t * restrict ptree, record_t *pr, unsigned int move );
-void out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time );
-void hash_store( const tree_t * restrict ptree, int ply, int depth, int turn,
- int value_type, int value, unsigned int move,
- unsigned int state_node );
-void *memory_alloc( size_t nbytes );
-void unmake_move_root( tree_t * restrict ptree, unsigned int move );
-void add_rejections_root( tree_t * restrict ptree, unsigned int move_made );
-void sub_rejections_root( tree_t * restrict ptree, unsigned int move_made );
-void add_rejections( tree_t * restrict ptree, int turn, int ply );
-void sub_rejections( tree_t * restrict ptree, int turn, int ply );
-void adjust_time( unsigned int elapsed_new, int turn );
-int popu_count012( unsigned int u0, unsigned int u1, unsigned int u2 );
-int first_one012( unsigned int u0, unsigned int u1, unsigned int u2 );
-int last_one210( unsigned int u2, unsigned int u1, unsigned int u0 );
-int first_one01( unsigned int u0, unsigned int u1 );
-int first_one12( unsigned int u1, unsigned int u2 );
-int last_one01( unsigned int u0, unsigned int u1 );
-int last_one12( unsigned int u1, unsigned int u2 );
-int first_one1( unsigned int u1 );
-int first_one2( unsigned int u2 );
-int last_one0( unsigned int u0 );
-int last_one1( unsigned int u1 );
-int memory_free( void *p );
-int reset_time( unsigned int b_remain, unsigned int w_remain );
-int all_hash_learn_store( void );
-int gen_legal_moves( tree_t * restrict ptree, unsigned int *p0 );
-int rejections_probe( tree_t * restrict ptree, int turn, int ply );
+void CONV out_pv( tree_t * restrict ptree, int value, int turn,
+ unsigned int time );
+void CONV hash_store( const tree_t * restrict ptree, int ply, int depth,
+ int turn, int value_type, int value, unsigned int move,
+ unsigned int state_node );
+void * CONV memory_alloc( size_t nbytes );
+void CONV adjust_time( unsigned int elapsed_new, int turn );
+int CONV load_fv( void );
+int CONV unmake_move_root( tree_t * restrict ptree );
+int CONV popu_count012( unsigned int u0, unsigned int u1, unsigned int u2 );
+int CONV first_one012( unsigned int u0, unsigned int u1, unsigned int u2 );
+int CONV last_one210( unsigned int u2, unsigned int u1, unsigned int u0 );
+int CONV first_one01( unsigned int u0, unsigned int u1 );
+int CONV first_one12( unsigned int u1, unsigned int u2 );
+int CONV last_one01( unsigned int u0, unsigned int u1 );
+int CONV last_one12( unsigned int u1, unsigned int u2 );
+int CONV first_one1( unsigned int u1 );
+int CONV first_one2( unsigned int u2 );
+int CONV last_one0( unsigned int u0 );
+int CONV last_one1( unsigned int u1 );
+int CONV memory_free( void *p );
+int CONV reset_time( unsigned int b_remain, unsigned int w_remain );
+int CONV gen_legal_moves( tree_t * restrict ptree, unsigned int *p0,
+ int flag );
+int CONV detect_signals( tree_t * restrict ptree );
int ini( tree_t * restrict ptree );
int fin( void );
int ponder( tree_t * restrict ptree );
-int hash_learn( const tree_t * restrict ptree, unsigned int move, int value,
- int depth );
-int book_on( void );
-int book_off( void );
-int hash_learn_on( void );
-int hash_learn_off( void );
-int is_move_check_b( const tree_t * restrict ptree, unsigned int move );
-int is_move_check_w( const tree_t * restrict ptree, unsigned int move );
-int solve_problems( tree_t * restrict ptree, unsigned int nposition );
+int CONV book_on( void );
+int CONV book_off( void );
+int CONV solve_problems( tree_t * restrict ptree, unsigned int nposition );
+int CONV solve_mate_problems( tree_t * restrict ptree,
+ unsigned int nposition );
int read_board_rep1( const char *str_line, min_posi_t *pmin_posi );
-int com_turn_start( tree_t * restrict ptree, int flag );
+int CONV com_turn_start( tree_t * restrict ptree, int flag );
int read_record( tree_t * restrict ptree, const char *str_file,
unsigned int moves, int flag );
int out_board( const tree_t * restrict ptree, FILE *pf, unsigned int move,
int flag );
-int make_root_move_list( tree_t * restrict ptree, int flag );
+int make_root_move_list( tree_t * restrict ptree );
int record_wind( record_t *pr );
-int book_probe( tree_t * restrict ptree );
-int detect_repetition( tree_t * restrict ptree, int ply, int turn, int nth );
-int is_mate( tree_t * restrict ptree, int ply );
-int is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop );
-int is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop );
-int clear_trans_table( void );
-int eval_max_score( const tree_t * restrict ptree, unsigned int move,
- int stand_pat, int turn, int diff );
-int estimate_score_diff( const tree_t * restrict ptree, unsigned int move,
- int turn );
-int eval_material( const tree_t * restrict ptree );
-int ini_trans_table( void );
-int is_hand_eq_supe( unsigned int u, unsigned int uref );
-int is_move_valid( tree_t * restrict ptree, unsigned int move, int turn );
-int is_hash_move_valid( tree_t * restrict ptree, unsigned int move, int turn );
-int iterate( tree_t * restrict ptree, int flag );
-int gen_next_move( tree_t * restrict ptree, int ply, int turn );
-int gen_next_evasion( tree_t * restrict ptree, int ply, int turn );
-int ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi, int flag,
- const char *str_name1, const char *str_name2 );
+int CONV book_probe( tree_t * restrict ptree );
+int CONV detect_repetition( tree_t * restrict ptree, int ply, int turn,
+ int nth );
+int CONV is_move( const char *str );
+int CONV is_mate( tree_t * restrict ptree, int ply );
+int CONV is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop );
+int CONV is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop );
+int CONV clear_trans_table( void );
+int CONV eval_max_score( const tree_t * restrict ptree, unsigned int move,
+ int value, int turn, int diff );
+int CONV estimate_score_diff( const tree_t * restrict ptree, unsigned int move,
+ int turn );
+int CONV eval_material( const tree_t * restrict ptree );
+int CONV ini_trans_table( void );
+int CONV is_hand_eq_supe( unsigned int u, unsigned int uref );
+int CONV is_move_valid( tree_t * restrict ptree, unsigned int move, int turn );
+int CONV iterate( tree_t * restrict ptree );
+int CONV gen_next_move( tree_t * restrict ptree, int ply, int turn );
+int CONV gen_next_evasion( tree_t * restrict ptree, int ply, int turn );
+int CONV ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi,
+ int flag, const char *str_name1, const char *str_name2 );
int open_history( const char *str_name1, const char *str_name2 );
int next_cmdline( int is_wait );
-int procedure( tree_t * restrict ptree );
-int get_cputime( unsigned int *ptime );
-int get_elapsed( unsigned int *ptime );
+int CONV procedure( tree_t * restrict ptree );
+int CONV get_cputime( unsigned int *ptime );
+int CONV get_elapsed( unsigned int *ptime );
int interpret_CSA_move( tree_t * restrict ptree, unsigned int *pmove,
const char *str );
int in_CSA( tree_t * restrict ptree, record_t *pr, unsigned int *pmove,
int do_history );
int in_CSA_record( FILE * restrict pf, tree_t * restrict ptree );
-int renovate_time( int turn );
-int exam_tree( const tree_t * restrict ptree );
+int CONV update_time( int turn );
+int CONV exam_tree( const tree_t * restrict ptree );
int rep_check_root( tree_t * restrict ptree );
-int make_move_root( tree_t * restrict ptree, unsigned int move, int flag );
-int search_quies( tree_t * restrict ptree, int alpha, int beta, int turn,
- int ply, int qui_ply );
-int search( tree_t * restrict ptree, int alpha, int beta, int turn,
- int depth, int ply, unsigned int state_node );
-int searchr( tree_t * restrict ptree, int alpha, int beta, int turn,
+int CONV make_move_root( tree_t * restrict ptree, unsigned int move,
+ int flag );
+int CONV search_quies( tree_t * restrict ptree, int alpha, int beta, int turn,
+ int ply, int qui_ply );
+int CONV search( tree_t * restrict ptree, int alpha, int beta, int turn,
+ int depth, int ply, unsigned int state_node );
+int CONV searchr( tree_t * restrict ptree, int alpha, int beta, int turn,
int depth );
-int evaluate( tree_t * restrict ptree, int ply, int turn );
-int swap( const tree_t * restrict ptree, unsigned int move, int alpha,
- int beta, int turn );
+int CONV evaluate( tree_t * restrict ptree, int ply, int turn );
+int CONV swap( const tree_t * restrict ptree, unsigned int move, int alpha,
+ int beta, int turn );
int file_close( FILE *pf );
int record_open( record_t *pr, const char *str_file,
record_mode_t record_mode, const char *str_name1,
const char *str_name2 );
int record_close( record_t *pr );
-unsigned int phash( unsigned int move, int turn );
-unsigned int is_mate_in3ply( tree_t * restrict ptree, int turn, int ply );
-unsigned int is_b_mate_in_1ply( tree_t * restrict ptree );
-unsigned int is_w_mate_in_1ply( tree_t * restrict ptree );
-unsigned int hash_probe( tree_t * restrict ptree, int ply, int depth, int turn,
- int alpha, int beta, unsigned int state_node );
+unsigned int CONV phash( unsigned int move, int turn );
+unsigned int CONV is_mate_in3ply( tree_t * restrict ptree, int turn, int ply );
+unsigned int CONV is_b_mate_in_1ply( tree_t * restrict ptree );
+unsigned int CONV is_w_mate_in_1ply( tree_t * restrict ptree );
+unsigned int CONV hash_probe( tree_t * restrict ptree, int ply, int depth,
+ int turn, int alpha, int beta,
+ unsigned int *pstate_node );
unsigned int rand32( void );
-unsigned int is_black_attacked( const tree_t * restrict ptree, int sq );
-unsigned int is_white_attacked( const tree_t * restrict ptree, int sq );
-unsigned int is_pinned_on_black_king( const tree_t * restrict ptree,
+unsigned int CONV is_black_attacked( const tree_t * restrict ptree, int sq );
+unsigned int CONV is_white_attacked( const tree_t * restrict ptree, int sq );
+unsigned int CONV is_pinned_on_black_king( const tree_t * restrict ptree,
int isquare, int idirec );
-unsigned int is_pinned_on_white_king( const tree_t * restrict ptree,
+unsigned int CONV is_pinned_on_white_king( const tree_t * restrict ptree,
int isquare, int idirec );
-unsigned int *b_gen_captures( const tree_t * restrict ptree,
- unsigned int * restrict pmove );
-unsigned int *b_gen_nocaptures( const tree_t * restrict ptree,
- unsigned int * restrict pmove );
-unsigned int *b_gen_drop( tree_t * restrict ptree,
+unsigned int * CONV b_gen_captures( const tree_t * restrict ptree,
+ unsigned int * restrict pmove );
+unsigned int * CONV b_gen_nocaptures( const tree_t * restrict ptree,
+ unsigned int * restrict pmove );
+unsigned int * CONV b_gen_drop( tree_t * restrict ptree,
unsigned int * restrict pmove );
-unsigned int *b_gen_evasion( tree_t *restrict ptree,
- unsigned int * restrict pmove );
-unsigned int *b_gen_checks( tree_t * restrict __ptree__,
- unsigned int * restrict pmove );
-unsigned int *b_gen_cap_nopro_ex2( const tree_t * restrict ptree,
+unsigned int * CONV b_gen_evasion( tree_t *restrict ptree,
unsigned int * restrict pmove );
-unsigned int *b_gen_nocap_nopro_ex2( const tree_t * restrict ptree,
+unsigned int * CONV b_gen_checks( tree_t * restrict __ptree__,
+ unsigned int * restrict pmove );
+unsigned int * CONV b_gen_cap_nopro_ex2( const tree_t * restrict ptree,
+ unsigned int * restrict pmove );
+unsigned int * CONV b_gen_nocap_nopro_ex2( const tree_t * restrict ptree,
unsigned int * restrict pmove );
-unsigned int *w_gen_captures( const tree_t * restrict ptree,
- unsigned int * restrict pmove );
-unsigned int *w_gen_nocaptures( const tree_t * restrict ptree,
+unsigned int * CONV w_gen_captures( const tree_t * restrict ptree,
+ unsigned int * restrict pmove );
+unsigned int * CONV w_gen_nocaptures( const tree_t * restrict ptree,
+ unsigned int * restrict pmove );
+unsigned int * CONV w_gen_drop( tree_t * restrict ptree,
unsigned int * restrict pmove );
-unsigned int *w_gen_drop( tree_t * restrict ptree,
- unsigned int * restrict pmove );
-unsigned int *w_gen_evasion( tree_t * restrict ptree,
- unsigned int * restrict pmove );
-unsigned int *w_gen_checks( tree_t * restrict __ptree__,
- unsigned int * restrict pmove );
-unsigned int *w_gen_cap_nopro_ex2( const tree_t * restrict ptree,
+unsigned int * CONV w_gen_evasion( tree_t * restrict ptree,
unsigned int * restrict pmove );
-unsigned int *w_gen_nocap_nopro_ex2( const tree_t * restrict ptree,
- unsigned int * restrict pmove );
-uint64_t hash_func( const tree_t * restrict ptree );
+unsigned int * CONV w_gen_checks( tree_t * restrict __ptree__,
+ unsigned int * restrict pmove );
+unsigned int * CONV w_gen_cap_nopro_ex2( const tree_t * restrict ptree,
+ unsigned int * restrict pmove );
+unsigned int * CONV w_gen_nocap_nopro_ex2( const tree_t * restrict ptree,
+ unsigned int * restrict pmove );
+int CONV b_have_checks( tree_t * restrict ptree );
+int CONV w_have_checks( tree_t * restrict ptree );
+int CONV b_have_evasion( tree_t * restrict ptree );
+int CONV w_have_evasion( tree_t * restrict ptree );
+int CONV is_move_check_b( const tree_t * restrict ptree, unsigned int move );
+int CONV is_move_check_w( const tree_t * restrict ptree, unsigned int move );
+uint64_t CONV hash_func( const tree_t * restrict ptree );
uint64_t rand64( void );
-trans_entry_t hash_learn_store( const tree_t * restrict ptree, int depth,
- int value, unsigned int move );
FILE *file_open( const char *str_file, const char *str_mode );
-bitboard_t attacks_to_piece( const tree_t * restrict ptree, int sq );
-bitboard_t horse_attacks( const tree_t * restrict ptree, int i );
-const char *str_time( unsigned int time );
-const char *str_time_symple( unsigned int time );
+bitboard_t CONV attacks_to_piece( const tree_t * restrict ptree, int sq );
+bitboard_t CONV b_attacks_to_piece( const tree_t * restrict ptree, int sq );
+bitboard_t CONV w_attacks_to_piece( const tree_t * restrict ptree, int sq );
+const char * CONV str_time( unsigned int time );
+const char * CONV str_time_symple( unsigned int time );
const char *str_CSA_move( unsigned int move );
-const char *str_CSA_move_plus( tree_t * restrict ptree, unsigned int move,
- int ply, int turn );
#if defined(MPV)
int root_mpv;
pv_t mpv_pv[ MPV_MAX_PV*2 + 1 ];
#endif
+# if ! defined(_WIN32) && ( defined(DFPN_CLIENT) || defined(TLP) )
+extern pthread_attr_t pthread_attr;
+# endif
+
+#if defined(DFPN_CLIENT) || defined(TLP)
+void CONV lock( lock_t *plock );
+void CONV unlock( lock_t *plock );
+int CONV lock_init( lock_t *plock );
+int CONV lock_free( lock_t *plock );
+void tlp_yield( void );
+extern lock_t io_lock;
+#endif
+
#if defined(TLP)
# define SignKey(word2, word1) word2 ^= ( word1 )
# define TlpEnd() tlp_end();
-# if ! defined(_WIN32)
-extern pthread_attr_t pthread_attr;
-# endif
-# if defined(MNJ_LAN)
+# if defined(MNJ_LAN) || defined(USI)
uint64_t tlp_count_node( tree_t * restrict ptree );
# endif
-void tlp_yield( void );
void tlp_set_abort( tree_t * restrict ptree );
-void lock( lock_t *plock );
-void unlock( lock_t *plock );
void tlp_end( void );
-int tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
+int CONV tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
int depth, int ply, unsigned int state_node );
int tlp_split( tree_t * restrict ptree );
int tlp_start( void );
int tlp_is_descendant( const tree_t * restrict ptree, int slot_ancestor );
-int lock_init( lock_t *plock );
-int lock_free( lock_t *plock );
extern lock_t tlp_lock;
extern volatile int tlp_abort;
extern volatile int tlp_idle;
extern int tlp_nsplit;
extern int tlp_nabort;
extern int tlp_nslot;
-extern SHARE unsigned short tlp_rejections_slot[ REJEC_MASK+1 ];
extern tree_t tlp_atree_work[ TLP_NUM_WORK ];
extern tree_t * volatile tlp_ptrees[ TLP_MAX_THREADS ];
#else /* no TLP */
int stdout_normal( void );
#endif
-#if defined(CSA_LAN) && defined(MNJ_LAN)
-# define ShutdownClient sckt_shutdown( sckt_mnj ); \
- sckt_shutdown( sckt_csa ); \
- sckt_mnj = sckt_csa = SCKT_NULL
-#elif defined(CSA_LAN)
-# define ShutdownClient sckt_shutdown( sckt_csa ); \
- sckt_csa = SCKT_NULL
-#elif defined(MNJ_LAN)
-# define ShutdownClient sckt_shutdown( sckt_mnj ); \
- sckt_mnj = SCKT_NULL
+#if defined(CSA_LAN) || defined(MNJ_LAN) || defined(DFPN)
+void CONV shutdown_all( void );
+# define ShutdownAll() shutdown_all();
#else
-# define ShutdownClient
+# define ShutdownAll()
#endif
-#if defined(CSA_LAN) || defined(MNJ_LAN)
+#if defined(CSA_LAN)||defined(MNJ_LAN)||defined(DFPN_CLIENT)||defined(DFPN)
int client_next_game( tree_t * restrict ptree, const char *str_addr,
int iport );
-sckt_t sckt_connect( const char *str_addr, int iport );
-int sckt_shutdown( sckt_t sd );
-int sckt_check( sckt_t sd );
-int sckt_in( sckt_t sd, char *str, int n );
-int sckt_out( sckt_t sd, const char *fmt, ... );
+sckt_t CONV sckt_connect( const char *str_addr, int iport );
+int CONV sckt_recv_all( sckt_t sd );
+int CONV sckt_shutdown( sckt_t sd );
+int CONV sckt_check( sckt_t sd );
+int CONV sckt_in( sckt_t sd, char *str, int n );
+int CONV sckt_out( sckt_t sd, const char *fmt, ... );
extern unsigned int time_last_send;
#endif
+#if defined(DFPN)
+# define DFPNOut( ... ) if ( dfpn_sckt != SCKT_NULL ) \
+ sckt_out( dfpn_sckt, __VA_ARGS__ )
+int CONV dfpn( tree_t * restrict ptree, int turn, int ply );
+int CONV dfpn_ini_hash( void );
+extern unsigned int dfpn_hash_log2;
+extern sckt_t dfpn_sckt;
+#else
+# define DFPNOut( ... )
+#endif
+
#if defined(CSA_LAN)
extern int client_turn;
extern int client_ngame;
extern sckt_t sckt_csa;
#endif
+#if defined(MNJ_LAN) || defined(USI)
+extern unsigned int moves_ignore[MAX_LEGAL_MOVES];
+#endif
+
#if defined(MNJ_LAN)
# define MnjOut( ... ) if ( sckt_mnj != SCKT_NULL ) \
sckt_out( sckt_mnj, __VA_ARGS__ )
-extern short mnj_tbl[ MNJ_MASK + 1 ];
extern sckt_t sckt_mnj;
-int mnj_reset_tbl( int sd, unsigned int seed );
+extern int mnj_posi_id;
+extern int mnj_depth_stable;
+void CONV mnj_check_results( void );
+int CONV mnj_reset_tbl( int sd, unsigned int seed );
int analyze( tree_t * restrict ptree );
-int mnj_posi_id;
-unsigned int mnj_move_last;
#else
# define MnjOut( ... )
#endif
-
-#if defined(DEKUNOBOU) || defined(CSA_LAN) || defined(MNJ_LAN)
-const char *str_WSAError( const char *str );
+#if defined(USI)
+# define USIOut( ... ) if ( usi_mode != usi_off ) usi_out( __VA_ARGS__ )
+enum usi_mode { usi_off, usi_on };
+extern enum usi_mode usi_mode;
+extern unsigned int usi_time_out_last;
+extern unsigned int usi_byoyomi;
+void CONV usi_out( const char *format, ... );
+int CONV usi_book( tree_t * restrict ptree );
+int CONV usi_root_list( tree_t * restrict ptree );
+int CONV usi2csa( const tree_t * restrict ptree, const char *str_usi,
+ char *str_csa );
+int CONV csa2usi( const tree_t * restrict ptree, const char *str_csa,
+ char *str_usi );
+int analyze( tree_t * restrict ptree );
+#else
+# define USIOut( ... )
#endif
-#if defined(DEKUNOBOU) && defined(_WIN32)
-# define OutDek( ... ) if ( dek_ngame ) { int i = dek_out( __VA_ARGS__ ); \
- if ( i < 0 ) { return i; } }
+#if defined(CSA_LAN) || defined(MNJ_LAN) || defined(DFPN_CLIENT)||defined(DFPN)
const char *str_WSAError( const char *str );
-int dek_start( const char *str_sddr, int port_dek, int port_bnz );
-int dek_next_game( tree_t * restrict ptree );
-int dek_in( char *str, int n );
-int dek_out( const char *format, ... );
-int dek_parse( char *str, int len );
-int dek_check( void );
-extern SOCKET dek_socket_in;
-extern SOCKET dek_s_accept;
-extern u_long dek_ul_addr;
-extern unsigned int dek_ngame;
-extern unsigned int dek_lost;
-extern unsigned int dek_win;
-extern int dek_turn;
-extern u_short dek_ns;
-#else
-# define OutDek( ... )
#endif
#if defined(CSASHOGI)
# define OutCsaShogi( ... )
#endif
-#define AttackBishop(bb,i) BBOr( bb, AttackDiag1(i), AttackDiag2(i) )
-#define AttackRook(bb,i) (bb) = AttackFile(i); \
- (bb).p[aslide[i].ir0] |= AttackRank(i)
-
extern check_table_t b_chk_tbl[nsquare];
extern unsigned int easy_move;
#endif
+#if defined(INANIWA_SHIFT)
+extern int inaniwa_flag;
+#endif
+
#if defined(MINIMUM)
# define MT_CAP_PAWN ( DPawn + DPawn )
# define MT_CAP_HORSE ( p_value_ex[ 15 + horse ] )
# define MT_CAP_DRAGON ( p_value_ex[ 15 + dragon ] )
# define MT_CAP_KING ( DKing + DKing )
-# define MT_PRO_PAWN ( benefit2promo[ 7 + pawn ] )
-# define MT_PRO_LANCE ( benefit2promo[ 7 + lance ] )
-# define MT_PRO_KNIGHT ( benefit2promo[ 7 + knight ] )
-# define MT_PRO_SILVER ( benefit2promo[ 7 + silver ] )
-# define MT_PRO_BISHOP ( benefit2promo[ 7 + bishop ] )
-# define MT_PRO_ROOK ( benefit2promo[ 7 + rook ] )
+# define MT_PRO_PAWN ( p_value_pm[ 7 + pawn ] )
+# define MT_PRO_LANCE ( p_value_pm[ 7 + lance ] )
+# define MT_PRO_KNIGHT ( p_value_pm[ 7 + knight ] )
+# define MT_PRO_SILVER ( p_value_pm[ 7 + silver ] )
+# define MT_PRO_BISHOP ( p_value_pm[ 7 + bishop ] )
+# define MT_PRO_ROOK ( p_value_pm[ 7 + rook ] )
void fill_param_zero( void );
void ini_param( param_t *p );
int record_setpos( record_t *pr, const rpos_t *prpos );
int record_getpos( record_t *pr, rpos_t *prpos );
int record_rewind( record_t *pr );
-int book_create( tree_t * restrict ptree );
-int hash_learn_create( void );
+int CONV book_create( tree_t * restrict ptree );
int out_param( void );
double calc_penalty( void );
#include <stdlib.h>
#include <limits.h>
+#include <assert.h>
#include "shogi.h"
-int
+int CONV
swap( const tree_t * restrict ptree, unsigned int move, int root_alpha,
int root_beta, int turn )
{
bitboard_t bb, bb_temp, bb_attack;
- unsigned int uattack;
- int attacked_piece, from, to, nc, ir0;
+ int attacked_piece, from, to, nc;
int piece_cap, piece, value, xvalue, alpha, beta, is_promo;
from = (int)I2From( move );
attacked_piece = p_value_ex[15+piece];
if ( is_promo )
{
- value += benefit2promo[7+piece];
- attacked_piece += benefit2promo[7+piece];
+ value += p_value_pm[7+piece];
+ attacked_piece += p_value_pm[7+piece];
}
xvalue = value - attacked_piece - MT_PRO_PAWN;
if ( xvalue >= root_beta ) { return xvalue; }
beta = value;
for ( nc = 1;; nc++ )
{
- /* remove an attacker, and add a hidden piece to attack bitmap */
+ /* remove an attacker, and add a hidden piece to bb_attack */
if ( from < nsquare )
{
Xor( from, bb_attack );
switch ( adirec[to][from] )
{
case direc_rank:
- ir0 = aslide[from].ir0;
- uattack = AttackRank( from );
- if ( from > to ) { uattack &= abb_plus_rays[from].p[ir0]; }
- else { uattack &= abb_minus_rays[from].p[ir0]; }
- uattack &= BB_B_RD.p[ir0] | BB_W_RD.p[ir0];
- bb_attack.p[ir0] |= uattack;
+ bb = AttackRank( from );
+ if ( from > to ) { BBAnd( bb, bb, abb_plus_rays[from] ); }
+ else { BBAnd( bb, bb, abb_minus_rays[from] ); }
+ BBOr( bb_temp, BB_B_RD, BB_W_RD );
+ BBAndOr( bb_attack, bb, bb_temp );
break;
case direc_file:
case direc_diag1:
bb = AttackDiag1( from );
if ( from > to ) { BBAnd( bb, bb, abb_plus_rays[from] ); }
- else { BBAnd( bb, bb, abb_minus_rays[from] ); }
+ else { BBAnd( bb, bb, abb_minus_rays[from] ); }
BBOr( bb_temp, BB_B_BH, BB_W_BH );
BBAnd( bb, bb, bb_temp );
BBOr( bb_attack, bb_attack, bb );
}
}
- if ( ! BBToU( bb_attack ) ) { break; }
- /* find a cheapest piece attacking the target */
- turn = Flip( turn );
- value = attacked_piece - value;
- if ( turn )
- {
- if( BBContract( bb_attack, BB_WPAWN ) )
- {
- from = to-nfile;
- attacked_piece = MT_CAP_PAWN;
- if ( to > 53 )
- {
- value += MT_PRO_PAWN;
- attacked_piece += MT_PRO_PAWN;
- }
- goto ab_cut;
- }
- BBAnd( bb, BB_WLANCE, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_LANCE;
- if ( to > 53 )
- {
- value += MT_PRO_LANCE;
- attacked_piece += MT_PRO_LANCE;
- }
- goto ab_cut;
- }
- BBAnd( bb, BB_WKNIGHT, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_KNIGHT;
- if ( to > 53 )
- {
- value += MT_PRO_KNIGHT;
- attacked_piece += MT_PRO_KNIGHT;
- }
- goto ab_cut;
- }
- BBAnd( bb, BB_WPRO_PAWN, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_PRO_PAWN;
- goto ab_cut;
- }
- BBAnd( bb, BB_WPRO_LANCE, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_PRO_LANCE;
- goto ab_cut;
- }
- BBAnd( bb, BB_WPRO_KNIGHT, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_PRO_KNIGHT;
- goto ab_cut;
- }
- BBAnd( bb, BB_WSILVER, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_SILVER;
- if ( from > 53 || to > 53 )
- {
- value += MT_PRO_SILVER;
- attacked_piece += MT_PRO_SILVER;
- }
- goto ab_cut;
- }
- BBAnd( bb, BB_WPRO_SILVER, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_PRO_SILVER;
- goto ab_cut;
- }
- BBAnd( bb, BB_WGOLD, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_GOLD;
- goto ab_cut;
- }
- BBAnd( bb, BB_WBISHOP, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_BISHOP;
- if ( from > 53 || to > 53 )
- {
- value += MT_PRO_BISHOP;
- attacked_piece += MT_PRO_BISHOP;
- }
- goto ab_cut;
- }
- BBAnd( bb, BB_WHORSE, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_HORSE;
- goto ab_cut;
- }
- BBAnd( bb, BB_WROOK, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_ROOK;
- if ( from > 53 || to > 53 )
- {
- value += MT_PRO_ROOK;
- attacked_piece += MT_PRO_ROOK;
- }
- goto ab_cut;
- }
- BBAnd( bb, BB_WDRAGON, bb_attack );
- if( BBToU( bb ) )
- {
- from = FirstOne( bb );
- attacked_piece = MT_CAP_DRAGON;
- goto ab_cut;
- }
- if( BBContract( bb_attack, BB_WKING ) )
- {
- from = SQ_WKING;
- attacked_piece = MT_CAP_KING;
- goto ab_cut;
- }
- }
- else {
+ /* find the cheapest piece attacks the target */
+ if ( turn ) {
+
+ if ( ! BBContract( bb_attack, BB_BOCCUPY ) ) { break; }
+ value = attacked_piece - value;
+
if( BBContract( bb_attack, BB_BPAWN ) )
{
from = to+nfile;
goto ab_cut;
}
BBAnd( bb, BB_BLANCE, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_LANCE;
goto ab_cut;
}
BBAnd( bb, BB_BKNIGHT, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_KNIGHT;
goto ab_cut;
}
BBAnd( bb, BB_BPRO_PAWN, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_PRO_PAWN;
goto ab_cut;
}
BBAnd( bb, BB_BPRO_LANCE, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_PRO_LANCE;
goto ab_cut;
}
BBAnd( bb, BB_BPRO_KNIGHT, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_PRO_KNIGHT;
goto ab_cut;
}
BBAnd( bb, BB_BSILVER, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_SILVER;
goto ab_cut;
}
BBAnd( bb, BB_BPRO_SILVER, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_PRO_SILVER;
goto ab_cut;
}
BBAnd( bb, BB_BGOLD, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_GOLD;
goto ab_cut;
}
BBAnd( bb, BB_BBISHOP, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_BISHOP;
goto ab_cut;
}
BBAnd( bb, BB_BHORSE, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_HORSE;
goto ab_cut;
}
BBAnd( bb, BB_BROOK, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_ROOK;
goto ab_cut;
}
BBAnd( bb, BB_BDRAGON, bb_attack );
- if( BBToU( bb ) )
+ if( BBTest( bb ) )
{
from = FirstOne( bb );
attacked_piece = MT_CAP_DRAGON;
goto ab_cut;
}
- if( BBContract( bb_attack, BB_BKING ) )
+
+ assert( BBContract( bb_attack, BB_BKING ) );
+
+ from = SQ_BKING;
+ attacked_piece = MT_CAP_KING;
+
+ } else {
+
+ if ( ! BBContract( bb_attack, BB_WOCCUPY ) ) { break; }
+
+ value = attacked_piece - value;
+
+ if( BBContract( bb_attack, BB_WPAWN ) )
+ {
+ from = to-nfile;
+ attacked_piece = MT_CAP_PAWN;
+ if ( to > 53 )
+ {
+ value += MT_PRO_PAWN;
+ attacked_piece += MT_PRO_PAWN;
+ }
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WLANCE, bb_attack );
+ if( BBTest( bb ) )
{
- from = SQ_BKING;
- attacked_piece = MT_CAP_KING;
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_LANCE;
+ if ( to > 53 )
+ {
+ value += MT_PRO_LANCE;
+ attacked_piece += MT_PRO_LANCE;
+ }
goto ab_cut;
}
+ BBAnd( bb, BB_WKNIGHT, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_KNIGHT;
+ if ( to > 53 )
+ {
+ value += MT_PRO_KNIGHT;
+ attacked_piece += MT_PRO_KNIGHT;
+ }
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WPRO_PAWN, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_PRO_PAWN;
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WPRO_LANCE, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_PRO_LANCE;
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WPRO_KNIGHT, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_PRO_KNIGHT;
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WSILVER, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_SILVER;
+ if ( from > 53 || to > 53 )
+ {
+ value += MT_PRO_SILVER;
+ attacked_piece += MT_PRO_SILVER;
+ }
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WPRO_SILVER, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_PRO_SILVER;
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WGOLD, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_GOLD;
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WBISHOP, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_BISHOP;
+ if ( from > 53 || to > 53 )
+ {
+ value += MT_PRO_BISHOP;
+ attacked_piece += MT_PRO_BISHOP;
+ }
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WHORSE, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_HORSE;
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WROOK, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_ROOK;
+ if ( from > 53 || to > 53 )
+ {
+ value += MT_PRO_ROOK;
+ attacked_piece += MT_PRO_ROOK;
+ }
+ goto ab_cut;
+ }
+ BBAnd( bb, BB_WDRAGON, bb_attack );
+ if( BBTest( bb ) )
+ {
+ from = FirstOne( bb );
+ attacked_piece = MT_CAP_DRAGON;
+ goto ab_cut;
+ }
+
+ assert( BBContract( bb_attack, BB_WKING ) );
+ from = SQ_WKING;
+ attacked_piece = MT_CAP_KING;
}
- break;
ab_cut:
+ turn = Flip( turn );
if ( nc & 1 )
{
if ( -value > alpha )
}
}
}
-
+
if ( nc & 1 ) { return beta; }
else { return alpha; }
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
#if defined(_WIN32)
# include <process.h>
#else
+# include <arpa/inet.h>
+# include <sys/types.h>
+# include <unistd.h>
# include <sched.h>
#endif
#include "shogi.h"
+
+#if defined(TLP) || defined(DFPN_CLIENT)
+int CONV
+lock_init( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ *plock = 0;
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ *plock = 0;
+# else
+ if ( pthread_mutex_init( plock, 0 ) )
+ {
+ str_error = "pthread_mutex_init() failed.";
+ return -1;
+ }
+# endif
+ return 1;
+}
+
+
+int CONV
+lock_free( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ *plock = 0;
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ *plock = 0;
+# else
+ if ( pthread_mutex_destroy( plock ) )
+ {
+ str_error = "pthread_mutex_destroy() failed.";
+ return -1;
+ }
+# endif
+ return 1;
+}
+
+
+void CONV
+unlock( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ *plock = 0;
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ *plock = 0;
+# else
+ pthread_mutex_unlock( plock );
+# endif
+}
+
+
+void CONV
+lock( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ while ( _InterlockedExchange( (void *)plock, 1 ) )
+ {
+ while ( *plock ) { tlp_yield();}
+ }
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ int itemp;
+
+ for ( ;; )
+ {
+ asm ( "1: movl $1, %1 \n\t"
+ " xchgl (%0), %1 \n\t"
+ : "=g" (plock), "=r" (itemp) : "0" (plock) );
+ if ( ! itemp ) { return; }
+ while ( *plock ) { tlp_yield();}
+ }
+# else
+ pthread_mutex_lock( plock );
+# endif
+}
+
+
+void
+tlp_yield( void )
+{
+#if defined(_WIN32)
+ Sleep( 0 );
+#else
+ sched_yield();
+#endif
+}
+#endif /* TLP || DFPN_CLIENT */
+
+
+#if defined(DFPN_CLIENT)
+
+static int CONV proce_line( char *line_buf );
+# if defined(_WIN32)
+static unsigned int __stdcall dfpn_client_receiver( void *arg );
+# else
+static void *dfpn_client_receiver( void *arg );
+# endif
+
+void CONV
+dfpn_client_start( const tree_t * restrict ptree )
+{
+ if ( root_turn != min_posi_no_handicap.turn_to_move
+ || HAND_B != min_posi_no_handicap.hand_black
+ || HAND_W != min_posi_no_handicap.hand_white
+ || memcmp( BOARD, min_posi_no_handicap.asquare, nsquare ) )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ return;
+ }
+
+ if ( dfpn_client_sckt != SCKT_NULL ) { return; }
+ if ( dfpn_client_str_addr[0] == '\0' ) { return; }
+
+ dfpn_client_sckt = sckt_connect( dfpn_client_str_addr, dfpn_client_port );
+ if ( dfpn_client_sckt == SCKT_NULL )
+ {
+ out_warning( "Connection to DFPN server failed." );
+ return;
+ }
+ else {
+ Out( "New connection to DFPN server: %s %d\n",
+ dfpn_client_str_addr, dfpn_client_port );
+ }
+
+# if defined(_WIN32)
+ if ( ! _beginthreadex( 0, 0, &dfpn_client_receiver, NULL, 0, 0 ) )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "_beginthreadex() failed." );
+ }
+# else
+ {
+ pthread_t pt;
+ if ( pthread_create( &pt, &pthread_attr, &dfpn_client_receiver, NULL ) )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "_beginthreadex() failed." );
+ }
+ }
+# endif
+
+ dfpn_client_out( "Client: anonymous\n" );
+}
+
+
+# if defined(_MSC_VER)
+# pragma warning(disable:4100)
+# elif defined(__ICC)
+# pragma warning(disable:869)
+# endif
+
+# if defined(_MSC_VER)
+static unsigned int __stdcall dfpn_client_receiver( void *arg )
+# else
+static void *dfpn_client_receiver( void *arg )
+#endif
+{
+#define SIZE_RECV_BUF ( 1024 * 16 )
+#define SIZE_LINE_BUF 1024
+ char recv_buf[ SIZE_RECV_BUF ];
+ char line_buf[ SIZE_LINE_BUF ];
+ char *str_end, *str_line_end;
+ size_t size;
+ int len_recv_buf;
+ struct timeval tv;
+ fd_set readfds;
+ int iret;
+
+ recv_buf[0] = '\0';
+
+ /* recv loop */
+ for ( ;; ) {
+
+ /* select loop */
+ for ( ;; ) {
+ tv.tv_sec = SEC_KEEP_ALIVE;
+ tv.tv_usec = 0;
+ FD_ZERO( &readfds );
+# if defined(_MSC_VER)
+# pragma warning(disable:4127)
+# endif
+ FD_SET( dfpn_client_sckt, &readfds );
+# if defined(_MSC_VER)
+# pragma warning(default:4127)
+# endif
+
+ iret = select( (int)dfpn_client_sckt+1, &readfds, NULL, NULL, &tv );
+ if ( iret == SOCKET_ERROR )
+ {
+ out_warning( "%s", str_error );
+ goto dfpn_client_receiver_shutdown;
+ }
+
+ /* message arrived */
+ if ( iret ) { break; }
+
+ /* timeout and keepalive */
+ lock( &dfpn_client_lock);
+ iret = dfpn_client_out( "ping\n" );
+ unlock( &dfpn_client_lock);
+ if ( iret < 0 ) { return 0; }
+ }
+
+ /* read messages */
+ len_recv_buf = (int)strlen( recv_buf );
+ str_end = recv_buf + len_recv_buf;
+
+ iret = recv( dfpn_client_sckt, str_end, SIZE_RECV_BUF-1-len_recv_buf, 0 );
+ if ( iret == SOCKET_ERROR )
+ {
+ str_error = str_WSAError( "recv() failed:" );
+ out_warning( "%s", str_error );
+ goto dfpn_client_receiver_shutdown;
+ }
+ if ( ! iret ) { goto dfpn_client_receiver_shutdown; }
+ recv_buf[ len_recv_buf + iret ] = '\0';
+
+ /* take each line */
+ lock( &dfpn_client_lock );
+ for ( ;; ) {
+
+ str_line_end = strchr( recv_buf, '\n' );
+ if ( str_line_end == NULL )
+ {
+ if ( iret + len_recv_buf + 1 >= SIZE_RECV_BUF )
+ {
+ unlock( &dfpn_client_lock );
+ out_warning( "%s", str_ovrflw_line );
+ goto dfpn_client_receiver_shutdown;
+ }
+ break;
+ }
+
+ size = str_line_end - recv_buf;
+ if ( size + 1 >= SIZE_LINE_BUF )
+ {
+ unlock( &dfpn_client_lock );
+ out_warning( "%s", str_ovrflw_line );
+ goto dfpn_client_receiver_shutdown;
+ }
+
+ memcpy( line_buf, recv_buf, size );
+ memmove( recv_buf, str_line_end+1, strlen(str_line_end+1) + 1 );
+
+ line_buf[size] = '\0';
+
+ if ( proce_line( line_buf ) < 0 )
+ {
+ unlock( &dfpn_client_lock );
+ out_warning( "invalid messages from DFPN server" );
+ goto dfpn_client_receiver_shutdown;
+ }
+ }
+ unlock( &dfpn_client_lock );
+ }
+
+ dfpn_client_receiver_shutdown:
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "A connection to DFPN server is down." );
+
+ return 0;
+}
+# if defined(_MSC_VER)
+# pragma warning(default:4100)
+# elif defined(__ICC)
+# pragma warning(default:869)
+#endif
+
+
+static int CONV proce_line( char *line_buf )
+{
+ const char *token;
+ volatile dfpn_client_cresult_t *pcresult;
+ char *last;
+
+ token = strtok_r( line_buf, str_delimiters, &last );
+ if ( token == NULL ) { return -1; }
+
+ /* check signature */
+ if ( strcmp( token, (const char *)dfpn_client_signature ) ) { return 1; }
+
+ token = strtok_r( NULL, str_delimiters, &last );
+ if ( token == NULL ) { return -1; }
+
+ /* root node */
+ if ( ! strcmp( token, "WIN" ) )
+ {
+ token = strtok_r( NULL, str_delimiters, &last );
+ if ( token == NULL || ! is_move( token ) ) { return -1; }
+ dfpn_client_rresult = dfpn_client_win;
+ dfpn_client_flag_read = 1;
+ memcpy( (char *)dfpn_client_str_move, token, 7 );
+ return 1;
+ }
+
+ if ( ! strcmp( token, "LOSE" ) )
+ {
+ dfpn_client_rresult = dfpn_client_lose;
+ dfpn_client_flag_read = 1;
+ return 1;
+ }
+
+ if ( ! strcmp( token, "UNSOLVED" ) )
+ {
+ dfpn_client_rresult = dfpn_client_misc;
+ dfpn_client_flag_read = 1;
+ return 1;
+ }
+
+ /* child node */
+ if ( ! is_move( token ) ) { return -1; }
+ if ( MAX_LEGAL_MOVES <= dfpn_client_num_cresult ) { return -1; }
+ pcresult = &dfpn_client_cresult[dfpn_client_num_cresult];
+ memcpy( (char *)pcresult->str_move, token, 7 );
+
+ token = strtok_r( NULL, str_delimiters, &last );
+ if ( token == NULL ) { return -1; }
+
+ if ( ! strcmp( token, "WIN" ) )
+ {
+ pcresult->result = dfpn_client_win;
+ dfpn_client_flag_read = 1;
+ dfpn_client_num_cresult += 1;
+ return 1;
+ }
+
+ if ( ! strcmp( token, "LOSE" ) )
+ {
+ pcresult->result = dfpn_client_lose;
+ dfpn_client_flag_read = 1;
+ dfpn_client_num_cresult += 1;
+ return 1;
+ }
+
+ if ( ! strcmp( token, "UNSOLVED" ) )
+ {
+ pcresult->result = dfpn_client_misc;
+ dfpn_client_flag_read = 1;
+ dfpn_client_num_cresult += 1;
+ return 1;
+ }
+
+ return -1;
+}
+
+#endif /* DFPN_CLINET */
+
+
#if defined(TLP)
# if defined(_WIN32)
}
-#if defined(MNJ_LAN)
+#if defined(MNJ_LAN) || defined(USI)
uint64_t
tlp_count_node( tree_t * restrict ptree )
{
}
-int
-lock_init( lock_t *plock )
-{
-# if defined(_MSC_VER)
- *plock = 0;
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- *plock = 0;
-# else
- if ( pthread_mutex_init( plock, 0 ) )
- {
- str_error = "pthread_mutex_init() failed.";
- return -1;
- }
-# endif
- return 1;
-}
-
-
-int
-lock_free( lock_t *plock )
-{
-# if defined(_MSC_VER)
- *plock = 0;
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- *plock = 0;
-# else
- if ( pthread_mutex_destroy( plock ) )
- {
- str_error = "pthread_mutex_destroy() failed.";
- return -1;
- }
-# endif
- return 1;
-}
-
-
-void
-unlock( lock_t *plock )
-{
-# if defined(_MSC_VER)
- *plock = 0;
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- *plock = 0;
-# else
- pthread_mutex_unlock( plock );
-# endif
-}
-
-
-void
-lock( lock_t *plock )
-{
-# if defined(_MSC_VER)
- long l;
-
- for ( ;; )
- {
- l = _InterlockedExchange( (void *)plock, 1 );
- if ( ! l ) { return; }
- while ( *plock );
- }
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- int itemp;
-
- for ( ;; )
- {
- asm ( "1: movl $1, %1 \n\t"
- " xchgl (%0), %1 \n\t"
- : "=g" (plock), "=r" (itemp) : "0" (plock) );
- if ( ! itemp ) { return; }
- while ( *plock );
- }
-# else
- pthread_mutex_lock( plock );
-# endif
-}
-
-
-void
-tlp_yield( void )
-{
-#if defined(_WIN32)
- Sleep( 0 );
-#else
- sched_yield();
-#endif
-}
-
-
# if defined(_MSC_VER)
static unsigned int __stdcall start_address( void *arg )
# else
child->nperpetual_check = 0;
child->nsuperior_rep = 0;
child->nrep_tried = 0;
- child->nreject_tried = 0;
- child->nreject_done = 0;
child->ntrans_always_hit = 0;
child->ntrans_prefer_hit = 0;
child->ntrans_probe = 0;
child->anext_move[ply].move_cap2 = parent->anext_move[ply].move_cap2;
child->move_last[ply] = child->amove;
- child->stand_pat[ply] = parent->stand_pat[ply];
+ child->save_eval[ply] = parent->save_eval[ply];
child->current_move[ply-1] = parent->current_move[ply-1];
child->nsuc_check[ply-1] = parent->nsuc_check[ply-1];
child->nsuc_check[ply] = parent->nsuc_check[ply];
+ child->nrep = parent->nrep;
memcpy( child->hist_good, parent->hist_good, sizeof(parent->hist_good) );
memcpy( child->hist_tried, parent->hist_tried, sizeof(parent->hist_tried) );
- for ( i = 0; i < root_nrep + ply - 1; i++ )
+ for ( i = 0; i < child->nrep + ply - 1; i++ )
{
child->rep_board_list[i] = parent->rep_board_list[i];
child->rep_hand_list[i] = parent->rep_hand_list[i];
parent->nfour_fold_rep += child->nfour_fold_rep;
parent->nperpetual_check += child->nperpetual_check;
parent->nsuperior_rep += child->nsuperior_rep;
- parent->nreject_tried += child->nreject_tried;
- parent->nreject_done += child->nreject_done;
parent->ntrans_always_hit += child->ntrans_always_hit;
parent->ntrans_prefer_hit += child->ntrans_prefer_hit;
parent->ntrans_probe += child->ntrans_probe;
if ( child->tlp_abort || value <= parent->tlp_best ) { return; }
- ply = parent->tlp_ply;
- parent->tlp_best = (short)value;
- parent->pv[ply] = child->pv[ply];
+ ply = parent->tlp_ply;
+ parent->tlp_best = (short)value;
+ parent->pv[ply] = child->pv[ply];
+
+ lock( &parent->tlp_lock );
parent->current_move[ply] = child->current_move[ply];
-
memcpy( parent->hist_tried, child->hist_tried, sizeof(child->hist_tried) );
memcpy( parent->hist_good, child->hist_good, sizeof(child->hist_good) );
-
for ( i = ply; i < PLY_MAX; i++ )
{
parent->amove_killer[i] = child->amove_killer[i];
parent->killers[i] = child->killers[i];
}
+ unlock( &parent->tlp_lock );
}
#include "shogi.h"
-void
+void CONV
set_search_limit_time( int turn )
/*
[inputs]
time_max_limit = time_limit = UINT_MAX;
return;
}
-
+
+#if defined(USI)
+ if ( usi_mode != usi_off && usi_byoyomi )
+ {
+ time_max_limit = time_limit = usi_byoyomi;
+ Out( "- time ctrl: %u -- %u\n", time_limit, time_max_limit );
+ return;
+ }
+#endif
+
/* not punctual to the time */
if ( ! sec_limit && ( game_status & flag_time_extendable ) )
{
if ( u0 == 2U ) { u0 = 3U; }
/* 'byo-yomi' is so long that the ordinary time-limit is negligible. */
- if ( u0 < sec_limit_up * 3U / 2U ) { u0 = sec_limit_up * 3U / 2U; }
+ if ( u0 < sec_limit_up * 5U ) { u0 = sec_limit_up * 5U; }
u1 = u0 * 5U;
}
-int
-renovate_time( int turn )
+int CONV
+update_time( int turn )
{
unsigned int te, time_elapsed;
int iret;
}
-void
+void CONV
adjust_time( unsigned int elapsed_new, int turn )
{
const char *str = "TIME SKEW DETECTED";
}
-int
+int CONV
reset_time( unsigned int b_remain, unsigned int w_remain )
{
if ( sec_limit_up == UINT_MAX )
}
-const char *
+const char * CONV
str_time( unsigned int time )
{
static char str[32];
}
-const char *
+const char * CONV
str_time_symple( unsigned int time )
{
static char str[32];
}
-int
+int CONV
get_cputime( unsigned int *ptime )
{
#if defined(_WIN32)
}
-int
+int CONV
get_elapsed( unsigned int *ptime )
{
#if defined(_WIN32)
BOARD[from] = piece
-void
+void CONV
unmake_move_b( tree_t * restrict ptree, unsigned int move, int ply )
{
int from = (int)I2From(move);
int to = (int)I2To(move);
- int nrep = root_nrep + ply - 1;
+ int nrep = ptree->nrep + ply - 1;
HASH_KEY = ptree->rep_board_list[nrep];
MATERIAL = ptree->save_material[ply];
}
-void
+void CONV
unmake_move_w( tree_t * restrict ptree, unsigned int move, int ply )
{
int from = (int)I2From(move);
int to = (int)I2To(move);
- int nrep = root_nrep + ply - 1;
+ int nrep = ptree->nrep + ply - 1;
HASH_KEY = ptree->rep_board_list[nrep];
MATERIAL = ptree->save_material[ply];
#include "shogi.h"
-int
+int CONV
ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi, int flag,
const char *str_name1, const char *str_name2 )
{
int piece;
int sq, iret;
+#if defined(INANIWA_SHIFT)
+ if ( inaniwa_flag )
+ {
+ inaniwa_flag = 0;
+ ehash_clear();
+ iret = ini_trans_table();
+ if ( iret < 0 ) { return iret; }
+ }
+#endif
+
if ( flag & flag_history )
{
iret = open_history( str_name1, str_name2 );
ptree->move_last[0] = ptree->amove;
ptree->nsuc_check[0] = 0;
ptree->nsuc_check[1] = 0;
- root_nrep = 0;
+ ptree->nrep = 0;
root_turn = pmin_posi->turn_to_move;
HAND_B = pmin_posi->hand_black;
HAND_W = pmin_posi->hand_white;
memset( ptree->hist_good, 0, sizeof(ptree->hist_good) );
memset( ptree->hist_tried, 0, sizeof(ptree->hist_tried) );
- memset( hash_rejections_parent, 0, sizeof(hash_rejections_parent) );
- memset( hash_rejections, 0, sizeof(hash_rejections) );
- game_status &= ( flag_quiet | flag_reverse | flag_narrow_book
+ game_status &= ( flag_reverse | flag_narrow_book
| flag_time_extendable | flag_learning
| flag_nobeep | flag_nostress | flag_nopeek
- | flag_noponder | flag_noprompt );
+ | flag_noponder | flag_noprompt | flag_sendpv
+ | flag_nostdout | flag_nonewlog );
sec_b_total = 0;
sec_w_total = 0;
sec_elapsed = 0;
last_root_value = 0;
- n_nobook_move = 0;
last_pv.depth = 0;
last_pv.length = 0;
last_pv.a[0] = 0;
return iret;
}
+ /* connect to Tsumeshogi server */
+#if defined(DFPN_CLIENT)
+ lock( &dfpn_client_lock );
+ dfpn_client_start( ptree );
+ snprintf( (char *)dfpn_client_signature, DFPN_CLIENT_SIZE_SIGNATURE,
+ "%" PRIx64 "_%x_%x_%x", HASH_KEY, HAND_B, HAND_W, root_turn );
+ dfpn_client_signature[DFPN_CLIENT_SIZE_SIGNATURE-1] = '\0';
+ dfpn_client_rresult = dfpn_client_na;
+ dfpn_client_num_cresult = 0;
+ dfpn_client_flag_read = 0;
+ dfpn_client_out( "new %s\n", dfpn_client_signature );
+ unlock( &dfpn_client_lock );
+#endif
+
return 1;
}
-int
-gen_legal_moves( tree_t * restrict ptree, unsigned int *p0 )
+int CONV gen_legal_moves( tree_t * restrict ptree, unsigned int *p0, int flag )
{
unsigned int *p1;
int i, j, n;
p1 = GenCaptures( root_turn, p0 );
p1 = GenNoCaptures( root_turn, p1 );
- p1 = GenCapNoProEx2( root_turn, p1 );
- p1 = GenNoCapNoProEx2( root_turn, p1 );
+ if ( flag )
+ {
+ p1 = GenCapNoProEx2( root_turn, p1 );
+ p1 = GenNoCapNoProEx2( root_turn, p1 );
+ }
p1 = GenDrop( root_turn, p1 );
n = (int)( p1 - p0 );
}
else { i++; }
}
-
+
return n;
}
- detection of perpetual check is omitted.
- weak moves are omitted.
*/
-int
+int CONV
is_mate( tree_t * restrict ptree, int ply )
{
int iret = 0;
}
-int
+int CONV
is_hand_eq_supe( unsigned int u, unsigned int uref )
{
#if 1
/* weak moves are omitted. */
-int
+int CONV
detect_repetition( tree_t * restrict ptree, int ply, int turn, int nth )
{
const unsigned int *p;
int n, i, imin, counter, irep, ncheck;
ncheck = (int)ptree->nsuc_check[ply];
- n = root_nrep + ply - 1;
+ n = ptree->nrep + ply - 1;
/*if ( ncheck >= 6 )*/
if ( ncheck >= nth * 2 )
}
-int
+int CONV
com_turn_start( tree_t * restrict ptree, int flag )
{
const char *str_move;
unsigned int move, sec_total;
- int iret, is_resign, value, ply;
+ int iret, is_resign, value;
if ( ! ( flag & flag_from_ponder ) )
{
time_start = time_turn_start;
game_status |= flag_thinking;
- iret = iterate( ptree, flag );
+ iret = iterate( ptree );
game_status &= ~flag_thinking;
if ( iret < 0 ) { return iret; }
}
move = last_pv.a[1];
value = root_turn ? -last_root_value : last_root_value;
- str_move = str_CSA_move( move );
if ( value < -resign_threshold && last_pv.type != pv_fail_high )
{
-#if defined(DEKUNOBOU)
- if ( dek_ngame )
- {
- dek_lost += 1;
- Out( "Bonanza lost against Dekunobou\n" );
- }
-#endif
is_resign = 1;
}
- else {
- is_resign = 0;
-
-#if defined(DEKUNOBOU)
- if ( dek_ngame && ! is_resign
- && value > ( MT_CAP_DRAGON * 3 ) / 2
- && value > resign_threshold
- && value != score_inferior )
- {
- is_resign = 1;
- dek_win += 1;
- Out( "Bonanza won against Dekunobou.\n" );
- }
- if ( dek_ngame && ! is_resign && value == -score_draw )
- {
- iret = make_move_root( ptree, move, ( flag_rep | flag_nomake_move ) );
- if ( iret < 0 )
- {
- Out( "%s\n\n", str_move );
- return iret;
- }
- else if ( iret == 2 )
- {
- is_resign = 1;
- Out( "The game with Dekunobou is drawn.\n" );
- }
- }
- if ( dek_ngame && ! is_resign && record_game.moves > 255 )
- {
- is_resign = 1;
- Out( "The game with Dekunobou is interrupted...\n" );
- }
-#endif
- }
+ else { is_resign = 0; }
#if defined(DBG_EASY)
if ( easy_move && easy_move != move )
}
#endif
OutCsaShogi( "resign\n" );
- OutDek( "%%TORYO\n" );
}
else {
-#if defined(CSA_LAN)
- if ( sckt_csa != SCKT_NULL )
+#if defined(USI)
+ if ( usi_mode != usi_off )
{
- iret = sckt_out( sckt_csa, "%c%s\n", ach_turn[root_turn], str_move );
- if ( iret < 0 ) { return iret; }
+ char buf[6];
+ csa2usi( ptree, str_CSA_move(move), buf );
+ USIOut( "bestmove %s\n", buf );
}
#endif
- OutCsaShogi( "move%s\n", str_move );
- OutDek( "%c%s\n", ach_turn[root_turn], str_move );
- }
- OutBeep();
+ OutCsaShogi( "move%s\n", str_CSA_move( move ) );
- /* learning and stuff */;
- ply = record_game.moves;
- if ( ply < HASH_REG_HIST_LEN )
- {
- history_book_learn[ply].data &= ~( (1U<<31) | 0xffffU );
- history_book_learn[ply].data |= (unsigned int)(value+32768);
- history_book_learn[ply].move_responsible = move;
- history_book_learn[ply].key_responsible = (unsigned int)HASH_KEY;
- history_book_learn[ply].hand_responsible = (unsigned int)HAND_B;
+#if defined(CSA_LAN)
+ if ( sckt_csa != SCKT_NULL ) {
+
+ if ( game_status & flag_sendpv ) {
+ int i, turn, byte;
+ char buf[256];
+
+ byte = snprintf( buf, 256, "%c%s,\'* %d",
+ ach_turn[root_turn], str_CSA_move( move ),
+ last_root_value );
+
+ turn = root_turn;
+ for( i = 2; i <= last_pv.length && i < 5; i++ )
+ {
+ turn = Flip(turn);
+ byte += snprintf( buf+byte, 256-byte, " %c%s",
+ ach_turn[turn], str_CSA_move(last_pv.a[i]) );
+ }
+
+ iret = sckt_out( sckt_csa, "%s\n", buf );
+ if ( iret < 0 ) { return iret; }
+
+ } else {
+
+ iret = sckt_out( sckt_csa, "%c%s\n", ach_turn[root_turn],
+ str_CSA_move( move ) );
+ if ( iret < 0 ) { return iret; }
+ }
}
-
- iret = hash_learn( ptree, move, value, iteration_depth - 1 );
- if ( iret < 0 ) { return iret; }
-
+#endif
+ }
+ OutBeep();
+
/* show search result and make a move */
if ( is_resign )
{
show_prompt();
game_status |= flag_resigned;
- renovate_time( root_turn );
+ update_time( root_turn );
out_CSA( ptree, &record_game, MOVE_RESIGN );
sec_total = root_turn ? sec_w_total : sec_b_total;
str_move = "resign";
else {
show_prompt();
iret = make_move_root( ptree, move,
- ( flag_rep | flag_time | flag_history
- | flag_rejections ) );
- if ( iret < 0 )
- {
- Out( "%s\n\n", str_move );
- return iret;
- }
+ ( flag_rep | flag_time | flag_history ) );
+ if ( iret < 0 ) { return iret; }
sec_total = root_turn ? sec_b_total : sec_w_total;
+ str_move = str_CSA_move( move );
}
OutCsaShogi( "info tt %03u:%02u\n", sec_total / 60U, sec_total % 60U );
if ( iret < 0 ) { return iret; }
#endif
}
-
+
return 1;
}
-
#if defined(MNJ_LAN)
-int mnj_reset_tbl( int sd, unsigned int seed )
+int CONV mnj_reset_tbl( int sd, unsigned int seed )
{
double average, deviation, d;
unsigned int u;
int i, j;
+ if ( sd <= 0 ) { return load_fv(); }
+
+ if ( load_fv() < 0 ) { return -1; }
if ( clear_trans_table() < 0 ) { return -1; }
ehash_clear();
- if ( sd <= 0 )
- {
- for ( i = 0; i < MNJ_MASK + 1; i++ ) { mnj_tbl[i] = 0; }
- return 1;
- }
ini_rand( seed );
+ average = 0.0;
+ deviation = 0.0;
- for( i = 0; i < MNJ_MASK + 1; i++ )
+ for( i = 0; i < nsquare * pos_n; i++ )
{
d = -6.0;
for ( j = 0; j < 12; j++ ) { d += (double)rand32() / (double)UINT_MAX; }
- mnj_tbl[i] = (short)( (double)sd * d );
+ d *= (double)sd;
+ average += d;
+ deviation += d * d;
+ pc_on_sq[0][i] = (short)( (int)pc_on_sq[0][i] + (int)d );
}
- average = 0.0;
- for ( i = 0; i < MNJ_MASK + 1; i++ ) { average += (double)mnj_tbl[i]; }
- average /= (double)( MNJ_MASK + 1 );
-
- deviation = 0.0;
- for ( i = 0; i < MNJ_MASK + 1; i++ )
+ for( i = 0; i < nsquare * nsquare * kkp_end; i++ )
{
- d = (double)mnj_tbl[i] - average;
- deviation += d * d;
+ d = -6.0;
+
+ for ( j = 0; j < 12; j++ ) { d += (double)rand32() / (double)UINT_MAX; }
+ d *= (double)sd;
+ average += d;
+ deviation += d * d;
+ kkp[0][0][i] = (short)( (int)kkp[0][0][i] + (int)d );
}
- deviation = sqrt( deviation / (double)( MNJ_MASK + 1 ) );
+
+ average /= (double)( nsquare * pos_n + nsquare * nsquare * kkp_end );
+ deviation /= (double)( nsquare * pos_n + nsquare * nsquare * kkp_end );
+ deviation = sqrt( deviation );
if ( get_elapsed( &u ) < 0 ) { return -1; }
ini_rand( u );
Out( "\nThe normal distribution N(0,sd^2) is generated.\n" );
- Out( " actual average: % .3f\n", average );
- Out( " actual standard deviation: % .3f\n", deviation );
+ Out( " actual average: % .7f\n", average );
+ Out( " actual standard deviation: % .7f\n", deviation );
Out( "rand seed = %x\n", u );
return 1;
}
#endif
-
-void *
-memory_alloc( size_t nbytes )
+void * CONV memory_alloc( size_t nbytes )
{
#if defined(_WIN32)
void *p = VirtualAlloc( NULL, nbytes, MEM_COMMIT, PAGE_READWRITE );
}
-int
-memory_free( void *p )
+int CONV memory_free( void *p )
{
#if defined(_WIN32)
if ( VirtualFree( p, 0, MEM_RELEASE ) ) { return 1; }
#include "shogi.h"
-int
+int CONV
is_move_valid( tree_t * restrict __ptree__, unsigned int move, int turn )
{
tree_t * restrict ptree = __ptree__;
case lance: case bishop: case horse: case rook: case dragon:
BBOr( bb, BB_BOCCUPY, BB_WOCCUPY );
BBAnd( bb, bb, abb_obstacle[from][to] );
- if ( BBToU( bb ) ) { return 0; }
+ if ( BBTest( bb ) ) { return 0; }
break;
}
str_error = "too many " # piece "s"; \
return -2; }
-int
+int CONV
exam_tree( const tree_t * restrict ptree )
{
int npawn, nlance, nknight, nsilver, ngold, nbishop, nrook;