From 31daebfc1031441aa180e3af2e547a8cd2b92c32 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Sun, 15 Sep 2013 10:05:54 +0200 Subject: [PATCH] Upgrade to Bonanza 6.0 --- Makefile | 85 ++- Makefile.vs | 76 +- attack.c | 294 ++++-- bitop.c | 22 +- book.c | 101 +- csa.c | 209 +++-- data.c | 166 ++- debug.c | 4 +- dek.c | 314 ----- evaldiff.c | 75 +- evaluate.c | 466 ++++++-- gencap.c | 72 +- genchk.c | 3877 +++++++++++++++++++++++++++++++++++++---------------------- gendrop.c | 8 +- genevasn.c | 573 ++++++++- gennocap.c | 56 +- hash.c | 660 ++--------- ini.c | 846 ++++++------- io.c | 387 ++++--- iterate.c | 518 ++++++-- learn1.c | 101 +- learn2.c | 36 +- main.c | 59 +- makemove.c | 139 ++- mate1ply.c | 518 ++++----- mate3.c | 179 ++- movgenex.c | 44 +- next.c | 7 +- param.h | 24 +- phash.c | 550 +++++----- ponder.c | 34 +- problem.c | 58 +- proce.c | 998 +++++++++++----- quiesrch.c | 64 +- readme.txt | 1207 ++++++++++--------- root.c | 120 +-- sckt.c | 149 ++- search.c | 550 +++------ searchr.c | 346 ++++-- shogi.h | 612 +++++----- swap.c | 329 +++--- thread.c | 467 ++++++-- time.c | 31 +- unmake.c | 8 +- utility.c | 231 ++-- valid.c | 6 +- 46 files changed, 9047 insertions(+), 6629 deletions(-) delete mode 100644 dek.c diff --git a/Makefile b/Makefile index 856e931..f5189ed 100644 --- a/Makefile +++ b/Makefile @@ -3,43 +3,96 @@ OBJS =data.o main.o io.o proce.o utility.o ini.o attack.o book.o makemove.o \ 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 diff --git a/Makefile.vs b/Makefile.vs index 6a966ba..f533d94 100644 --- a/Makefile.vs +++ b/Makefile.vs @@ -1,24 +1,30 @@ 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\ @@ -26,22 +32,66 @@ OBJS = data.obj main.obj io.obj proce.obj ini.obj utility.obj attack.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 @@ -50,6 +100,12 @@ bonanza.res : bonanza.rc bonanza.ico $(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 diff --git a/attack.c b/attack.c index 2c9cf78..798a30b 100644 --- a/attack.c +++ b/attack.c @@ -2,21 +2,19 @@ #include #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; @@ -52,20 +50,19 @@ is_pinned_on_white_king( const tree_t * restrict ptree, int isquare, } -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; @@ -101,7 +98,7 @@ is_pinned_on_black_king( const tree_t * restrict ptree, int isquare, /* 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; @@ -121,7 +118,7 @@ is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop ) 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 ); @@ -137,9 +134,8 @@ is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop ) 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 ) ) @@ -159,7 +155,7 @@ is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop ) } -int +int CONV is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop ) { bitboard_t bb, bb_sum, bb_move; @@ -179,7 +175,7 @@ is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop ) 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 ); @@ -195,9 +191,8 @@ is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop ) 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 ) ) @@ -217,7 +212,131 @@ is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop ) } -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; @@ -234,10 +353,8 @@ attacks_to_piece( const tree_t * restrict ptree, int sq ) 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] ); @@ -249,71 +366,112 @@ attacks_to_piece( const tree_t * restrict ptree, int 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); } diff --git a/bitop.c b/bitop.c index 13fbe58..805a6a4 100644 --- a/bitop.c +++ b/bitop.c @@ -1,6 +1,6 @@ #include "shogi.h" -int +int CONV popu_count012( unsigned int u0, unsigned int u1, unsigned int u2 ) { int counter = 0; @@ -13,7 +13,7 @@ popu_count012( unsigned int u0, unsigned int u1, unsigned int u2 ) #if defined(_MSC_VER) -int +int CONV first_one012( unsigned int u0, unsigned int u1, unsigned int u2 ) { unsigned long index; @@ -24,7 +24,7 @@ first_one012( unsigned int u0, unsigned int u1, unsigned int u2 ) return 80 - index; } -int +int CONV last_one210( unsigned int u2, unsigned int u1, unsigned int u0 ) { unsigned long index; @@ -35,7 +35,7 @@ last_one210( unsigned int u2, unsigned int u1, unsigned int u0 ) return 26 - index; } -int +int CONV first_one01( unsigned int u0, unsigned int u1 ) { unsigned long index; @@ -45,7 +45,7 @@ first_one01( unsigned int u0, unsigned int u1 ) return 53 - index; } -int +int CONV first_one12( unsigned int u1, unsigned int u2 ) { unsigned long index; @@ -55,7 +55,7 @@ first_one12( unsigned int u1, unsigned int u2 ) return 80 - index; } -int +int CONV last_one01( unsigned int u0, unsigned int u1 ) { unsigned long index; @@ -65,7 +65,7 @@ last_one01( unsigned int u0, unsigned int u1 ) return 26 - index; } -int +int CONV last_one12( unsigned int u1, unsigned u2 ) { unsigned long index; @@ -75,7 +75,7 @@ last_one12( unsigned int u1, unsigned u2 ) return 53 - index; } -int +int CONV first_one1( unsigned int u1 ) { unsigned long index; @@ -84,7 +84,7 @@ first_one1( unsigned int u1 ) return 53 - index; } -int +int CONV first_one2( unsigned int u2 ) { unsigned long index; @@ -93,7 +93,7 @@ first_one2( unsigned int u2 ) return 80 - index; } -int +int CONV last_one0( unsigned int u0 ) { unsigned long index; @@ -102,7 +102,7 @@ last_one0( unsigned int u0 ) return 26 - index; } -int +int CONV last_one1( unsigned int u1 ) { unsigned long index; diff --git a/book.c b/book.c index e8336e6..9a732b8 100644 --- a/book.c +++ b/book.c @@ -48,16 +48,18 @@ typedef struct { unsigned short smove, freq; } book_move_t; 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 ); @@ -70,7 +72,7 @@ book_on( void ) } -int +int CONV book_off( void ) { int iret = file_close( pf_book ); @@ -82,7 +84,7 @@ book_off( void ) } -int +int CONV book_probe( tree_t * restrict ptree ) { book_move_t abook_move[ BK_MAX_MOVE+1 ]; @@ -163,18 +165,6 @@ book_probe( tree_t * restrict ptree ) 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; @@ -182,7 +172,7 @@ book_probe( tree_t * restrict ptree ) } -static int +static int CONV book_read( uint64_t key, book_move_t *pbook_move, unsigned int *pposition ) { uint64_t book_key; @@ -252,7 +242,7 @@ book_read( uint64_t key, book_move_t *pbook_move, unsigned int *pposition ) } -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; @@ -290,7 +280,7 @@ flip_ft( ft_t ft, int turn, int is_flip ) } -static unsigned int +static unsigned int CONV bm2move( const tree_t * restrict ptree, unsigned int bmove, int is_flip ) { ft_t ft; @@ -319,7 +309,7 @@ bm2move( const tree_t * restrict ptree, unsigned int bmove, int is_flip ) } -static uint64_t +static uint64_t CONV book_hash_func( const tree_t * restrict ptree, int *pis_flip ) { uint64_t key, key_flip; @@ -409,7 +399,7 @@ book_hash_func( const tree_t * restrict ptree, int *pis_flip ) } -static int +static int CONV normalize_book_move( book_move_t * restrict pbook_move, int moves ) { book_move_t swap; @@ -458,7 +448,7 @@ normalize_book_move( book_move_t * restrict pbook_move, int moves ) #if ! defined(MINIMUM) #define MaxNumCell 0x400000 -#if defined(BK_SMALL) +#if defined(BK_SMALL) || defined(BK_TINY) # define MaxPlyBook 64 #else # define MaxPlyBook 128 @@ -474,21 +464,21 @@ typedef struct { 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; @@ -590,7 +580,7 @@ book_create( tree_t * restrict ptree ) } -static int +static int CONV read_anti_book( tree_t * restrict ptree, record_t * pr ) { uint64_t key; @@ -675,7 +665,7 @@ read_anti_book( tree_t * restrict ptree, record_t * pr ) } -static int +static int CONV make_cell_csa( tree_t * restrict ptree, record_t *pr, cell_t *pcell, int num_tmpfile ) { @@ -793,7 +783,7 @@ make_cell_csa( tree_t * restrict ptree, record_t *pr, cell_t *pcell, } -static int +static int CONV merge_cell( record_move_t *precord_move, FILE **ppf, int num_tmpfile ) { double dscale; @@ -1004,13 +994,15 @@ merge_cell( record_move_t *precord_move, FILE **ppf, int num_tmpfile ) } -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 @@ -1028,7 +1020,7 @@ move_selection( const record_move_t *p, int ngame, int nwin ) } -static int +static int CONV find_min_cell( const cell_t *pcell, int num_tmpfile ) { int imin, i; @@ -1042,7 +1034,7 @@ find_min_cell( const cell_t *pcell, int num_tmpfile ) } -static int +static int CONV read_a_cell( cell_t *pcell, FILE *pf ) { if ( fread( &pcell->key, sizeof(uint64_t), 1, pf ) != 1 ) @@ -1070,7 +1062,7 @@ read_a_cell( cell_t *pcell, FILE *pf ) } -static int +static int CONV examine_game( tree_t * restrict ptree, record_t *pr, int *presult, unsigned int *pmoves ) { @@ -1143,7 +1135,7 @@ examine_game( tree_t * restrict ptree, record_t *pr, int *presult, } -static int +static int CONV dump_cell( cell_t *pcell, int ncell, int num_tmpfile ) { char str_filename[SIZE_FILENAME]; @@ -1189,8 +1181,7 @@ dump_cell( cell_t *pcell, int ncell, int num_tmpfile ) } -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; @@ -1208,7 +1199,7 @@ compare( const void * p1, const void * p2 ) } -static unsigned int +static unsigned int CONV move2bm( unsigned int move, int turn, int is_flip ) { ft_t ft; diff --git a/csa.c b/csa.c index e99f953..cbf1bf6 100644 --- a/csa.c +++ b/csa.c @@ -421,77 +421,6 @@ interpret_CSA_move( tree_t * restrict ptree, unsigned int *pmove, 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]; @@ -575,6 +504,144 @@ read_board_rep1( const char *str_line, min_posi_t *pmin_posi ) } +#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 ) { diff --git a/data.c b/data.c index 97e9500..5941400 100644 --- a/data.c +++ b/data.c @@ -3,19 +3,15 @@ #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 ]; @@ -26,6 +22,7 @@ bitboard_t abb_w_gold_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 ]; @@ -78,6 +75,7 @@ uint64_t w_hand_bishop_rand[ nbishop_max ]; 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; @@ -96,12 +94,8 @@ unsigned int time_turn_start; 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; @@ -115,23 +109,20 @@ SHARE int fmg_cap_king; 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; @@ -140,9 +131,14 @@ int ngold_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 ]; @@ -158,10 +154,37 @@ int mpv_width; 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 ]; @@ -172,7 +195,6 @@ int tlp_max; int tlp_nsplit; int tlp_nabort; int tlp_nslot; -volatile unsigned short tlp_rejections_slot[ REJEC_MASK+1 ]; #else tree_t tree; #endif @@ -186,7 +208,7 @@ FILE *pf_log; 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 @@ -201,22 +223,21 @@ char client_str_pwd[256]; 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]; @@ -244,33 +265,37 @@ const char *str_myname = ( "Bonanza " BNZ_VER " Debug Build (" 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 @@ -281,16 +306,25 @@ const char *astr_table_piece[16] = { "* ", "FU", "KY", "KE", "GI", "KI", 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, diff --git a/debug.c b/debug.c index d18b86f..9132c6c 100644 --- a/debug.c +++ b/debug.c @@ -15,13 +15,13 @@ # 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 ); } \ diff --git a/dek.c b/dek.c deleted file mode 100644 index b3464ac..0000000 --- a/dek.c +++ /dev/null @@ -1,314 +0,0 @@ -#include -#include -#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 */ diff --git a/evaldiff.c b/evaldiff.c index c43e4fe..9702365 100644 --- a/evaldiff.c +++ b/evaldiff.c @@ -1,13 +1,16 @@ #include #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; @@ -51,7 +54,7 @@ check_futile_score_quies( const tree_t * restrict ptree, unsigned int move, else { if ( I2IsPromote(move) ) { - fmt -= benefit2promo[7+I2PieceMove(move)]; + fmt -= p_value_pm[7+I2PieceMove(move)]; } if ( ipc_cap ) @@ -67,19 +70,21 @@ check_futile_score_quies( const tree_t * restrict ptree, unsigned int move, } -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 ) { @@ -110,7 +115,7 @@ eval_max_score( const tree_t * restrict ptree, unsigned int move, if ( I2IsPromote(move) ) { - score_mt += benefit2promo[7+I2PieceMove(move)]; + score_mt += p_value_pm[7+I2PieceMove(move)]; } score_sp += FMG_MG; @@ -120,7 +125,7 @@ eval_max_score( const tree_t * restrict ptree, unsigned int move, } -int +int CONV estimate_score_diff( const tree_t * restrict ptree, unsigned int move, int turn ) { @@ -135,8 +140,8 @@ estimate_score_diff( const tree_t * restrict ptree, unsigned int move, 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]; } @@ -146,8 +151,8 @@ estimate_score_diff( const tree_t * restrict ptree, unsigned int move, 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 { @@ -164,48 +169,48 @@ estimate_score_diff( const tree_t * restrict ptree, unsigned int move, } 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; } } diff --git a/evaluate.c b/evaluate.c index 85b8a63..e573385 100644 --- a/evaluate.c +++ b/evaluate.c @@ -1,15 +1,31 @@ #include #include #include +#include #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; @@ -70,29 +86,67 @@ eval_material( const tree_t * restrict ptree ) } -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 ); @@ -113,13 +167,18 @@ evaluate( tree_t * restrict ptree, int ply, int turn ) } 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 ) @@ -128,24 +187,16 @@ evaluate( tree_t * restrict ptree, int ply, int turn ) } #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; @@ -155,28 +206,28 @@ static int ehash_probe( uint64_t current_key, unsigned int hand_b, 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; @@ -186,7 +237,138 @@ static void ehash_store( uint64_t key, unsigned int hand_b, int score ) } -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] ) { @@ -201,36 +383,6 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, 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) ]; @@ -249,7 +401,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BPAWN; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -261,7 +413,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WPAWN; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -275,7 +427,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BLANCE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -287,7 +439,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WLANCE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -302,7 +454,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BKNIGHT; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -314,7 +466,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WKNIGHT; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -329,7 +481,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BSILVER; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -341,7 +493,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WSILVER; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -356,7 +508,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BTGOLD; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -368,7 +520,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WTGOLD; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -383,7 +535,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BBISHOP; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -395,7 +547,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WBISHOP; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -410,7 +562,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BHORSE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -422,7 +574,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WHORSE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -437,7 +589,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BROOK; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -449,7 +601,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WROOK; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -464,7 +616,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, n2 = 0; bb = BB_BDRAGON; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -476,7 +628,7 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, } bb = BB_WDRAGON; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -489,6 +641,148 @@ make_list( const tree_t * restrict ptree, int * restrict pscore, 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 diff --git a/gencap.c b/gencap.c index 06ba52b..cb38d4c 100644 --- a/gencap.c +++ b/gencap.c @@ -1,6 +1,6 @@ #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; @@ -26,13 +26,13 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -45,13 +45,13 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -64,7 +64,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ); @@ -74,7 +74,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_BBISHOP; - while ( BBToU( bb_piece ) ) + while ( BBTest( bb_piece ) ) { ifrom = LastOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -91,7 +91,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) bb_desti.p[2] &= bb_capture.p[2]; } - while ( BBToU( bb_desti ) ) + while ( BBTest( bb_desti ) ) { ito = LastOne( bb_desti ); Xor( ito, bb_desti ); @@ -104,7 +104,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_BROOK; - while ( BBToU( bb_piece ) ) + while ( BBTest( bb_piece ) ) { ifrom = LastOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -121,7 +121,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) bb_desti.p[2] &= bb_capture.p[2]; } - while ( BBToU( bb_desti ) ) + while ( BBTest( bb_desti ) ) { ito = LastOne( bb_desti ); Xor( ito, bb_desti ); @@ -134,14 +134,14 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -152,14 +152,14 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -170,7 +170,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_BLANCE; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { ifrom = LastOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -181,7 +181,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ); @@ -199,7 +199,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_BKNIGHT; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { ifrom = LastOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -209,7 +209,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ); @@ -230,7 +230,7 @@ b_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } -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; @@ -256,13 +256,13 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -275,13 +275,13 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -294,7 +294,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ); @@ -304,7 +304,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_WBISHOP; - while ( BBToU( bb_piece ) ) + while ( BBTest( bb_piece ) ) { ifrom = FirstOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -321,7 +321,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) bb_desti.p[0] &= bb_capture.p[0]; } - while ( BBToU( bb_desti ) ) + while ( BBTest( bb_desti ) ) { ito = FirstOne( bb_desti ); Xor( ito, bb_desti ); @@ -334,7 +334,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_WROOK; - while ( BBToU( bb_piece ) ) + while ( BBTest( bb_piece ) ) { ifrom = FirstOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -351,7 +351,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) bb_desti.p[0] &= bb_capture.p[0]; } - while ( BBToU( bb_desti ) ) + while ( BBTest( bb_desti ) ) { ito = FirstOne( bb_desti ); Xor( ito, bb_desti ); @@ -364,14 +364,14 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -382,14 +382,14 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ); @@ -400,7 +400,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_WLANCE; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { ifrom = FirstOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -411,7 +411,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ); @@ -429,7 +429,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_WKNIGHT; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { ifrom = FirstOne( bb_piece ); Xor( ifrom, bb_piece ); @@ -439,7 +439,7 @@ w_gen_captures( const tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ); diff --git a/genchk.c b/genchk.c index dfefee0..a7d7992 100644 --- a/genchk.c +++ b/genchk.c @@ -1,1441 +1,2436 @@ -#include -#include "shogi.h" - - -static bitboard_t add_behind_attacks( int idirec, int ik, bitboard_t bb ); - - -unsigned int * -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; - const tree_t * restrict ptree = __ptree__; - unsigned int u0, u1, u2; - int from, to, sq_wk, idirec; - - sq_wk = SQ_WKING; - bb_rook_chk = bb_file_chk = AttackFile( sq_wk ); - bb_rook_chk.p[aslide[sq_wk].ir0] |= AttackRank( sq_wk ); - 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 ); - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - BBAnd( bb_chk, bb_chk, abb_king_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - AttackDragon( bb_desti, from ); - BBAnd( bb_chk, bb_chk, bb_desti ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - AttackHorse( bb_desti, from ); - BBAnd( bb_chk, bb_chk, bb_desti ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - } - - 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk ); - 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( BBToU( bb_chk ) ) - { - to = LastOne( bb_chk ); - Xor( to, bb_chk ); - *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance) - | Cap2Move(-BOARD[to]); - } - } - - - BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN ); - while ( BBToU(bb_piece) ) - { - from = LastOne( bb_piece ); - Xor( from, bb_piece ); - - to = from - nfile; - if ( BOARD[to] != empty ) { continue; } - - bb_desti = AttackDiag1( from ); - if ( BBContract( bb_desti, BB_B_BH ) ) - { - *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 ( BBToU(bb_piece) ) - { - from = LastOne( bb_piece ); - Xor( from, bb_piece ); - - to = from - nfile; - if ( BOARD[to] != empty ) { continue; } - - bb_desti = AttackDiag2( from ); - if ( BBContract( bb_desti, BB_B_BH ) ) - { - *pmove = To2Move(to) | From2Move(from) - | Piece2Move(pawn) | Cap2Move(-BOARD[to]); - if ( from < A5 ) { *pmove |= FLAG_PROMO; } - pmove += 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 ); - while ( BBToU(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( BBToU( 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( BBToU( 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 * -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; - const tree_t * restrict ptree = __ptree__; - unsigned int u0, u1, u2; - int from, to, sq_bk, idirec; - - sq_bk = SQ_BKING; - bb_rook_chk = bb_file_chk = AttackFile( sq_bk ); - bb_rook_chk.p[aslide[sq_bk].ir0] |= AttackRank( sq_bk ); - bb_diag1_chk = AttackDiag1( sq_bk ); - bb_diag2_chk = AttackDiag2( sq_bk ); - AttackBishop( bb_bishop_chk, sq_bk ); - 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 ); - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - BBAnd( bb_chk, bb_chk, abb_king_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - AttackDragon( bb_desti, from ); - BBAnd( bb_chk, bb_chk, bb_desti ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - AttackHorse( bb_desti, from ); - BBAnd( bb_chk, bb_chk, bb_desti ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] ); - BBAnd( bb_chk, bb_chk, bb_move_to ); - - while( BBToU( 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - } - - 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( BBToU( 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 ) ) - { - bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk ); - 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( BBToU( bb_chk ) ) - { - to = FirstOne( bb_chk ); - Xor( to, bb_chk ); - *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance) - | Cap2Move(BOARD[to]); - } - } - - - BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN ); - while ( BBToU(bb_piece) ) - { - from = FirstOne( bb_piece ); - Xor( from, bb_piece ); - - to = from + nfile; - if ( BOARD[to] != empty ) { continue; } - - bb_desti = AttackDiag1( from ); - if ( BBContract( bb_desti, BB_W_BH ) ) - { - *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 ( BBToU(bb_piece) ) - { - from = FirstOne( bb_piece ); - Xor( from, bb_piece ); - - to = from + nfile; - if ( BOARD[to] != empty ) { continue; } - - bb_desti = AttackDiag2( from ); - if ( BBContract( bb_desti, BB_W_BH ) ) - { - *pmove = To2Move(to) | From2Move(from) - | Piece2Move(pawn) | Cap2Move(BOARD[to]); - if ( from > I5 ) { *pmove |= FLAG_PROMO; } - pmove += 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 ); - while ( BBToU(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( BBToU( 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( BBToU( 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; -} - - -static bitboard_t -add_behind_attacks( int idirec, int ik, bitboard_t bb ) -{ - 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 ); - BBIni( bb_tmp ); - bb_tmp.p[aslide[ik].ir0] = ai_rook_attacks_r0[ik][0]; - } - BBNot( bb_tmp, bb_tmp ); - BBOr( bb, bb, bb_tmp ); - - return bb; -} +#include +#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 ); +} diff --git a/gendrop.c b/gendrop.c index 4066827..ad4bded 100644 --- a/gendrop.c +++ b/gendrop.c @@ -1,6 +1,6 @@ #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__; @@ -32,7 +32,7 @@ b_gen_drop( tree_t * restrict __ptree__, unsigned int * restrict pmove ) 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 ); @@ -97,7 +97,7 @@ b_gen_drop( tree_t * restrict __ptree__, unsigned int * restrict pmove ) } -unsigned int * +unsigned int * CONV w_gen_drop( tree_t * restrict __ptree__, unsigned int * restrict pmove ) { const tree_t * restrict ptree = __ptree__; @@ -129,7 +129,7 @@ w_gen_drop( tree_t * restrict __ptree__, unsigned int * restrict pmove ) 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 ); diff --git a/genevasn.c b/genevasn.c index f34775b..c682945 100644 --- a/genevasn.c +++ b/genevasn.c @@ -3,7 +3,7 @@ #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; @@ -21,10 +21,9 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ) ) @@ -39,8 +38,7 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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; } @@ -51,7 +49,7 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict 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 ); @@ -68,7 +66,7 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_BLANCE; - while ( BBToU( bb_piece ) ) + while ( BBTest( bb_piece ) ) { from = LastOne( bb_piece ); Xor( from, bb_piece ); @@ -76,7 +74,7 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ) ) @@ -91,13 +89,13 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ) ) @@ -110,17 +108,17 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ) ) @@ -131,17 +129,17 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) | 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 ) ) @@ -151,18 +149,18 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) *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 { @@ -173,18 +171,18 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) | 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 { @@ -195,18 +193,18 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) | 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 ) ) @@ -215,18 +213,18 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ) ) @@ -235,11 +233,11 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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; @@ -273,7 +271,7 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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); @@ -298,7 +296,7 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) } } else { - while ( BBToU( bb_target ) ) + while ( BBTest( bb_target ) ) { to = LastOne( bb_target ); utemp = To2Move(to); @@ -327,7 +325,7 @@ b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) } -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; @@ -345,10 +343,9 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ) ) @@ -363,8 +360,7 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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; } @@ -375,7 +371,7 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict 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 ); @@ -392,7 +388,7 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) } bb_piece = BB_WLANCE; - while ( BBToU( bb_piece ) ) + while ( BBTest( bb_piece ) ) { from = FirstOne( bb_piece ); Xor( from, bb_piece ); @@ -400,7 +396,7 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ) ) @@ -415,13 +411,13 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) } 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 ) ) @@ -433,17 +429,17 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) | 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 ) ) @@ -454,17 +450,17 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) | 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 ) ) @@ -474,18 +470,18 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) *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 ) ) @@ -497,18 +493,18 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) | 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 { @@ -519,18 +515,18 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) | 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 ) ) @@ -539,18 +535,18 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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 ) ) @@ -559,11 +555,11 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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; @@ -597,7 +593,7 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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); @@ -622,7 +618,7 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) } } else { - while ( BBToU( bb_target ) ) + while ( BBTest( bb_target ) ) { to = FirstOne( bb_target ); utemp = To2Move(to); @@ -649,3 +645,448 @@ w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove ) 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; +} diff --git a/gennocap.c b/gennocap.c index 1f68b4b..b5f441a 100644 --- a/gennocap.c +++ b/gennocap.c @@ -1,6 +1,6 @@ #include "shogi.h" -unsigned int * +unsigned int * CONV b_gen_nocaptures( const tree_t * restrict ptree, unsigned int * restrict pmove ) { @@ -23,13 +23,13 @@ b_gen_nocaptures( const tree_t * restrict ptree, } 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 ); @@ -41,14 +41,14 @@ b_gen_nocaptures( const tree_t * restrict ptree, } 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 ); @@ -59,7 +59,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -111,7 +111,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, } bb_piece = BB_BHORSE; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { from = LastOne( bb_piece ); Xor( from, bb_piece ); @@ -119,7 +119,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -128,7 +128,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, } bb_piece = BB_BDRAGON; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { from = LastOne( bb_piece ); Xor( from, bb_piece ); @@ -136,7 +136,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -147,7 +147,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -157,7 +157,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -166,14 +166,14 @@ b_gen_nocaptures( const tree_t * restrict ptree, } 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 ); @@ -185,7 +185,7 @@ b_gen_nocaptures( const tree_t * restrict ptree, } -unsigned int * +unsigned int * CONV w_gen_nocaptures( const tree_t * restrict ptree, unsigned int * restrict pmove ) { @@ -208,13 +208,13 @@ w_gen_nocaptures( const tree_t * restrict ptree, } 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 ); @@ -226,14 +226,14 @@ w_gen_nocaptures( const tree_t * restrict ptree, } 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 ); @@ -244,7 +244,7 @@ w_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -296,7 +296,7 @@ w_gen_nocaptures( const tree_t * restrict ptree, } bb_piece = BB_WHORSE; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { from = FirstOne( bb_piece ); Xor( from, bb_piece ); @@ -304,7 +304,7 @@ w_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -313,7 +313,7 @@ w_gen_nocaptures( const tree_t * restrict ptree, } bb_piece = BB_WDRAGON; - while( BBToU( bb_piece ) ) + while( BBTest( bb_piece ) ) { from = FirstOne( bb_piece ); Xor( from, bb_piece ); @@ -321,7 +321,7 @@ w_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -332,7 +332,7 @@ w_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -342,7 +342,7 @@ w_gen_nocaptures( const tree_t * restrict ptree, 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 ); @@ -351,14 +351,14 @@ w_gen_nocaptures( const tree_t * restrict ptree, } 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 ); diff --git a/hash.c b/hash.c index 5ab568a..9a66ff1 100644 --- a/hash.c +++ b/hash.c @@ -4,11 +4,12 @@ #include #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; @@ -29,19 +30,19 @@ ini_trans_table( void ) #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; @@ -84,7 +85,7 @@ word2 key 57 7 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 ) @@ -140,7 +141,7 @@ hash_store( const tree_t * restrict ptree, int ply, int depth, int turn, } -void +void CONV hash_store_pv( const tree_t * restrict ptree, unsigned int move, int turn ) { uint64_t key_turn_pv, word1, word2; @@ -200,87 +201,18 @@ hash_store_pv( const tree_t * restrict ptree, unsigned int move, int turn ) } -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 ); @@ -312,6 +244,7 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, { if ( value_hash > 0 ) { value_hash -= ply-1; } else { value_hash += ply-1; } + #if ! defined(MINIMUM) if ( abs(value_hash) > score_mate1ply ) { @@ -319,8 +252,10 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, } #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)]); @@ -331,8 +266,26 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, 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; @@ -371,17 +324,6 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, 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, @@ -410,7 +352,7 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, || 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++; @@ -418,32 +360,37 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, } } - } 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; + } + } } } } @@ -473,6 +420,7 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, { if ( value_hash > 0 ) { value_hash -= ply-1; } else { value_hash += ply-1; } + #if ! defined(MINIMUM) if ( abs(value_hash) > score_mate1ply ) { @@ -481,7 +429,9 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, #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)]); @@ -496,6 +446,24 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_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 <= 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 ) ) @@ -537,17 +505,6 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, 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, @@ -579,7 +536,7 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, || 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++; @@ -587,35 +544,37 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, } } - } 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; - } - } - } } } } @@ -661,170 +620,13 @@ hash_probe( tree_t * restrict ptree, int ply, int depth_current, 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 ) @@ -860,7 +662,7 @@ eval_supe( unsigned int hand_current, unsigned int hand_hash, } -int +int CONV clear_trans_table( void ) { unsigned int elapsed_start, elapsed_end; @@ -887,221 +689,3 @@ clear_trans_table( void ) 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; -} diff --git a/ini.c b/ini.c index 13db541..6522316 100644 --- a/ini.c +++ b/ini.c @@ -16,7 +16,6 @@ static int last_one00( int pcs ); 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 ); @@ -24,8 +23,7 @@ static void ini_attack_tables( void ); static void ini_random_table( void ); -static int -load_fv( void ) +int CONV load_fv( void ) { FILE *pf; size_t size; @@ -83,35 +81,6 @@ load_fv( void ) 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 ) @@ -123,7 +92,7 @@ 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; @@ -144,6 +113,7 @@ ini( tree_t * restrict ptree ) 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; @@ -151,9 +121,22 @@ ini( tree_t * restrict ptree ) 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; @@ -177,8 +160,9 @@ ini( tree_t * restrict ptree ) 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 ) ) @@ -186,26 +170,52 @@ ini( tree_t * restrict ptree ) 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 @@ -224,13 +234,6 @@ ini( tree_t * restrict ptree ) } #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(); @@ -250,24 +253,29 @@ ini( tree_t * restrict ptree ) 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; } @@ -281,6 +289,14 @@ fin( void ) 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(); } @@ -290,14 +306,14 @@ fin( void ) { 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; } @@ -306,6 +322,7 @@ fin( void ) if ( file_close( pf_log ) < 0 ) { return -1; } #endif + ShutdownAll(); return 1; } @@ -328,12 +345,12 @@ set_derivative_param( void ) 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]; @@ -365,12 +382,12 @@ set_derivative_param( void ) 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]; } @@ -512,28 +529,28 @@ ini_tables( void ) } 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; @@ -659,218 +676,169 @@ ini_attack_tables( void ) 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); } + } } @@ -885,25 +853,15 @@ set_attacks( int irank, int ifile, bitboard_t *pbb ) 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; } @@ -912,164 +870,160 @@ static void 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 ); } + } } @@ -1080,7 +1034,7 @@ static int first_one00( int pcs ) { int i; - + for ( i = 0; i < 9; i++ ) { if ( pcs & (1<<(8-i)) ) { break; } } return i; } @@ -1090,7 +1044,7 @@ static int last_one00( int pcs ) { int i; - + for ( i = 8; i >= 0; i-- ) { if ( pcs & (1<<(8-i)) ) { break; } } return i; } diff --git a/io.c b/io.c index 14f841e..c0595f1 100644 --- a/io.c +++ b/io.c @@ -27,30 +27,60 @@ static int out_board0( FILE *pf, int piece, int i, int ito, int ifrom, # 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 ); @@ -77,70 +107,57 @@ out_csashogi( const char *format, ... ) 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 ) { @@ -199,13 +216,6 @@ show_prompt( void ) { 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 ) { @@ -237,8 +247,7 @@ open_history( const char *str_name1, const char *str_name2 ) 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; } @@ -267,34 +276,52 @@ open_history( const char *str_name1, const char *str_name2 ) 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 } @@ -310,6 +337,8 @@ out_board( const tree_t * restrict ptree, FILE *pf, unsigned int move, int is_promote; #endif + if ( game_status & flag_nostdout ) { return 1; } + if ( ! is_strict && move ) { ito = I2To( move ); @@ -392,34 +421,7 @@ next_cmdline( int is_wait ) } } 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 ); @@ -445,19 +447,6 @@ next_cmdline( int is_wait ) 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 ); @@ -614,7 +603,7 @@ stdout_stress( int is_promote, int ifrom ) #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" ); @@ -627,7 +616,7 @@ out_hand( FILE *pf, unsigned int hand, const char *str_prefix ) } -static void +static void CONV out_hand0( FILE *pf, int n, const char *str_prefix, const char *str ) { int i; @@ -641,7 +630,7 @@ out_hand0( FILE *pf, int n, const char *str_prefix, const char *str ) } -static int +static int CONV read_command( char ** pstr_line_end ) { char *str_end; @@ -650,15 +639,6 @@ read_command( char ** pstr_line_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 ) { @@ -677,6 +657,15 @@ read_command( char ** pstr_line_end ) } #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 ); @@ -687,10 +676,13 @@ read_command( char ** pstr_line_end ) } *( 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 @@ -704,69 +696,104 @@ read_command( char ** pstr_line_end ) 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 */ +} diff --git a/iterate.c b/iterate.c index d940814..1a684bc 100644 --- a/iterate.c +++ b/iterate.c @@ -4,46 +4,34 @@ #include #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; } @@ -54,33 +42,71 @@ iterate( tree_t * restrict ptree, int flag ) 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; @@ -103,6 +129,8 @@ iterate( tree_t * restrict ptree, int flag ) 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; @@ -111,15 +139,14 @@ iterate( tree_t * restrict ptree, int flag ) 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 ); @@ -127,6 +154,10 @@ iterate( tree_t * restrict ptree, int flag ) easy_move = 0; #endif +#if defined(USI) + usi_time_out_last = time_start; +#endif + #if defined(TLP) ptree->tlp_abort = 0; tlp_nsplit = 0; @@ -152,6 +183,12 @@ iterate( tree_t * restrict ptree, int flag ) 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++ ) { @@ -169,12 +206,15 @@ iterate( tree_t * restrict ptree, int flag ) 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; @@ -189,21 +229,18 @@ iterate( tree_t * restrict ptree, int flag ) #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; } @@ -220,9 +257,9 @@ iterate( tree_t * restrict ptree, int flag ) 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 @@ -235,16 +272,21 @@ iterate( tree_t * restrict ptree, int flag ) 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; } @@ -256,6 +298,7 @@ iterate( tree_t * restrict ptree, int flag ) ptree->pv[0].depth = 1; ptree->pv[0].type = no_rep; root_value = value; + root_index = 0; } #if defined(MPV) @@ -272,21 +315,72 @@ iterate( tree_t * restrict ptree, int flag ) } +#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 @@ -297,11 +391,6 @@ iterate( tree_t * restrict ptree, int flag ) return 1; } - if ( ! is_hash_learn_stored ) - { - iret = ini_hash(); - if ( iret < 0 ) { return iret; } - } /* iterative deepening search */ #if defined(TLP) @@ -312,15 +401,12 @@ iterate( tree_t * restrict ptree, int flag ) 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) @@ -392,12 +478,39 @@ iterate( tree_t * restrict ptree, int flag ) 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 ) { @@ -405,14 +518,8 @@ iterate( tree_t * restrict ptree, int flag ) } 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 ); @@ -442,7 +549,6 @@ iterate( tree_t * restrict ptree, int flag ) } 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; } @@ -454,8 +560,7 @@ iterate( tree_t * restrict ptree, int flag ) 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 ) { @@ -472,7 +577,7 @@ iterate( tree_t * restrict ptree, int flag ) 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; @@ -541,9 +646,7 @@ iterate( tree_t * restrict ptree, int flag ) } } - /* iteration ended */ - sub_rejections( ptree, root_turn, 1 ); - + /* iteration finished */ if ( game_status & flag_problem ) { if ( is_answer_right( ptree->pv[0].a[1] ) ) @@ -556,7 +659,7 @@ iterate( tree_t * restrict ptree, int flag ) { 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; @@ -564,16 +667,13 @@ iterate( tree_t * restrict ptree, int flag ) } /* 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; @@ -587,10 +687,8 @@ iterate( tree_t * restrict ptree, int flag ) 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, @@ -679,6 +777,60 @@ iterate( tree_t * restrict ptree, int flag ) } #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; @@ -709,14 +861,12 @@ iterate( tree_t * restrict ptree, int flag ) 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; } @@ -726,29 +876,161 @@ iterate( tree_t * restrict ptree, int flag ) } -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; @@ -768,8 +1050,7 @@ adjust_fmg( void ) } -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; @@ -798,8 +1079,7 @@ set_root_beta( int nfail_high, int root_beta_old ) } -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; @@ -828,8 +1108,7 @@ set_root_alpha( int nfail_low, int root_alpha_old ) } -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; @@ -846,8 +1125,7 @@ str_fail_high( int turn, int nfail_high ) } -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; diff --git a/learn1.c b/learn1.c index a52ed68..a6b7c52 100644 --- a/learn1.c +++ b/learn1.c @@ -234,6 +234,7 @@ learn_parse1( tree_t * restrict ptree, book_entry_t *pbook_entry, FILE *pf_tmp, } #if defined(TLP) + tlp_num = nworker; for ( id = 1; id < nworker; id++ ) { # if defined(_WIN32) @@ -302,11 +303,11 @@ learn_parse1( tree_t * restrict ptree, book_entry_t *pbook_entry, FILE *pf_tmp, 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" ); @@ -341,20 +342,9 @@ static void *parse1_worker( void *arg ) 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; @@ -369,7 +359,7 @@ static void *parse1_worker( void *arg ) pdata->target_out_window = 0.0; for ( ;; ) { - /* make results */ + /* make pv */ pdata->pos_buf = 2U; for ( imove = 0; imove < (int)pdata->record_length; imove++ ) { @@ -391,10 +381,10 @@ static void *parse1_worker( void *arg ) } #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 ) @@ -420,7 +410,7 @@ static void *parse1_worker( void *arg ) } #if defined(TLP) - if ( pdata->nworker > 1 ) { unlock( &tlp_lock ); } + unlock( &tlp_lock ); #endif if ( iret < 0 ) { break; } @@ -428,12 +418,9 @@ static void *parse1_worker( void *arg ) } #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; @@ -449,7 +436,7 @@ make_pv( parse1_data_t *pdata, unsigned int record_move ) 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; @@ -459,20 +446,23 @@ make_pv( parse1_data_t *pdata, unsigned int record_move ) 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 ); @@ -484,9 +474,11 @@ make_pv( parse1_data_t *pdata, unsigned int record_move ) 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; @@ -508,16 +500,20 @@ make_pv( parse1_data_t *pdata, unsigned int record_move ) 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 ); @@ -633,7 +629,7 @@ read_game( parse1_data_t *pdata ) } 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; } } @@ -674,6 +670,7 @@ learn_parse2( tree_t * restrict ptree, FILE *pf_tmp, int nsteps, for ( ;; ) { #if defined(TLP) + tlp_num = nworker; for ( id = 1; id < nworker; id++ ) { # if defined(_WIN32) @@ -723,7 +720,7 @@ learn_parse2( tree_t * restrict ptree, FILE *pf_tmp, int nsteps, 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 " ); } @@ -760,16 +757,6 @@ static void *parse2_worker( void *arg ) 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; @@ -777,11 +764,11 @@ static void *parse2_worker( void *arg ) 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 */ @@ -807,18 +794,14 @@ static void *parse2_worker( void *arg ) 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; @@ -1060,7 +1043,7 @@ rep_check_learn( tree_t * restrict ptree, int ply ) { int n, i, imin; - n = root_nrep + ply - 1; + n = ptree->nrep + ply - 1; imin = n - REP_MAX_PLY; if ( imin < 0 ) { imin = 0; } diff --git a/learn2.c b/learn2.c index 109424f..0c886b1 100644 --- a/learn2.c +++ b/learn2.c @@ -538,7 +538,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BPAWN; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -551,7 +551,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WPAWN; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -566,7 +566,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BLANCE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -579,7 +579,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WLANCE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -595,7 +595,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BKNIGHT; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -608,7 +608,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WKNIGHT; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -624,7 +624,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BSILVER; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -637,7 +637,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WSILVER; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -653,7 +653,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BTGOLD; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -666,7 +666,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WTGOLD; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -682,7 +682,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BBISHOP; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -695,7 +695,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WBISHOP; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -711,7 +711,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BHORSE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -724,7 +724,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WHORSE; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -740,7 +740,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BROOK; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -753,7 +753,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WROOK; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -769,7 +769,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], n2 = 0; bb = BB_BDRAGON; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); @@ -782,7 +782,7 @@ make_list( const tree_t * restrict ptree, int list0[52], int list1[52], } bb = BB_WDRAGON; - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { sq = FirstOne( bb ); Xor( sq, bb ); diff --git a/main.c b/main.c index f84ad15..1591760 100644 --- a/main.c +++ b/main.c @@ -1,36 +1,3 @@ -/* - 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 #include #include @@ -41,8 +8,8 @@ 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() @@ -58,7 +25,6 @@ main() #endif #if defined(CSASHOGI) && defined(_WIN32) - FreeConsole(); if ( argc != 2 || strcmp( argv[1], "csa_shogi" ) ) { MessageBox( NULL, @@ -70,6 +36,11 @@ main() } #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 ); @@ -82,13 +53,13 @@ main() 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; } @@ -105,18 +76,6 @@ main_child( tree_t * restrict ptree ) { 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 ); diff --git a/makemove.c b/makemove.c index 83d8c9e..17713d3 100644 --- a/makemove.c +++ b/makemove.c @@ -1,3 +1,4 @@ +#include #include #include #include "shogi.h" @@ -53,12 +54,12 @@ 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 ); @@ -67,7 +68,7 @@ make_move_b( tree_t * restrict ptree, unsigned int move, int ply ) 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 ) { @@ -202,12 +203,12 @@ make_move_b( tree_t * restrict ptree, unsigned int move, int ply ) } -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 ); @@ -216,7 +217,7 @@ make_move_w( tree_t * restrict ptree, unsigned int move, int ply ) 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 ) { @@ -361,14 +362,12 @@ make_move_w( tree_t * restrict ptree, unsigned int move, int ply ) * 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 */ @@ -413,11 +412,11 @@ make_move_root( tree_t * restrict ptree, unsigned int move, int flag ) 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 ); @@ -426,26 +425,10 @@ make_move_root( tree_t * restrict ptree, unsigned int move, int flag ) 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++ ) @@ -454,15 +437,26 @@ make_move_root( tree_t * restrict ptree, unsigned int move, int flag ) 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 ) @@ -484,25 +478,74 @@ make_move_root( tree_t * restrict ptree, unsigned int move, int flag ) 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; } diff --git a/mate1ply.c b/mate1ply.c index b09a6d1..b4d52db 100644 --- a/mate1ply.c +++ b/mate1ply.c @@ -5,13 +5,15 @@ #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; @@ -26,20 +28,18 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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); } @@ -49,7 +49,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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); @@ -62,7 +62,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -71,8 +71,8 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -83,13 +83,12 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) { 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 ); @@ -97,8 +96,8 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -108,8 +107,9 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 { @@ -120,7 +120,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) } } - while ( BBToU(bb) ) + while ( BBTest(bb) ) { to = FirstOne( bb ); Xor( to, bb ); @@ -128,8 +128,8 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -138,14 +138,14 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -154,14 +154,14 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -178,16 +178,15 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -197,7 +196,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -215,7 +214,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -231,16 +230,15 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -249,7 +247,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -272,7 +270,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -291,21 +289,19 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -317,7 +313,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -329,14 +325,14 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) } 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 ); @@ -354,10 +350,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -367,7 +363,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -385,7 +381,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -402,10 +398,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -414,7 +410,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -437,7 +433,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -459,10 +455,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -474,7 +470,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -486,13 +482,13 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) } 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 ); @@ -507,10 +503,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -519,7 +515,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -562,10 +558,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -584,10 +580,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -634,10 +630,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -656,10 +652,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -705,10 +701,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -731,7 +727,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) } BBAnd( bb, BB_BKNIGHT, b_chk_tbl[SQ_WKING].knight ); - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { from = FirstOne( bb ); Xor( from, bb ); @@ -754,10 +750,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -782,7 +778,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -796,10 +792,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -810,7 +806,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -824,7 +820,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) } BBAnd( bb, BB_BLANCE, b_chk_tbl[SQ_WKING].lance ); - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { from = FirstOne( bb ); Xor( from, bb ); @@ -845,7 +841,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ) ) { @@ -853,10 +849,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -876,10 +872,10 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -912,12 +908,12 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -952,11 +948,11 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -983,7 +979,7 @@ is_b_mate_in_1ply( tree_t * restrict ptree ) } -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; @@ -1001,17 +997,16 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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); } @@ -1021,7 +1016,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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); @@ -1034,7 +1029,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1043,8 +1038,8 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -1055,13 +1050,12 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) { 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 ); @@ -1069,8 +1063,8 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -1080,8 +1074,9 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 { @@ -1092,7 +1087,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) } } - while ( BBToU(bb) ) + while ( BBTest(bb) ) { to = LastOne( bb ); Xor( to, bb ); @@ -1100,8 +1095,8 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -1110,14 +1105,14 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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); } } @@ -1126,14 +1121,14 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1150,16 +1145,15 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1169,7 +1163,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1187,7 +1181,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -1203,16 +1197,15 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1221,7 +1214,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1244,7 +1237,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -1263,20 +1256,18 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1288,7 +1279,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1300,14 +1291,14 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) } 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 ); @@ -1325,10 +1316,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1338,7 +1329,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1356,7 +1347,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -1373,10 +1364,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1385,7 +1376,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1408,7 +1399,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -1430,10 +1421,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1445,7 +1436,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1457,13 +1448,13 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) } 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 ); @@ -1478,10 +1469,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1490,7 +1481,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1533,10 +1524,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1555,10 +1546,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1605,10 +1596,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1627,10 +1618,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1677,10 +1668,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1703,7 +1694,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) } BBAnd( bb, BB_WKNIGHT, w_chk_tbl[SQ_BKING].knight ); - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { from = LastOne( bb ); Xor( from, bb ); @@ -1726,10 +1717,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1754,7 +1745,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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]; @@ -1768,10 +1759,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1782,7 +1773,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1796,7 +1787,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) } BBAnd( bb, BB_WLANCE, w_chk_tbl[SQ_BKING].lance ); - while ( BBToU(bb) ) { + while ( BBTest(bb) ) { from = LastOne( bb ); Xor( from, bb ); @@ -1817,7 +1808,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ) ) { @@ -1825,10 +1816,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1848,10 +1839,10 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1884,12 +1875,12 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1924,11 +1915,11 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) 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 ); @@ -1955,7 +1946,7 @@ is_w_mate_in_1ply( tree_t * restrict ptree ) } -static int +static int CONV can_w_piece_capture( const tree_t * restrict ptree, int to ) { bitboard_t bb_sum, bb, bb_attacks; @@ -1970,29 +1961,22 @@ can_w_piece_capture( const tree_t * restrict ptree, int to ) 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 ); @@ -2005,10 +1989,10 @@ can_w_piece_capture( const tree_t * restrict ptree, int to ) } -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; @@ -2020,29 +2004,21 @@ can_b_piece_capture( const tree_t * restrict ptree, int to ) 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 ); @@ -2055,9 +2031,11 @@ can_b_piece_capture( const tree_t * restrict ptree, int to ) } -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] ) @@ -2074,10 +2052,9 @@ can_w_king_escape( tree_t * restrict ptree, int to, bitboard_t bb ) 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 ) ) @@ -2104,9 +2081,11 @@ 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 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] ) @@ -2124,10 +2103,9 @@ can_b_king_escape( tree_t * restrict ptree, int to, bitboard_t bb ) 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 ) ) diff --git a/mate3.c b/mate3.c index 61d1036..29b4a0f 100644 --- a/mate3.c +++ b/mate3.c @@ -15,29 +15,90 @@ enum { mate_king_cap_checker = 0, 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; @@ -64,7 +125,11 @@ is_mate_in3ply( tree_t * restrict ptree, int turn, int ply ) 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]) ) @@ -73,11 +138,12 @@ is_mate_in3ply( tree_t * restrict ptree, int turn, int ply ) } } + 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; @@ -118,7 +184,7 @@ mate3_and( tree_t * restrict ptree, int turn, int ply, int flag ) } -static int +static int CONV mate_weak_or( tree_t * restrict ptree, int turn, int ply, int from, int to ) { @@ -172,7 +238,7 @@ mate_weak_or( tree_t * restrict ptree, int turn, int ply, int from, } -static int +static int CONV gen_next_evasion_mate( tree_t * restrict ptree, const char *psq, int ply, int turn, int flag ) { @@ -272,30 +338,29 @@ gen_next_evasion_mate( tree_t * restrict ptree, const char *psq, int ply, } -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] ) ) @@ -311,7 +376,7 @@ checker( const tree_t * restrict ptree, char *psq, int turn ) } -static unsigned int +static unsigned int CONV gen_king_cap_checker( const tree_t * restrict ptree, int to, int turn ) { unsigned int move; @@ -338,19 +403,18 @@ gen_king_cap_checker( const tree_t * restrict ptree, int to, int turn ) } -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 ); @@ -401,9 +465,9 @@ gen_move_to( const tree_t * restrict ptree, int to, int turn, } } 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 ); @@ -458,7 +522,7 @@ gen_move_to( const tree_t * restrict ptree, int to, int turn, } -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 ) { @@ -468,28 +532,28 @@ gen_king_move( const tree_t * restrict ptree, const char *psq, int turn, 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 ); @@ -530,7 +594,7 @@ gen_king_move( const tree_t * restrict ptree, const char *psq, int turn, } -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 ) @@ -549,12 +613,12 @@ gen_intercept( tree_t * restrict __ptree__, int sq_checker, int ply, int turn, { 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] ) @@ -591,7 +655,7 @@ gen_intercept( tree_t * restrict __ptree__, int sq_checker, int ply, int turn, 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 ); @@ -689,7 +753,8 @@ gen_intercept( tree_t * restrict __ptree__, int sq_checker, int ply, int turn, /* -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; diff --git a/movgenex.c b/movgenex.c index f21d240..fdbccf2 100644 --- a/movgenex.c +++ b/movgenex.c @@ -5,33 +5,33 @@ #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 ) { @@ -106,7 +106,7 @@ b_gen_cap_nopro_ex2( const tree_t * restrict ptree, 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] @@ -125,7 +125,7 @@ b_gen_cap_nopro_ex2( const tree_t * restrict ptree, } -unsigned int * +unsigned int * CONV b_gen_nocap_nopro_ex2( const tree_t * restrict ptree, unsigned int * restrict pmove ) { @@ -201,7 +201,7 @@ b_gen_nocap_nopro_ex2( const tree_t * restrict ptree, 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] @@ -220,7 +220,7 @@ b_gen_nocap_nopro_ex2( const tree_t * restrict ptree, } -unsigned int * +unsigned int * CONV w_gen_cap_nopro_ex2( const tree_t * restrict ptree, unsigned int * restrict pmove ) { @@ -295,7 +295,7 @@ w_gen_cap_nopro_ex2( const tree_t * restrict ptree, 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] @@ -314,7 +314,7 @@ w_gen_cap_nopro_ex2( const tree_t * restrict ptree, } -unsigned int * +unsigned int * CONV w_gen_nocap_nopro_ex2( const tree_t * restrict ptree, unsigned int * restrict pmove ) { @@ -390,7 +390,7 @@ w_gen_nocap_nopro_ex2( const tree_t * restrict ptree, 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] diff --git a/next.c b/next.c index f0153ac..a6937a3 100644 --- a/next.c +++ b/next.c @@ -3,7 +3,7 @@ #include #include "shogi.h" -int +int CONV gen_next_move( tree_t * restrict ptree, int ply, int turn ) { switch ( ptree->anext_move[ply].next_phase ) @@ -163,6 +163,7 @@ gen_next_move( tree_t * restrict ptree, int ply, int turn ) 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++ ) @@ -260,7 +261,7 @@ gen_next_move( tree_t * restrict ptree, int ply, int turn ) } -int +int CONV gen_next_evasion( tree_t * restrict ptree, int ply, int turn ) { switch ( ptree->anext_move[ply].next_phase ) @@ -345,7 +346,7 @@ gen_next_evasion( tree_t * restrict ptree, int ply, int turn ) { 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++; diff --git a/param.h b/param.h index e9cecce..26f3193 100644 --- a/param.h +++ b/param.h @@ -1,15 +1,15 @@ #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 diff --git a/phash.c b/phash.c index 8592ee5..d00dcb2 100644 --- a/phash.c +++ b/phash.c @@ -1,275 +1,275 @@ -#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 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]; -} +#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]; +} diff --git a/ponder.c b/ponder.c index 2eb8b7a..634ce23 100644 --- a/ponder.c +++ b/ponder.c @@ -15,7 +15,7 @@ ponder( tree_t * restrict ptree ) || ! 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; } @@ -23,7 +23,7 @@ ponder( tree_t * restrict ptree ) 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; } @@ -44,7 +44,7 @@ ponder( tree_t * restrict ptree ) 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" ); @@ -54,15 +54,14 @@ ponder( tree_t * restrict ptree ) 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; @@ -75,30 +74,37 @@ ponder( tree_t * restrict ptree ) } 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; diff --git a/problem.c b/problem.c index 4980e9a..dda22e4 100644 --- a/problem.c +++ b/problem.c @@ -1,6 +1,8 @@ +#include +#include #include "shogi.h" -int +int CONV solve_problems( tree_t * restrict ptree, unsigned int nposition ) { const char *str_move; @@ -15,8 +17,7 @@ solve_problems( tree_t * restrict ptree, unsigned int nposition ) 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 ) @@ -70,7 +71,7 @@ solve_problems( tree_t * restrict ptree, unsigned int nposition ) 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; } @@ -100,3 +101,52 @@ solve_problems( tree_t * restrict ptree, unsigned int nposition ) 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 diff --git a/proce.c b/proce.c index bb41877..2578634 100644 --- a/proce.c +++ b/proce.c @@ -21,78 +21,109 @@ #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; @@ -109,7 +140,9 @@ proce_cui( tree_t * restrict ptree ) 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 ); } @@ -118,18 +151,24 @@ proce_cui( tree_t * restrict ptree ) 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 @@ -146,8 +185,7 @@ proce_cui( tree_t * restrict ptree ) #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; @@ -193,8 +231,11 @@ proce_csalan( tree_t * restrict ptree ) 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(); } @@ -207,8 +248,7 @@ proce_csalan( tree_t * restrict ptree ) #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; @@ -226,10 +266,31 @@ proce_mnj( tree_t * restrict ptree ) 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; @@ -237,8 +298,54 @@ proce_mnj( tree_t * restrict ptree ) } -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 ); @@ -262,7 +369,13 @@ cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter ) 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; } @@ -270,12 +383,10 @@ cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter ) 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) @@ -283,25 +394,222 @@ cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter ) 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; } @@ -309,7 +617,7 @@ cmd_move_now( void ) } -static int +static int CONV cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts ) { const char *str; @@ -364,10 +672,6 @@ cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts ) if ( sckt_csa != SCKT_NULL ) { AbortDifficultCommand; } #endif -#if defined(DEKUNOBOU) - if ( dek_ngame ) { AbortDifficultCommand; } -#endif - #if defined(CSASHOGI) AbortDifficultCommand; #else @@ -384,24 +688,17 @@ cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts ) 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" ); @@ -417,7 +714,6 @@ cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts ) 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 ) { @@ -436,18 +732,6 @@ cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts ) } #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 ); @@ -476,10 +760,6 @@ cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts ) } #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 ); @@ -490,8 +770,7 @@ cmd_usrmove( tree_t * restrict ptree, const char *str_move, char **lasts ) } -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 ) @@ -511,8 +790,7 @@ cmd_beep( char **lasts ) } -static int -cmd_peek( char **lasts ) +static int CONV cmd_peek( char **lasts ) { const char *str = strtok_r( NULL, str_delimiters, lasts ); @@ -533,8 +811,49 @@ cmd_peek( char **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 ); @@ -544,7 +863,7 @@ cmd_ponder( char **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 ) ) @@ -563,8 +882,7 @@ cmd_ponder( char **lasts ) #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 ); @@ -586,7 +904,7 @@ cmd_stress( char **lasts ) #endif -static int +static int CONV #if defined(MINIMUM) cmd_book( char **lasts ) #else @@ -629,8 +947,7 @@ cmd_book( tree_t * restrict ptree, char **lasts ) } -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; @@ -666,8 +983,7 @@ cmd_display( tree_t * restrict ptree, char **lasts ) } -static int -cmd_ping( void ) +static int CONV cmd_ping( void ) { OutCsaShogi( "pong\n" ); Out( "pong\n" ); @@ -675,8 +991,7 @@ cmd_ping( void ) } -static int -cmd_hash( char **lasts ) +static int CONV cmd_hash( char **lasts ) { const char *str = strtok_r( NULL, str_delimiters, lasts ); char *ptr; @@ -688,29 +1003,6 @@ cmd_hash( char **lasts ) 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 ) { @@ -726,8 +1018,7 @@ cmd_hash( char **lasts ) } -static int -cmd_limit( char **lasts ) +static int CONV cmd_limit( char **lasts ) { const char *str = strtok_r( NULL, str_delimiters, lasts ); char *ptr; @@ -845,7 +1136,7 @@ cmd_limit( char **lasts ) } -static int +static int CONV cmd_read( tree_t * restrict ptree, char **lasts ) { const char *str1 = strtok_r( NULL, str_delimiters, lasts ); @@ -859,7 +1150,7 @@ cmd_read( tree_t * restrict ptree, char **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; @@ -900,7 +1191,7 @@ cmd_read( tree_t * restrict ptree, char **lasts ) 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; } @@ -944,8 +1235,7 @@ cmd_read( tree_t * restrict ptree, char **lasts ) } -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; @@ -957,16 +1247,8 @@ cmd_resign( tree_t * restrict ptree, char **lasts ) 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 { @@ -983,12 +1265,13 @@ cmd_resign( tree_t * restrict ptree, char **lasts ) } -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 ) { @@ -1003,54 +1286,47 @@ cmd_move( tree_t * restrict ptree, char **lasts ) 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 ); @@ -1089,14 +1365,77 @@ cmd_new( tree_t * restrict ptree, char **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 ) { @@ -1110,12 +1449,17 @@ cmd_problem( tree_t * restrict ptree, char **lasts ) } 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 ); @@ -1125,23 +1469,18 @@ cmd_problem( tree_t * restrict ptree, char **lasts ) 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 ) ) { @@ -1154,8 +1493,7 @@ cmd_suspend( void ) } -static int -cmd_time( char **lasts ) +static int CONV cmd_time( char **lasts ) { const char *str = strtok_r( NULL, str_delimiters, lasts ); char *ptr; @@ -1229,8 +1567,7 @@ cmd_time( char **lasts ) #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 ); @@ -1343,8 +1680,7 @@ cmd_learn( tree_t * restrict ptree, char **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; @@ -1404,9 +1740,92 @@ cmd_mpv( char **lasts ) #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 ); @@ -1450,9 +1869,48 @@ cmd_thread( char **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; @@ -1501,21 +1959,42 @@ cmd_connect( tree_t * restrict ptree, char **lasts ) 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 ) @@ -1569,6 +2048,28 @@ cmd_mnj( tree_t * restrict ptree, char **lasts ) 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; @@ -1581,74 +2082,11 @@ cmd_mnj( tree_t * restrict ptree, char **lasts ) 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 - diff --git a/quiesrch.c b/quiesrch.c index 6ceb5fb..cfc4016 100644 --- a/quiesrch.c +++ b/quiesrch.c @@ -11,14 +11,14 @@ # 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; @@ -45,44 +45,37 @@ search_quies( tree_t * restrict ptree, int alpha, int beta, int turn, int ply, 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; } @@ -106,8 +99,8 @@ search_quies( tree_t * restrict ptree, int alpha, int beta, int turn, int ply, 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 ); @@ -125,28 +118,17 @@ search_quies( tree_t * restrict ptree, int alpha, int beta, int turn, int ply, 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 ) { @@ -179,7 +161,7 @@ gen_next_quies( tree_t * restrict ptree, int alpha, int turn, int 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 ) diff --git a/readme.txt b/readme.txt index 7aaf0fb..b90acd3 100644 --- a/readme.txt +++ b/readme.txt @@ -1,562 +1,645 @@ ----------------------------------------------------------------------- - 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. +---------------------------------------------------------------------- + Bonanza 6.0 - Client Source Code + Kunihito Hoki, May 2011 +---------------------------------------------------------------------- + + +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 +--------------- + +Version 6.0 + +Search() function is modified to ignore moves which receive negative +values from Static Exchange Evaluation (SEE) at frontier and +pre-frontier nodes. Self-play experiments showed that this modification +makes Bonanza slightly stronger. Similar results were also observed in +experiments using a shogi program YSS, +http://www32.ocn.ne.jp/~yss/horizon.txt. Moreover, the branch cut by +means of SEE at frontier nodes can also be found in a chess program, +Stockfish. + +Now Bonanza does Late Move Reduction (LMR) at root nodes, and recursive +iterative deepening more often. Self-play experiments showed that these +modifications make Bonanza slightly stronger. + +DFPN searcher is added to the set of Bonanza source codes (dfpn.c, +dfpn.h, and dfpnhash.c). You can use the searcher by using 'dfpn' +command with a compile option -DDFPN turned on. To make use of the DFPN +searcher in ordinary search, use 'dfpn_client' command with a compile +option -DDFPN_CLIENT turned on. To provide a proper service to the DFPN +client, you also need to use a server script 'src/server/dfpn_server.pl' +with one or more DFPN worker(s) connected with 'dfpn connect' command. +I am thankful to Dr. A. Nagai for his kind and fruitful advice. + +Now Bonanza can be a client of parallel searches using cluster computing +environment with mnj command. 'src/server/parallel_server.pl' is a +server script of root-node parallelizations, and the server can be a +client of majority voting cluster computation. + +Some techniques which increase computational efficiency of Bonanza are +reported by E. Ito, http://aleag.cocolog-nifty.com/. In his website, +two ideas are shown, i.e., (i) speed up of the computation of the static +evaluation function, and (2) use of SSE instructions of Intel processors +for bitboard operations. By adopting his ideas to Bonanza, NPS value +nearly doubled. This is amazing. To use SSE instructions, specify -DSSE2 +or -DSSE4 compiler option. I am thankful to Mr. E. Ito for his kind and +fruitful advice. + +-DINANIWA_SHIFT compilation flag is supplied to enable an Inaniwa-strategy detection + +There are many other modifications and bug fixes. + + +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 +- bitop.h bit operations +- dfpn.h header of DFPN codes + +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 operations +- utility.c misc. functions + +I/O +- proce.c input procedures +- csa.c csa file format I/O +- io.c basic I/O +- sckt.c Socket communications + +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 +- phash.c perfect hash function of moves +- 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 + +DFPN search +- dfpn.c DFPN search +- dfpnhash.c Hashing for DFPN search + +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 + +- HAVE_SSE2 use SSE2 instructions for speed + +- HAVE_SSE4 use SSE2 and SSE4.1 instructions for speed + +- MNJ_LAN enables a client-mode of cluster searches + +- INANIWA_SHIFT enables an Inaniwa strategy detection + +- DFPN build the DFPN worker of mate-problems server + +- DFPN_CLIENT enables the client-mode of mate-problem server + + +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. + +- dfpn go + Bonanza does DFPN search at a current position. + +- dfpn hash 'num' + This command is used to initialize the transposition table of + DFPN search and set the size of the table to 2^'num'. This + command becomes effective when DFPN macro is defined in the + Makefile. + +- dfpn connect 'hostname' 'port#' 'ID' + This command is used to connect to the server script + dfpn_server.pl as a worker. This command becomes effective when + DFPN macro is defined in the Makefile. + +- dfpn_client 'hostname' 'port#' + This command is used to connect to the server script + dfpn_server.pl as a client. With this, a root and its child + posittions are examined by the DFPN worker(s). This command + becomes effective when DFPN_CLIENT macro is defined in the + Makefile. + +- 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' 'factor' 'stable_depth' + This command connects Bonanza to the majority or parallel server in + src/server/. 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 15. Note + that all clients should use different seeds. The following three + arguments are network address, port number, user ID, + respectively. You can specify factor as a voting weight. Also + stable_depth is useful to detect opening positions. Here, when + Bonanza reaches the specified depth, then this is reported to the + server to reduce thinking time. 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. diff --git a/root.c b/root.c index e778431..d83b417 100644 --- a/root.c +++ b/root.c @@ -2,25 +2,19 @@ #include #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] ); @@ -28,58 +22,18 @@ make_root_move_list( tree_t * restrict ptree, int flag ) 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)) ) @@ -97,11 +51,8 @@ make_root_move_list( tree_t * restrict ptree, int flag ) 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] ) { @@ -113,7 +64,6 @@ make_root_move_list( tree_t * restrict ptree, int flag ) 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-- ) @@ -153,6 +103,9 @@ make_root_move_list( tree_t * restrict ptree, int flag ) 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; @@ -204,46 +157,17 @@ make_root_move_list( tree_t * restrict ptree, int flag ) } -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 diff --git a/sckt.c b/sckt.c index 9bf0f3f..b09e4a6 100644 --- a/sckt.c +++ b/sckt.c @@ -10,7 +10,28 @@ #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 ) { @@ -26,7 +47,7 @@ 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; @@ -39,7 +60,7 @@ client_next_game( tree_t * restrict ptree, const char *str_addr, int iport ) 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 ); @@ -79,7 +100,7 @@ client_next_game( tree_t * restrict ptree, const char *str_addr, int iport ) if ( ! memcmp( str_cmdline, "REJECT:", 7 ) ) { - ShutdownClient; + ShutdownAll(); continue; } else if ( ! memcmp( str_cmdline, "START:", 6 ) ) { break; } @@ -113,14 +134,15 @@ client_next_game( tree_t * restrict ptree, const char *str_addr, int iport ) #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) { @@ -158,34 +180,42 @@ sckt_connect( const char *str_addr, int iport ) 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; } @@ -194,7 +224,7 @@ sckt_shutdown( sckt_t sd ) 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; } @@ -203,20 +233,21 @@ sckt_shutdown( sckt_t sd ) 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."; @@ -244,7 +275,26 @@ sckt_shutdown( sckt_t sd ) } -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; @@ -265,7 +315,7 @@ sckt_check( sckt_t sd ) 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; } @@ -273,7 +323,7 @@ sckt_check( sckt_t sd ) } -int +int CONV sckt_in( sckt_t sd, char *str, int n ) { struct timeval tv; @@ -309,7 +359,7 @@ sckt_in( sckt_t sd, char *str, int n ) if ( sckt_out( sd, "\n" ) == SOCKET_ERROR ) { - str_error = str_WSAError( "send() failed." ); + str_error = str_WSAError( "send() failed:" ); return -1; } } @@ -317,7 +367,7 @@ sckt_in( sckt_t sd, char *str, int n ) 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'; @@ -334,7 +384,7 @@ sckt_in( sckt_t sd, char *str, int n ) } -int +int CONV sckt_out( sckt_t sd, const char *fmt, ... ) { int nch; @@ -354,11 +404,48 @@ sckt_out( sckt_t sd, const char *fmt, ... ) 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 */ diff --git a/search.c b/search.c index d7ca199..3ef962c 100644 --- a/search.c +++ b/search.c @@ -1,16 +1,16 @@ #include #include #include +#include #include #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) @@ -19,13 +19,13 @@ static int rep_type( const tree_t * restrict ptree, int n, int i, int ply, # 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 ); } @@ -109,18 +109,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, } 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; - } } /* @@ -143,52 +131,47 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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] ) { @@ -204,10 +187,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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; } @@ -222,26 +201,20 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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 ) { @@ -251,10 +224,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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" ); @@ -272,30 +241,29 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, } } - /* 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 ); } } { @@ -319,15 +287,15 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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] @@ -353,7 +321,8 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, && 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) ) { @@ -368,6 +337,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, /* reductions */ if ( PLY_INC <= new_depth + && first_move_expanded && ! ( state_node & node_mate_threat ) && ! ptree->nsuc_check[ply] && ! UToCap(MOVE_CURR) @@ -381,15 +351,14 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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; } @@ -397,7 +366,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, new_depth -= depth_reduced; } - + /* futility pruning */ if ( ! ptree->nsuc_check[ply+1] && ! ptree->nsuc_check[ply] @@ -409,7 +378,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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; @@ -419,6 +388,22 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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] @@ -430,15 +415,13 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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 ); @@ -446,18 +429,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, } } - 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 ); @@ -465,20 +437,21 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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; } @@ -488,11 +461,11 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, { 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 ) @@ -506,11 +479,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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; } @@ -539,11 +507,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, { 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 ); @@ -564,8 +527,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, 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) @@ -617,7 +578,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth, #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 ) { @@ -630,11 +591,17 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn, 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 ); @@ -642,12 +609,12 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn, 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] @@ -666,7 +633,8 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn, && 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) ) { @@ -693,14 +661,13 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn, 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; } @@ -719,7 +686,7 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn, 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; @@ -737,15 +704,13 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn, 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; @@ -803,14 +768,52 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn, } #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 */ @@ -823,7 +826,7 @@ detect_signals( tree_t * restrict ptree ) else if ( iret == -2 ) { out_warning( "%s", str_error ); - ShutdownClient; + ShutdownAll(); } else if ( game_status & flag_quit ) { return 1; } /* EOF */ else if ( iret ) @@ -840,7 +843,7 @@ detect_signals( tree_t * restrict ptree ) { out_warning( "%s", str_error ); next_cmdline( 1 ); - ShutdownClient; + ShutdownAll(); } else if ( iret == 1 ) { next_cmdline( 1 ); } @@ -872,10 +875,11 @@ detect_signals( tree_t * restrict ptree ) } #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 ); @@ -885,12 +889,28 @@ detect_signals( tree_t * restrict ptree ) 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 @@ -935,12 +955,10 @@ detect_signals( tree_t * restrict ptree ) if ( tlimit != tmax ) { tcount = tsearched; - tmax_limit_count = tmax; tlimit_count = tlimit; } else { tcount = telapsed; - tmax_limit_count = tmax + tpondered; tlimit_count = tlimit + tpondered; } @@ -953,22 +971,6 @@ detect_signals( tree_t * restrict ptree ) 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 ) @@ -998,7 +1000,7 @@ detect_signals( tree_t * restrict ptree ) else if ( tsearched + 500U > u ) { easy_time = 1; } } - /* renew node_per_second */ + /* update node_per_second */ { double dn, dd; @@ -1010,7 +1012,7 @@ detect_signals( tree_t * restrict ptree ) 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; @@ -1025,203 +1027,31 @@ detect_signals( tree_t * restrict ptree ) } 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; } @@ -1237,7 +1067,7 @@ detect_rep( tree_t * restrict ptree, int ply, int turn ) } -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; @@ -1267,7 +1097,7 @@ rep_type( const tree_t * restrict ptree, int n, int i, int ply, int turn ) } -static void +static void CONV hist_add( tree_t * restrict ptree, int ply ) { if ( ptree->nsuc_check[ply] ) { return; } @@ -1280,7 +1110,7 @@ hist_add( tree_t * restrict ptree, int ply ) } -static void +static void CONV hist_good( tree_t * restrict ptree, unsigned int move_good, int ply, int depth, int turn ) { diff --git a/searchr.c b/searchr.c index a3aba06..3afd2aa 100644 --- a/searchr.c +++ b/searchr.c @@ -4,49 +4,111 @@ #include #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++; @@ -58,14 +120,14 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) 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 ); @@ -78,7 +140,7 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) return value; } - first_move_expanded = 0; + first_move = 0; } #if defined(MPV) else if ( root_mpv ) @@ -88,13 +150,13 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) { 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 ) { @@ -108,25 +170,74 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) } #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; @@ -136,7 +247,6 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) 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 ) @@ -148,7 +258,7 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) 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 ) @@ -169,8 +279,8 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) 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 ) @@ -179,7 +289,7 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) if ( bound < value && mpv_add_result( ptree, value ) < 0 ) { game_status |= flag_search_error; - return 1; + return 0; } } #endif @@ -189,45 +299,45 @@ searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth ) 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 ); @@ -241,8 +351,7 @@ out_pv( tree_t * restrict ptree, int value, int turn, unsigned int 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 ); } @@ -254,13 +363,22 @@ out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time ) { 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 ); @@ -270,13 +388,15 @@ out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time ) 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 ) ) ) @@ -289,14 +409,22 @@ out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time ) 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 ); @@ -314,7 +442,7 @@ out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time ) 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 " ); } @@ -335,7 +463,8 @@ out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time ) } for ( ply--; ply >= 1; ply-- ) { - tt = Flip(tt); + tt = Flip(tt); + value = -value; UnMakeMove( tt, ptree->pv[0].a[ply], ply ); } @@ -343,40 +472,55 @@ out_pv( tree_t * restrict ptree, int value, int turn, unsigned int time ) { 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 ); } @@ -384,7 +528,7 @@ save_result( tree_t * restrict ptree, int value, int beta, int turn ) } -static int +static int CONV #if defined(NO_STDOUT) && defined(NO_LOGGING) next_root_move( tree_t * restrict ptree ) #else @@ -399,15 +543,15 @@ next_root_move( tree_t * restrict ptree, int turn ) 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 ) { @@ -428,21 +572,8 @@ next_root_move( tree_t * restrict ptree, int turn ) } -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; @@ -488,11 +619,11 @@ mpv_out( tree_t * restrict ptree, int turn, unsigned int time ) { 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 ); } @@ -505,13 +636,15 @@ mpv_out( tree_t * restrict ptree, int turn, unsigned int time ) 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) ) ) @@ -525,12 +658,11 @@ mpv_out( tree_t * restrict ptree, int turn, unsigned int time ) 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 ); } @@ -550,7 +682,7 @@ mpv_out( tree_t * restrict ptree, int turn, unsigned int time ) 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 " ); } @@ -582,7 +714,7 @@ mpv_out( tree_t * restrict ptree, int turn, unsigned int time ) } -static void +static void CONV mpv_sub_result( unsigned int move ) { int i; @@ -611,7 +743,7 @@ mpv_sub_result( unsigned int move ) } -static int +static int CONV mpv_add_result( tree_t * restrict ptree, int value ) { pv_t pv_tmp, pv; @@ -678,7 +810,7 @@ mpv_add_result( tree_t * restrict ptree, int value ) } -static int +static int CONV mpv_set_bound( int alpha ) { int bound, num, value; @@ -698,7 +830,7 @@ mpv_set_bound( int alpha ) } -static int +static int CONV mpv_find_min( int *pnum ) { int i, num; diff --git a/shogi.h b/shogi.h index 809e687..23a7329 100644 --- a/shogi.h +++ b/shogi.h @@ -2,12 +2,13 @@ #define SHOGI_H #include +#include "bitop.h" #include "param.h" #if defined(_WIN32) # include -# define CONV_CDECL __cdecl +# define CONV __fastcall # define SCKT_NULL INVALID_SOCKET typedef SOCKET sckt_t; @@ -15,14 +16,14 @@ typedef SOCKET sckt_t; # include # include -# 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 @@ -53,17 +54,18 @@ typedef volatile int lock_t; #else # include +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 */ @@ -83,29 +85,29 @@ extern unsigned char ailast_one[512]; # 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 ) ) @@ -128,10 +130,6 @@ extern unsigned char ailast_one[512]; #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 ) @@ -147,9 +145,15 @@ extern unsigned char ailast_one[512]; #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 @@ -229,6 +233,11 @@ extern unsigned char ailast_one[512]; ( (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); \ @@ -263,6 +272,7 @@ extern unsigned char ailast_one[512]; #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 @@ -287,89 +297,11 @@ extern unsigned char ailast_one[512]; #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 ]) @@ -389,6 +321,8 @@ extern unsigned char ailast_one[512]; #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]) @@ -484,6 +418,7 @@ enum { flag_diag1 = b0001, flag_plus = b0010 }; enum { score_draw = 1, score_max_eval = 30000, + score_matelong = 30002, score_mate1ply = 32598, score_inferior = 32599, score_bound = 32600, @@ -507,6 +442,7 @@ enum { next_move_hash = 0, next_move_capture, next_move_history2, /* 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, @@ -537,25 +473,24 @@ enum { value_null = b0000, 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, @@ -569,8 +504,9 @@ enum { flag_mated = b0001, 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, @@ -579,7 +515,9 @@ enum { flag_mated = b0001, 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, @@ -646,8 +584,6 @@ enum { f_hand_pawn = 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) @@ -667,11 +603,6 @@ typedef struct { trans_entry_t prefer, always[2]; } trans_table_t; 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; @@ -739,6 +670,9 @@ typedef struct { typedef struct { uint64_t nodes; unsigned int move, status; +#if defined(DFPN_CLIENT) + volatile int dfpn_cresult; +#endif } root_move_t; typedef struct { @@ -778,8 +712,6 @@ struct tree { 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; @@ -801,8 +733,9 @@ struct tree { 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; @@ -823,7 +756,6 @@ struct tree { 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; @@ -839,17 +771,15 @@ extern int ponder_nmove; 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; @@ -860,9 +790,12 @@ extern unsigned int hash_mask; 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; @@ -889,16 +822,15 @@ extern unsigned int sec_w_total; 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 ]; @@ -911,6 +843,7 @@ extern bitboard_t abb_king_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 ]; @@ -960,10 +893,7 @@ extern uint64_t w_hand_silver_rand[ nsilver_max ]; 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; @@ -1011,6 +941,7 @@ extern const char *str_fopen_error; 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; @@ -1018,180 +949,204 @@ 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; @@ -1200,27 +1155,32 @@ int mpv_width; 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; @@ -1229,7 +1189,6 @@ extern int tlp_max; 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 */ @@ -1271,31 +1230,36 @@ int stdout_stress( int is_promote, int ifrom ); 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; @@ -1307,44 +1271,43 @@ extern char client_str_pwd[256]; 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) @@ -1354,10 +1317,6 @@ void out_csashogi( const char *format, ... ); # 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]; @@ -1367,6 +1326,10 @@ extern check_table_t w_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 ) @@ -1406,12 +1369,12 @@ extern unsigned int easy_move; # 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 ); @@ -1426,8 +1389,7 @@ int learn( tree_t * restrict ptree, int is_ini, int nsteps, 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 ); diff --git a/swap.c b/swap.c index a195364..cf177c1 100644 --- a/swap.c +++ b/swap.c @@ -1,14 +1,14 @@ #include #include +#include #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 ); @@ -29,8 +29,8 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, 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; } @@ -41,19 +41,18 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, 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: @@ -75,7 +74,7 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, 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 ); @@ -92,141 +91,13 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, } } - 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; @@ -239,7 +110,7 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, goto ab_cut; } BBAnd( bb, BB_BLANCE, bb_attack ); - if( BBToU( bb ) ) + if( BBTest( bb ) ) { from = FirstOne( bb ); attacked_piece = MT_CAP_LANCE; @@ -251,7 +122,7 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, goto ab_cut; } BBAnd( bb, BB_BKNIGHT, bb_attack ); - if( BBToU( bb ) ) + if( BBTest( bb ) ) { from = FirstOne( bb ); attacked_piece = MT_CAP_KNIGHT; @@ -263,28 +134,28 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, 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; @@ -296,21 +167,21 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, 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; @@ -322,14 +193,14 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, 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; @@ -341,22 +212,152 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, 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 ) @@ -385,7 +386,7 @@ swap( const tree_t * restrict ptree, unsigned int move, int root_alpha, } } } - + if ( nc & 1 ) { return beta; } else { return alpha; } } diff --git a/thread.c b/thread.c index c88461a..f170edd 100644 --- a/thread.c +++ b/thread.c @@ -1,13 +1,369 @@ #include #include #include +#include +#include #if defined(_WIN32) # include #else +# include +# include +# include # include #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) @@ -138,7 +494,7 @@ tlp_set_abort( tree_t * restrict ptree ) } -#if defined(MNJ_LAN) +#if defined(MNJ_LAN) || defined(USI) uint64_t tlp_count_node( tree_t * restrict ptree ) { @@ -169,95 +525,6 @@ tlp_is_descendant( const tree_t * restrict ptree, int slot_ancestor ) } -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 @@ -361,8 +628,6 @@ init_state( const tree_t * restrict parent, tree_t * restrict child ) 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; @@ -381,15 +646,16 @@ init_state( const tree_t * restrict parent, tree_t * restrict child ) 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]; @@ -424,8 +690,6 @@ copy_state( tree_t * restrict parent, const tree_t * restrict child, 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; @@ -439,19 +703,20 @@ copy_state( tree_t * restrict parent, const tree_t * restrict child, 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 ); } diff --git a/time.c b/time.c index 203c3bf..fbeb04a 100644 --- a/time.c +++ b/time.c @@ -7,7 +7,7 @@ #include "shogi.h" -void +void CONV set_search_limit_time( int turn ) /* [inputs] @@ -46,7 +46,16 @@ set_search_limit_time( int turn ) 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 ) ) { @@ -69,7 +78,7 @@ set_search_limit_time( int turn ) 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; @@ -115,8 +124,8 @@ set_search_limit_time( int turn ) } -int -renovate_time( int turn ) +int CONV +update_time( int turn ) { unsigned int te, time_elapsed; int iret; @@ -137,7 +146,7 @@ renovate_time( int turn ) } -void +void CONV adjust_time( unsigned int elapsed_new, int turn ) { const char *str = "TIME SKEW DETECTED"; @@ -162,7 +171,7 @@ adjust_time( unsigned int elapsed_new, int turn ) } -int +int CONV reset_time( unsigned int b_remain, unsigned int w_remain ) { if ( sec_limit_up == UINT_MAX ) @@ -187,7 +196,7 @@ reset_time( unsigned int b_remain, unsigned int w_remain ) } -const char * +const char * CONV str_time( unsigned int time ) { static char str[32]; @@ -208,7 +217,7 @@ str_time( unsigned int time ) } -const char * +const char * CONV str_time_symple( unsigned int time ) { static char str[32]; @@ -226,7 +235,7 @@ str_time_symple( unsigned int time ) } -int +int CONV get_cputime( unsigned int *ptime ) { #if defined(_WIN32) @@ -269,7 +278,7 @@ get_cputime( unsigned int *ptime ) } -int +int CONV get_elapsed( unsigned int *ptime ) { #if defined(_WIN32) diff --git a/unmake.c b/unmake.c index 91e363d..164a626 100644 --- a/unmake.c +++ b/unmake.c @@ -18,12 +18,12 @@ 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]; @@ -169,12 +169,12 @@ unmake_move_b( tree_t * restrict ptree, unsigned int move, int 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]; diff --git a/utility.c b/utility.c index 75b1b9a..198aa90 100644 --- a/utility.c +++ b/utility.c @@ -7,7 +7,7 @@ #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 ) { @@ -15,6 +15,16 @@ ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi, int flag, 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 ); @@ -35,7 +45,7 @@ ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi, int flag, 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; @@ -160,19 +170,17 @@ ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi, int flag, 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; @@ -245,20 +253,36 @@ ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi, int flag, 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 ); @@ -295,7 +319,7 @@ gen_legal_moves( tree_t * restrict ptree, unsigned int *p0 ) } else { i++; } } - + return n; } @@ -304,7 +328,7 @@ gen_legal_moves( tree_t * restrict ptree, unsigned int *p0 ) - detection of perpetual check is omitted. - weak moves are omitted. */ -int +int CONV is_mate( tree_t * restrict ptree, int ply ) { int iret = 0; @@ -318,7 +342,7 @@ is_mate( tree_t * restrict ptree, int ply ) } -int +int CONV is_hand_eq_supe( unsigned int u, unsigned int uref ) { #if 1 @@ -359,7 +383,7 @@ is_hand_eq_supe( unsigned int u, unsigned int uref ) /* weak moves are omitted. */ -int +int CONV detect_repetition( tree_t * restrict ptree, int ply, int turn, int nth ) { const unsigned int *p; @@ -367,7 +391,7 @@ detect_repetition( tree_t * restrict ptree, int ply, int turn, int nth ) 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 ) @@ -449,12 +473,12 @@ detect_repetition( tree_t * restrict ptree, int ply, int turn, int nth ) } -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 ) ) { @@ -463,7 +487,7 @@ com_turn_start( tree_t * restrict ptree, int flag ) 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; } } @@ -471,53 +495,12 @@ com_turn_start( tree_t * restrict ptree, int flag ) 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 ) @@ -537,42 +520,58 @@ com_turn_start( tree_t * restrict ptree, int flag ) } #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"; @@ -580,14 +579,10 @@ com_turn_start( tree_t * restrict ptree, int flag ) 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 ); @@ -605,64 +600,67 @@ com_turn_start( tree_t * restrict ptree, int flag ) 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 ); @@ -675,8 +673,7 @@ memory_alloc( size_t nbytes ) } -int -memory_free( void *p ) +int CONV memory_free( void *p ) { #if defined(_WIN32) if ( VirtualFree( p, 0, MEM_RELEASE ) ) { return 1; } diff --git a/valid.c b/valid.c index e462c62..c043801 100644 --- a/valid.c +++ b/valid.c @@ -4,7 +4,7 @@ #include "shogi.h" -int +int CONV is_move_valid( tree_t * restrict __ptree__, unsigned int move, int turn ) { tree_t * restrict ptree = __ptree__; @@ -34,7 +34,7 @@ is_move_valid( tree_t * restrict __ptree__, unsigned int move, int turn ) 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; } @@ -79,7 +79,7 @@ is_move_valid( tree_t * restrict __ptree__, unsigned int move, int turn ) 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; -- 1.7.0.4