Upgrade to Bonanza 6.0
authorH.G. Muller <h.g.muller@hccnet.nl>
Sun, 15 Sep 2013 08:05:54 +0000 (10:05 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Sun, 15 Sep 2013 08:05:54 +0000 (10:05 +0200)
46 files changed:
Makefile
Makefile.vs
attack.c
bitop.c
book.c
csa.c
data.c
debug.c
dek.c [deleted file]
evaldiff.c
evaluate.c
gencap.c
genchk.c
gendrop.c
genevasn.c
gennocap.c
hash.c
ini.c
io.c
iterate.c
learn1.c
learn2.c
main.c
makemove.c
mate1ply.c
mate3.c
movgenex.c
next.c
param.h
phash.c
ponder.c
problem.c
proce.c
quiesrch.c
readme.txt
root.c
sckt.c
search.c
searchr.c
shogi.h
swap.c
thread.c
time.c
unmake.c
utility.c
valid.c

index 856e931..f5189ed 100644 (file)
--- 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
index 6a966ba..f533d94 100644 (file)
@@ -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
index 2c9cf78..798a30b 100644 (file)
--- a/attack.c
+++ b/attack.c
@@ -2,21 +2,19 @@
 #include <stdlib.h>
 #include "shogi.h"
 
-
-unsigned int
+unsigned int CONV
 is_pinned_on_white_king( const tree_t * restrict ptree, int isquare,
                        int idirec )
 {
-  unsigned int ubb_attacks;
   bitboard_t bb_attacks, bb_attacker;
 
   switch ( idirec )
     {
     case direc_rank:
-      ubb_attacks = AttackRank( isquare );
-      if ( ubb_attacks & (BB_WKING.p[aslide[isquare].ir0]) )
+      bb_attacks = AttackRank( isquare );
+      if ( BBContract( bb_attacks, BB_WKING ) )
        {
-         return ubb_attacks & BB_B_RD.p[aslide[isquare].ir0];
+         return BBContract( bb_attacks, BB_B_RD );
        }
       break;
 
@@ -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 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- a/debug.c
+++ b/debug.c
 
 #  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 (file)
index b3464ac..0000000
--- a/dek.c
+++ /dev/null
@@ -1,314 +0,0 @@
-#include <string.h>
-#include <stdarg.h>
-#include "shogi.h"
-
-#if defined(DEKUNOBOU)
-
-int
-dek_start( const char *str_addr, int port_dek, int port_bnz )
-{
-  SOCKADDR_IN service;
-  WSADATA wsaData;
-  u_short dek_ns_bnz;
-
-  /* initialize winsock */
-  if ( WSAStartup( MAKEWORD(1,1), &wsaData ) )
-    {
-      str_error = "WSAStartup() failed.";
-      return -2;
-    }
-
-  dek_ul_addr = inet_addr( str_addr );
-  if ( dek_ul_addr == INADDR_NONE )
-    {
-      struct hostent *phe = gethostbyname( str_addr );
-      if ( ! phe )
-       {
-         str_error = str_WSAError( "gethostbyname() faild." );
-         return -2;
-       }
-      dek_ul_addr = *( (u_long *)phe->h_addr_list[0] );
-    }
-
-  dek_ns      = htons( (u_short)port_dek );
-  dek_ns_bnz  = htons( (u_short)port_bnz );
-
-  dek_socket_in = socket( AF_INET, SOCK_STREAM, 0 );
-  if ( dek_socket_in == INVALID_SOCKET )
-    {
-      str_error = str_WSAError( "socket() failed." );
-      return -2;
-    }
-  
-  service.sin_family      = AF_INET;
-  service.sin_addr.s_addr = dek_ul_addr;
-  service.sin_port        = dek_ns_bnz;
-  if ( bind( dek_socket_in, (SOCKADDR *)&service, sizeof(service) )
-       == SOCKET_ERROR )
-    {
-      str_error = "bind() failed.";
-      return -2;
-    }
-
-  if ( listen( dek_socket_in, 1 ) == SOCKET_ERROR )
-    {
-      str_error = "listen() failed.";
-      return -2;
-    }
-
-  dek_s_accept = (SOCKET)SOCKET_ERROR;
-
-  return 1;
-}
-
-
-int
-dek_next_game( tree_t * restrict ptree )
-{
-  if ( dek_ngame != 1 && dek_turn )
-    {
-      Out( "take a nap ..." );
-      Sleep( 37000 );
-      Out( " done\n" );
-    }
-
-  if ( ini_game( ptree, &min_posi_no_handicap, flag_history, NULL, NULL ) < 0
-       || get_elapsed( &time_turn_start ) < 0
-       || ( dek_turn && com_turn_start( ptree, 0 ) < 0 ) ) { return -1; }
-
-  dek_turn  ^= 1;
-  dek_ngame += 1;
-
-  return 1;
-}
-
-
-int
-dek_check( void )
-{
-  struct timeval tv;
-  fd_set readfds;
-  int iret;
-  char ch;
-
-  tv.tv_sec = tv.tv_usec = 0;
-
-  if ( dek_s_accept == SOCKET_ERROR )
-    {
-      FD_ZERO( &readfds );
-#if defined(_MSC_VER)
-#  pragma warning(disable:4127)
-#endif
-      FD_SET( dek_socket_in, &readfds );
-#if defined(_MSC_VER)
-#  pragma warning(default:4127)
-#endif
-      iret = select( 1, &readfds, NULL, NULL, &tv );
-      if ( iret == SOCKET_ERROR )
-       {
-         snprintf( str_message, SIZE_MESSAGE,
-                   "select() with a socket listening failed:%d",
-                  WSAGetLastError() );
-         str_error = str_message;
-         return -1;
-       
-       }
-      if ( ! iret ) { return 0; } /* no connection is pending. */
-
-      dek_s_accept = accept( dek_socket_in, NULL, NULL );
-      if ( dek_s_accept == SOCKET_ERROR )
-       {
-         snprintf( str_message, SIZE_MESSAGE,
-                   "accept() following select() failed:%d",
-                  WSAGetLastError() );
-         str_error = str_message;
-         return -1;
-       }
-    }
-
-  FD_ZERO( &readfds );
-#if defined(_MSC_VER)
-#  pragma warning(disable:4127)
-#endif
-  FD_SET( dek_s_accept, &readfds );
-#if defined(_MSC_VER)
-#  pragma warning(default:4127)
-#endif
-
-  iret = select( 0, &readfds, NULL, NULL, &tv );
-  if ( iret == SOCKET_ERROR )
-    {
-      snprintf( str_message, SIZE_MESSAGE,
-               "select() with a socket accepted failed:%d",
-               WSAGetLastError() );
-      str_error = str_message;
-      return -1;
-    }
-  if ( ! iret ) { return 0; } /* the connection isn't closed,
-                                nor has available data. */
-
-  iret = recv( dek_s_accept, &ch, 1, MSG_PEEK );
-  if ( iret == SOCKET_ERROR )
-    {
-      closesocket( dek_s_accept );
-      dek_s_accept = (SOCKET)SOCKET_ERROR;
-      snprintf( str_message, SIZE_MESSAGE,
-               "recv() with flag MSG_PEEK failed:%d",
-               WSAGetLastError() );
-      str_error = str_message;
-      return -1;
-    }
-  if ( ! iret )
-    {
-      if ( closesocket( dek_s_accept ) )
-       {
-         dek_s_accept = (SOCKET)SOCKET_ERROR;
-         snprintf( str_message, SIZE_MESSAGE,
-                   "closesocket() failed:%d", WSAGetLastError() );
-         str_error = str_message;
-         return -1;
-       }
-      dek_s_accept = (SOCKET)SOCKET_ERROR;
-      return 0; /* the connection has been closed. */
-    }
-
-  return 1; /* data is available for reading. */
-}
-
-
-int
-dek_in( char *str, int n )
-{
-#if defined(_MSC_VER)
-#  pragma warning(disable:4127)
-#endif
-  int count_byte;
-
-  for (;;) {
-    if ( dek_s_accept == SOCKET_ERROR )
-      {
-       Out( "\nwait for new connection...\n" );
-       dek_s_accept = accept( dek_socket_in, NULL, NULL );
-       if ( dek_s_accept == SOCKET_ERROR )
-         {
-           str_error = str_WSAError( "accept() failed." );
-           return -1;
-         }
-      }
-  
-    count_byte = recv( dek_s_accept, str, n, 0 );
-    if ( count_byte == SOCKET_ERROR )
-      {
-       closesocket( dek_s_accept );
-       dek_s_accept = (SOCKET)SOCKET_ERROR;
-       str_error = str_WSAError( "recv() failed." );
-       return -1;
-      }
-    if ( count_byte ) { break; }
-
-    if ( closesocket( dek_s_accept ) )
-      {
-       dek_s_accept = (SOCKET)SOCKET_ERROR;
-       str_error = str_WSAError( "closesocket() failed." );
-       return -1;
-      }
-    dek_s_accept = (SOCKET)SOCKET_ERROR;
-  }
-
-  *( str + count_byte ) = '\0';
-  Out( "recieved %s", str );
-
-  return count_byte;
-#if defined(_MSC_VER)
-#  pragma warning(default:4127)
-#endif
-}
-
-
-int
-dek_out( const char *format, ... )
-{
-  SOCKADDR_IN service;
-  SOCKET socket_out;
-  int nch, iret;
-  char buf[256];
-  va_list arg;
-
-  va_start( arg, format );
-  nch = vsnprintf( buf, 256, format, arg );
-  va_end( arg );
-
-  Out( "send %s", buf );
-
-  socket_out = socket( AF_INET, SOCK_STREAM, 0 );
-  if ( socket_out == INVALID_SOCKET )
-    {
-      snprintf( str_message, SIZE_MESSAGE,
-               "socket() failed:%d", WSAGetLastError() );
-      str_error = str_message;
-      return -2;
-    }
-
-  service.sin_family      = AF_INET;
-  service.sin_addr.s_addr = dek_ul_addr;
-  service.sin_port        = dek_ns;
-  if ( connect( socket_out, (SOCKADDR *)&service, sizeof(service) )
-       == SOCKET_ERROR )
-    {
-      snprintf( str_message, SIZE_MESSAGE,
-               "connect() failed:%d", WSAGetLastError() );
-      str_error = str_message;
-      return -2;
-    }
-
-  iret = send( socket_out, buf, nch, 0 );
-  if ( iret == SOCKET_ERROR )
-    {
-      closesocket( socket_out );
-      snprintf( str_message, SIZE_MESSAGE,
-               "send() failed:%d", WSAGetLastError() );
-      str_error = str_message;
-      return -2;
-    }
-  if ( iret != nch )
-    {
-      closesocket( socket_out );
-      str_error = "send() wrote partial number of bytes.";
-      return -2;
-    }
-
-  if ( closesocket( socket_out ) )
-    {
-      snprintf( str_message, SIZE_MESSAGE,
-               "closesocket() failed:%d", WSAGetLastError() );
-      str_error = str_message;
-      return -2;
-    }
-
-  return 1;
-}
-
-int
-dek_parse( char *str, int len )
-{
-  if ( *str == '+' || *str == '-' )
-    {
-      memmove( str, str+1, 6 );
-      str[6] = '\0';
-    }
-  else if ( ! strcmp( str, str_resign ) )
-    {
-      strncpy( str, "resign", len-1 );
-      str[len-1] = '\0';
-      dek_win += 1;
-      Out( "Bonanza won against Dekunobou\n" );
-    }
-  else {
-    str_error = "unknown command is recieved from Deknobou.";
-    return -2;
-  }
-
-  return 1;
-}
-
-#  endif /* DEKUNOBOU */
index c43e4fe..9702365 100644 (file)
@@ -1,13 +1,16 @@
 #include <assert.h>
 #include "shogi.h"
 
-void
+void CONV
 check_futile_score_quies( const tree_t * restrict ptree, unsigned int move,
                          int old_val, int new_val, int turn )
 {
   const int ifrom = I2From(move);
   int fsp, fmt, ipc_cap;
 
+  old_val /= FV_SCALE;
+  new_val /= FV_SCALE;
+
   if ( I2PieceMove(move) == king )
     {
       fmt = new_val;
@@ -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;
     }
   }
index 85b8a63..e573385 100644 (file)
@@ -1,15 +1,31 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <limits.h>
 #include "shogi.h"
 
-static int ehash_probe( uint64_t current_key, unsigned int hand_b,
-                       int *pscore );
-static void ehash_store( uint64_t key, unsigned int hand_b, int score );
-static int make_list( const tree_t * restrict ptree, int * restrict pscore,
-                     int list0[52], int list1[52] );
+#define PcPcOnSqAny(k,i,j) ( i >= j ? PcPcOnSq(k,i,j) : PcPcOnSq(k,j,i) )
+
+static int CONV doacapt( const tree_t * restrict ptree, int pc, int turn,
+                        int hand_index, const int list0[52],
+                        const int list1[52], int nlist );
+static int CONV doapc( const tree_t * restrict ptree, int pc, int sq,
+                      const int list0[52], const int list1[52], int nlist );
+static int CONV ehash_probe( uint64_t current_key, unsigned int hand_b,
+                            int * restrict pscore );
+static void CONV ehash_store( uint64_t key, unsigned int hand_b, int score );
+static int CONV calc_difference( const tree_t * restrict ptree, int ply,
+                                int turn, int list0[52], int list1[52],
+                                int * restrict pscore );
+static int CONV make_list( const tree_t * restrict ptree,
+                          int * restrict pscore,
+                          int list0[52], int list1[52] );
+
+#if defined(INANIWA_SHIFT)
+static int inaniwa_score( const tree_t * restrict ptree );
+#endif
 
-int
+int CONV
 eval_material( const tree_t * restrict ptree )
 {
   int material, itemp;
@@ -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
index 06ba52b..cb38d4c 100644 (file)
--- 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 );
index dfefee0..a7d7992 100644 (file)
--- a/genchk.c
+++ b/genchk.c
-#include <assert.h>\r
-#include "shogi.h"\r
-\r
-\r
-static bitboard_t add_behind_attacks( int idirec, int ik, bitboard_t bb );\r
-\r
-\r
-unsigned int *\r
-b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
-{\r
-  bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
-  bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
-  const tree_t * restrict ptree = __ptree__;\r
-  unsigned int u0, u1, u2;\r
-  int from, to, sq_wk, idirec;\r
-\r
-  sq_wk = SQ_WKING;\r
-  bb_rook_chk  = bb_file_chk = AttackFile( sq_wk );\r
-  bb_rook_chk.p[aslide[sq_wk].ir0] |= AttackRank( sq_wk );\r
-  bb_diag1_chk = AttackDiag1( sq_wk );\r
-  bb_diag2_chk = AttackDiag2( sq_wk );\r
-  BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );\r
-  BBNot( bb_move_to, BB_BOCCUPY );\r
-  BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
-  BBNot( bb_drop_to, bb_drop_to );\r
-\r
-  from  = SQ_BKING;\r
-  idirec = (int)adirec[sq_wk][from];\r
-  if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-    {\r
-      BBIni( bb_chk );\r
-      bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-      BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-\r
-\r
-  bb_piece = BB_BDRAGON;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = LastOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      AttackDragon( bb_desti, from );\r
-      BBAnd( bb_chk, bb_chk, bb_desti );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-\r
-  bb_piece = BB_BHORSE;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = LastOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      AttackHorse( bb_desti, from );\r
-      BBAnd( bb_chk, bb_chk, bb_desti );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-\r
-  u1 = BB_BROOK.p[1];\r
-  u2 = BB_BROOK.p[2];\r
-  while( u1 | u2 )\r
-    {\r
-      from = last_one12( u1, u2 );\r
-      u1   ^= abb_mask[from].p[1];\r
-      u2   ^= abb_mask[from].p[2];\r
-\r
-      AttackRook( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       bb_chk       = bb_rook_chk;\r
-       bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while ( bb_chk.p[0] )\r
-       {\r
-         to          = last_one0( bb_chk.p[0] );\r
-         bb_chk.p[0] ^= abb_mask[to].p[0];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
-           | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-\r
-      while( bb_chk.p[1] | bb_chk.p[2] )\r
-       {\r
-         to          = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
-         bb_chk.p[1] ^= abb_mask[to].p[1];\r
-         bb_chk.p[2] ^= abb_mask[to].p[2];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-\r
-  u0 = BB_BROOK.p[0];\r
-  while( u0 )\r
-    {\r
-      from = last_one0( u0 );\r
-      u0   ^= abb_mask[from].p[0];\r
-      \r
-      AttackRook( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
-           | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-\r
-  u1 = BB_BBISHOP.p[1];\r
-  u2 = BB_BBISHOP.p[2];\r
-  while( u1 | u2 )\r
-    {\r
-      from = last_one12( u1, u2 );\r
-      u1   ^= abb_mask[from].p[1];\r
-      u2   ^= abb_mask[from].p[2];\r
-\r
-      AttackBishop( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       bb_chk       = bb_bishop_chk;\r
-       bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while ( bb_chk.p[0] )\r
-       {\r
-         to          = last_one0( bb_chk.p[0] );\r
-         bb_chk.p[0] ^= abb_mask[to].p[0];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
-           | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-\r
-      while( bb_chk.p[1] | bb_chk.p[2] )\r
-       {\r
-         to          = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
-         bb_chk.p[1] ^= abb_mask[to].p[1];\r
-         bb_chk.p[2] ^= abb_mask[to].p[2];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-\r
-  u0 = BB_BBISHOP.p[0];\r
-  while( u0 )\r
-    {\r
-      from = last_one0( u0 );\r
-      u0   ^= abb_mask[from].p[0];\r
-      \r
-      AttackBishop( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
-           | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-\r
-\r
-  bb_piece = BB_BTGOLD;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = LastOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      bb_chk = abb_w_gold_attacks[sq_wk];\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = ( To2Move(to) | From2Move(from)\r
-                      | Piece2Move(BOARD[from])\r
-                      | Cap2Move(-BOARD[to]) );\r
-       }\r
-    }\r
-  \r
-\r
-  u0 = BB_BSILVER.p[0];\r
-  while( u0 )\r
-    {\r
-      from = last_one0( u0 );\r
-      u0   ^= abb_mask[from].p[0];\r
-\r
-      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
-      bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];\r
-      bb_chk.p[2] = 0;\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
-      bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];\r
-\r
-      while( bb_chk.p[0] | bb_chk.p[1] )\r
-       {\r
-         to          = last_one01( bb_chk.p[0], bb_chk.p[1] );\r
-         bb_chk.p[0] ^= abb_mask[to].p[0];\r
-         bb_chk.p[1] ^= abb_mask[to].p[1];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
-           | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  u1 = BB_BSILVER.p[1] & 0x7fc0000U;\r
-  while( u1 )\r
-    {\r
-      from = last_one1( u1 );\r
-      u1   ^= abb_mask[from].p[1];\r
-      \r
-      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
-      bb_chk.p[1] = bb_chk.p[2] = 0;\r
-      \r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
-      while ( bb_chk.p[0] )\r
-       {\r
-         to          = last_one0( bb_chk.p[0] );\r
-         bb_chk.p[0] ^= abb_mask[to].p[0];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
-           | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  bb_piece = BB_BSILVER;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = LastOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      bb_chk = abb_w_silver_attacks[sq_wk];\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-  \r
-\r
-  u0 = BB_BKNIGHT.p[0];\r
-  u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;\r
-  while( u0 | u1 )\r
-    {\r
-      from = last_one01( u0, u1 );\r
-      u0   ^= abb_mask[from].p[0];\r
-      u1   ^= abb_mask[from].p[1];\r
-\r
-      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
-      bb_chk.p[1] = bb_chk.p[2] = 0;\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];\r
-\r
-      while( bb_chk.p[0] )\r
-       {\r
-         to          = last_one0( bb_chk.p[0] );\r
-         bb_chk.p[0] ^= abb_mask[to].p[0];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
-                      | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  u2 = BB_BKNIGHT.p[2];\r
-  u1 = BB_BKNIGHT.p[1] & 0x3ffffU;\r
-  while( u2 | u1 )\r
-    {\r
-      from = last_one12( u1, u2 );\r
-      u2   ^= abb_mask[from].p[2];\r
-      u1   ^= abb_mask[from].p[1];\r
-\r
-      bb_chk = abb_w_knight_attacks[sq_wk];\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-\r
-\r
-  bb_piece = BB_BLANCE;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = LastOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
-      bb_chk.p[1] = bb_chk.p[2] = 0;\r
-\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
-      BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
-           | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  u1 = BB_BLANCE.p[1];\r
-  u2 = BB_BLANCE.p[2];\r
-  while( u1| u2 )\r
-    {\r
-      from = last_one12( u1, u2 );\r
-      u1   ^= abb_mask[from].p[1];\r
-      u2   ^= abb_mask[from].p[2];\r
-\r
-      bb_chk = bb_file_chk;\r
-      idirec = (int)adirec[sq_wk][from];\r
-      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
-         BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
-       }\r
-      else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}\r
-\r
-      BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
-           | Cap2Move(-BOARD[to]);\r
-       }\r
-    }\r
-\r
-\r
-  BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );\r
-  while ( BBToU(bb_piece) )\r
-    {\r
-      from = LastOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-      \r
-      to = from - nfile;\r
-      if ( BOARD[to] != empty ) { continue; }\r
-\r
-      bb_desti = AttackDiag1( from );\r
-      if ( BBContract( bb_desti, BB_B_BH ) )\r
-       {\r
-         *pmove = To2Move(to) | From2Move(from)\r
-           | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
-         if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
-         pmove += 1;\r
-       }\r
-    }\r
-\r
-  BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );\r
-  while ( BBToU(bb_piece) )\r
-    {\r
-      from = LastOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-      \r
-      to = from - nfile;\r
-      if ( BOARD[to] != empty ) { continue; }\r
-\r
-      bb_desti = AttackDiag2( from );\r
-      if ( BBContract( bb_desti, BB_B_BH ) )\r
-       {\r
-         *pmove = To2Move(to) | From2Move(from)\r
-           | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
-         if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
-         pmove += 1;\r
-       }\r
-    }\r
-\r
-  BBIni( bb_chk );\r
-  bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
-  if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };\r
-  BBAnd( bb_chk, bb_chk, bb_move_to );\r
-  BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );\r
-  while ( BBToU(bb_chk) )\r
-    {\r
-      to = LastOne( bb_chk );\r
-      Xor( to, bb_chk );\r
-\r
-      from = to + nfile;\r
-      *pmove = To2Move(to) | From2Move(from)\r
-       | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
-      if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
-      pmove += 1;\r
-    }\r
-\r
-\r
-  if ( IsHandGold(HAND_B) )\r
-    {\r
-      BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | Drop2Move(gold);\r
-       }\r
-    }\r
-  \r
-\r
-  if ( IsHandSilver(HAND_B) )\r
-    {\r
-      BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | Drop2Move(silver);\r
-       }\r
-    }\r
-  \r
-\r
-  if ( IsHandKnight(HAND_B) && sq_wk < A2 )\r
-    {\r
-      to = sq_wk + 2*nfile - 1;\r
-      if ( aifile[sq_wk] != file1 && BOARD[to] == empty )\r
-       {\r
-         *pmove++ = To2Move(to) | Drop2Move(knight);\r
-       }\r
-\r
-      to = sq_wk + 2*nfile + 1;\r
-      if ( aifile[sq_wk] != file9 && BOARD[to] == empty )\r
-       {\r
-         *pmove++ = To2Move(to) | Drop2Move(knight);\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandPawn(HAND_B)\r
-       && sq_wk < A1\r
-       && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )\r
-    {\r
-      to = sq_wk + nfile;\r
-      if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )\r
-       {\r
-         *pmove++ = To2Move(to) | Drop2Move(pawn);\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandLance(HAND_B) )\r
-    {\r
-      unsigned int move;\r
-      int dist, min_dist;\r
-\r
-      if ( (int)aifile[sq_wk] == file1\r
-          || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
-      else                                  { min_dist = 3; }\r
-\r
-      for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
-           to += nfile, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(lance);\r
-         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandRook(HAND_B) )\r
-    {\r
-      unsigned int move;\r
-      int file, dist, min_dist;\r
-\r
-      if ( (int)aifile[sq_wk] == file1\r
-          || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
-      else                                  { min_dist = 3; }\r
-\r
-      for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
-           to += nfile, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;\r
-           file >= file1 && BOARD[to] == empty;\r
-           file -= 1, to -= 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if      ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }\r
-      else                            { min_dist = 3; }\r
-\r
-      for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;\r
-           file <= file9 && BOARD[to] == empty;\r
-           file += 1, to += 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
-           to -= nfile, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
-         if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandBishop(HAND_B) )\r
-    {\r
-      unsigned int move;\r
-      int file, rank, dist;\r
-\r
-      to   = sq_wk;\r
-      file = (int)aifile[sq_wk];\r
-      rank = (int)airank[sq_wk];\r
-      for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
-           file >= 0 && rank >= 0 && BOARD[to] == empty;\r
-           to -= 10, file -= 1, rank -= 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      to   = sq_wk;\r
-      file = (int)aifile[sq_wk];\r
-      rank = (int)airank[sq_wk];\r
-      for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
-           file <= file9 && rank >= 0 && BOARD[to] == empty;\r
-           to -= 8, file += 1, rank -= 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      to   = sq_wk;\r
-      file = (int)aifile[sq_wk];\r
-      rank = (int)airank[sq_wk];\r
-      for ( to += 8, file -= 1, rank += 1, dist = 1;\r
-           file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
-           to += 8, file -= 1, rank += 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      to   = sq_wk;\r
-      file = (int)aifile[sq_wk];\r
-      rank = (int)airank[sq_wk];\r
-      for ( to += 10, file += 1, rank += 1, dist = 1;\r
-           file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
-           to += 10, file += 1, rank += 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-    }\r
-\r
-\r
-  return pmove;\r
-}\r
-\r
-\r
-unsigned int *\r
-w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
-{\r
-  bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
-  bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
-  const tree_t * restrict ptree = __ptree__;\r
-  unsigned int u0, u1, u2;\r
-  int from, to, sq_bk, idirec;\r
-\r
-  sq_bk = SQ_BKING;\r
-  bb_rook_chk = bb_file_chk = AttackFile( sq_bk );\r
-  bb_rook_chk.p[aslide[sq_bk].ir0] |= AttackRank( sq_bk );\r
-  bb_diag1_chk = AttackDiag1( sq_bk );\r
-  bb_diag2_chk = AttackDiag2( sq_bk );\r
-  AttackBishop( bb_bishop_chk, sq_bk );\r
-  BBNot( bb_move_to, BB_WOCCUPY );\r
-  BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
-  BBNot( bb_drop_to, bb_drop_to );\r
-\r
-\r
-  from  = SQ_WKING;\r
-  idirec = (int)adirec[sq_bk][from];\r
-  if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-    {\r
-      BBIni( bb_chk );\r
-      bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-      BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-\r
-  bb_piece = BB_WDRAGON;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = FirstOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      AttackDragon( bb_desti, from );\r
-      BBAnd( bb_chk, bb_chk, bb_desti );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = LastOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-\r
-  bb_piece = BB_WHORSE;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = FirstOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      AttackHorse( bb_desti, from );\r
-      BBAnd( bb_chk, bb_chk, bb_desti );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-  u0 = BB_WROOK.p[0];\r
-  u1 = BB_WROOK.p[1];\r
-  while( u0 | u1 )\r
-    {\r
-      from = first_one01( u0, u1 );\r
-      u0   ^= abb_mask[from].p[0];\r
-      u1   ^= abb_mask[from].p[1];\r
-\r
-      AttackRook( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       bb_chk       = bb_rook_chk;\r
-       bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while ( bb_chk.p[2] )\r
-       {\r
-         to          = first_one2( bb_chk.p[2] );\r
-         bb_chk.p[2] ^= abb_mask[to].p[2];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
-           | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-\r
-      while( bb_chk.p[0] | bb_chk.p[1] )\r
-       {\r
-         to          = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
-         bb_chk.p[0] ^= abb_mask[to].p[0];\r
-         bb_chk.p[1] ^= abb_mask[to].p[1];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-  u2 = BB_WROOK.p[2];\r
-  while( u2 )\r
-    {\r
-      from = first_one2( u2 );\r
-      u2   ^= abb_mask[from].p[2];\r
-      \r
-      AttackRook( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
-           | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-\r
-  u0 = BB_WBISHOP.p[0];\r
-  u1 = BB_WBISHOP.p[1];\r
-  while( u0 | u1 )\r
-    {\r
-      from = first_one01( u0, u1 );\r
-      u0   ^= abb_mask[from].p[0];\r
-      u1   ^= abb_mask[from].p[1];\r
-\r
-      AttackBishop( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       bb_chk       = bb_bishop_chk;\r
-       bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while ( bb_chk.p[2] )\r
-       {\r
-         to          = first_one2( bb_chk.p[2] );\r
-         bb_chk.p[2] ^= abb_mask[to].p[2];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
-           | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-\r
-      while( bb_chk.p[0] | bb_chk.p[1] )\r
-       {\r
-         to          = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
-         bb_chk.p[0] ^= abb_mask[to].p[0];\r
-         bb_chk.p[1] ^= abb_mask[to].p[1];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-  u2 = BB_WBISHOP.p[2];\r
-  while( u2 )\r
-    {\r
-      from = first_one2( u2 );\r
-      u2   ^= abb_mask[from].p[2];\r
-      \r
-      AttackBishop( bb_desti, from );\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         BBAnd( bb_chk, bb_desti, bb_move_to );\r
-       }\r
-      else {\r
-       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
-       BBAnd( bb_chk, bb_chk, bb_desti );\r
-       BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      }\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
-           | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-\r
-\r
-  bb_piece = BB_WTGOLD;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = FirstOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      bb_chk = abb_b_gold_attacks[sq_bk];\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = ( To2Move(to) | From2Move(from)\r
-                      | Piece2Move(-BOARD[from])\r
-                      | Cap2Move(BOARD[to]) );\r
-       }\r
-    }\r
-\r
-  \r
-  u2 = BB_WSILVER.p[2];\r
-  while( u2 )\r
-    {\r
-      from = first_one2( u2 );\r
-      u2   ^= abb_mask[from].p[2];\r
-\r
-      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
-      bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];\r
-      bb_chk.p[0] = 0;\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
-      bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];\r
-\r
-      while( bb_chk.p[2] | bb_chk.p[1] )\r
-       {\r
-         to          = first_one12( bb_chk.p[1], bb_chk.p[2] );\r
-         bb_chk.p[1] ^= abb_mask[to].p[1];\r
-         bb_chk.p[2] ^= abb_mask[to].p[2];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
-           | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  u1 = BB_WSILVER.p[1] & 0x1ffU;\r
-  while( u1 )\r
-    {\r
-      from = first_one1( u1 );\r
-      u1   ^= abb_mask[from].p[1];\r
-      \r
-      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
-      bb_chk.p[1] = bb_chk.p[0] = 0;\r
-      \r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
-      while ( bb_chk.p[2] )\r
-       {\r
-         to          = first_one2( bb_chk.p[2] );\r
-         bb_chk.p[2] ^= abb_mask[to].p[2];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
-           | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  bb_piece = BB_WSILVER;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = FirstOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      bb_chk = abb_b_silver_attacks[sq_bk];\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-  \r
-  u2 = BB_WKNIGHT.p[2];\r
-  u1 = BB_WKNIGHT.p[1] & 0x3ffffU;\r
-  while( u2 | u1 )\r
-    {\r
-      from = first_one12( u1, u2 );\r
-      u2   ^= abb_mask[from].p[2];\r
-      u1   ^= abb_mask[from].p[1];\r
-\r
-      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
-      bb_chk.p[1] = bb_chk.p[0] = 0;\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];\r
-\r
-      while( bb_chk.p[2] )\r
-       {\r
-         to          = first_one2( bb_chk.p[2] );\r
-         bb_chk.p[2] ^= abb_mask[to].p[2];\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
-                      | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  u0 = BB_WKNIGHT.p[0];\r
-  u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;\r
-  while( u0 | u1 )\r
-    {\r
-      from = first_one01( u0, u1 );\r
-      u0   ^= abb_mask[from].p[0];\r
-      u1   ^= abb_mask[from].p[1];\r
-\r
-      bb_chk = abb_b_knight_attacks[sq_bk];\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-\r
-  bb_piece = BB_WLANCE;\r
-  while( BBToU( bb_piece ) )\r
-    {\r
-      from = FirstOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-\r
-      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
-      bb_chk.p[1] = bb_chk.p[0] = 0;\r
-\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-       }\r
-\r
-      BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
-      BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
-           | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
-       }\r
-    }\r
-  \r
-\r
-  u0 = BB_WLANCE.p[0];\r
-  u1 = BB_WLANCE.p[1];\r
-  while( u0 | u1 )\r
-    {\r
-      from = first_one01( u0, u1 );\r
-      u0   ^= abb_mask[from].p[0];\r
-      u1   ^= abb_mask[from].p[1];\r
-\r
-      bb_chk = bb_file_chk;\r
-      idirec = (int)adirec[sq_bk][from];\r
-      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
-       {\r
-         bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
-         BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
-       }\r
-      else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }\r
-\r
-      BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
-      BBAnd( bb_chk, bb_chk, bb_move_to );\r
-      bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;\r
-\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
-           | Cap2Move(BOARD[to]);\r
-       }\r
-    }\r
-\r
-\r
-  BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );\r
-  while ( BBToU(bb_piece) )\r
-    {\r
-      from = FirstOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-      \r
-      to = from + nfile;\r
-      if ( BOARD[to] != empty ) { continue; }\r
-\r
-      bb_desti = AttackDiag1( from );\r
-      if ( BBContract( bb_desti, BB_W_BH ) )\r
-       {\r
-         *pmove = To2Move(to) | From2Move(from)\r
-           | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
-         if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
-         pmove += 1;\r
-       }\r
-    }\r
-\r
-  BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );\r
-  while ( BBToU(bb_piece) )\r
-    {\r
-      from = FirstOne( bb_piece );\r
-      Xor( from, bb_piece );\r
-      \r
-      to = from + nfile;\r
-      if ( BOARD[to] != empty ) { continue; }\r
-\r
-      bb_desti = AttackDiag2( from );\r
-      if ( BBContract( bb_desti, BB_W_BH ) )\r
-       {\r
-         *pmove = To2Move(to) | From2Move(from)\r
-           | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
-         if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
-         pmove += 1;\r
-       }\r
-    }\r
-\r
-  BBIni( bb_chk );\r
-  bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
-  if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };\r
-  BBAnd( bb_chk, bb_chk, bb_move_to );\r
-  BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );\r
-  while ( BBToU(bb_chk) )\r
-    {\r
-      to = FirstOne( bb_chk );\r
-      Xor( to, bb_chk );\r
-\r
-      from = to - nfile;\r
-      *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)\r
-       | Cap2Move(BOARD[to]);\r
-      if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
-      pmove += 1;\r
-    }\r
-\r
-\r
-  if ( IsHandGold(HAND_W) )\r
-    {\r
-      BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | Drop2Move(gold);\r
-       }\r
-    }\r
-  \r
-\r
-  if ( IsHandSilver(HAND_W) )\r
-    {\r
-      BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );\r
-      while( BBToU( bb_chk ) )\r
-       {\r
-         to = FirstOne( bb_chk );\r
-         Xor( to, bb_chk );\r
-         *pmove++ = To2Move(to) | Drop2Move(silver);\r
-       }\r
-    }\r
-  \r
-\r
-  if ( IsHandKnight(HAND_W) && sq_bk > I8 )\r
-    {\r
-      to = sq_bk - 2*nfile - 1;\r
-      if ( aifile[sq_bk] != file1 && BOARD[to] == empty )\r
-       {\r
-         *pmove++ = To2Move(to) | Drop2Move(knight);\r
-       }\r
-\r
-      to = sq_bk - 2*nfile + 1;\r
-      if ( aifile[sq_bk] != file9 && BOARD[to] == empty )\r
-       {\r
-         *pmove++ = To2Move(to) | Drop2Move(knight);\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandPawn(HAND_W)\r
-       && sq_bk > I9\r
-       && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )\r
-    {\r
-      to = sq_bk - nfile;\r
-      if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )\r
-       {\r
-         *pmove++ = To2Move(to) | Drop2Move(pawn);\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandLance(HAND_W) )\r
-    {\r
-      unsigned int move;\r
-      int dist, min_dist;\r
-\r
-      if ( (int)aifile[sq_bk] == file1\r
-          || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
-      else                                  { min_dist = 3; }\r
-\r
-      for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
-           to -= nfile, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(lance);\r
-         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandRook(HAND_W) )\r
-    {\r
-      unsigned int move;\r
-      int file, dist, min_dist;\r
-\r
-      if ( (int)aifile[sq_bk] == file1\r
-          || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
-      else                                  { min_dist = 3; }\r
-\r
-      for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
-           to -= nfile, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if      ( dist == 1 )        { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist )  { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
-           to += nfile, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
-         if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-\r
-      if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }\r
-      else                            { min_dist = 3; }\r
-\r
-      for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;\r
-           file <= file9 && BOARD[to] == empty;\r
-           file += 1, to += 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;\r
-           file >= file1 && BOARD[to] == empty;\r
-           file -= 1, to -= 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(rook);\r
-         if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-    }\r
-\r
-\r
-  if ( IsHandBishop(HAND_W) )\r
-    {\r
-      unsigned int move;\r
-      int file, rank, dist;\r
-\r
-      to   = sq_bk;\r
-      file = (int)aifile[sq_bk];\r
-      rank = (int)airank[sq_bk];\r
-      for ( to += 10, file += 1, rank += 1, dist = 1;\r
-           file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
-           to += 10, file += 1, rank += 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      to   = sq_bk;\r
-      file = (int)aifile[sq_bk];\r
-      rank = (int)airank[sq_bk];\r
-      for ( to += 8, file -= 1, rank += 1, dist = 1;\r
-           file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
-           to += 8, file -= 1, rank += 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      to   = sq_bk;\r
-      file = (int)aifile[sq_bk];\r
-      rank = (int)airank[sq_bk];\r
-      for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
-           file <= file9 && rank >= 0 && BOARD[to] == empty;\r
-           to -= 8, file += 1, rank -= 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-\r
-      to   = sq_bk;\r
-      file = (int)aifile[sq_bk];\r
-      rank = (int)airank[sq_bk];\r
-      for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
-           file >= 0 && rank >= 0 && BOARD[to] == empty;\r
-           to -= 10, file -= 1, rank -= 1, dist += 1 )\r
-       {\r
-         move = To2Move(to) | Drop2Move(bishop);\r
-         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
-         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
-         *pmove++ = move;\r
-       }\r
-    }\r
-\r
-\r
-  return pmove;\r
-}\r
-\r
-\r
-static bitboard_t\r
-add_behind_attacks( int idirec, int ik, bitboard_t bb )\r
-{\r
-  bitboard_t bb_tmp;\r
-\r
-  if ( idirec == direc_diag1 )\r
-    {\r
-      bb_tmp = abb_bishop_attacks_rr45[ik][0];\r
-    }\r
-  else if ( idirec == direc_diag2 )\r
-    {\r
-      bb_tmp = abb_bishop_attacks_rl45[ik][0];\r
-    }\r
-  else if ( idirec == direc_file )\r
-    {\r
-      bb_tmp = abb_file_attacks[ik][0];\r
-    }\r
-  else {\r
-    assert( idirec == direc_rank );\r
-    BBIni( bb_tmp );\r
-    bb_tmp.p[aslide[ik].ir0] = ai_rook_attacks_r0[ik][0];\r
-  }\r
-  BBNot( bb_tmp, bb_tmp );\r
-  BBOr( bb, bb, bb_tmp );\r
-\r
-  return bb;\r
-}\r
+#include <assert.h>
+#include "shogi.h"
+
+
+static void CONV add_behind_attacks( bitboard_t * restrict pbb, int idirec,
+                                    int ik );
+
+unsigned int * CONV
+b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
+{
+  bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+  bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+  bitboard_t bb_rank_chk;
+  const tree_t * restrict ptree = __ptree__;
+  unsigned int u0, u1, u2;
+  int from, to, sq_wk, idirec;
+
+  sq_wk = SQ_WKING;
+  bb_file_chk = AttackFile( sq_wk );
+  bb_rank_chk = AttackRank( sq_wk );
+  BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+  bb_diag1_chk = AttackDiag1( sq_wk );
+  bb_diag2_chk = AttackDiag2( sq_wk );
+  BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+  BBNot( bb_move_to, BB_BOCCUPY );
+  BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+  BBNot( bb_drop_to, bb_drop_to );
+
+  from  = SQ_BKING;
+  idirec = (int)adirec[sq_wk][from];
+  if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+    {
+      BBIni( bb_chk );
+      add_behind_attacks( &bb_chk, idirec, sq_wk );
+      BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+      
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+  
+  
+  bb_piece = BB_BDRAGON;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      AttackDragon( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+
+  bb_piece = BB_BHORSE;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      AttackHorse( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+
+  u1 = BB_BROOK.p[1];
+  u2 = BB_BROOK.p[2];
+  while( u1 | u2 )
+    {
+      from = last_one12( u1, u2 );
+      u1   ^= abb_mask[from].p[1];
+      u2   ^= abb_mask[from].p[2];
+
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_rook_chk;
+       bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while ( bb_chk.p[0] )
+       {
+         to          = last_one0( bb_chk.p[0] );
+         bb_chk.p[0] ^= abb_mask[to].p[0];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+           | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+
+      while( bb_chk.p[1] | bb_chk.p[2] )
+       {
+         to          = last_one12( bb_chk.p[1], bb_chk.p[2] );
+         bb_chk.p[1] ^= abb_mask[to].p[1];
+         bb_chk.p[2] ^= abb_mask[to].p[2];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+
+  u0 = BB_BROOK.p[0];
+  while( u0 )
+    {
+      from = last_one0( u0 );
+      u0   ^= abb_mask[from].p[0];
+      
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+           | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+    }
+
+  u1 = BB_BBISHOP.p[1];
+  u2 = BB_BBISHOP.p[2];
+  while( u1 | u2 )
+    {
+      from = last_one12( u1, u2 );
+      u1   ^= abb_mask[from].p[1];
+      u2   ^= abb_mask[from].p[2];
+
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_bishop_chk;
+       bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while ( bb_chk.p[0] )
+       {
+         to          = last_one0( bb_chk.p[0] );
+         bb_chk.p[0] ^= abb_mask[to].p[0];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+           | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+
+      while( bb_chk.p[1] | bb_chk.p[2] )
+       {
+         to          = last_one12( bb_chk.p[1], bb_chk.p[2] );
+         bb_chk.p[1] ^= abb_mask[to].p[1];
+         bb_chk.p[2] ^= abb_mask[to].p[2];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+
+  u0 = BB_BBISHOP.p[0];
+  while( u0 )
+    {
+      from = last_one0( u0 );
+      u0   ^= abb_mask[from].p[0];
+      
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+           | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+    }
+
+
+  bb_piece = BB_BTGOLD;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_w_gold_attacks[sq_wk];
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = ( To2Move(to) | From2Move(from)
+                      | Piece2Move(BOARD[from])
+                      | Cap2Move(-BOARD[to]) );
+       }
+    }
+  
+
+  u0 = BB_BSILVER.p[0];
+  while( u0 )
+    {
+      from = last_one0( u0 );
+      u0   ^= abb_mask[from].p[0];
+
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
+      bb_chk.p[2] = 0;
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+      bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
+
+      while( bb_chk.p[0] | bb_chk.p[1] )
+       {
+         to          = last_one01( bb_chk.p[0], bb_chk.p[1] );
+         bb_chk.p[0] ^= abb_mask[to].p[0];
+         bb_chk.p[1] ^= abb_mask[to].p[1];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+           | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  u1 = BB_BSILVER.p[1] & 0x7fc0000U;
+  while( u1 )
+    {
+      from = last_one1( u1 );
+      u1   ^= abb_mask[from].p[1];
+      
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = bb_chk.p[2] = 0;
+      
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+      while ( bb_chk.p[0] )
+       {
+         to          = last_one0( bb_chk.p[0] );
+         bb_chk.p[0] ^= abb_mask[to].p[0];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+           | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  bb_piece = BB_BSILVER;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_w_silver_attacks[sq_wk];
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+  
+
+  u0 = BB_BKNIGHT.p[0];
+  u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
+  while( u0 | u1 )
+    {
+      from = last_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = bb_chk.p[2] = 0;
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
+
+      while( bb_chk.p[0] )
+       {
+         to          = last_one0( bb_chk.p[0] );
+         bb_chk.p[0] ^= abb_mask[to].p[0];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+                      | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  u2 = BB_BKNIGHT.p[2];
+  u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
+  while( u2 | u1 )
+    {
+      from = last_one12( u1, u2 );
+      u2   ^= abb_mask[from].p[2];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk = abb_w_knight_attacks[sq_wk];
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+
+
+  bb_piece = BB_BLANCE;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = bb_chk.p[2] = 0;
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+           | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  u1 = BB_BLANCE.p[1];
+  u2 = BB_BLANCE.p[2];
+  while( u1| u2 )
+    {
+      from = last_one12( u1, u2 );
+      u1   ^= abb_mask[from].p[1];
+      u2   ^= abb_mask[from].p[2];
+
+      bb_chk = bb_file_chk;
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+         BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+       }
+      else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+      bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+           | Cap2Move(-BOARD[to]);
+       }
+    }
+
+  BBIni( bb_chk );
+  bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+  if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); }
+  BBAnd( bb_chk, bb_chk, bb_move_to );
+  BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
+
+  BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from - nfile;
+      if ( BOARD[to] > 0 ) { continue; }
+
+      bb_desti = AttackDiag1( from );
+      if ( BBContract( bb_desti, BB_B_BH ) )
+       {
+         BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+         *pmove = To2Move(to) | From2Move(from)
+           | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+         if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+         pmove += 1;
+       }
+    }
+
+  BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from - nfile;
+      if ( BOARD[to] > 0 ) { continue; }
+
+      bb_desti = AttackDiag2( from );
+      if ( BBContract( bb_desti, BB_B_BH ) )
+       {
+         BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+         *pmove = To2Move(to) | From2Move(from)
+           | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+         if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+         pmove += 1;
+       }
+    }
+
+  BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from - nfile;
+      if ( BOARD[to] > 0 ) { continue; }
+
+      bb_desti = AttackRank( from );
+      if ( BBContract( bb_desti, BB_B_RD ) )
+       {
+         BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+         *pmove = To2Move(to) | From2Move(from)
+           | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+         if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+         pmove += 1;
+       }
+    }
+
+  while ( BBTest(bb_chk) )
+    {
+      to = LastOne( bb_chk );
+      Xor( to, bb_chk );
+
+      from = to + nfile;
+      *pmove = To2Move(to) | From2Move(from)
+       | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+      if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+      pmove += 1;
+    }
+
+
+  if ( IsHandGold(HAND_B) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | Drop2Move(gold);
+       }
+    }
+  
+
+  if ( IsHandSilver(HAND_B) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | Drop2Move(silver);
+       }
+    }
+  
+
+  if ( IsHandKnight(HAND_B) && sq_wk < A2 )
+    {
+      to = sq_wk + 2*nfile - 1;
+      if ( aifile[sq_wk] != file1 && BOARD[to] == empty )
+       {
+         *pmove++ = To2Move(to) | Drop2Move(knight);
+       }
+
+      to = sq_wk + 2*nfile + 1;
+      if ( aifile[sq_wk] != file9 && BOARD[to] == empty )
+       {
+         *pmove++ = To2Move(to) | Drop2Move(knight);
+       }
+    }
+
+
+  if ( IsHandPawn(HAND_B)
+       && sq_wk < A1
+       && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )
+    {
+      to = sq_wk + nfile;
+      if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )
+       {
+         *pmove++ = To2Move(to) | Drop2Move(pawn);
+       }
+    }
+
+
+  if ( IsHandLance(HAND_B) )
+    {
+      unsigned int move;
+      int dist, min_dist;
+
+      if ( (int)aifile[sq_wk] == file1
+          || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
+      else                                  { min_dist = 3; }
+
+      for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+           to += nfile, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(lance);
+         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+    }
+
+
+  if ( IsHandRook(HAND_B) )
+    {
+      unsigned int move;
+      int file, dist, min_dist;
+
+      if ( (int)aifile[sq_wk] == file1
+          || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
+      else                                  { min_dist = 3; }
+
+      for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+           to += nfile, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;
+           file >= file1 && BOARD[to] == empty;
+           file -= 1, to -= 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if      ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }
+      else                            { min_dist = 3; }
+
+      for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;
+           file <= file9 && BOARD[to] == empty;
+           file += 1, to += 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+           to -= nfile, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }
+         if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+    }
+
+
+  if ( IsHandBishop(HAND_B) )
+    {
+      unsigned int move;
+      int file, rank, dist;
+
+      to   = sq_wk;
+      file = (int)aifile[sq_wk];
+      rank = (int)airank[sq_wk];
+      for ( to -= 10, file -= 1, rank -= 1, dist = 1;
+           file >= 0 && rank >= 0 && BOARD[to] == empty;
+           to -= 10, file -= 1, rank -= 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      to   = sq_wk;
+      file = (int)aifile[sq_wk];
+      rank = (int)airank[sq_wk];
+      for ( to -= 8, file += 1, rank -= 1, dist = 1;
+           file <= file9 && rank >= 0 && BOARD[to] == empty;
+           to -= 8, file += 1, rank -= 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      to   = sq_wk;
+      file = (int)aifile[sq_wk];
+      rank = (int)airank[sq_wk];
+      for ( to += 8, file -= 1, rank += 1, dist = 1;
+           file >= 0 && rank <= rank9 && BOARD[to] == empty;
+           to += 8, file -= 1, rank += 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      to   = sq_wk;
+      file = (int)aifile[sq_wk];
+      rank = (int)airank[sq_wk];
+      for ( to += 10, file += 1, rank += 1, dist = 1;
+           file <= file9 && rank <= rank9 && BOARD[to] == empty;
+           to += 10, file += 1, rank += 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+    }
+
+
+  return pmove;
+}
+
+
+unsigned int * CONV
+w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
+{
+  bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+  bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+  bitboard_t bb_rank_chk;
+  const tree_t * restrict ptree = __ptree__;
+  unsigned int u0, u1, u2;
+  int from, to, sq_bk, idirec;
+
+  sq_bk = SQ_BKING;
+  bb_file_chk = AttackFile( sq_bk );
+  bb_rank_chk = AttackRank( sq_bk );
+  BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+  bb_diag1_chk = AttackDiag1( sq_bk );
+  bb_diag2_chk = AttackDiag2( sq_bk );
+  BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+  BBNot( bb_move_to, BB_WOCCUPY );
+  BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+  BBNot( bb_drop_to, bb_drop_to );
+
+
+  from  = SQ_WKING;
+  idirec = (int)adirec[sq_bk][from];
+  if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+    {
+      BBIni( bb_chk );
+      add_behind_attacks( &bb_chk, idirec, sq_bk );
+      BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+
+  bb_piece = BB_WDRAGON;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      AttackDragon( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = LastOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+
+  bb_piece = BB_WHORSE;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      AttackHorse( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+  u0 = BB_WROOK.p[0];
+  u1 = BB_WROOK.p[1];
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_rook_chk;
+       bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while ( bb_chk.p[2] )
+       {
+         to          = first_one2( bb_chk.p[2] );
+         bb_chk.p[2] ^= abb_mask[to].p[2];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+           | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+
+      while( bb_chk.p[0] | bb_chk.p[1] )
+       {
+         to          = first_one01( bb_chk.p[0], bb_chk.p[1] );
+         bb_chk.p[0] ^= abb_mask[to].p[0];
+         bb_chk.p[1] ^= abb_mask[to].p[1];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+  u2 = BB_WROOK.p[2];
+  while( u2 )
+    {
+      from = first_one2( u2 );
+      u2   ^= abb_mask[from].p[2];
+      
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+           | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+    }
+
+  u0 = BB_WBISHOP.p[0];
+  u1 = BB_WBISHOP.p[1];
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_bishop_chk;
+       bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while ( bb_chk.p[2] )
+       {
+         to          = first_one2( bb_chk.p[2] );
+         bb_chk.p[2] ^= abb_mask[to].p[2];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+           | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+
+      while( bb_chk.p[0] | bb_chk.p[1] )
+       {
+         to          = first_one01( bb_chk.p[0], bb_chk.p[1] );
+         bb_chk.p[0] ^= abb_mask[to].p[0];
+         bb_chk.p[1] ^= abb_mask[to].p[1];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+  u2 = BB_WBISHOP.p[2];
+  while( u2 )
+    {
+      from = first_one2( u2 );
+      u2   ^= abb_mask[from].p[2];
+      
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+           | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+    }
+
+
+  bb_piece = BB_WTGOLD;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_b_gold_attacks[sq_bk];
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = ( To2Move(to) | From2Move(from)
+                      | Piece2Move(-BOARD[from])
+                      | Cap2Move(BOARD[to]) );
+       }
+    }
+
+  
+  u2 = BB_WSILVER.p[2];
+  while( u2 )
+    {
+      from = first_one2( u2 );
+      u2   ^= abb_mask[from].p[2];
+
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
+      bb_chk.p[0] = 0;
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+      bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
+
+      while( bb_chk.p[2] | bb_chk.p[1] )
+       {
+         to          = first_one12( bb_chk.p[1], bb_chk.p[2] );
+         bb_chk.p[1] ^= abb_mask[to].p[1];
+         bb_chk.p[2] ^= abb_mask[to].p[2];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+           | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  u1 = BB_WSILVER.p[1] & 0x1ffU;
+  while( u1 )
+    {
+      from = first_one1( u1 );
+      u1   ^= abb_mask[from].p[1];
+      
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = bb_chk.p[0] = 0;
+      
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+      while ( bb_chk.p[2] )
+       {
+         to          = first_one2( bb_chk.p[2] );
+         bb_chk.p[2] ^= abb_mask[to].p[2];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+           | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  bb_piece = BB_WSILVER;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_b_silver_attacks[sq_bk];
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+  
+  u2 = BB_WKNIGHT.p[2];
+  u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
+  while( u2 | u1 )
+    {
+      from = first_one12( u1, u2 );
+      u2   ^= abb_mask[from].p[2];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = bb_chk.p[0] = 0;
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
+
+      while( bb_chk.p[2] )
+       {
+         to          = first_one2( bb_chk.p[2] );
+         bb_chk.p[2] ^= abb_mask[to].p[2];
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+                      | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  u0 = BB_WKNIGHT.p[0];
+  u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk = abb_b_knight_attacks[sq_bk];
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+
+  bb_piece = BB_WLANCE;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = bb_chk.p[0] = 0;
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+           | Cap2Move(BOARD[to]) | FLAG_PROMO;
+       }
+    }
+  
+
+  u0 = BB_WLANCE.p[0];
+  u1 = BB_WLANCE.p[1];
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk = bb_file_chk;
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+         BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+       }
+      else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+      bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
+
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+           | Cap2Move(BOARD[to]);
+       }
+    }
+
+  BBIni( bb_chk );
+  bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+  if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); }
+  BBAnd( bb_chk, bb_chk, bb_move_to );
+  BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
+
+  BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from + nfile;
+      if ( BOARD[to] < 0 ) { continue; }
+
+      bb_desti = AttackDiag1( from );
+      if ( BBContract( bb_desti, BB_W_BH ) )
+       {
+         BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+         *pmove = To2Move(to) | From2Move(from)
+           | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+         if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+         pmove += 1;
+       }
+    }
+
+  BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from + nfile;
+      if ( BOARD[to] < 0 ) { continue; }
+
+      bb_desti = AttackDiag2( from );
+      if ( BBContract( bb_desti, BB_W_BH ) )
+       {
+         BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+         *pmove = To2Move(to) | From2Move(from)
+           | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+         if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+         pmove += 1;
+       }
+    }
+
+  BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from + nfile;
+      if ( BOARD[to] < 0 ) { continue; }
+
+      bb_desti = AttackRank( from );
+      if ( BBContract( bb_desti, BB_W_RD ) )
+       {
+         BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+         *pmove = To2Move(to) | From2Move(from)
+           | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+         if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+         pmove += 1;
+       }
+    }
+
+  while ( BBTest(bb_chk) )
+    {
+      to = FirstOne( bb_chk );
+      Xor( to, bb_chk );
+
+      from = to - nfile;
+      *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)
+       | Cap2Move(BOARD[to]);
+      if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+      pmove += 1;
+    }
+
+
+  if ( IsHandGold(HAND_W) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | Drop2Move(gold);
+       }
+    }
+  
+
+  if ( IsHandSilver(HAND_W) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
+      while( BBTest( bb_chk ) )
+       {
+         to = FirstOne( bb_chk );
+         Xor( to, bb_chk );
+         *pmove++ = To2Move(to) | Drop2Move(silver);
+       }
+    }
+  
+
+  if ( IsHandKnight(HAND_W) && sq_bk > I8 )
+    {
+      to = sq_bk - 2*nfile - 1;
+      if ( aifile[sq_bk] != file1 && BOARD[to] == empty )
+       {
+         *pmove++ = To2Move(to) | Drop2Move(knight);
+       }
+
+      to = sq_bk - 2*nfile + 1;
+      if ( aifile[sq_bk] != file9 && BOARD[to] == empty )
+       {
+         *pmove++ = To2Move(to) | Drop2Move(knight);
+       }
+    }
+
+
+  if ( IsHandPawn(HAND_W)
+       && sq_bk > I9
+       && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )
+    {
+      to = sq_bk - nfile;
+      if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )
+       {
+         *pmove++ = To2Move(to) | Drop2Move(pawn);
+       }
+    }
+
+
+  if ( IsHandLance(HAND_W) )
+    {
+      unsigned int move;
+      int dist, min_dist;
+
+      if ( (int)aifile[sq_bk] == file1
+          || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
+      else                                  { min_dist = 3; }
+
+      for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+           to -= nfile, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(lance);
+         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+    }
+
+
+  if ( IsHandRook(HAND_W) )
+    {
+      unsigned int move;
+      int file, dist, min_dist;
+
+      if ( (int)aifile[sq_bk] == file1
+          || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
+      else                                  { min_dist = 3; }
+
+      for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+           to -= nfile, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if      ( dist == 1 )        { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist )  { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+           to += nfile, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }
+         if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+
+      if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }
+      else                            { min_dist = 3; }
+
+      for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;
+           file <= file9 && BOARD[to] == empty;
+           file += 1, to += 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;
+           file >= file1 && BOARD[to] == empty;
+           file -= 1, to -= 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(rook);
+         if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+    }
+
+
+  if ( IsHandBishop(HAND_W) )
+    {
+      unsigned int move;
+      int file, rank, dist;
+
+      to   = sq_bk;
+      file = (int)aifile[sq_bk];
+      rank = (int)airank[sq_bk];
+      for ( to += 10, file += 1, rank += 1, dist = 1;
+           file <= file9 && rank <= rank9 && BOARD[to] == empty;
+           to += 10, file += 1, rank += 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      to   = sq_bk;
+      file = (int)aifile[sq_bk];
+      rank = (int)airank[sq_bk];
+      for ( to += 8, file -= 1, rank += 1, dist = 1;
+           file >= 0 && rank <= rank9 && BOARD[to] == empty;
+           to += 8, file -= 1, rank += 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      to   = sq_bk;
+      file = (int)aifile[sq_bk];
+      rank = (int)airank[sq_bk];
+      for ( to -= 8, file += 1, rank -= 1, dist = 1;
+           file <= file9 && rank >= 0 && BOARD[to] == empty;
+           to -= 8, file += 1, rank -= 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+
+      to   = sq_bk;
+      file = (int)aifile[sq_bk];
+      rank = (int)airank[sq_bk];
+      for ( to -= 10, file -= 1, rank -= 1, dist = 1;
+           file >= 0 && rank >= 0 && BOARD[to] == empty;
+           to -= 10, file -= 1, rank -= 1, dist += 1 )
+       {
+         move = To2Move(to) | Drop2Move(bishop);
+         if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
+         else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+         *pmove++ = move;
+       }
+    }
+
+
+  return pmove;
+}
+
+
+int CONV b_have_checks( tree_t * restrict __ptree__ )
+{
+  bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+  bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+  bitboard_t bb_rank_chk;
+  const tree_t * restrict ptree = __ptree__;
+  unsigned int u0, u1, u2;
+  int from, to, sq_wk, idirec;
+
+  sq_wk = SQ_WKING;
+  BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+  BBNot( bb_drop_to, bb_drop_to );
+
+  if ( IsHandGold(HAND_B) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  if ( IsHandSilver(HAND_B) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  if ( IsHandKnight(HAND_B) && sq_wk < A2 )
+    {
+      if ( aifile[sq_wk] != file1
+          && BOARD[sq_wk + 2*nfile - 1] == empty ) { return 1; }
+
+      if ( aifile[sq_wk] != file9
+          && BOARD[sq_wk + 2*nfile + 1] == empty ) { return 1; }
+    }
+
+  if ( IsHandLance(HAND_B)
+       && sq_wk + nfile < nsquare
+       && BOARD[sq_wk + nfile] == empty ) { return 1; }
+
+  if ( IsHandRook(HAND_B) )
+    {
+      if ( sq_wk + nfile < nsquare
+          && BOARD[sq_wk + nfile] == empty ) { return 1; }
+
+      if ( file1 < (int)aifile[sq_wk]
+          && BOARD[sq_wk - 1] == empty ) { return 1; }
+
+      if ( (int)aifile[sq_wk] < file9
+          && BOARD[sq_wk + 1] == empty ) { return 1; }
+
+      if ( 0 <= sq_wk - nfile
+          && BOARD[sq_wk - nfile] == empty ) { return 1; }
+    }
+
+  if ( IsHandBishop(HAND_B) )
+    {
+      if ( 0 < (int)aifile[sq_wk]
+          && 0 < (int)airank[sq_wk]
+          && BOARD[sq_wk - 10] == empty ) { return 1; }
+
+      if ( (int)aifile[sq_wk] < file9
+          && 0 < (int)airank[sq_wk]
+          && BOARD[sq_wk - 8] == empty ) { return 1; }
+
+      if ( 0 < (int)aifile[sq_wk]
+          && (int)airank[sq_wk] < rank9
+          && BOARD[sq_wk + 8] == empty ) { return 1; }
+
+      if ( (int)aifile[sq_wk] < file9
+          && (int)airank[sq_wk] < rank9
+          && BOARD[sq_wk + 10] == empty ) { return 1; }
+    }
+
+  if ( IsHandPawn(HAND_B)
+       && sq_wk < A1
+       && BOARD[sq_wk+nfile] == empty
+       && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) )
+       && ! is_mate_b_pawn_drop( __ptree__, sq_wk+nfile ) )
+    {
+      return 1;
+    }
+  
+  
+  bb_file_chk = AttackFile( sq_wk );
+  bb_rank_chk = AttackRank( sq_wk );
+  BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+  bb_diag1_chk = AttackDiag1( sq_wk );
+  bb_diag2_chk = AttackDiag2( sq_wk );
+  BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+  BBNot( bb_move_to, BB_BOCCUPY );
+
+  from  = SQ_BKING;
+  idirec = (int)adirec[sq_wk][from];
+  if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+    {
+      BBIni( bb_chk );
+      add_behind_attacks( &bb_chk, idirec, sq_wk );
+      BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+
+  bb_piece = BB_BDRAGON;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      AttackDragon( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  bb_piece = BB_BHORSE;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      AttackHorse( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u1 = BB_BROOK.p[1];
+  u2 = BB_BROOK.p[2];
+  while( u1 | u2 )
+    {
+      from = last_one12( u1, u2 );
+      u1   ^= abb_mask[from].p[1];
+      u2   ^= abb_mask[from].p[2];
+
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_rook_chk;
+       bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u0 = BB_BROOK.p[0];
+  while( u0 )
+    {
+      from = last_one0( u0 );
+      u0   ^= abb_mask[from].p[0];
+      
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u1 = BB_BBISHOP.p[1];
+  u2 = BB_BBISHOP.p[2];
+  while( u1 | u2 )
+    {
+      from = last_one12( u1, u2 );
+      u1   ^= abb_mask[from].p[1];
+      u2   ^= abb_mask[from].p[2];
+
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_bishop_chk;
+       bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u0 = BB_BBISHOP.p[0];
+  while( u0 )
+    {
+      from = last_one0( u0 );
+      u0   ^= abb_mask[from].p[0];
+      
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+
+  bb_piece = BB_BTGOLD;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_w_gold_attacks[sq_wk];
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+  
+
+  u0 = BB_BSILVER.p[0];
+  while( u0 )
+    {
+      from = last_one0( u0 );
+      u0   ^= abb_mask[from].p[0];
+
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
+      bb_chk.p[2] = 0;
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+      bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
+
+      if ( bb_chk.p[0] | bb_chk.p[1] ) { return 1; }
+    }
+  
+
+  u1 = BB_BSILVER.p[1] & 0x7fc0000U;
+  while( u1 )
+    {
+      from = last_one1( u1 );
+      u1   ^= abb_mask[from].p[1];
+      
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = bb_chk.p[2] = 0;
+      
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+
+      if ( bb_chk.p[0] ) { return 1; }
+    }
+  
+
+  bb_piece = BB_BSILVER;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_w_silver_attacks[sq_wk];
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+  
+
+  u0 = BB_BKNIGHT.p[0];
+  u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
+  while( u0 | u1 )
+    {
+      from = last_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = bb_chk.p[2] = 0;
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
+
+      if ( bb_chk.p[0] ) { return 1; }
+    }
+  
+
+  u2 = BB_BKNIGHT.p[2];
+  u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
+  while( u2 | u1 )
+    {
+      from = last_one12( u1, u2 );
+      u2   ^= abb_mask[from].p[2];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk = abb_w_knight_attacks[sq_wk];
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+
+  bb_piece = BB_BLANCE;
+  while( BBTest( bb_piece ) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+      bb_chk.p[1] = bb_chk.p[2] = 0;
+
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+       }
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+  
+
+  u1 = BB_BLANCE.p[1];
+  u2 = BB_BLANCE.p[2];
+  while( u1| u2 )
+    {
+      from = last_one12( u1, u2 );
+      u1   ^= abb_mask[from].p[1];
+      u2   ^= abb_mask[from].p[2];
+
+      bb_chk = bb_file_chk;
+      idirec = (int)adirec[sq_wk][from];
+      if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_wk );
+         BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+       }
+      else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+      bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  BBIni( bb_chk );
+  bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+  if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };
+  BBAnd( bb_chk, bb_chk, bb_move_to );
+  BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
+  if ( BBTest(bb_chk) ) { return 1; }
+
+  BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from - nfile;
+      if ( BOARD[to] > 0 ) { continue; }
+
+      bb_desti = AttackDiag1( from );
+
+      if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
+    }
+
+  BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from - nfile;
+      if ( BOARD[to] > 0 ) { continue; }
+
+      bb_desti = AttackDiag2( from );
+
+      if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
+    }
+  
+  BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = LastOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from - nfile;
+      if ( BOARD[to] > 0 ) { continue; }
+      
+      bb_desti = AttackRank( from );
+      if ( BBContract( bb_desti, BB_B_RD ) ) { return 1; }
+    }
+
+  return 0;
+}
+
+
+int CONV w_have_checks( tree_t * restrict __ptree__ )
+{
+  bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+  bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+  bitboard_t bb_rank_chk;
+  const tree_t * restrict ptree = __ptree__;
+  unsigned int u0, u1, u2;
+  int from, to, sq_bk, idirec;
+
+  sq_bk = SQ_BKING;
+  BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+  BBNot( bb_drop_to, bb_drop_to );
+
+  if ( IsHandGold(HAND_W) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  if ( IsHandSilver(HAND_W) )
+    {
+      BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  if ( IsHandKnight(HAND_W) && sq_bk > I8 )
+    {
+      if ( aifile[sq_bk] != file1
+          && BOARD[sq_bk - 2*nfile - 1] == empty ) { return 1; }
+
+      if ( aifile[sq_bk] != file9
+          && BOARD[sq_bk - 2*nfile + 1] == empty ) { return 1; }
+    }
+
+  if ( IsHandLance(HAND_W)
+       && 0 <= sq_bk - nfile
+       && BOARD[sq_bk - nfile] == empty ) { return 1; }
+
+  if ( IsHandRook(HAND_W) )
+    {
+      if ( sq_bk + nfile < nsquare
+          && BOARD[sq_bk + nfile] == empty ) { return 1; }
+
+      if ( file1 < (int)aifile[sq_bk]
+          && BOARD[sq_bk - 1] == empty ) { return 1; }
+
+      if ( (int)aifile[sq_bk] < file9
+          && BOARD[sq_bk + 1] == empty ) { return 1; }
+
+      if ( 0 <= sq_bk - nfile
+          && BOARD[sq_bk - nfile] == empty ) { return 1; }
+    }
+
+  if ( IsHandBishop(HAND_W) )
+    {
+      if ( 0 < (int)aifile[sq_bk]
+          && 0 < (int)airank[sq_bk]
+          && BOARD[sq_bk - 10] == empty ) { return 1; }
+
+      if ( (int)aifile[sq_bk] < file9
+          && 0 < (int)airank[sq_bk]
+          && BOARD[sq_bk - 8] == empty ) { return 1; }
+
+      if ( 0 < (int)aifile[sq_bk]
+          && (int)airank[sq_bk] < rank9
+          && BOARD[sq_bk + 8] == empty ) { return 1; }
+
+      if ( (int)aifile[sq_bk] < file9
+          && (int)airank[sq_bk] < rank9
+          && BOARD[sq_bk + 10] == empty ) { return 1; }
+    }
+
+  if ( IsHandPawn(HAND_W)
+       && sq_bk > I9
+       && BOARD[sq_bk - nfile] == empty
+       && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) )
+       && ! is_mate_w_pawn_drop( __ptree__, sq_bk - nfile ) )
+    {
+      return 1;
+    }
+
+
+  bb_file_chk = AttackFile( sq_bk );
+  bb_rank_chk = AttackRank( sq_bk );
+  BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+  bb_diag1_chk = AttackDiag1( sq_bk );
+  bb_diag2_chk = AttackDiag2( sq_bk );
+  BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+  BBNot( bb_move_to, BB_WOCCUPY );
+
+
+  from  = SQ_WKING;
+  idirec = (int)adirec[sq_bk][from];
+  if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+    {
+      BBIni( bb_chk );
+      add_behind_attacks( &bb_chk, idirec, sq_bk );
+      BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+
+  bb_piece = BB_WDRAGON;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      AttackDragon( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+
+  bb_piece = BB_WHORSE;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      AttackHorse( bb_desti, from );
+      BBAnd( bb_chk, bb_chk, bb_desti );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u0 = BB_WROOK.p[0];
+  u1 = BB_WROOK.p[1];
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_rook_chk;
+       bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u2 = BB_WROOK.p[2];
+  while( u2 )
+    {
+      from = first_one2( u2 );
+      u2   ^= abb_mask[from].p[2];
+      
+      AttackRook( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u0 = BB_WBISHOP.p[0];
+  u1 = BB_WBISHOP.p[1];
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       bb_chk       = bb_bishop_chk;
+       bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  u2 = BB_WBISHOP.p[2];
+  while( u2 )
+    {
+      from = first_one2( u2 );
+      u2   ^= abb_mask[from].p[2];
+      
+      AttackBishop( bb_desti, from );
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         BBAnd( bb_chk, bb_desti, bb_move_to );
+       }
+      else {
+       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+       BBAnd( bb_chk, bb_chk, bb_desti );
+       BBAnd( bb_chk, bb_chk, bb_move_to );
+      }
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+
+  bb_piece = BB_WTGOLD;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_b_gold_attacks[sq_bk];
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  
+  u2 = BB_WSILVER.p[2];
+  while( u2 )
+    {
+      from = first_one2( u2 );
+      u2   ^= abb_mask[from].p[2];
+
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
+      bb_chk.p[0] = 0;
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+      bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
+
+      if ( bb_chk.p[2] | bb_chk.p[1] ) { return 1; }
+    }
+  
+
+  u1 = BB_WSILVER.p[1] & 0x1ffU;
+  while( u1 )
+    {
+      from = first_one1( u1 );
+      u1   ^= abb_mask[from].p[1];
+      
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = bb_chk.p[0] = 0;
+      
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+
+      if ( bb_chk.p[2] ) { return 1; }
+    }
+  
+
+  bb_piece = BB_WSILVER;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk = abb_b_silver_attacks[sq_bk];
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  
+  u2 = BB_WKNIGHT.p[2];
+  u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
+  while( u2 | u1 )
+    {
+      from = first_one12( u1, u2 );
+      u2   ^= abb_mask[from].p[2];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = bb_chk.p[0] = 0;
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
+
+      if ( bb_chk.p[2] ) { return 1; }
+    }
+  
+
+  u0 = BB_WKNIGHT.p[0];
+  u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk = abb_b_knight_attacks[sq_bk];
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+
+  bb_piece = BB_WLANCE;
+  while( BBTest( bb_piece ) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+
+      bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+      bb_chk.p[1] = bb_chk.p[0] = 0;
+
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+       }
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+  
+
+  u0 = BB_WLANCE.p[0];
+  u1 = BB_WLANCE.p[1];
+  while( u0 | u1 )
+    {
+      from = first_one01( u0, u1 );
+      u0   ^= abb_mask[from].p[0];
+      u1   ^= abb_mask[from].p[1];
+
+      bb_chk = bb_file_chk;
+      idirec = (int)adirec[sq_bk][from];
+      if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+       {
+         add_behind_attacks( &bb_chk, idirec, sq_bk );
+         BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+       }
+      else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
+
+      BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+      BBAnd( bb_chk, bb_chk, bb_move_to );
+      bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
+
+      if ( BBTest( bb_chk ) ) { return 1; }
+    }
+
+  BBIni( bb_chk );
+  bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+  if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };
+  BBAnd( bb_chk, bb_chk, bb_move_to );
+  BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
+  if ( BBTest( bb_chk ) ) { return 1; }
+
+  BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from + nfile;
+      if ( BOARD[to] < 0 ) { continue; }
+
+      bb_desti = AttackDiag1( from );
+
+      if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
+    }
+
+  BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from + nfile;
+      if ( BOARD[to] < 0 ) { continue; }
+
+      bb_desti = AttackDiag2( from );
+
+      if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
+    }
+
+  BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
+  while ( BBTest(bb_piece) )
+    {
+      from = FirstOne( bb_piece );
+      Xor( from, bb_piece );
+      
+      to = from + nfile;
+      if ( BOARD[to] < 0 ) { continue; }
+
+      bb_desti = AttackRank( from );
+      if ( BBContract( bb_desti, BB_W_RD ) ) { return 1; }
+    }
+
+  return 0;
+}
+
+
+static void CONV
+add_behind_attacks( bitboard_t * restrict pbb, int idirec, int ik )
+{
+  bitboard_t bb_tmp;
+
+  if ( idirec == direc_diag1 )
+    {
+      bb_tmp = abb_bishop_attacks_rr45[ik][0];
+    }
+  else if ( idirec == direc_diag2 )
+    {
+      bb_tmp = abb_bishop_attacks_rl45[ik][0];
+    }
+  else if ( idirec == direc_file )
+    {
+      bb_tmp = abb_file_attacks[ik][0];
+    }
+  else {
+    assert( idirec == direc_rank );
+    bb_tmp = abb_rank_attacks[ik][0];
+  }
+  BBNot( bb_tmp, bb_tmp );
+  BBOr( *pbb, *pbb, bb_tmp );
+}
index 4066827..ad4bded 100644 (file)
--- 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 );
index f34775b..c682945 100644 (file)
@@ -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;
+}
index 1f68b4b..b5f441a 100644 (file)
@@ -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 (file)
--- a/hash.c
+++ b/hash.c
@@ -4,11 +4,12 @@
 #include <assert.h>
 #include "shogi.h"
 
-static int eval_supe( unsigned int hand_current, unsigned int hand_hash,
-                     int turn_current, int turn_hash,
-                     int * restrict pvalue_hash, int * restrict ptype_hash );
+static int CONV eval_supe( unsigned int hand_current, unsigned int hand_hash,
+                          int turn_current, int turn_hash,
+                          int * restrict pvalue_hash,
+                          int * restrict ptype_hash );
 
-int
+int CONV
 ini_trans_table( void )
 {
   size_t size;
@@ -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 (file)
--- 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 (file)
--- 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 */
+}
index d940814..1a684bc 100644 (file)
--- a/iterate.c
+++ b/iterate.c
@@ -4,46 +4,34 @@
 #include <stdlib.h>
 #include "shogi.h"
 
-static void adjust_fmg( void );
-static int ini_hash( void );
-static int set_root_alpha( int nfail_low, int root_alpha_old );
-static int set_root_beta( int nfail_high, int root_beta_old );
-static int is_answer_right( unsigned int move );
-static const char *str_fail_high( int turn, int nfail_high );
+static void CONV adjust_fmg( void );
+static int CONV set_root_alpha( int nfail_low, int root_alpha_old );
+static int CONV set_root_beta( int nfail_high, int root_beta_old );
+static int CONV is_answer_right( unsigned int move );
+static int CONV rep_book_prob( tree_t * restrict ptree );
+static const char * CONV str_fail_high( int turn, int nfail_high );
 
 
-static int rep_book_prob( tree_t * restrict ptree )
+int CONV
+iterate( tree_t * restrict ptree )
 {
-  int i;
-
-  for ( i = root_nrep - 2; i >= 0; i -= 2 )
-    if ( ptree->rep_board_list[i] == HASH_KEY
-        && ptree->rep_hand_list[i] == HAND_B )
-      {
-       Out( "- book is ignored due to a repetition.\n" );
-       return 1;
-      }
-
-  return 0;
-}
-
-
-int
-iterate( tree_t * restrict ptree, int flag )
-{
-  int value, iret, ply, is_hash_learn_stored;
+  int value, iret, ply;
   unsigned int cpu_start;
   int right_answer_made;
 
   /* probe the opening book */
-  if ( pf_book != NULL && n_nobook_move < 7 && ! rep_book_prob( ptree  ) )
+  if ( pf_book != NULL
+#if defined(USI) || defined(MNJ_LAN)
+       && moves_ignore[0] == MOVE_NA
+#endif
+       && ! rep_book_prob( ptree ) )
     {
       int is_book_hit, i;
       unsigned int elapsed;
-
+      
       is_book_hit = book_probe( ptree );
       if ( is_book_hit < 0 ) { return is_book_hit; }
-
+      
       iret = get_elapsed( &elapsed );
       if ( iret < 0 ) { return iret; }
 
@@ -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;
index a52ed68..a6b7c52 100644 (file)
--- 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; }
 
index 109424f..0c886b1 100644 (file)
--- 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 (file)
--- 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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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 );
index 83d8c9e..17713d3 100644 (file)
@@ -1,3 +1,4 @@
+#include <limits.h>
 #include <assert.h>
 #include <string.h>
 #include "shogi.h"
           BOARD[to] = - piece
 
 
-void
+void CONV
 make_move_b( tree_t * restrict ptree, unsigned int move, int ply )
 {
   const int from = (int)I2From(move);
   const int to   = (int)I2To(move);
-  const int nrep  = root_nrep + ply - 1;
+  const int nrep = ptree->nrep + ply - 1;
 
   assert( UToCap(move) != king );
   assert( move );
@@ -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;
 }
index b09a6d1..b4d52db 100644 (file)
@@ -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 (file)
--- 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;
index f21d240..fdbccf2 100644 (file)
@@ -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 (file)
--- a/next.c
+++ b/next.c
@@ -3,7 +3,7 @@
 #include <limits.h>
 #include "shogi.h"
 
-int
+int CONV
 gen_next_move( tree_t * restrict ptree, int ply, int turn )
 {
   switch ( ptree->anext_move[ply].next_phase )
@@ -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 (file)
--- 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 (file)
--- a/phash.c
+++ b/phash.c
-#include "shogi.h"\r
-\r
-static unsigned short tab[] = {\r
-5866,14081,15663,4534,14969,3034,8274,7570,\r
-14571,15428,2921,37,2534,4727,660,249,\r
-8308,3662,15794,10079,13857,13019,6070,9141,\r
-3942,14629,6891,11561,12156,4793,11132,12989,\r
-10044,16304,9389,2228,5053,3789,5988,4479,\r
-8719,13901,15524,3098,7570,12949,1074,0,\r
-10079,16233,7531,14642,13600,8087,0,11690,\r
-8579,15413,6522,1076,2677,6914,10881,13803,\r
-13806,15789,14642,2135,15427,14023,14079,7708,\r
-3602,0,4976,10910,4821,4543,5455,9368,\r
-4201,9970,10647,15130,10079,15020,5558,15902,\r
-7858,2962,10386,2155,14641,12308,8021,8170,\r
-2490,10528,15427,14629,10528,15136,999,1883,\r
-14912,10788,6360,3677,14960,12257,2294,12614,\r
-8698,12433,9867,12663,16016,11332,8568,8348,\r
-0,3228,8594,11249,6674,3098,9297,10077,\r
-10340,5803,5420,6070,660,5676,1,9497,\r
-8700,14264,5846,12433,16282,12561,12032,13732,\r
-8239,10731,7236,10286,2678,7321,13368,6594,\r
-9047,5291,8293,2809,3268,6485,10509,2277,\r
-10471,595,8887,15919,14413,15881,8827,13726,\r
-13975,14092,7634,1652,8753,6801,6568,15853,\r
-1022,5664,0,9303,15719,6128,6674,7433,\r
-157,9360,6555,12432,9593,9660,14081,13927,\r
-8702,13702,8663,5629,3691,16298,1573,902,\r
-1272,2376,1084,14447,14666,1692,15316,15129,\r
-3833,920,8348,15839,15902,15635,10340,6603,\r
-1764,9634,3833,2470,4704,9646,385,13200,\r
-3009,1562,6846,6598,15861,8924,11762,3766,\r
-9095,431,6599,1987,15902,11064,4972,12175,\r
-14642,13857,6130,5833,13857,12112,8170,9867,\r
-2569,9648,1883,10205,12365,6801,5222,14506,\r
-1819,5142,2172,5291,15542,12112,2092,5560,\r
-4538,5461,15059,11773,15884,2099,6876,11914,\r
-3833,4972,8164,6240,12487,1341,10731,11762,\r
-14548,4471,5044,7576,2392,16129,8175,7559,\r
-12559,15861,6396,2926,7618,8417,15759,0,\r
-9095,3510,7247,1712,16345,2209,8055,0,\r
-319,12209,13144,15159,8238,7822,5014,10077,\r
-2284,7177,6555,15861,14479,2510,8170,11806,\r
-12149,12440,14185,11762,11552,8260,11864,11728,\r
-15046,11561,4707,13420,3615,2233,2277,10668,\r
-2228,8016,1813,2677,5240,6594,6636,9911,\r
-1737,4396,12500,9682,7176,2027,12500,5244,\r
-12112,1768,14571,12663,6729,3662,8170,15641,\r
-15316,9648,5373,5475,6522,14571,3662,15902,\r
-1652,9648,2228,8348,902,5988,9150,13250,\r
-13411,4675,431,5507,10616,13987,15316,1378,\r
-13832,13356,10087,9543,9093,8065,10497,8228,\r
-11762,616,12968,5411,9648,12487,9463,15597,\r
-11292,13985,14482,14600,1705,4678,12020,8828,\r
-6210,9481,14980,5738,5990,14447,1569,8618,\r
-2273,8543,1819,16158,12447,12470,10160,4725,\r
-10778,1412,8040,4300,9550,568,7394,592,\r
-9481,15680,3476,16128,7660,1214,359,6181,\r
-8618,4067,14699,13368,514,11355,8914,3801,\r
-14520,8885,10434,8274,7709,4312,7243,12633,\r
-4867,5981,4538,2490,3034,5558,6801,7512,\r
-14971,4315,4905,11682,8845,3732,1475,11661,\r
-10189,1741,11667,5605,2656,9573,10898,2796,\r
-1817,15216,11152,470,5988,6164,4972,10386,\r
-13128,7247,3268,6729,4300,13101,8568,12663,\r
-13849,3600,9718,11203,10528,13732,5251,14148,\r
-8568,13128,10205,11332,1712,12821,9557,12753,\r
-10505,5276,109,10394,10122,9809,3513,16093,\r
-2490,9943,14798,15084,4598,5174,15648,13109,\r
-0,6971,15426,14500,14571,6831,2623,6801,\r
-6522,15388,3228,11053,0,2902,4285,13853,\r
-14830,5373,15137,10087,3268,2569,6284,2902,\r
-1483,3838,12159,4764,15130,6846,6957,12499,\r
-4604,2739,14629,996,4867,13420,7791,5263,\r
-8119,10088,4128,7950,11875,16244,1147,3473,\r
-3268,15869,12821,11152,9922,1987,8238,15271,\r
-852,6921,4155,7857,11187,2275,14224,15725,\r
-9967,4479,6522,11152,2457,5962,13732,10088,\r
-11226,11359,5053,13420,3727,12487,3823,13412,\r
-13732,5962,11005,11173,8719,4354,6821,11421,\r
-15640,4769,14868,9369,215,8176,2363,1930,\r
-4124,11338,5373,2135,5253,10648,6220,5853,\r
-2741,12020,14070,14571,7476,9011,11415,1306,\r
-5318,13418,7293,15364,8898,3402,11976,9325,\r
-1562,7366,3395,10762,7144,2336,13458,4538,\r
-1159,1987,11652,12964,13513,541,13792,9741,\r
-10840,16129,10917,4534,13600,5462,2357,3890,\r
-6299,11315,13376,13820,13369,4450,14282,3510,\r
-10008,2381,9301,10165,4832,13042,3789,11751,\r
-8021,14286,9341,436,9171,8623,12745,12738,\r
-567,13996,3654,9495,844,8260,15108,2851,\r
-10351,2756,8572,3694,8851,5833,4280,12168,\r
-9550,9095,1652,6594,2534,3662,12009,6827,\r
-7447,2228,6555,15919,2294,6522,6674,0,\r
-13128,15478,3098,14571,1573,13117,16336,3422,\r
-12751,4635,9808,13171,11875,14148,14759,15680,\r
-610,780,14127,15067,12717,11768,2223,4745,\r
-2111,4363,6821,12230,13200,16093,410,15205,\r
-3838,15020,12230,3473,7951,2926,981,13414,\r
-3034,9835,3875,7247,15776,11053,10533,6393,\r
-6729,1712,12233,10088,5152,1378,6043,3871,\r
-6043,12487,15527,11769,12308,5962,11864,10804,\r
-3268,14005,13662,10647,4972,15137,14485,7784,\r
-7275,410,6555,2470,7074,359,12751,12054,\r
-8851,2993,9487,13270,9267,2370,8119,14112,\r
-6639,157,10245,16121,9967,14912,10307,8011,\r
-12094,2470,10322,3570,6154,1453,15084,14801,\r
-3823,7259,780,4972,13047,14500,2569,5833,\r
-56,14601,2690,5036,788,46,2738,9922,\r
-11332,10619,8011,13128,3268,431,13412,8851,\r
-14748,5036,12185,13042,10030,11716,100,16205,\r
-7951,5738,8417,10757,6463,7114,1183,14798,\r
-10205,9721,15359,10074,8727,4587,11875,14615,\r
-10340,9171,9171,4686,7731,4269,13042,8574,\r
-16298,7024,10309,2858,4904,7223,8238,7512,\r
-4556,3532,15222,2161,1162,6476,3221,10290,\r
-11229,15137,14921,1319,4925,1991,7817,7427,\r
-15089,9366,920,3875,4641,11787,14255,4915,\r
-7588,15555,13106,16014,12882,10324,341,1331,\r
-10685,7950,12292,10230,15336,7431,7576,6158,\r
-5058,12149,2777,13434,5263,15769,9877,2704,\r
-10300,867,1443,5285,2155,4474,935,12586,\r
-12601,158,16191,8119,3726,3554,10398,13418,\r
-8170,4867,14642,15478,1712,10136,6674,0,\r
-46,9867,3766,12433,6057,3972,2156,852,\r
-2144,9856,14761,11491,46,363,10561,4484,\r
-999,9557,2902,7323,15084,8274,16087,6679,\r
-6867,6971,2914,586,6240,5988,10386,8304,\r
-3662,10088,5988,12821,7409,8308,15931,14376,\r
-14700,15998,4484,1766,15794,3833,2464,4342,\r
-1358,319,10099,15776,15839,1530,8538,7800,\r
-3641,5569,7469,2104,8314,8976,5962,11857,\r
-10330,8293,12356,1399,1991,5415,10497,15478,\r
-15931,8308,11608,10167,4185,9369,1658,6193,\r
-5962,5132,12322,319,7802,4707,3034,11308,\r
-9559,10788,2228,8339,13513,5222,1712,3098,\r
-1987,2719,1548,15427,13361,13736,5139,1255,\r
-11064,8011,985,6135,788,2761,6522,5362,\r
-13128,3476,6164,12032,2902,15881,11053,14538,\r
-12964,14730,3751,12890,396,1132,6164,7938,\r
-3165,7677,12218,7007,4824,6266,4198,9127,\r
-12821,6463,199,6522,5462,1084,7232,15717,\r
-3354,2788,6294,11857,14174,2235,6135,7808,\r
-15931,10377,1168,9162,7176,3595,10046,1960,\r
-3726,1723,6779,10955,11201,4721,661,7247,\r
-5988,11291,9095,8555,7017,5975,14500,15822,\r
-10887,7999,9648,15908,2938,8293,14629,4233,\r
-8419,5141,12427,9360,2948,9321,13473,1134,\r
-87,4180,2284,8822,3893,15653,15668,12175,\r
-7951,12668,13119,7839,4793,4686,914,9481,\r
-11912,13196,4235,15293,5704,9063,1605,15640,\r
-13270,1192,9967,8698,5576,3059,4067,11809,\r
-5420,7691,16087,764,12487,2273,14224,13412,\r
-5373,12663,788,12433,8870,15902,14019,3966,\r
-1104,11153,13117,8913,46,9922,15240,8260,\r
-9874,1712,9096,7708,4544,15601,0,10529,\r
-7419,9404,653,4067,10717,4901,10009,7229,\r
-9867,7620,1412,14284,9931,8845,13975,8238,\r
-10941,10205,678,11308,14985,12099,3268,11120,\r
-14148,7900,5934,10099,12903,6274,9648,2851,\r
-972,5149,9506,12102,723,15873,14497,5447,\r
-13505,13658,13128,4699,11152,0,0,7808,\r
-2623,6674,9557,7920,10004,14081,0,15478,\r
-12498,7162,13662,14438,6939,10841,6599,7074,\r
-2129,9303,3614,5121,13626,14806,13096,5275,\r
-12032,11431,12265,242,12651,6465,11153,15635,\r
-6154,7864,3263,7708,13216,9466,4929,4763,\r
-16121,12949,6801,14244,6289,3766,8913,3228,\r
-10099,4198,11895,286,13119,10778,12230,7238,\r
-3614,14081,7323,4050,6846,14629,13420,9427,\r
-5460,5130,10528,15705,6369,8361,1212,8866,\r
-12821,15427,7323,2777,9648,8744,5386,8241,\r
-11875,14112,14770,15369,9813,6750,13732,6594,\r
-2464,11682,2031,15129,3532,12112,4831,4354,\r
-2275,10376,11226,11611,8313,9590,14500,8598,\r
-13403,4316,15388,13458,961,208,5995,1225,\r
-6455,5932,11987,2902,13128,1224,1003,7409,\r
-3028,650,13436,8485,6653,911,9425,11421,\r
-9554,10993,15293,514,6670,14578,4972,9874,\r
-8483,2534,14969,1934,14154,8926,11830,8784,\r
-2987,9634,6670,13501,13957,4260,5761,15347,\r
-7991,13414,7159,7233,14206,11665,6715,11079,\r
-3545,5185,15639,14307,9338,8971,15994,5645,\r
-3098,14081,788,8170,10188,8016,5988,15919,\r
-12788,14960,10214,12606,11152,2470,13420,2927,\r
-5240,7370,9648,10099,2039,4846,10610,11823,\r
-13270,14761,5962,7512,10079,4867,8260,2135,\r
-1052,10823,5729,10395,14361,13382,12200,8162,\r
-5117,7531,13361,14520,10602,8685,3654,9777,\r
-16263,6135,6389,11745,10383,8550,12618,10340,\r
-4128,15459,7062,5135,9047,9346,5897,15479,\r
-7268,5576,0,14937,12736,5545,10079,6507,\r
-3238,3204,9865,5843,12487,198,8251,13195,\r
-158,8913,6598,4373,15991,13857,3615,11106,\r
-3244,10654,6394,6183,11633,3098,12257,15427,\r
-1768,7209,11987,963,13857,7247,16046,7239,\r
-13200,11773,2914,12927,11669,13011,1905,9089,\r
-16176,3743,158,5222,12717,5825,16087,9519,\r
-9227,15563,1712,8511,11005,4867,13200,13106,\r
-10788,3606,8680,3447,5833,3709,4526,10847,\r
-2871,6000,2204,15769,2969,7617,15976,7618,\r
-4067,10757,15316,6476,10509,8772,9095,0,\r
-8996,410,14742,7239,10532,9406,7419,15903,\r
-5437,5560,12608,9141,3986,14358,7409,3992,\r
-3221,6170,11821,508,6434,1442,4260,3813,\r
-8308,6456,3534,431,4538,3406,12435,5643,\r
-7144,8870,9186,3775,1817,9905,7951,4336,\r
-2273,12264,6513,2993,16270,5541,5077,6263,\r
-1259,2559,1675,16218,1790,12804,15098,4445,\r
-10336,15216,12144,8618,4573,13679,15000,10189,\r
-2209,4583,5353,13784,2623,7720,5833,11064,\r
-10088,10077,10610,6786,10939,10867,1768,8119,\r
-7394,12056,3789,1074,15413,10527,7247,12487,\r
-8568,10136,2228,13412,4840,1652,6740,11322,\r
-5037,2910,5174,10340,2135,8011,11895,11895,\r
-109,11957,14336,13234,8225,14343,9063,9819,\r
-13517,11635,13549,14936,988,3809,5833,7857,\r
-13462,297,7668,14482,4316,10848,2569,13931,\r
-5593,12056,11103,14170,448,902,1768,11552,\r
-6043,0,0,8646,10391,0,15316,3737,\r
-10594,11026,13280,14667,5713,4057,2787,4191,\r
-3838,7247,8772,14185,15641,8772,0,14081,\r
-0,9429,17,613,7428,15131,15651,14350,\r
-4365,15856,9521,3228,7950,3395,0,6594,\r
-11078,14975,6889,10768,4288,6707,7175,2235,\r
-10896,911,7707,7592,12916,15570,15644,6997,\r
-12523,14757,11895,7109,16279,12969,11690,0,\r
-8854,16304,8568,11334,15641,15478,2275,6193,\r
-7323,5230,9835,12821,1652,12477,5044,359,\r
-12487,13881,10731,8246,14642,14885,6555,15919,\r
-13857,1982,7646,12528,12009,7310,12310,3193,\r
-359,1483,5322,10476,46,3751,3766,6729,\r
-4512,13853,5558,12736,1733,2718,9956,7857,\r
-6519,2187,12964,12949,750,8877,15136,3742,\r
-4495,13851,3811,906,11592,9943,920,10806,\r
-10442,12561,5035,988,15861,8024,10272,16372,\r
-13353,15946,7330,4834,9414,8267,1668,12498,\r
-4530,9162,8648,3883,9451,3900,2028,12427,\r
-11203,3071,5645,10228,11875,8198,4563,215,\r
-3614,5717,11332,1617,11382,13987,12626,11857,\r
-12156,6513,13496,6997,16158,9093,6725,13737,\r
-5890,10008,14447,5475,12215,141,16192,10200,\r
-4450,6688,11090,16109,12256,9027,15355,3422,\r
-10079,14571,13101,9967,12296,3460,8348,15413,\r
-5222,11762,3823,13412,6729,6599,10528,9922,\r
-11152,9171,5362,5373,750,8969,1652,6220,\r
-5373,2569,3742,15119,10340,999,10088,10731,\r
-1028,3228,7369,15256,11822,12904,8121,11641,\r
-11158,5016,10725,8412,1183,9674,11806,12112,\r
-2623,15516,4226,10021,13316,12075,792,4972,\r
-8506,8921,6133,14718,567,4349,13420,5953,\r
-2265,11902,10019,16265,16312,0,9922,3009,\r
-8170,3473,10757,3567,2825,6915,5174,4299,\r
-0,8274,6292,295,6522,1475,359,4538,\r
-5358,5174,3008,6317,12688,4165,752,12052,\r
-10008,3912,7431,13364,9894,13524,284,16013,\r
-9820,11295,1144,2845,3538,10678,13806,1469,\r
-14210,7870,3766,10528,13642,10823,4200,8031,\r
-4671,14093,5541,1214,4115,3286,8217,8018 };\r
-\r
-\r
-unsigned int phash( unsigned int move, int turn )\r
-{\r
-  unsigned int a, b;\r
-  \r
-  move |= ( (unsigned int)turn << 31 );\r
-  move += 0x69fe378e;\r
-  move ^= ( move >> 16 );\r
-  move += ( move << 8 );\r
-  move ^= ( move >> 4 );\r
-  b     = ( move >> 7 ) & 0x7ff;\r
-  a     = move >> 18;\r
-  \r
-  return a ^ tab[b];\r
-}\r
+#include "shogi.h"
+
+static unsigned short tab[] = {
+5866,14081,15663,4534,14969,3034,8274,7570,
+14571,15428,2921,37,2534,4727,660,249,
+8308,3662,15794,10079,13857,13019,6070,9141,
+3942,14629,6891,11561,12156,4793,11132,12989,
+10044,16304,9389,2228,5053,3789,5988,4479,
+8719,13901,15524,3098,7570,12949,1074,0,
+10079,16233,7531,14642,13600,8087,0,11690,
+8579,15413,6522,1076,2677,6914,10881,13803,
+13806,15789,14642,2135,15427,14023,14079,7708,
+3602,0,4976,10910,4821,4543,5455,9368,
+4201,9970,10647,15130,10079,15020,5558,15902,
+7858,2962,10386,2155,14641,12308,8021,8170,
+2490,10528,15427,14629,10528,15136,999,1883,
+14912,10788,6360,3677,14960,12257,2294,12614,
+8698,12433,9867,12663,16016,11332,8568,8348,
+0,3228,8594,11249,6674,3098,9297,10077,
+10340,5803,5420,6070,660,5676,1,9497,
+8700,14264,5846,12433,16282,12561,12032,13732,
+8239,10731,7236,10286,2678,7321,13368,6594,
+9047,5291,8293,2809,3268,6485,10509,2277,
+10471,595,8887,15919,14413,15881,8827,13726,
+13975,14092,7634,1652,8753,6801,6568,15853,
+1022,5664,0,9303,15719,6128,6674,7433,
+157,9360,6555,12432,9593,9660,14081,13927,
+8702,13702,8663,5629,3691,16298,1573,902,
+1272,2376,1084,14447,14666,1692,15316,15129,
+3833,920,8348,15839,15902,15635,10340,6603,
+1764,9634,3833,2470,4704,9646,385,13200,
+3009,1562,6846,6598,15861,8924,11762,3766,
+9095,431,6599,1987,15902,11064,4972,12175,
+14642,13857,6130,5833,13857,12112,8170,9867,
+2569,9648,1883,10205,12365,6801,5222,14506,
+1819,5142,2172,5291,15542,12112,2092,5560,
+4538,5461,15059,11773,15884,2099,6876,11914,
+3833,4972,8164,6240,12487,1341,10731,11762,
+14548,4471,5044,7576,2392,16129,8175,7559,
+12559,15861,6396,2926,7618,8417,15759,0,
+9095,3510,7247,1712,16345,2209,8055,0,
+319,12209,13144,15159,8238,7822,5014,10077,
+2284,7177,6555,15861,14479,2510,8170,11806,
+12149,12440,14185,11762,11552,8260,11864,11728,
+15046,11561,4707,13420,3615,2233,2277,10668,
+2228,8016,1813,2677,5240,6594,6636,9911,
+1737,4396,12500,9682,7176,2027,12500,5244,
+12112,1768,14571,12663,6729,3662,8170,15641,
+15316,9648,5373,5475,6522,14571,3662,15902,
+1652,9648,2228,8348,902,5988,9150,13250,
+13411,4675,431,5507,10616,13987,15316,1378,
+13832,13356,10087,9543,9093,8065,10497,8228,
+11762,616,12968,5411,9648,12487,9463,15597,
+11292,13985,14482,14600,1705,4678,12020,8828,
+6210,9481,14980,5738,5990,14447,1569,8618,
+2273,8543,1819,16158,12447,12470,10160,4725,
+10778,1412,8040,4300,9550,568,7394,592,
+9481,15680,3476,16128,7660,1214,359,6181,
+8618,4067,14699,13368,514,11355,8914,3801,
+14520,8885,10434,8274,7709,4312,7243,12633,
+4867,5981,4538,2490,3034,5558,6801,7512,
+14971,4315,4905,11682,8845,3732,1475,11661,
+10189,1741,11667,5605,2656,9573,10898,2796,
+1817,15216,11152,470,5988,6164,4972,10386,
+13128,7247,3268,6729,4300,13101,8568,12663,
+13849,3600,9718,11203,10528,13732,5251,14148,
+8568,13128,10205,11332,1712,12821,9557,12753,
+10505,5276,109,10394,10122,9809,3513,16093,
+2490,9943,14798,15084,4598,5174,15648,13109,
+0,6971,15426,14500,14571,6831,2623,6801,
+6522,15388,3228,11053,0,2902,4285,13853,
+14830,5373,15137,10087,3268,2569,6284,2902,
+1483,3838,12159,4764,15130,6846,6957,12499,
+4604,2739,14629,996,4867,13420,7791,5263,
+8119,10088,4128,7950,11875,16244,1147,3473,
+3268,15869,12821,11152,9922,1987,8238,15271,
+852,6921,4155,7857,11187,2275,14224,15725,
+9967,4479,6522,11152,2457,5962,13732,10088,
+11226,11359,5053,13420,3727,12487,3823,13412,
+13732,5962,11005,11173,8719,4354,6821,11421,
+15640,4769,14868,9369,215,8176,2363,1930,
+4124,11338,5373,2135,5253,10648,6220,5853,
+2741,12020,14070,14571,7476,9011,11415,1306,
+5318,13418,7293,15364,8898,3402,11976,9325,
+1562,7366,3395,10762,7144,2336,13458,4538,
+1159,1987,11652,12964,13513,541,13792,9741,
+10840,16129,10917,4534,13600,5462,2357,3890,
+6299,11315,13376,13820,13369,4450,14282,3510,
+10008,2381,9301,10165,4832,13042,3789,11751,
+8021,14286,9341,436,9171,8623,12745,12738,
+567,13996,3654,9495,844,8260,15108,2851,
+10351,2756,8572,3694,8851,5833,4280,12168,
+9550,9095,1652,6594,2534,3662,12009,6827,
+7447,2228,6555,15919,2294,6522,6674,0,
+13128,15478,3098,14571,1573,13117,16336,3422,
+12751,4635,9808,13171,11875,14148,14759,15680,
+610,780,14127,15067,12717,11768,2223,4745,
+2111,4363,6821,12230,13200,16093,410,15205,
+3838,15020,12230,3473,7951,2926,981,13414,
+3034,9835,3875,7247,15776,11053,10533,6393,
+6729,1712,12233,10088,5152,1378,6043,3871,
+6043,12487,15527,11769,12308,5962,11864,10804,
+3268,14005,13662,10647,4972,15137,14485,7784,
+7275,410,6555,2470,7074,359,12751,12054,
+8851,2993,9487,13270,9267,2370,8119,14112,
+6639,157,10245,16121,9967,14912,10307,8011,
+12094,2470,10322,3570,6154,1453,15084,14801,
+3823,7259,780,4972,13047,14500,2569,5833,
+56,14601,2690,5036,788,46,2738,9922,
+11332,10619,8011,13128,3268,431,13412,8851,
+14748,5036,12185,13042,10030,11716,100,16205,
+7951,5738,8417,10757,6463,7114,1183,14798,
+10205,9721,15359,10074,8727,4587,11875,14615,
+10340,9171,9171,4686,7731,4269,13042,8574,
+16298,7024,10309,2858,4904,7223,8238,7512,
+4556,3532,15222,2161,1162,6476,3221,10290,
+11229,15137,14921,1319,4925,1991,7817,7427,
+15089,9366,920,3875,4641,11787,14255,4915,
+7588,15555,13106,16014,12882,10324,341,1331,
+10685,7950,12292,10230,15336,7431,7576,6158,
+5058,12149,2777,13434,5263,15769,9877,2704,
+10300,867,1443,5285,2155,4474,935,12586,
+12601,158,16191,8119,3726,3554,10398,13418,
+8170,4867,14642,15478,1712,10136,6674,0,
+46,9867,3766,12433,6057,3972,2156,852,
+2144,9856,14761,11491,46,363,10561,4484,
+999,9557,2902,7323,15084,8274,16087,6679,
+6867,6971,2914,586,6240,5988,10386,8304,
+3662,10088,5988,12821,7409,8308,15931,14376,
+14700,15998,4484,1766,15794,3833,2464,4342,
+1358,319,10099,15776,15839,1530,8538,7800,
+3641,5569,7469,2104,8314,8976,5962,11857,
+10330,8293,12356,1399,1991,5415,10497,15478,
+15931,8308,11608,10167,4185,9369,1658,6193,
+5962,5132,12322,319,7802,4707,3034,11308,
+9559,10788,2228,8339,13513,5222,1712,3098,
+1987,2719,1548,15427,13361,13736,5139,1255,
+11064,8011,985,6135,788,2761,6522,5362,
+13128,3476,6164,12032,2902,15881,11053,14538,
+12964,14730,3751,12890,396,1132,6164,7938,
+3165,7677,12218,7007,4824,6266,4198,9127,
+12821,6463,199,6522,5462,1084,7232,15717,
+3354,2788,6294,11857,14174,2235,6135,7808,
+15931,10377,1168,9162,7176,3595,10046,1960,
+3726,1723,6779,10955,11201,4721,661,7247,
+5988,11291,9095,8555,7017,5975,14500,15822,
+10887,7999,9648,15908,2938,8293,14629,4233,
+8419,5141,12427,9360,2948,9321,13473,1134,
+87,4180,2284,8822,3893,15653,15668,12175,
+7951,12668,13119,7839,4793,4686,914,9481,
+11912,13196,4235,15293,5704,9063,1605,15640,
+13270,1192,9967,8698,5576,3059,4067,11809,
+5420,7691,16087,764,12487,2273,14224,13412,
+5373,12663,788,12433,8870,15902,14019,3966,
+1104,11153,13117,8913,46,9922,15240,8260,
+9874,1712,9096,7708,4544,15601,0,10529,
+7419,9404,653,4067,10717,4901,10009,7229,
+9867,7620,1412,14284,9931,8845,13975,8238,
+10941,10205,678,11308,14985,12099,3268,11120,
+14148,7900,5934,10099,12903,6274,9648,2851,
+972,5149,9506,12102,723,15873,14497,5447,
+13505,13658,13128,4699,11152,0,0,7808,
+2623,6674,9557,7920,10004,14081,0,15478,
+12498,7162,13662,14438,6939,10841,6599,7074,
+2129,9303,3614,5121,13626,14806,13096,5275,
+12032,11431,12265,242,12651,6465,11153,15635,
+6154,7864,3263,7708,13216,9466,4929,4763,
+16121,12949,6801,14244,6289,3766,8913,3228,
+10099,4198,11895,286,13119,10778,12230,7238,
+3614,14081,7323,4050,6846,14629,13420,9427,
+5460,5130,10528,15705,6369,8361,1212,8866,
+12821,15427,7323,2777,9648,8744,5386,8241,
+11875,14112,14770,15369,9813,6750,13732,6594,
+2464,11682,2031,15129,3532,12112,4831,4354,
+2275,10376,11226,11611,8313,9590,14500,8598,
+13403,4316,15388,13458,961,208,5995,1225,
+6455,5932,11987,2902,13128,1224,1003,7409,
+3028,650,13436,8485,6653,911,9425,11421,
+9554,10993,15293,514,6670,14578,4972,9874,
+8483,2534,14969,1934,14154,8926,11830,8784,
+2987,9634,6670,13501,13957,4260,5761,15347,
+7991,13414,7159,7233,14206,11665,6715,11079,
+3545,5185,15639,14307,9338,8971,15994,5645,
+3098,14081,788,8170,10188,8016,5988,15919,
+12788,14960,10214,12606,11152,2470,13420,2927,
+5240,7370,9648,10099,2039,4846,10610,11823,
+13270,14761,5962,7512,10079,4867,8260,2135,
+1052,10823,5729,10395,14361,13382,12200,8162,
+5117,7531,13361,14520,10602,8685,3654,9777,
+16263,6135,6389,11745,10383,8550,12618,10340,
+4128,15459,7062,5135,9047,9346,5897,15479,
+7268,5576,0,14937,12736,5545,10079,6507,
+3238,3204,9865,5843,12487,198,8251,13195,
+158,8913,6598,4373,15991,13857,3615,11106,
+3244,10654,6394,6183,11633,3098,12257,15427,
+1768,7209,11987,963,13857,7247,16046,7239,
+13200,11773,2914,12927,11669,13011,1905,9089,
+16176,3743,158,5222,12717,5825,16087,9519,
+9227,15563,1712,8511,11005,4867,13200,13106,
+10788,3606,8680,3447,5833,3709,4526,10847,
+2871,6000,2204,15769,2969,7617,15976,7618,
+4067,10757,15316,6476,10509,8772,9095,0,
+8996,410,14742,7239,10532,9406,7419,15903,
+5437,5560,12608,9141,3986,14358,7409,3992,
+3221,6170,11821,508,6434,1442,4260,3813,
+8308,6456,3534,431,4538,3406,12435,5643,
+7144,8870,9186,3775,1817,9905,7951,4336,
+2273,12264,6513,2993,16270,5541,5077,6263,
+1259,2559,1675,16218,1790,12804,15098,4445,
+10336,15216,12144,8618,4573,13679,15000,10189,
+2209,4583,5353,13784,2623,7720,5833,11064,
+10088,10077,10610,6786,10939,10867,1768,8119,
+7394,12056,3789,1074,15413,10527,7247,12487,
+8568,10136,2228,13412,4840,1652,6740,11322,
+5037,2910,5174,10340,2135,8011,11895,11895,
+109,11957,14336,13234,8225,14343,9063,9819,
+13517,11635,13549,14936,988,3809,5833,7857,
+13462,297,7668,14482,4316,10848,2569,13931,
+5593,12056,11103,14170,448,902,1768,11552,
+6043,0,0,8646,10391,0,15316,3737,
+10594,11026,13280,14667,5713,4057,2787,4191,
+3838,7247,8772,14185,15641,8772,0,14081,
+0,9429,17,613,7428,15131,15651,14350,
+4365,15856,9521,3228,7950,3395,0,6594,
+11078,14975,6889,10768,4288,6707,7175,2235,
+10896,911,7707,7592,12916,15570,15644,6997,
+12523,14757,11895,7109,16279,12969,11690,0,
+8854,16304,8568,11334,15641,15478,2275,6193,
+7323,5230,9835,12821,1652,12477,5044,359,
+12487,13881,10731,8246,14642,14885,6555,15919,
+13857,1982,7646,12528,12009,7310,12310,3193,
+359,1483,5322,10476,46,3751,3766,6729,
+4512,13853,5558,12736,1733,2718,9956,7857,
+6519,2187,12964,12949,750,8877,15136,3742,
+4495,13851,3811,906,11592,9943,920,10806,
+10442,12561,5035,988,15861,8024,10272,16372,
+13353,15946,7330,4834,9414,8267,1668,12498,
+4530,9162,8648,3883,9451,3900,2028,12427,
+11203,3071,5645,10228,11875,8198,4563,215,
+3614,5717,11332,1617,11382,13987,12626,11857,
+12156,6513,13496,6997,16158,9093,6725,13737,
+5890,10008,14447,5475,12215,141,16192,10200,
+4450,6688,11090,16109,12256,9027,15355,3422,
+10079,14571,13101,9967,12296,3460,8348,15413,
+5222,11762,3823,13412,6729,6599,10528,9922,
+11152,9171,5362,5373,750,8969,1652,6220,
+5373,2569,3742,15119,10340,999,10088,10731,
+1028,3228,7369,15256,11822,12904,8121,11641,
+11158,5016,10725,8412,1183,9674,11806,12112,
+2623,15516,4226,10021,13316,12075,792,4972,
+8506,8921,6133,14718,567,4349,13420,5953,
+2265,11902,10019,16265,16312,0,9922,3009,
+8170,3473,10757,3567,2825,6915,5174,4299,
+0,8274,6292,295,6522,1475,359,4538,
+5358,5174,3008,6317,12688,4165,752,12052,
+10008,3912,7431,13364,9894,13524,284,16013,
+9820,11295,1144,2845,3538,10678,13806,1469,
+14210,7870,3766,10528,13642,10823,4200,8031,
+4671,14093,5541,1214,4115,3286,8217,8018 };
+
+
+unsigned int CONV phash( unsigned int move, int turn )
+{
+  unsigned int a, b;
+  
+  move |= ( (unsigned int)turn << 31 );
+  move += 0x69fe378e;
+  move ^= ( move >> 16 );
+  move += ( move << 8 );
+  move ^= ( move >> 4 );
+  b     = ( move >> 7 ) & 0x7ff;
+  a     = move >> 18;
+  
+  return a ^ tab[b];
+}
index 2eb8b7a..634ce23 100644 (file)
--- 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;
index 4980e9a..dda22e4 100644 (file)
--- a/problem.c
+++ b/problem.c
@@ -1,6 +1,8 @@
+#include <math.h>
+#include <limits.h>
 #include "shogi.h"
 
-int
+int CONV
 solve_problems( tree_t * restrict ptree, unsigned int nposition )
 {
   const char *str_move;
@@ -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 (file)
--- a/proce.c
+++ b/proce.c
 
 #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
-
index 6ceb5fb..cfc4016 100644 (file)
 #  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 )
index 7aaf0fb..b90acd3 100644 (file)
-----------------------------------------------------------------------
-              Bonanza Feliz 0.0 - Executable Source Code
-                                            Kunihito Hoki, 1 Apr 2010
-----------------------------------------------------------------------
-
-
-1. Introduction
-----------------
-
-Bonanza is a state-of-the art computer shogi engine which runs on
-Windows and Linux machines, and this directory contains a
-platform-independent source code.
-
-This source code is distributed with a hope that it will be useful in
-addition to the main part of the shogi engine. This program includes
-many useful functions such as manipulating a shogi board, reading and
-writing a CSA record file, speaking of a CSA protocol with a socket
-communication, and controlling time, and etc.. I believe this program
-can be a good starting point if you are interested in making shogi
-programs.
-
-One main feature of this program is that it employs a brute-force
-search method together with bitboard techniques as many chess programs
-do. Another notable feature is a machine learning of shogi evaluation
-functions. The details of the learning algorithm (aka Bonanza method)
-were already presented [1], and this source code provides an example
-of implementation of the learning method.
-
-I admit that some parts of the source code are cryptic, e.g. codes in
-"mate1ply.c". I hope that I will have some time to make a quality
-documentation and comments on the program code, or someone else could
-decrypt my program and provide a documentation.
-
-Any comments or suggestions are welcome [2].
-
-[1] K. Hoki, "Optimal control of minimax search results to learn
-    positional evaluation", Game Programming Workshop, Hakone, Japan
-    2008.
-
-[2] Contact to "bonanza_query [at] hotmail.com".
-
-
-2. Legal Notices
------------------
-
-This program is protected by copyright. Without a specific 
-permission, any means of commercial applications are prohibited.
-Furthermore, this program is distributed without any warranty.
-Within these limits, you can use, redistribute, and/or modify it.
-
-
-3. Change Logs
----------------
-
-Feliz 0.0
-
-- Some results from Y. Sato's experiments with Bonanza inspired me
-  to use the history table in LMR in Shogi, as Fruit did in chess. By
-  doing so, some improvement in performance of the tree search is
-  made.
-
-- From private communications with Yaneurao, it turned out that the
-  3-ply-mate detections in 'mate3.c' can search game trees more
-  efficiently by using several heuristic pruning techniques. Now
-  'mate3.c' adopts some of these techniques.
-
-- E. Ito kindly reported two bugs in the source codes. One is in
-  hash_store(), and the other is in ehash_probe() and
-  ehash_store(). Now these are fixed.
-
-- The structure of history table is modified from 'square-to' and
-  'square-from' method to an exact match method by using the perfect
-  hash technique. The hash function of moves in 'phash.c' is generated
-  by codes at http://burtleburtle.net/bob/hash/perfect.html.
-
-- A command 'mnj' is added to connect to the cluster-computing server
-  in src/cluster/.
-
-- In client_next_game(), the way of dealing with REJECT message from a
-  CSA Shogi server is revised. Now Bonanza connects to the server again
-  when the game is rejected by an opponent.
-
-
-Version 4.1.3
-- The owner of 'LS3600 Blog Webpage' pointed out that there were two
-  serious bugs. Thank you very much! According to his indication,
-  is_hand_eq_supe() in 'utility.c' and read_CSA_line() in 'csa.c' are
-  revised.
-- In MPV code in 'searchr.c', a test of 'root_abort' flag had been
-  forgotten. Now the flag is tested after every call of search().
-- 'lan.txt' is added to 'src/executable/' directory. This is an
-  example of an input sequence to connect to CSA Shogi server.
-- 'book.bin' now has smaller moves and positions than previous one does.
-  Also, 'book_anti.csa' is added to 'src/executable/' directory. This
-  is an example of bad moves which apear in records of human experts.
-- 'Legal Notices' in this document is corrected.
-
-Version 4.1.2
-- In 'Makefile' and 'Makefile.vs', targets which require profile-guided
-  optimization are removed. Furthermore, an option, which controls
-  optimization, has been reverted from the aggressive flag, -O3, to a
-  moderate one, '-O2'. These modifications were necessary for avoiding
-  abnormal terminations of the program.
-- In 'ini.c', the attribute of POSIX thread in a global-variable
-  'pthread_attr' is set to 'detach-state'. Because threads will never
-  join with any other threads in this program, the thread should be
-  created in the detached state to free system resources.
-- In 'ini.c', the default size of the transposition table is lifted
-  from 12MByte to 48MByte.
-- In 'iterate.c", probing the opening book is avoided when the move
-  history of a current game has repetitions.
-- In 'shogi.h', the margins of futility pruning are increased in
-  accord with new positional evaluation of the feature vector in
-  'fv.bin'.
-- The quality of an opening book, 'winbin/book.bin', has been improved
-  at the expense of quantity.
-
-Version 4.1.0 and 4.1.1 (26 Apr 2009)
-- In 'Makefile' and 'Makefile.vs', some options of Intel C compiler
-  are modified. Here, agressive optimization '-O3' is substituted for
-  the default '-O2', pthreads support '-pthread' is substituted for
-  '-lpthread', and an obsolete '-static-libcxx' is removed.
-- In 'Makefile', the conformance of GNU C and Intel C compilers are
-  set to GNU extensions of ISO C99 by setting '-std=gnu99' because a
-  POSIX function 'strtok_r()' is not in the C99 standard library.
-- In 'Makefile', targets for GNU C with gprof and profile-guided
-  optimization of GNU C are removed.
-- In 'shogi.h', inline assemblies and intrinsics are used on x86-64 as
-  well as x86. To detect the targets, pre-defined macros '__i386__'
-  and '__x86_64__' are examined.
-- In 'evaluate.c', the evaluation function looks up the table
-  'stand_pat[ply]' to see if the position have been evaluated since
-  the previous move is made by 'make_move_[bw]()' functions. Also, the
-  evaluation function probes the hash table 'ehash_tbl[]' to avoid
-  re-evaluation of the same position.
-- In 'io.c', an immediate value 0 is substituted for 'fileno(stdin)'
-  because the POSIX function 'fileno()' is not part of ANSI C. POSIX
-  requires that the file descriptor associated with 'stdin' be 0.
-- In 'iterate.c', a criterion for aging of transposition-table, i.e.,
-  increment of a global variable 'trans_table_age', is lifted from 7%
-  to 9% of saturation ratio of the table.
-- In 'learn1.c', the macro 'SEARCH_DEPTH' is set to 2. The macro
-  specifies the depth threashold of searches for finding all of
-  principle variations of positions in a set of games.
-- In 'learn1.c', a step size of increment/decrement of feature vectors
-  is fixed to 1 in 'learn_parse2()' function.
-- In 'hash.c', when a node can be pruned by using a hash value based on
-  futility pruning, a return value of the node is set to beta.
-- In 'rand.c', some codes of initialization of PRNG variables are
-  moved to 'ini_genrand()' from 'ini()' function.
-- In 'sckt.c', a function 'send_crlf()' is removed.
-- In 'search.c', now 'search()' calls 'search_quies()' and returns if
-  a search depth reaches a threashold. So that we can call 'search()'
-  function anytime, and this makes source codes simple.
-- In 'search.c', the static evaluation value is evaluated and used to
-  see if the late-move reduction is applicable or not. The evaluation
-  value is also used by the futility pruning.
-- In 'search.c', the futility pruning is not applied if the node is in
-  check or the move is a check.
-- In 'search.c', now Bonanza sends the keep-alive command '0x0a' to
-  the server in 'detect_signals()'.
-- In 'time.c', 'set_seach_limit_time()' is simplified.
-- In 'time.c', the second argument of 'gettimeofday()' is set to 'NULL'.
-
-Version 4.0.4 (2 Feb 2009)
-- An error of GCC inline assembly for spinlock in "thread.c" is fixed.
-- In Windows OS, Bonanza now opens all streams with file sharing by
-  using "_SH_DENYNO" constant in "io.c".
-- GCC built-in functions are substituted for GCC inline assemblies for
-  bit-scan operations in "bitop.h". Furthermore, "bitop.h" is removed,
-  and some of macros in the header are integrated into "shogi.h".
-
-Version 4.0.3 (Jan 2008)
-
-
-4. Files
----------
-
-Here is a list of files you can find in this directory.
-
-C headers
-- param.h     piece values
-- shogi.h     main header
-
-basic C functions
-- main.c      main function of C program
-- data.c      definition of global variables
-- ini.c       initializations
-- rand.c      pseudo random number generator
-- time.c      time functions
-- bitop.c     bit operation
-- utility.c   misc. functions
-
-I/O
-- proce.c     input procedure 
-- csa.c       csa file format I/O
-- io.c        basic I/O
-- dek.c       dekunobou
-- sckt.c      TCP/IP client of CSA SHOGI protocol
-
-bitboard manipulations
-- attack.c    piece attacks
-- genchk.c    move generation (checks)
-- genevasn.c  move generation (evasions)
-- gendrop.c   move generation (drops)
-- gennocap.c  move generation (non-captures)
-- gencap.c    move generation (captures)
-- movgenex.c  move generation (inferior moves)
-- makemove.c  make moves
-- unmake.c    unmake move
-- mate1ply.c  1-ply mate detection
-- debug.c     examine bitboard validity
-
-brute-force search
-- iterate.c   iterative deepning search at root node
-- searchr.c   alpha-beta search at root node
-- search.c    alpha-beta search
-- next.c      obtains next move
-- quiesrch.c  quiescence search
-- evaluate.c  static eveluation function
-- evaldiff.c  easy and fast evaluation function
-- swap.c      static exchange evaluation
-- hash.c      transposition table
-- thread.c    thread-level parallelization
-- root.c      root move genelation and shallow min-max search
-- mate3.c     3-ply mate detection
-- ponder.c    pondering
-- book.c      creates and probes opening book
-- problem.c   auto problem solver
-- valid.c     examine move validity
-
-optimal control of min-max search
-- learn1.c    main functions
-- learn2.c    feture vector manipuration
-
-misc.
-- bonanza.txt which now you are looking at
-- Makefile    makefile for gnu make.exe
-- Makefile.vs makefile for Microsoft nmake.exe
-- bonanza.ico icon file for windows
-- bonanza.rc  resource-definition file for windows
-- lan.txt     example of input sequence to connect CSA Shogi server
-- book_anti.csa example of a set of bad moves which apear in records
-              of human exparts. This is used by 'book create' command.
-
-4. How to build Bonanza
------------------------
-
-You can build Bonanza by means of GNU Make on Linux or Microsoft NMAKE
-on Windows. Here is some examples:
-
-- GCC on Linux
-> make -f Makefile gcc
-
-- Intel C++ Compiler on Linux
-> make -f Makefile icc
-
-- Microsoft C/C++ Compiler on Windows
-> nmake -f Makefile.vs cl
-
-- Intel C++ Compiler on Windows
-> nmake -f Makefile.vs icl
-
-The C source codes are written by using ANSI C plus a small number of
-new features in ISO C99. Therefore, I think this can be easily built
-in many platforms without much effort.
-
-It may be necessary to define some macros in Makefile or
-Makefile.vs. The macros are:
-
-- NDEBUG (DEBUG)    builds release (debug) version of Bonanza
-
-- MINIMUM           disables some auxiliary functions that are not
-                    necessary to play a game, e.g., book composition
-                    and optimization of evaluation functions
-
-- TLP               enables thread-level parallel search
-
-- MPV               enables multi-PV search
-
-- CSA_LAN           enables Bonanza to communicate by CSA Shogi TCP/IP
-                    protcol
-
-- DEKUNOBOU         enables dekunobou interface (available only for
-                    Windows)
-
-- CSASHOGI          builds an engine for CSA Shogi (available only for
-                    Windows)
-
-- NO_LOGGING        suppresses dumping log files
-
-Bonanza is an application that does not provide graphical user
-interface. If you could build "bonanza.exe" properly without CSASHOGI
-macro, it shows a prompt "Black 1>" when you execute it at a computer
-console.
-
-Bonanza uses three binary files: a feature vector of static evaluation
-function "fv.bin",  an opening book "book.bin", and a
-position-learning database "hash.bin". You can find these in "winbin/"
-directory. Without the NO_LOGGING option, Bonanza must find "log/"
-directory to dump log files.
-
-
-5. Command List
----------------
-
-- beep on
-- beep off
-    These commands enable (on) or disable (off) a beep when Bonanza
-    makes a move.  The default is on.
-
-- book on
-- book off
-    These commands enable (on) or disable (off) to probe the opening
-    book, "./book.bin".  The default is on.
-
-- book narrow
-- book wide
-    When the command with "narrow" is used, Bonanza selects a book
-    move from a small set of opening moves. The default is "wide". The
-    narrowing of the opening moves is useful if you want Bonanza
-    choose a common opening line.
-
-- book create
-    This command creates the opening book file, "./book.bin", by using
-    numerous experts' games in a single CSA record file, "./book.csa".
-    It also uses another CSA record file, "book_anti.csa", where you
-    can register bad moves that may appear in the experts' games at
-    the last moves in the record file. Here is the example:
-
-    ----------------------------------------
-    PI, +, +6978KI, %TORYO
-    /
-    PI, +, +6978KI, -8384FU, %TORYO
-    /
-    PI, +, +7776FU, -4132KI, %TORYO
-    /
-    PI, +, +7776FU, -4132KI, +2726FU, %TORYO
-    ----------------------------------------
-
-    This command becomes effective when MINIMUM macro is not defined
-    in the Makefile.
-
-- connect 'addr' 'port' 'id' 'passwd' ['ngame']
-    This command connects Bonanza to a shogi server by using the CSA
-    protocol. The first four arguments specify the network address,
-    port number, user ID, and password, respectively. The last
-    argument limits a number of games that will be played by Bonanza.
-    This command becomes effective when CSA_LAN macro is defined in
-    the Makefile.
-
-- dekunobou 'addr' 'port-dekunobou' 'port-bonanza'
-    This command connects Bonanza to Dekunobou.
-
-- display ['num']
-    This command prints the shogi board. If you want to flip the
-    board, set 'num' to 2. If not, set it to 1.
-
-- s
-    Bonanza makes a prompt reply while thinking as soon as this
-    command is used.
-
-- hash 'num'
-    This command is used to initialize the transposition table and
-    set the size of the table to 2^'num'.
-
-- hash learn create
-    This command is used to make a zero-filled position-lerning
-    database, "hash.bin". This command becomes effective when MINIMUM
-    macro is not defined in the Makefile.
-
-- hash learn on
-- hash learn off
-    These commands enable (on) or disable (off) the position learning.
-    The default is on.
-
-- learn 'str' 'steps' ['games' ['iterations' ['num1' ['num2']]]]
-    This command optimizes a feature vector of the static evaluation
-    function by using numorous experts' games in a single CSA record
-    file, "./records.csa". If you want to use a zero-filled vector as
-    an initial guess of the optimization procedure, set 'str' to
-    "ini". If not, set it to "no-ini". The third argument 'games' is a
-    number of games to be read from the record file. If the third
-    argument is negative or omitted, all games are read from the file.
-
-    The learning method iterates a set of procedures, and the number
-    of iteration can be limited by the fourth argument. It continues
-    as long as the argument is negative. The procedures consist of two
-    parts. The first part reads the record file and creates principal
-    variations by using 'num1' threads. The default value of 'num1' is
-    1. The second part renews the feature vector 'steps' times by using
-    'num2' threads in accord with the principal variations. The default
-    value of 'steps' and 'num2' is 1. Note that each thread in the
-    second procedure uses about 500MByte of the main memory. The two
-    arguments 'num1' and 'num2' become effective when TLP macro is
-    defined in the Makefile. After the procedures, the optimized
-    vector is saved in "./fv.bin". This command become effective when
-    MINIMUM macro is not defined in the Makefile.
-
-- limit depth 'num'
-    This command is used to specify a depth, 'num', at which Bonanza
-    ends the iterative deepening search.
-
-- limit nodes 'num'
-    When this command is used, Bonanza stops thinking after searched
-    nodes reach to 'num'.
-
-- limit time 'minute' 'second' ['depth']
-    This command limits thinking time of Bonanza. It tries to make
-    each move by consuming the time 'minute'. When the time is spent
-    all, it makes each move in 'second'. The last argument 'depth' can
-    be used if you want Bonanza to stop thinking after the iterative
-    deepening searches reach sufficient depth.
-
-- limit time extendable
-- limit time strict
-    The command, "limit time extendable", allows Bonanza to think
-    longer than the time limited by the previous command if it wishes
-    to. The default is "strict".
-
-- mnj 'sd' 'seed' 'addr' 'port' 'id'
-    This command connects Bonanza to the council server in
-    src/cluster/. The first two integers specify the standard
-    deviation and initial seed of pseudo-random numbers which are
-    added to the static evaluation function. Experiments suggested
-    that an appropriate value for the standard deviation is 50. Note
-    that all clients should use different seeds. The last three
-    arguments are network address, port number, user ID,
-    respectively. This command becomes effective when MNJ_LAN macro is
-    defined in the Makefile.
-
-- move ['str']
-    Bonanza makes a move of 'str'. If the argument is omitted, Bonanza
-    thinks of its next move by itself.
-
-- mpv num 'nroot'
-- mpv width 'threshold'
-    These commands control the number of root moves, 'nroot', to
-    constitute principal variations. The default number is 1. A root
-    move that yields a smaller value than the best value by 'threshold'
-    is neglected. The default threshold is about 200. These commands
-    become effective when MPV macro is defined in the Makefile.
-
-- new ['str']
-    This command initializes the shogi board. The argument 'str'
-    controls an initial configuration of the board.  If you want to
-    play a no-handicapped game, set 'str' to "PI" and this is the
-    default value. In a handicapped game, specify squares and pieces
-    to drop, e.g. "new PI82HI22KA" or "new PI19KY".
-
-- peek on
-- peek off
-    The command "peek on (off)" enables (disables) peeks at a buffer
-    of the standard input file while Bonanza is thinking. The default
-    is on. This command is useful when you want to process a set of
-    commands as "> ./bonanza.exe < infile".
-
-- ping
-    Prompt Bonanza to print "pong".
-
-- ponder on
-- ponder off
-    The command "ponder on (off)" enables (disables) thinks on the
-    opponent's time. The default is on.
-
-- problem ['num']
-    This command is used to solve problems in "./problem.csa". Here
-    is an example of the problem file.
-
-    -----------------------------
-    $ANSWER:+0024FU
-    P1-KY-KE-OU-KI *  *  *  * -KY
-    P2 *  *  *  *  * -KI *  *  * 
-    P3 *  * -FU-GI-FU * -KE * -KA
-    P4-FU *  * -FU-GI-FU-HI * -FU
-    P5 *  *  *  *  *  *  * -FU+KY
-    P6+FU+KA+FU+FU+GI+FU+KI *  * 
-    P7 * +FU *  * +FU *  *  *  * 
-    P8 * +OU+KI+GI *  * +HI *  * 
-    P9+KY+KE *  *  *  *  * +KE * 
-    P+00FU00FU
-    P-00FU00FU00FU
-    +
-    /
-    $ANSWER:+0087KY:+0088KY
-    P1-OU-KE *  *  *  *  * +GI * 
-    P2-KY-KI *  *  *  *  *  *  * 
-    P3-FU-HI * -KI *  * -GI *  * 
-    P4 *  * -KE *  *  *  *  * -FU
-    P5 * +GI * -FU-FU-FU-FU-FU * 
-    P6+FU+HI-FU *  *  *  *  *  * 
-    P7 *  *  * +FU *  *  *  * +FU
-    P8 *  * +OU+KI+KI *  *  *  * 
-    P9+KY+KE *  *  *  *  * +KE+KY
-    P+00KA00GI00KY00FU00FU
-    P-00KA00FU00FU00FU00FU00FU
-    +
-    -----------------------------
-
-    The argument 'num' specifies the number of problems to solve.
-
-- quit
-    The quit command and EOF character will exit Bonanza.
-
-- read 'filename' [(t|nil) ['num']]
-    This command is used to read a CSA record 'filename' up to 'num'
-    moves. Set the second argument to "nil" when you want to ignore
-    time information in the record. The default value is "t". Bonanza
-    reads all move sequence if the last argument is neglected. If
-    'filename' is ".", the command reads an ongoing game from the
-    initial position.
-
-- resign
-    Use this command when you resign a game.
-
-- resign 'num'
-    This command specifies the threshold to resign. 'num' is a value
-    of the threshold. The default is around 1000.
-
-- stress on
-- stress off
-    When the command "stress on" is used, last-move shown in shogi
-    board is stressed. The default is on.
-
-- time remain 'num1' 'num2'
-    This command tells Bonanza the remaining time. 'num1' ('num2') is
-    the remaining time of black (white) in seconds.
-
-- time response 'num'
-    This command specifies a margin to control time. The time margin
-    saves Bonanza from time up due to TCP/IP communication to a server
-    program, sudden disc access, or imperfection of time control of
-    Bonanza. 'num' is the time margin in milli-second. The default
-    value is 200.
-
-- tlp 'num'
-    This command controls the number of threads to be created when
-    Bonana considers a move to make. The command becomes effective
-    when TLP macro is defined in the Makefile. 'num' is the number of
-    threads. The default value is 1.
-
-- #
-    A line beginning with # causes all characters on that line
-    to be ignored.
-
-- [move command]
-    A move command consists of four digits followed by two
-    capital alphabets, e.g. 7776FU. The first two digits
-    are a starting square and the last two are a target square. The
-    starting square is "OO" if the  move is a dorp, e.g. 0087FU. The
-    following two alphabets specify a piece type as the following,
-
-      FU - pawn             (Fuhyo)       TO - promoted pawn    (Tokin)
-      KY - lance            (Kyousha)     NY - promoted lance   (Narikyo)
-      KE - knight           (Keima)       NK - promoted knight  (Narikei)
-      GI - silver general   (Ginsho)      NG - promoted silver  (Narigin)
-      KI - gold general     (Kinsyo)
-      KA - Bishop           (Kakugyo)     UM - Dragon horse     (Ryuma)
-      HI - Rook             (Hisha)       RY - Dragon king      (Ryuo)
-      OU - King             (Osho)
-
-    Here, words in parentheses are romanization of Japanese words.
+----------------------------------------------------------------------\r
+                        Bonanza 6.0 - Client Source Code\r
+                                            Kunihito Hoki, May 2011\r
+----------------------------------------------------------------------\r
+\r
+\r
+1. Introduction\r
+----------------\r
+\r
+Bonanza is a state-of-the art computer shogi engine which runs on\r
+Windows and Linux machines, and this directory contains a\r
+platform-independent source code.\r
+\r
+This source code is distributed with a hope that it will be useful in\r
+addition to the main part of the shogi engine. This program includes\r
+many useful functions such as manipulating a shogi board, reading and\r
+writing a CSA record file, speaking of a CSA protocol with a socket\r
+communication, and controlling time, and etc.. I believe this program\r
+can be a good starting point if you are interested in making shogi\r
+programs.\r
+\r
+One main feature of this program is that it employs a brute-force\r
+search method together with bitboard techniques as many chess programs\r
+do. Another notable feature is a machine learning of shogi evaluation\r
+functions. The details of the learning algorithm (aka Bonanza method)\r
+were already presented [1], and this source code provides an example\r
+of implementation of the learning method.\r
+\r
+I admit that some parts of the source code are cryptic, e.g. codes in\r
+"mate1ply.c". I hope that I will have some time to make a quality\r
+documentation and comments on the program code, or someone else could\r
+decrypt my program and provide a documentation.\r
+\r
+Any comments or suggestions are welcome [2].\r
+\r
+[1] K. Hoki, "Optimal control of minimax search results to learn\r
+    positional evaluation", Game Programming Workshop, Hakone, Japan\r
+    2008.\r
+\r
+[2] Contact to "bonanza_query [at] hotmail.com".\r
+\r
+\r
+2. Legal Notices\r
+-----------------\r
+\r
+This program is protected by copyright. Without a specific \r
+permission, any means of commercial applications are prohibited.\r
+Furthermore, this program is distributed without any warranty.\r
+Within these limits, you can use, redistribute, and/or modify it.\r
+\r
+\r
+3. Change Logs\r
+---------------\r
+\r
+Version 6.0\r
+\r
+Search() function is modified to ignore moves which receive negative\r
+values from Static Exchange Evaluation (SEE) at frontier and\r
+pre-frontier nodes. Self-play experiments showed that this modification\r
+makes Bonanza slightly stronger. Similar results were also observed in\r
+experiments using a shogi program YSS,\r
+http://www32.ocn.ne.jp/~yss/horizon.txt. Moreover, the branch cut by\r
+means of SEE at frontier nodes can also be found in a chess program,\r
+Stockfish.\r
+\r
+Now Bonanza does Late Move Reduction (LMR) at root nodes, and recursive\r
+iterative deepening more often. Self-play experiments showed that these\r
+modifications make Bonanza slightly stronger.\r
+\r
+DFPN searcher is added to the set of Bonanza source codes (dfpn.c,\r
+dfpn.h, and dfpnhash.c). You can use the searcher by using 'dfpn'\r
+command with a compile option -DDFPN turned on. To make use of the DFPN\r
+searcher in ordinary search, use 'dfpn_client' command with a compile\r
+option -DDFPN_CLIENT turned on. To provide a proper service to the DFPN\r
+client, you also need to use a server script 'src/server/dfpn_server.pl'\r
+with one or more DFPN worker(s) connected with 'dfpn connect' command.\r
+I am thankful to Dr. A. Nagai for his kind and fruitful advice.\r
+\r
+Now Bonanza can be a client of parallel searches using cluster computing\r
+environment with mnj command. 'src/server/parallel_server.pl' is a\r
+server script of root-node parallelizations, and the server can be a\r
+client of majority voting cluster computation.\r
+\r
+Some techniques which increase computational efficiency of Bonanza are\r
+reported by E. Ito, http://aleag.cocolog-nifty.com/. In his website,\r
+two ideas are shown, i.e., (i) speed up of the computation of the static\r
+evaluation function, and (2) use of SSE instructions of Intel processors\r
+for bitboard operations. By adopting his ideas to Bonanza, NPS value\r
+nearly doubled. This is amazing. To use SSE instructions, specify -DSSE2\r
+or -DSSE4 compiler option. I am thankful to Mr. E. Ito for his kind and\r
+fruitful advice.\r
+\r
+-DINANIWA_SHIFT compilation flag is supplied to enable an Inaniwa-strategy detection\r
+\r
+There are many other modifications and bug fixes.\r
+\r
+\r
+Feliz 0.0\r
+\r
+- Some results from Y. Sato's experiments with Bonanza inspired me\r
+  to use the history table in LMR in Shogi, as Fruit did in chess. By\r
+  doing so, some improvement in performance of the tree search is\r
+  made.\r
+\r
+- From private communications with Yaneurao, it turned out that the\r
+  3-ply-mate detections in 'mate3.c' can search game trees more\r
+  efficiently by using several heuristic pruning techniques. Now\r
+  'mate3.c' adopts some of these techniques.\r
+\r
+- E. Ito kindly reported two bugs in the source codes. One is in\r
+  hash_store(), and the other is in ehash_probe() and\r
+  ehash_store(). Now these are fixed.\r
+\r
+- The structure of history table is modified from 'square-to' and\r
+  'square-from' method to an exact match method by using the perfect\r
+  hash technique. The hash function of moves in 'phash.c' is generated\r
+  by codes at http://burtleburtle.net/bob/hash/perfect.html.\r
+\r
+- A command 'mnj' is added to connect to the cluster-computing server\r
+  in src/cluster/.\r
+\r
+- In client_next_game(), the way of dealing with REJECT message from a\r
+  CSA Shogi server is revised. Now Bonanza connects to the server again\r
+  when the game is rejected by an opponent.\r
+\r
+\r
+Version 4.1.3\r
+- The owner of 'LS3600 Blog Webpage' pointed out that there were two\r
+  serious bugs. Thank you very much! According to his indication,\r
+  is_hand_eq_supe() in 'utility.c' and read_CSA_line() in 'csa.c' are\r
+  revised.\r
+- In MPV code in 'searchr.c', a test of 'root_abort' flag had been\r
+  forgotten. Now the flag is tested after every call of search().\r
+- 'lan.txt' is added to 'src/executable/' directory. This is an\r
+  example of an input sequence to connect to CSA Shogi server.\r
+- 'book.bin' now has smaller moves and positions than previous one does.\r
+  Also, 'book_anti.csa' is added to 'src/executable/' directory. This\r
+  is an example of bad moves which apear in records of human experts.\r
+- 'Legal Notices' in this document is corrected.\r
+\r
+Version 4.1.2\r
+- In 'Makefile' and 'Makefile.vs', targets which require profile-guided\r
+  optimization are removed. Furthermore, an option, which controls\r
+  optimization, has been reverted from the aggressive flag, -O3, to a\r
+  moderate one, '-O2'. These modifications were necessary for avoiding\r
+  abnormal terminations of the program.\r
+- In 'ini.c', the attribute of POSIX thread in a global-variable\r
+  'pthread_attr' is set to 'detach-state'. Because threads will never\r
+  join with any other threads in this program, the thread should be\r
+  created in the detached state to free system resources.\r
+- In 'ini.c', the default size of the transposition table is lifted\r
+  from 12MByte to 48MByte.\r
+- In 'iterate.c", probing the opening book is avoided when the move\r
+  history of a current game has repetitions.\r
+- In 'shogi.h', the margins of futility pruning are increased in\r
+  accord with new positional evaluation of the feature vector in\r
+  'fv.bin'.\r
+- The quality of an opening book, 'winbin/book.bin', has been improved\r
+  at the expense of quantity.\r
+\r
+Version 4.1.0 and 4.1.1 (26 Apr 2009)\r
+- In 'Makefile' and 'Makefile.vs', some options of Intel C compiler\r
+  are modified. Here, agressive optimization '-O3' is substituted for\r
+  the default '-O2', pthreads support '-pthread' is substituted for\r
+  '-lpthread', and an obsolete '-static-libcxx' is removed.\r
+- In 'Makefile', the conformance of GNU C and Intel C compilers are\r
+  set to GNU extensions of ISO C99 by setting '-std=gnu99' because a\r
+  POSIX function 'strtok_r()' is not in the C99 standard library.\r
+- In 'Makefile', targets for GNU C with gprof and profile-guided\r
+  optimization of GNU C are removed.\r
+- In 'shogi.h', inline assemblies and intrinsics are used on x86-64 as\r
+  well as x86. To detect the targets, pre-defined macros '__i386__'\r
+  and '__x86_64__' are examined.\r
+- In 'evaluate.c', the evaluation function looks up the table\r
+  'stand_pat[ply]' to see if the position have been evaluated since\r
+  the previous move is made by 'make_move_[bw]()' functions. Also, the\r
+  evaluation function probes the hash table 'ehash_tbl[]' to avoid\r
+  re-evaluation of the same position.\r
+- In 'io.c', an immediate value 0 is substituted for 'fileno(stdin)'\r
+  because the POSIX function 'fileno()' is not part of ANSI C. POSIX\r
+  requires that the file descriptor associated with 'stdin' be 0.\r
+- In 'iterate.c', a criterion for aging of transposition-table, i.e.,\r
+  increment of a global variable 'trans_table_age', is lifted from 7%\r
+  to 9% of saturation ratio of the table.\r
+- In 'learn1.c', the macro 'SEARCH_DEPTH' is set to 2. The macro\r
+  specifies the depth threashold of searches for finding all of\r
+  principle variations of positions in a set of games.\r
+- In 'learn1.c', a step size of increment/decrement of feature vectors\r
+  is fixed to 1 in 'learn_parse2()' function.\r
+- In 'hash.c', when a node can be pruned by using a hash value based on\r
+  futility pruning, a return value of the node is set to beta.\r
+- In 'rand.c', some codes of initialization of PRNG variables are\r
+  moved to 'ini_genrand()' from 'ini()' function.\r
+- In 'sckt.c', a function 'send_crlf()' is removed.\r
+- In 'search.c', now 'search()' calls 'search_quies()' and returns if\r
+  a search depth reaches a threashold. So that we can call 'search()'\r
+  function anytime, and this makes source codes simple.\r
+- In 'search.c', the static evaluation value is evaluated and used to\r
+  see if the late-move reduction is applicable or not. The evaluation\r
+  value is also used by the futility pruning.\r
+- In 'search.c', the futility pruning is not applied if the node is in\r
+  check or the move is a check.\r
+- In 'search.c', now Bonanza sends the keep-alive command '0x0a' to\r
+  the server in 'detect_signals()'.\r
+- In 'time.c', 'set_seach_limit_time()' is simplified.\r
+- In 'time.c', the second argument of 'gettimeofday()' is set to 'NULL'.\r
+\r
+Version 4.0.4 (2 Feb 2009)\r
+- An error of GCC inline assembly for spinlock in "thread.c" is fixed.\r
+- In Windows OS, Bonanza now opens all streams with file sharing by\r
+  using "_SH_DENYNO" constant in "io.c".\r
+- GCC built-in functions are substituted for GCC inline assemblies for\r
+  bit-scan operations in "bitop.h". Furthermore, "bitop.h" is removed,\r
+  and some of macros in the header are integrated into "shogi.h".\r
+\r
+Version 4.0.3 (Jan 2008)\r
+\r
+\r
+4. Files\r
+---------\r
+\r
+Here is a list of files you can find in this directory.\r
+\r
+C headers\r
+- param.h     piece values\r
+- shogi.h     main header\r
+- bitop.h     bit operations\r
+- dfpn.h      header of DFPN codes\r
+\r
+basic C functions\r
+- main.c      main function of C program\r
+- data.c      definition of global variables\r
+- ini.c       initializations\r
+- rand.c      pseudo random number generator\r
+- time.c      time functions\r
+- bitop.c     bit operations\r
+- utility.c   misc. functions\r
+\r
+I/O\r
+- proce.c     input procedures\r
+- csa.c       csa file format I/O\r
+- io.c        basic I/O\r
+- sckt.c      Socket communications\r
+\r
+bitboard manipulations\r
+- attack.c    piece attacks\r
+- genchk.c    move generation (checks)\r
+- genevasn.c  move generation (evasions)\r
+- gendrop.c   move generation (drops)\r
+- gennocap.c  move generation (non-captures)\r
+- gencap.c    move generation (captures)\r
+- movgenex.c  move generation (inferior moves)\r
+- makemove.c  make moves\r
+- unmake.c    unmake move\r
+- mate1ply.c  1-ply mate detection\r
+- debug.c     examine bitboard validity\r
+\r
+brute-force search\r
+- iterate.c   iterative deepning search at root node\r
+- searchr.c   alpha-beta search at root node\r
+- search.c    alpha-beta search\r
+- next.c      obtains next move\r
+- quiesrch.c  quiescence search\r
+- evaluate.c  static eveluation function\r
+- evaldiff.c  easy and fast evaluation function\r
+- swap.c      static exchange evaluation\r
+- hash.c      transposition table\r
+- phash.c     perfect hash function of moves\r
+- thread.c    thread-level parallelization\r
+- root.c      root move genelation and shallow min-max search\r
+- mate3.c     3-ply mate detection\r
+- ponder.c    pondering\r
+- book.c      creates and probes opening book\r
+- problem.c   auto problem solver\r
+- valid.c     examine move validity\r
+\r
+DFPN search\r
+- dfpn.c      DFPN search\r
+- dfpnhash.c  Hashing for DFPN search\r
+\r
+optimal control of min-max search\r
+- learn1.c    main functions\r
+- learn2.c    feture vector manipuration\r
+\r
+misc.\r
+- bonanza.txt which now you are looking at\r
+- Makefile    makefile for gnu make.exe\r
+- Makefile.vs makefile for Microsoft nmake.exe\r
+- bonanza.ico icon file for windows\r
+- bonanza.rc  resource-definition file for windows\r
+- lan.txt     example of input sequence to connect CSA Shogi server\r
+- book_anti.csa example of a set of bad moves which apear in records\r
+              of human exparts. This is used by 'book create' command.\r
+\r
+4. How to build Bonanza\r
+-----------------------\r
+\r
+You can build Bonanza by means of GNU Make on Linux or Microsoft NMAKE\r
+on Windows. Here is some examples:\r
+\r
+- GCC on Linux\r
+> make -f Makefile gcc\r
+\r
+- Intel C++ Compiler on Linux\r
+> make -f Makefile icc\r
+\r
+- Microsoft C/C++ Compiler on Windows\r
+> nmake -f Makefile.vs cl\r
+\r
+- Intel C++ Compiler on Windows\r
+> nmake -f Makefile.vs icl\r
+\r
+The C source codes are written by using ANSI C plus a small number of\r
+new features in ISO C99. Therefore, I think this can be easily built\r
+in many platforms without much effort.\r
+\r
+It may be necessary to define some macros in Makefile or\r
+Makefile.vs. The macros are:\r
+\r
+- NDEBUG (DEBUG)    builds release (debug) version of Bonanza\r
+\r
+- MINIMUM           disables some auxiliary functions that are not\r
+                    necessary to play a game, e.g., book composition\r
+                    and optimization of evaluation functions\r
+\r
+- TLP               enables thread-level parallel search\r
+\r
+- MPV               enables multi-PV search\r
+\r
+- CSA_LAN           enables Bonanza to communicate by CSA Shogi TCP/IP\r
+                    protcol\r
+\r
+- DEKUNOBOU         enables dekunobou interface (available only for\r
+                    Windows)\r
+\r
+- CSASHOGI          builds an engine for CSA Shogi (available only for\r
+                    Windows)\r
+\r
+- NO_LOGGING        suppresses dumping log files\r
+\r
+- HAVE_SSE2         use SSE2 instructions for speed\r
+\r
+- HAVE_SSE4         use SSE2 and SSE4.1 instructions for speed\r
+\r
+- MNJ_LAN           enables a client-mode of cluster searches\r
+\r
+- INANIWA_SHIFT     enables an Inaniwa strategy detection\r
+\r
+- DFPN              build the DFPN worker of mate-problems server\r
+\r
+- DFPN_CLIENT       enables the client-mode of mate-problem server\r
+\r
+\r
+Bonanza is an application that does not provide graphical user\r
+interface. If you could build "bonanza.exe" properly without CSASHOGI\r
+macro, it shows a prompt "Black 1>" when you execute it at a computer\r
+console.\r
+\r
+Bonanza uses three binary files: a feature vector of static evaluation\r
+function "fv.bin",  an opening book "book.bin", and a\r
+position-learning database "hash.bin". You can find these in "winbin/"\r
+directory. Without the NO_LOGGING option, Bonanza must find "log/"\r
+directory to dump log files.\r
+\r
+\r
+5. Command List\r
+---------------\r
+\r
+- beep on\r
+- beep off\r
+    These commands enable (on) or disable (off) a beep when Bonanza\r
+    makes a move.  The default is on.\r
+\r
+- book on\r
+- book off\r
+    These commands enable (on) or disable (off) to probe the opening\r
+    book, "./book.bin".  The default is on.\r
+\r
+- book narrow\r
+- book wide\r
+    When the command with "narrow" is used, Bonanza selects a book\r
+    move from a small set of opening moves. The default is "wide". The\r
+    narrowing of the opening moves is useful if you want Bonanza\r
+    choose a common opening line.\r
+\r
+- book create\r
+    This command creates the opening book file, "./book.bin", by using\r
+    numerous experts' games in a single CSA record file, "./book.csa".\r
+    It also uses another CSA record file, "book_anti.csa", where you\r
+    can register bad moves that may appear in the experts' games at\r
+    the last moves in the record file. Here is the example:\r
+\r
+    ----------------------------------------\r
+    PI, +, +6978KI, %TORYO\r
+    /\r
+    PI, +, +6978KI, -8384FU, %TORYO\r
+    /\r
+    PI, +, +7776FU, -4132KI, %TORYO\r
+    /\r
+    PI, +, +7776FU, -4132KI, +2726FU, %TORYO\r
+    ----------------------------------------\r
+\r
+    This command becomes effective when MINIMUM macro is not defined\r
+    in the Makefile.\r
+\r
+- connect 'addr' 'port' 'id' 'passwd' ['ngame']\r
+    This command connects Bonanza to a shogi server by using the CSA\r
+    protocol. The first four arguments specify the network address,\r
+    port number, user ID, and password, respectively. The last\r
+    argument limits a number of games that will be played by Bonanza.\r
+    This command becomes effective when CSA_LAN macro is defined in\r
+    the Makefile.\r
+\r
+- dfpn go\r
+    Bonanza does DFPN search at a current position.\r
+\r
+- dfpn hash 'num'\r
+    This command is used to initialize the transposition table of\r
+    DFPN search and set the size of the table to 2^'num'. This\r
+    command becomes effective when DFPN macro is defined in the\r
+    Makefile.\r
+\r
+- dfpn connect 'hostname' 'port#' 'ID'\r
+    This command is used to connect to the server script\r
+    dfpn_server.pl as a worker. This command becomes effective when\r
+    DFPN macro is defined in the Makefile.\r
+\r
+- dfpn_client 'hostname' 'port#'\r
+    This command is used to connect to the server script\r
+    dfpn_server.pl as a client. With this, a root and its child\r
+    posittions are examined by the DFPN worker(s). This command\r
+    becomes effective when DFPN_CLIENT macro is defined in the\r
+    Makefile.\r
+\r
+- display ['num']\r
+    This command prints the shogi board. If you want to flip the\r
+    board, set 'num' to 2. If not, set it to 1.\r
+\r
+- s\r
+    Bonanza makes a prompt reply while thinking as soon as this\r
+    command is used.\r
+\r
+- hash 'num'\r
+    This command is used to initialize the transposition table and\r
+    set the size of the table to 2^'num'.\r
+\r
+- hash learn create\r
+    This command is used to make a zero-filled position-lerning\r
+    database, "hash.bin". This command becomes effective when MINIMUM\r
+    macro is not defined in the Makefile.\r
+\r
+- hash learn on\r
+- hash learn off\r
+    These commands enable (on) or disable (off) the position learning.\r
+    The default is on.\r
+\r
+- learn 'str' 'steps' ['games' ['iterations' ['num1' ['num2']]]]\r
+    This command optimizes a feature vector of the static evaluation\r
+    function by using numorous experts' games in a single CSA record\r
+    file, "./records.csa". If you want to use a zero-filled vector as\r
+    an initial guess of the optimization procedure, set 'str' to\r
+    "ini". If not, set it to "no-ini". The third argument 'games' is a\r
+    number of games to be read from the record file. If the third\r
+    argument is negative or omitted, all games are read from the file.\r
+\r
+    The learning method iterates a set of procedures, and the number\r
+    of iteration can be limited by the fourth argument. It continues\r
+    as long as the argument is negative. The procedures consist of two\r
+    parts. The first part reads the record file and creates principal\r
+    variations by using 'num1' threads. The default value of 'num1' is\r
+    1. The second part renews the feature vector 'steps' times by using\r
+    'num2' threads in accord with the principal variations. The default\r
+    value of 'steps' and 'num2' is 1. Note that each thread in the\r
+    second procedure uses about 500MByte of the main memory. The two\r
+    arguments 'num1' and 'num2' become effective when TLP macro is\r
+    defined in the Makefile. After the procedures, the optimized\r
+    vector is saved in "./fv.bin". This command become effective when\r
+    MINIMUM macro is not defined in the Makefile.\r
+\r
+- limit depth 'num'\r
+    This command is used to specify a depth, 'num', at which Bonanza\r
+    ends the iterative deepening search.\r
+\r
+- limit nodes 'num'\r
+    When this command is used, Bonanza stops thinking after searched\r
+    nodes reach to 'num'.\r
+\r
+- limit time 'minute' 'second' ['depth']\r
+    This command limits thinking time of Bonanza. It tries to make\r
+    each move by consuming the time 'minute'. When the time is spent\r
+    all, it makes each move in 'second'. The last argument 'depth' can\r
+    be used if you want Bonanza to stop thinking after the iterative\r
+    deepening searches reach sufficient depth.\r
+\r
+- limit time extendable\r
+- limit time strict\r
+    The command, "limit time extendable", allows Bonanza to think\r
+    longer than the time limited by the previous command if it wishes\r
+    to. The default is "strict".\r
+\r
+- mnj 'sd' 'seed' 'addr' 'port' 'id' 'factor' 'stable_depth'\r
+    This command connects Bonanza to the majority or parallel server in\r
+    src/server/. The first two integers specify the standard\r
+    deviation and initial seed of pseudo-random numbers which are\r
+    added to the static evaluation function. Experiments suggested\r
+    that an appropriate value for the standard deviation is 15. Note\r
+    that all clients should use different seeds. The following three\r
+    arguments are network address, port number, user ID,\r
+    respectively. You can specify factor as a voting weight. Also\r
+    stable_depth is useful to detect opening positions. Here, when\r
+    Bonanza reaches the specified depth, then this is reported to the\r
+    server to reduce thinking time. This command becomes effective\r
+    when MNJ_LAN macro is defined in the Makefile.\r
+\r
+- move ['str']\r
+    Bonanza makes a move of 'str'. If the argument is omitted, Bonanza\r
+    thinks of its next move by itself.\r
+\r
+- mpv num 'nroot'\r
+- mpv width 'threshold'\r
+    These commands control the number of root moves, 'nroot', to\r
+    constitute principal variations. The default number is 1. A root\r
+    move that yields a smaller value than the best value by 'threshold'\r
+    is neglected. The default threshold is about 200. These commands\r
+    become effective when MPV macro is defined in the Makefile.\r
+\r
+- new ['str']\r
+    This command initializes the shogi board. The argument 'str'\r
+    controls an initial configuration of the board.  If you want to\r
+    play a no-handicapped game, set 'str' to "PI" and this is the\r
+    default value. In a handicapped game, specify squares and pieces\r
+    to drop, e.g. "new PI82HI22KA" or "new PI19KY".\r
+\r
+- peek on\r
+- peek off\r
+    The command "peek on (off)" enables (disables) peeks at a buffer\r
+    of the standard input file while Bonanza is thinking. The default\r
+    is on. This command is useful when you want to process a set of\r
+    commands as "> ./bonanza.exe < infile".\r
+\r
+- ping\r
+    Prompt Bonanza to print "pong".\r
+\r
+- ponder on\r
+- ponder off\r
+    The command "ponder on (off)" enables (disables) thinks on the\r
+    opponent's time. The default is on.\r
+\r
+- problem ['num']\r
+    This command is used to solve problems in "./problem.csa". Here\r
+    is an example of the problem file.\r
+\r
+    -----------------------------\r
+    $ANSWER:+0024FU\r
+    P1-KY-KE-OU-KI *  *  *  * -KY\r
+    P2 *  *  *  *  * -KI *  *  * \r
+    P3 *  * -FU-GI-FU * -KE * -KA\r
+    P4-FU *  * -FU-GI-FU-HI * -FU\r
+    P5 *  *  *  *  *  *  * -FU+KY\r
+    P6+FU+KA+FU+FU+GI+FU+KI *  * \r
+    P7 * +FU *  * +FU *  *  *  * \r
+    P8 * +OU+KI+GI *  * +HI *  * \r
+    P9+KY+KE *  *  *  *  * +KE * \r
+    P+00FU00FU\r
+    P-00FU00FU00FU\r
+    +\r
+    /\r
+    $ANSWER:+0087KY:+0088KY\r
+    P1-OU-KE *  *  *  *  * +GI * \r
+    P2-KY-KI *  *  *  *  *  *  * \r
+    P3-FU-HI * -KI *  * -GI *  * \r
+    P4 *  * -KE *  *  *  *  * -FU\r
+    P5 * +GI * -FU-FU-FU-FU-FU * \r
+    P6+FU+HI-FU *  *  *  *  *  * \r
+    P7 *  *  * +FU *  *  *  * +FU\r
+    P8 *  * +OU+KI+KI *  *  *  * \r
+    P9+KY+KE *  *  *  *  * +KE+KY\r
+    P+00KA00GI00KY00FU00FU\r
+    P-00KA00FU00FU00FU00FU00FU\r
+    +\r
+    -----------------------------\r
+\r
+    The argument 'num' specifies the number of problems to solve.\r
+\r
+- quit\r
+    The quit command and EOF character will exit Bonanza.\r
+\r
+- read 'filename' [(t|nil) ['num']]\r
+    This command is used to read a CSA record 'filename' up to 'num'\r
+    moves. Set the second argument to "nil" when you want to ignore\r
+    time information in the record. The default value is "t". Bonanza\r
+    reads all move sequence if the last argument is neglected. If\r
+    'filename' is ".", the command reads an ongoing game from the\r
+    initial position.\r
+\r
+- resign\r
+    Use this command when you resign a game.\r
+\r
+- resign 'num'\r
+    This command specifies the threshold to resign. 'num' is a value\r
+    of the threshold. The default is around 1000.\r
+\r
+- stress on\r
+- stress off\r
+    When the command "stress on" is used, last-move shown in shogi\r
+    board is stressed. The default is on.\r
+\r
+- time remain 'num1' 'num2'\r
+    This command tells Bonanza the remaining time. 'num1' ('num2') is\r
+    the remaining time of black (white) in seconds.\r
+\r
+- time response 'num'\r
+    This command specifies a margin to control time. The time margin\r
+    saves Bonanza from time up due to TCP/IP communication to a server\r
+    program, sudden disc access, or imperfection of time control of\r
+    Bonanza. 'num' is the time margin in milli-second. The default\r
+    value is 200.\r
+\r
+- tlp 'num'\r
+    This command controls the number of threads to be created when\r
+    Bonana considers a move to make. The command becomes effective\r
+    when TLP macro is defined in the Makefile. 'num' is the number of\r
+    threads. The default value is 1.\r
+\r
+- #\r
+    A line beginning with # causes all characters on that line\r
+    to be ignored.\r
+\r
+- [move command]\r
+    A move command consists of four digits followed by two\r
+    capital alphabets, e.g. 7776FU. The first two digits\r
+    are a starting square and the last two are a target square. The\r
+    starting square is "OO" if the  move is a dorp, e.g. 0087FU. The\r
+    following two alphabets specify a piece type as the following,\r
+\r
+      FU - pawn             (Fuhyo)       TO - promoted pawn    (Tokin)\r
+      KY - lance            (Kyousha)     NY - promoted lance   (Narikyo)\r
+      KE - knight           (Keima)       NK - promoted knight  (Narikei)\r
+      GI - silver general   (Ginsho)      NG - promoted silver  (Narigin)\r
+      KI - gold general     (Kinsyo)\r
+      KA - Bishop           (Kakugyo)     UM - Dragon horse     (Ryuma)\r
+      HI - Rook             (Hisha)       RY - Dragon king      (Ryuo)\r
+      OU - King             (Osho)\r
+\r
+    Here, words in parentheses are romanization of Japanese words.\r
diff --git a/root.c b/root.c
index e778431..d83b417 100644 (file)
--- a/root.c
+++ b/root.c
@@ -2,25 +2,19 @@
 #include <limits.h>
 #include "shogi.h"
 
-static int read_rest_list( tree_t * restrict ptree,
-                          unsigned int * restrict pmove_list );
-
-static int is_move_rest( unsigned int move,
-                        const unsigned int * restrict pmove_restraint );
+#if defined(USI) || defined(MNJ_LAN)
+static int is_move_ignore( unsigned int move );
+#endif
 
 int
-make_root_move_list( tree_t * restrict ptree, int flag )
+make_root_move_list( tree_t * restrict ptree )
 {
   unsigned int * restrict pmove;
-  unsigned int arestraint_list[ MAX_LEGAL_MOVES ];
   int asort[ MAX_LEGAL_MOVES ];
-  unsigned int move, move_best;
+  unsigned int move;
   int i, j, k, h, value, num_root_move, iret, value_pre_pv;
   int value_best;
 
-  if ( flag & flag_refer_rest ) { read_rest_list( ptree, arestraint_list ); }
-  else                          { arestraint_list[0] = 0; }
-
   pmove = ptree->move_last[0];
   ptree->move_last[1] = GenCaptures( root_turn, pmove );
   ptree->move_last[1] = GenNoCaptures( root_turn, ptree->move_last[1] );
@@ -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 (file)
--- a/sckt.c
+++ b/sckt.c
 #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 */
index d7ca199..3ef962c 100644 (file)
--- a/search.c
+++ b/search.c
@@ -1,16 +1,16 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 #include <assert.h>
 #include "shogi.h"
 
-static void hist_add( tree_t * restrict ptree, int ply );
-static void hist_good( tree_t * restrict ptree, unsigned int move, int ply,
-                      int depth, int turn );
-static int detect_signals( tree_t * restrict ptree );
-static int detect_rep( tree_t * restrict ptree, int ply, int turn );
-static int rep_type( const tree_t * restrict ptree, int n, int i, int ply,
-                    int turn );
+static void CONV hist_add( tree_t * restrict ptree, int ply );
+static void CONV hist_good( tree_t * restrict ptree, unsigned int move,
+                           int ply, int depth, int turn );
+static int CONV detect_rep( tree_t * restrict ptree, int ply, int turn );
+static int CONV rep_type( const tree_t * restrict ptree, int n, int i, int ply,
+                         int turn );
 
 /* #define DBG_SEARCH */
 #if defined(DBG_SEARCH)
@@ -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 )
 {
index a3aba06..3afd2aa 100644 (file)
--- a/searchr.c
+++ b/searchr.c
 #include <limits.h>
 #include "shogi.h"
 
-static int find_root_move( unsigned int move );
-static int save_result( tree_t * restrict ptree, int value, int beta,
-                       int turn );
+static int CONV save_result( tree_t * restrict ptree, int value, int beta,
+                            int turn );
 
 #if defined(MPV)
-static int mpv_set_bound( int alpha );
-static int mpv_find_min( int *pnum );
-static int mpv_add_result( tree_t * restrict ptree, int value );
-static void mpv_sub_result( unsigned int move );
-static void mpv_out( tree_t * restrict ptree, int turn, unsigned int time );
+static int CONV mpv_set_bound( int alpha );
+static int CONV mpv_find_min( int *pnum );
+static int CONV mpv_add_result( tree_t * restrict ptree, int value );
+static void CONV mpv_sub_result( unsigned int move );
+static void CONV mpv_out( tree_t * restrict ptree, int turn,
+                         unsigned int time );
 #endif
 
 #if defined(NO_STDOUT) && defined(NO_LOGGING)
 #  define NextRootMove(a,b) next_root_move(a)
-static int next_root_move( tree_t * restrict ptree );
+static int CONV next_root_move( tree_t * restrict ptree );
 #else
 #  define NextRootMove(a,b) next_root_move(a,b)
-static int next_root_move( tree_t * restrict ptree, int turn );
+static int CONV next_root_move( tree_t * restrict ptree, int turn );
 #endif
 
-int
+static int CONV
+search_wrapper( tree_t * restrict ptree, int alpha, int beta, int turn,
+               int depth, int ply, unsigned int state_node )
+{
+  int value;
+
+#if defined(DFPN_CLIENT)
+  /* try beta cut using results from DFPN server */
+  if ( root_move_list[root_index].dfpn_cresult == dfpn_client_win )
+    {
+      if ( ! root_index ) { Out( "- best move is proofed, skip.\n" ); }
+      ptree->pv[1].a[1]   = MOVE_LAST;
+      ptree->pv[1].length = 1;
+      ptree->pv[1].depth  = 0;
+      ptree->pv[1].type   = no_rep;
+      MOVE_CURR           = MOVE_NA;
+      return score_matelong;
+    }
+#endif
+  
+  value = search( ptree, alpha, beta, turn, depth, ply, state_node );
+
+#if defined(DFPN_CLIENT)
+  /* catch a signal, i.e., the first move has to be ignored */
+  if ( game_status & flag_skip_root_move )
+    {
+      if ( root_index )
+       {
+         Out( "- %s is proofed while searching.\n", str_CSA_move(MOVE_LAST) );
+       }
+      else {
+       Out( "- %s (best move) is proofed while searching.\n",
+            str_CSA_move(MOVE_LAST) );
+      }
+
+      game_status &= ~flag_skip_root_move;
+      root_abort          = 0;
+
+      ptree->pv[1].a[1]   = MOVE_LAST;
+      ptree->pv[1].length = 1;
+      ptree->pv[1].depth  = 0;
+      ptree->pv[1].type   = no_rep;
+      MOVE_CURR           = MOVE_NA;
+      return score_matelong;
+    }
+#endif
+
+  return value;
+}
+
+
+int CONV
 searchr( tree_t * restrict ptree, int alpha, int beta, int turn, int depth )
 {
   uint64_t root_nodes_start;
-  int value, first_move_expanded, i;
+  int value, first_move;
   int new_depth, extension, ply, state_node_new;
 #if defined(MPV)
   int bound = INT_MIN;
 #endif
+#if defined(USI)
+  char str_usi[6];
+#endif
 
-  first_move_expanded = 1;
+  first_move          = 1;
   ply                 = 1;
   ptree->move_last[1] = ptree->move_last[0];
 
   while( NextRootMove( ptree, turn ) )
     {
       root_nodes_start = ptree->node_searched;
+#if defined(USI)
+      if ( usi_mode != usi_off )
+       {
+         csa2usi( ptree, str_CSA_move(MOVE_CURR), str_usi );
+       }
+#endif
+
       MakeMove( turn, MOVE_CURR, 1 );
 
       assert( ! InCheck( turn ) );
 
       state_node_new = ( node_do_mate | node_do_null | node_do_futile
-                        | node_do_recap );
+                        | node_do_recap | node_do_recursion
+                        | node_do_hashcut );
       if ( InCheck(Flip(turn)) )
        {
          ptree->check_extension_done++;
@@ -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 (file)
--- a/shogi.h
+++ b/shogi.h
@@ -2,12 +2,13 @@
 #define SHOGI_H
 
 #include <stdio.h>
+#include "bitop.h"
 #include "param.h"
 
 #if defined(_WIN32)
 
 #  include <Winsock2.h>
-#  define CONV_CDECL         __cdecl
+#  define CONV              __fastcall
 #  define SCKT_NULL         INVALID_SOCKET
 typedef SOCKET sckt_t;
 
@@ -15,14 +16,14 @@ typedef SOCKET sckt_t;
 
 #  include <pthread.h>
 #  include <sys/times.h>
-#  define CONV_CDECL
+#  define CONV
 #  define SCKT_NULL         -1
 #  define SOCKET_ERROR      -1
 typedef int sckt_t;
 
 #endif
 
-/* Microsoft C/C++ */
+/* Microsoft C/C++ on x86 and x86-64 */
 #if defined(_MSC_VER)
 
 #  define _CRT_DISABLE_PERFCRIT_LOCKS
@@ -53,17 +54,18 @@ typedef volatile int lock_t;
 #else
 
 #  include <inttypes.h>
+typedef struct { unsigned int p[3]; } bitboard_t;
 typedef pthread_mutex_t lock_t;
 extern unsigned char aifirst_one[512];
 extern unsigned char ailast_one[512];
 
 #endif
 
+#define BK_TINY
 /*
+  #define BK_SMALL
   #define BK_ULTRA_NARROW
   #define BK_COM
-  #define BK_SMALL
-  #define NO_NULL_PRUNE
   #define NO_STDOUT
   #define DBG_EASY
 */
@@ -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 (file)
--- a/swap.c
+++ b/swap.c
@@ -1,14 +1,14 @@
 #include <stdlib.h>
 #include <limits.h>
+#include <assert.h>
 #include "shogi.h"
 
-int
+int CONV
 swap( const tree_t * restrict ptree, unsigned int move, int root_alpha,
       int root_beta, int turn )
 {
   bitboard_t bb, bb_temp, bb_attack;
-  unsigned int uattack;
-  int attacked_piece, from, to, nc, ir0;
+  int attacked_piece, from, to, nc;
   int piece_cap, piece, value, xvalue, alpha, beta, is_promo;
 
   from = (int)I2From( move );
@@ -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; }
 }
index c88461a..f170edd 100644 (file)
--- a/thread.c
+++ b/thread.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
+#include <stdarg.h>
 #if defined(_WIN32)
 #  include <process.h>
 #else
+#  include <arpa/inet.h>
+#  include <sys/types.h>
+#  include <unistd.h>
 #  include <sched.h>
 #endif
 #include "shogi.h"
 
+
+#if defined(TLP) || defined(DFPN_CLIENT)
+int CONV
+lock_init( lock_t *plock )
+{
+#  if defined(_MSC_VER)
+  *plock = 0;
+#  elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+  *plock = 0;
+#  else
+  if ( pthread_mutex_init( plock, 0 ) )
+    {
+      str_error = "pthread_mutex_init() failed.";
+      return -1;
+    }
+#  endif
+  return 1;
+}
+
+
+int CONV
+lock_free( lock_t *plock )
+{
+#  if defined(_MSC_VER)
+  *plock = 0;
+#  elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+  *plock = 0;
+#  else
+  if ( pthread_mutex_destroy( plock ) )
+    {
+      str_error = "pthread_mutex_destroy() failed.";
+      return -1;
+    }
+#  endif
+  return 1;
+}
+
+
+void CONV
+unlock( lock_t *plock )
+{
+#  if defined(_MSC_VER)
+  *plock = 0;
+#  elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+  *plock = 0;
+#  else
+  pthread_mutex_unlock( plock );
+#  endif
+}
+
+
+void CONV
+lock( lock_t *plock )
+{
+#  if defined(_MSC_VER)
+  while ( _InterlockedExchange( (void *)plock, 1 ) )
+    {
+      while ( *plock ) { tlp_yield();}
+    }
+#  elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+  int itemp;
+
+  for ( ;; )
+    {
+      asm ( "1:   movl     $1,  %1 \n\t"
+           "     xchgl   (%0), %1 \n\t"
+           : "=g" (plock), "=r" (itemp) : "0" (plock) );
+      if ( ! itemp ) { return; }
+      while ( *plock ) { tlp_yield();}
+    }
+#  else
+  pthread_mutex_lock( plock );
+#  endif
+}
+
+
+void
+tlp_yield( void )
+{
+#if defined(_WIN32)
+  Sleep( 0 );
+#else
+  sched_yield();
+#endif
+}
+#endif /* TLP || DFPN_CLIENT */
+
+
+#if defined(DFPN_CLIENT)
+
+static int CONV proce_line( char *line_buf );
+#  if defined(_WIN32)
+static unsigned int __stdcall dfpn_client_receiver( void *arg );
+#  else
+static void *dfpn_client_receiver( void *arg );
+#  endif
+
+void CONV
+dfpn_client_start( const tree_t * restrict ptree )
+{
+  if ( root_turn != min_posi_no_handicap.turn_to_move
+       || HAND_B != min_posi_no_handicap.hand_black
+       || HAND_W != min_posi_no_handicap.hand_white
+       || memcmp( BOARD, min_posi_no_handicap.asquare, nsquare ) )
+    {
+      sckt_shutdown( dfpn_client_sckt );
+      dfpn_client_sckt = SCKT_NULL;
+      return;
+    }
+
+  if ( dfpn_client_sckt        != SCKT_NULL ) { return; }
+  if ( dfpn_client_str_addr[0] == '\0' )      { return; }
+
+  dfpn_client_sckt = sckt_connect( dfpn_client_str_addr, dfpn_client_port );
+  if ( dfpn_client_sckt == SCKT_NULL )
+    {
+      out_warning( "Connection to DFPN server failed." );
+      return;
+    }
+  else {
+    Out( "New connection to DFPN server: %s %d\n",
+        dfpn_client_str_addr, dfpn_client_port );
+  }
+
+#  if defined(_WIN32)
+  if ( ! _beginthreadex( 0, 0, &dfpn_client_receiver, NULL, 0, 0 ) )
+    {
+      sckt_shutdown( dfpn_client_sckt );
+      dfpn_client_sckt = SCKT_NULL;
+      out_warning( "_beginthreadex() failed." );
+    }
+#  else
+  {
+    pthread_t pt;
+    if ( pthread_create( &pt, &pthread_attr, &dfpn_client_receiver, NULL ) )
+      {
+       sckt_shutdown( dfpn_client_sckt );
+       dfpn_client_sckt = SCKT_NULL;
+       out_warning( "_beginthreadex() failed." );
+      }
+  }
+#  endif
+
+  dfpn_client_out( "Client: anonymous\n" );
+}
+
+
+#  if defined(_MSC_VER)
+#    pragma warning(disable:4100)
+#  elif defined(__ICC)
+#    pragma warning(disable:869)
+#  endif
+
+#  if defined(_MSC_VER)
+static unsigned int __stdcall dfpn_client_receiver( void *arg )
+#  else
+static void *dfpn_client_receiver( void *arg )
+#endif
+{
+#define SIZE_RECV_BUF ( 1024 * 16 )
+#define SIZE_LINE_BUF 1024
+  char recv_buf[ SIZE_RECV_BUF ];
+  char line_buf[ SIZE_LINE_BUF ];
+  char *str_end, *str_line_end;
+  size_t size;
+  int len_recv_buf;
+  struct timeval tv;
+  fd_set readfds;
+  int iret;
+
+  recv_buf[0] = '\0';
+
+  /* recv loop */
+  for ( ;; ) {
+
+    /* select loop */
+    for ( ;; ) {
+      tv.tv_sec  = SEC_KEEP_ALIVE;
+      tv.tv_usec = 0;
+      FD_ZERO( &readfds );
+#  if defined(_MSC_VER)
+#    pragma warning(disable:4127)
+#  endif
+      FD_SET( dfpn_client_sckt, &readfds );
+#  if defined(_MSC_VER)
+#    pragma warning(default:4127)
+#  endif
+      
+      iret = select( (int)dfpn_client_sckt+1, &readfds, NULL, NULL, &tv );
+      if ( iret == SOCKET_ERROR )
+       {
+         out_warning( "%s", str_error );
+         goto dfpn_client_receiver_shutdown;
+       }
+
+      /* message arrived */
+      if ( iret ) { break; }
+
+      /* timeout and keepalive */
+      lock( &dfpn_client_lock);
+      iret = dfpn_client_out( "ping\n" );
+      unlock( &dfpn_client_lock);
+      if ( iret < 0 ) { return 0; }
+    }
+
+    /* read messages */
+    len_recv_buf = (int)strlen( recv_buf );
+    str_end      = recv_buf + len_recv_buf;
+
+    iret = recv( dfpn_client_sckt, str_end, SIZE_RECV_BUF-1-len_recv_buf, 0 );
+    if ( iret == SOCKET_ERROR )
+      {
+       str_error = str_WSAError( "recv() failed:" );
+       out_warning( "%s", str_error );
+       goto dfpn_client_receiver_shutdown;
+      }
+    if ( ! iret ) { goto dfpn_client_receiver_shutdown; }
+    recv_buf[ len_recv_buf + iret ] = '\0';
+
+    /* take each line */
+    lock( &dfpn_client_lock );
+    for ( ;; ) {
+
+      str_line_end = strchr( recv_buf, '\n' );
+      if ( str_line_end == NULL )
+       {
+         if ( iret + len_recv_buf + 1 >= SIZE_RECV_BUF )
+           {
+             unlock( &dfpn_client_lock );
+             out_warning( "%s", str_ovrflw_line );
+             goto dfpn_client_receiver_shutdown;
+           }
+         break;
+       }
+
+      size = str_line_end - recv_buf;
+      if ( size + 1 >= SIZE_LINE_BUF )
+       {
+         unlock( &dfpn_client_lock );
+         out_warning( "%s", str_ovrflw_line );
+         goto dfpn_client_receiver_shutdown;
+       }
+      
+      memcpy( line_buf, recv_buf, size );
+      memmove( recv_buf, str_line_end+1, strlen(str_line_end+1) + 1 );
+
+      line_buf[size] = '\0';
+
+      if ( proce_line( line_buf ) < 0 )
+       {
+         unlock( &dfpn_client_lock );
+         out_warning( "invalid messages from DFPN server" );
+         goto dfpn_client_receiver_shutdown;
+       }
+    }
+    unlock( &dfpn_client_lock );
+  }
+
+ dfpn_client_receiver_shutdown:
+  sckt_shutdown( dfpn_client_sckt );
+  dfpn_client_sckt = SCKT_NULL;
+  out_warning( "A connection to DFPN server is down." );
+
+  return 0;
+}
+#  if defined(_MSC_VER)
+#    pragma warning(default:4100)
+#  elif defined(__ICC)
+#    pragma warning(default:869)
+#endif
+
+
+static int CONV proce_line( char *line_buf )
+{
+  const char *token;
+  volatile dfpn_client_cresult_t *pcresult;
+  char *last;
+
+  token = strtok_r( line_buf, str_delimiters, &last );
+  if ( token == NULL ) { return -1; }
+
+  /* check signature */
+  if ( strcmp( token, (const char *)dfpn_client_signature ) ) { return 1; }
+
+  token = strtok_r( NULL, str_delimiters, &last );
+  if ( token == NULL ) { return -1; }
+
+  /* root node */
+  if ( ! strcmp( token, "WIN" ) )
+    {
+      token = strtok_r( NULL, str_delimiters, &last );
+      if ( token == NULL || ! is_move( token ) ) { return -1; }
+      dfpn_client_rresult   = dfpn_client_win;
+      dfpn_client_flag_read = 1;
+      memcpy( (char *)dfpn_client_str_move, token, 7 );
+      return 1;
+    }
+
+  if ( ! strcmp( token, "LOSE" ) )
+    {
+      dfpn_client_rresult   = dfpn_client_lose;
+      dfpn_client_flag_read = 1;
+      return 1;
+    }
+
+  if ( ! strcmp( token, "UNSOLVED" ) )
+    {
+      dfpn_client_rresult   = dfpn_client_misc;
+      dfpn_client_flag_read = 1;
+      return 1;
+    }
+
+  /* child node */
+  if ( ! is_move( token ) ) { return -1; }
+  if ( MAX_LEGAL_MOVES <= dfpn_client_num_cresult ) { return -1; }
+  pcresult = &dfpn_client_cresult[dfpn_client_num_cresult];
+  memcpy( (char *)pcresult->str_move, token, 7 );
+
+  token = strtok_r( NULL, str_delimiters, &last );
+  if ( token == NULL ) { return -1; }
+  
+  if ( ! strcmp( token, "WIN" ) )
+    {
+      pcresult->result         = dfpn_client_win;
+      dfpn_client_flag_read    = 1;
+      dfpn_client_num_cresult += 1;
+      return 1;
+    }
+
+  if ( ! strcmp( token, "LOSE" ) )
+    {
+      pcresult->result         = dfpn_client_lose;
+      dfpn_client_flag_read    = 1;
+      dfpn_client_num_cresult += 1;
+      return 1;
+    }
+
+  if ( ! strcmp( token, "UNSOLVED" ) )
+    {
+      pcresult->result         = dfpn_client_misc;
+      dfpn_client_flag_read    = 1;
+      dfpn_client_num_cresult += 1;
+      return 1;
+    }
+
+  return -1;
+}
+
+#endif /* DFPN_CLINET */
+
+
 #if defined(TLP)
 
 #  if defined(_WIN32)
@@ -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 (file)
--- 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)
index 91e363d..164a626 100644 (file)
--- a/unmake.c
+++ b/unmake.c
                                               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];
index 75b1b9a..198aa90 100644 (file)
--- 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 (file)
--- 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;