#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <limits.h>
#include "shogi.h"
-static int ehash_probe( uint64_t current_key, unsigned int hand_b,
- int *pscore );
-static void ehash_store( uint64_t key, unsigned int hand_b, int score );
-static int make_list( const tree_t * restrict ptree, int * restrict pscore,
- int list0[52], int list1[52] );
+#define PcPcOnSqAny(k,i,j) ( i >= j ? PcPcOnSq(k,i,j) : PcPcOnSq(k,j,i) )
+
+static int CONV doacapt( const tree_t * restrict ptree, int pc, int turn,
+ int hand_index, const int list0[52],
+ const int list1[52], int nlist );
+static int CONV doapc( const tree_t * restrict ptree, int pc, int sq,
+ const int list0[52], const int list1[52], int nlist );
+static int CONV ehash_probe( uint64_t current_key, unsigned int hand_b,
+ int * restrict pscore );
+static void CONV ehash_store( uint64_t key, unsigned int hand_b, int score );
+static int CONV calc_difference( const tree_t * restrict ptree, int ply,
+ int turn, int list0[52], int list1[52],
+ int * restrict pscore );
+static int CONV make_list( const tree_t * restrict ptree,
+ int * restrict pscore,
+ int list0[52], int list1[52] );
+
+#if defined(INANIWA_SHIFT)
+static int inaniwa_score( const tree_t * restrict ptree );
+#endif
-int
+int CONV
eval_material( const tree_t * restrict ptree )
{
int material, itemp;
}
-int
+int CONV
evaluate( tree_t * restrict ptree, int ply, int turn )
{
int list0[52], list1[52];
int nlist, score, sq_bk, sq_wk, k0, k1, l0, l1, i, j, sum;
+ assert( 0 < ply );
ptree->neval_called++;
- if ( ptree->stand_pat[ply] != score_bound )
+ if ( ptree->save_eval[ply] != INT_MAX )
{
- return (int)ptree->stand_pat[ply];
+ return (int)ptree->save_eval[ply] / FV_SCALE;
}
if ( ehash_probe( HASH_KEY, HAND_B, &score ) )
{
score = turn ? -score : score;
- ptree->stand_pat[ply] = (short)score;
+ ptree->save_eval[ply] = score;
- return score;
+ return score / FV_SCALE;
}
+ list0[ 0] = f_hand_pawn + I2HandPawn(HAND_B);
+ list0[ 1] = e_hand_pawn + I2HandPawn(HAND_W);
+ list0[ 2] = f_hand_lance + I2HandLance(HAND_B);
+ list0[ 3] = e_hand_lance + I2HandLance(HAND_W);
+ list0[ 4] = f_hand_knight + I2HandKnight(HAND_B);
+ list0[ 5] = e_hand_knight + I2HandKnight(HAND_W);
+ list0[ 6] = f_hand_silver + I2HandSilver(HAND_B);
+ list0[ 7] = e_hand_silver + I2HandSilver(HAND_W);
+ list0[ 8] = f_hand_gold + I2HandGold(HAND_B);
+ list0[ 9] = e_hand_gold + I2HandGold(HAND_W);
+ list0[10] = f_hand_bishop + I2HandBishop(HAND_B);
+ list0[11] = e_hand_bishop + I2HandBishop(HAND_W);
+ list0[12] = f_hand_rook + I2HandRook(HAND_B);
+ list0[13] = e_hand_rook + I2HandRook(HAND_W);
+
+ list1[ 0] = f_hand_pawn + I2HandPawn(HAND_W);
+ list1[ 1] = e_hand_pawn + I2HandPawn(HAND_B);
+ list1[ 2] = f_hand_lance + I2HandLance(HAND_W);
+ list1[ 3] = e_hand_lance + I2HandLance(HAND_B);
+ list1[ 4] = f_hand_knight + I2HandKnight(HAND_W);
+ list1[ 5] = e_hand_knight + I2HandKnight(HAND_B);
+ list1[ 6] = f_hand_silver + I2HandSilver(HAND_W);
+ list1[ 7] = e_hand_silver + I2HandSilver(HAND_B);
+ list1[ 8] = f_hand_gold + I2HandGold(HAND_W);
+ list1[ 9] = e_hand_gold + I2HandGold(HAND_B);
+ list1[10] = f_hand_bishop + I2HandBishop(HAND_W);
+ list1[11] = e_hand_bishop + I2HandBishop(HAND_B);
+ list1[12] = f_hand_rook + I2HandRook(HAND_W);
+ list1[13] = e_hand_rook + I2HandRook(HAND_B);
+
+ if ( calc_difference( ptree, ply, turn, list0, list1, &score ) )
+ {
+ ehash_store( HASH_KEY, HAND_B, score );
+ score = turn ? -score : score;
+ ptree->save_eval[ply] = score;
+
+ return score / FV_SCALE;
+ }
- score = 0;
nlist = make_list( ptree, &score, list0, list1 );
sq_bk = SQ_BKING;
sq_wk = Inv( SQ_WKING );
}
score += sum;
- score /= FV_SCALE;
+ score += MATERIAL * FV_SCALE;
+#if defined(INANIWA_SHIFT)
+ score += inaniwa_score( ptree );
+#endif
- score += MATERIAL;
+ ehash_store( HASH_KEY, HAND_B, score );
-#if defined(MNJ_LAN)
- if ( sckt_mnj != SCKT_NULL ) { score += mnj_tbl[ HASH_KEY & MNJ_MASK ]; }
-#endif
+ score = turn ? -score : score;
+
+ ptree->save_eval[ply] = score;
+
+ score /= FV_SCALE;
#if ! defined(MINIMUM)
if ( abs(score) > score_max_eval )
}
#endif
- ehash_store( HASH_KEY, HAND_B, score );
-
- score = turn ? -score : score;
- ptree->stand_pat[ply] = (short)score;
-
return score;
}
-void ehash_clear( void )
-{
- memset( ehash_tbl, 0, sizeof(ehash_tbl) );
-}
+void CONV ehash_clear( void ) { memset( ehash_tbl, 0, sizeof(ehash_tbl) ); }
-static int ehash_probe( uint64_t current_key, unsigned int hand_b,
- int *pscore )
+static int CONV ehash_probe( uint64_t current_key, unsigned int hand_b,
+ int * restrict pscore )
{
uint64_t hash_word, hash_key;
hash_word ^= hash_word << 32;
#endif
- current_key ^= (uint64_t)hand_b << 16;
- current_key &= ~(uint64_t)0xffffU;
+ current_key ^= (uint64_t)hand_b << 21;
+ current_key &= ~(uint64_t)0x1fffffU;
hash_key = hash_word;
- hash_key &= ~(uint64_t)0xffffU;
+ hash_key &= ~(uint64_t)0x1fffffU;
if ( hash_key != current_key ) { return 0; }
- *pscore = (int)( (unsigned int)hash_word & 0xffffU ) - 32768;
+ *pscore = (int)( (unsigned int)hash_word & 0x1fffffU ) - 0x100000;
return 1;
}
-static void ehash_store( uint64_t key, unsigned int hand_b, int score )
+static void CONV ehash_store( uint64_t key, unsigned int hand_b, int score )
{
uint64_t hash_word;
hash_word = key;
- hash_word ^= (uint64_t)hand_b << 16;
- hash_word &= ~(uint64_t)0xffffU;
- hash_word |= (uint64_t)( score + 32768 );
+ hash_word ^= (uint64_t)hand_b << 21;
+ hash_word &= ~(uint64_t)0x1fffffU;
+ hash_word |= (uint64_t)( score + 0x100000 );
#if ! defined(__x86_64__)
hash_word ^= hash_word << 32;
}
-static int
+static int CONV
+calc_difference( const tree_t * restrict ptree, int ply, int turn,
+ int list0[52], int list1[52], int * restrict pscore )
+{
+ bitboard_t bb;
+ int nlist, diff, from, to, sq, pc;
+
+#if defined(INANIWA_SHIFT)
+ if ( inaniwa_flag ) { return 0; }
+#endif
+
+ if ( ptree->save_eval[ply-1] == INT_MAX ) { return 0; }
+ if ( I2PieceMove(MOVE_LAST) == king ) { return 0; }
+
+ assert( MOVE_LAST != MOVE_PASS );
+
+ nlist = 14;
+ diff = 0;
+ from = I2From(MOVE_LAST);
+ to = I2To(MOVE_LAST);
+
+ BBOr( bb, BB_BOCCUPY, BB_WOCCUPY );
+ Xor( SQ_BKING, bb );
+ Xor( SQ_WKING, bb );
+ Xor( to, bb );
+
+ while ( BBTest(bb) )
+ {
+ sq = FirstOne(bb);
+ Xor( sq, bb );
+
+ pc = BOARD[sq];
+ list0[nlist ] = aikpp[15+pc] + sq;
+ list1[nlist++] = aikpp[15-pc] + Inv(sq);
+ }
+
+ pc = BOARD[to];
+ list0[nlist ] = aikpp[15+pc] + to;
+ list1[nlist++] = aikpp[15-pc] + Inv(to);
+
+ diff = doapc( ptree, pc, to, list0, list1, nlist );
+ nlist -= 1;
+
+ if ( from >= nsquare )
+ {
+ unsigned int hand;
+ int hand_index;
+
+ pc = From2Drop(from);
+ hand = turn ? HAND_B : HAND_W;
+
+ switch ( pc )
+ {
+ case pawn: hand_index = I2HandPawn(hand); break;
+ case lance: hand_index = I2HandLance(hand); break;
+ case knight: hand_index = I2HandKnight(hand); break;
+ case silver: hand_index = I2HandSilver(hand); break;
+ case gold: hand_index = I2HandGold(hand); break;
+ case bishop: hand_index = I2HandBishop(hand); break;
+ default: hand_index = I2HandRook(hand); break;
+ }
+
+ diff += doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+
+ list0[ 2*(pc-1) + 1 - turn ] += 1;
+ list1[ 2*(pc-1) + turn ] += 1;
+ hand_index += 1;
+
+ diff -= doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+ }
+ else {
+ int pc_cap = UToCap(MOVE_LAST);
+ if ( pc_cap )
+ {
+ unsigned int hand;
+ int hand_index;
+
+ pc = pc_cap & ~promote;
+ hand = turn ? HAND_B : HAND_W;
+ pc_cap = turn ? -pc_cap : pc_cap;
+ diff += turn ? p_value_ex[15+pc_cap] * FV_SCALE
+ : -p_value_ex[15+pc_cap] * FV_SCALE;
+
+ switch ( pc )
+ {
+ case pawn: hand_index = I2HandPawn(hand); break;
+ case lance: hand_index = I2HandLance(hand); break;
+ case knight: hand_index = I2HandKnight(hand); break;
+ case silver: hand_index = I2HandSilver(hand); break;
+ case gold: hand_index = I2HandGold(hand); break;
+ case bishop: hand_index = I2HandBishop(hand); break;
+ default: hand_index = I2HandRook(hand); break;
+ }
+
+ diff += doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+
+ list0[ 2*(pc-1) + 1 - turn ] -= 1;
+ list1[ 2*(pc-1) + turn ] -= 1;
+ hand_index -= 1;
+
+ diff -= doacapt( ptree, pc, turn, hand_index, list0, list1, nlist );
+
+ list0[nlist ] = aikpp[15+pc_cap] + to;
+ list1[nlist++] = aikpp[15-pc_cap] + Inv(to);
+
+ diff -= doapc( ptree, pc_cap, to, list0, list1, nlist );
+ }
+
+ pc = I2PieceMove(MOVE_LAST);
+ if ( I2IsPromote(MOVE_LAST) )
+ {
+ diff += ( turn ? p_value_pm[7+pc] : -p_value_pm[7+pc] ) * FV_SCALE;
+ }
+
+ pc = turn ? pc : -pc;
+
+ list0[nlist ] = aikpp[15+pc] + from;
+ list1[nlist++] = aikpp[15-pc] + Inv(from);
+
+ diff -= doapc( ptree, pc, from, list0, list1, nlist );
+
+ }
+
+ diff += turn ? ptree->save_eval[ply-1] : - ptree->save_eval[ply-1];
+
+ *pscore = diff;
+
+ return 1;
+}
+
+
+static int CONV
make_list( const tree_t * restrict ptree, int * restrict pscore,
int list0[52], int list1[52] )
{
sq_bk1 = Inv(SQ_WKING);
sq_wk1 = Inv(SQ_BKING);
- list0[ 0] = f_hand_pawn + I2HandPawn(HAND_B);
- list0[ 1] = e_hand_pawn + I2HandPawn(HAND_W);
- list0[ 2] = f_hand_lance + I2HandLance(HAND_B);
- list0[ 3] = e_hand_lance + I2HandLance(HAND_W);
- list0[ 4] = f_hand_knight + I2HandKnight(HAND_B);
- list0[ 5] = e_hand_knight + I2HandKnight(HAND_W);
- list0[ 6] = f_hand_silver + I2HandSilver(HAND_B);
- list0[ 7] = e_hand_silver + I2HandSilver(HAND_W);
- list0[ 8] = f_hand_gold + I2HandGold(HAND_B);
- list0[ 9] = e_hand_gold + I2HandGold(HAND_W);
- list0[10] = f_hand_bishop + I2HandBishop(HAND_B);
- list0[11] = e_hand_bishop + I2HandBishop(HAND_W);
- list0[12] = f_hand_rook + I2HandRook(HAND_B);
- list0[13] = e_hand_rook + I2HandRook(HAND_W);
-
- list1[ 0] = f_hand_pawn + I2HandPawn(HAND_W);
- list1[ 1] = e_hand_pawn + I2HandPawn(HAND_B);
- list1[ 2] = f_hand_lance + I2HandLance(HAND_W);
- list1[ 3] = e_hand_lance + I2HandLance(HAND_B);
- list1[ 4] = f_hand_knight + I2HandKnight(HAND_W);
- list1[ 5] = e_hand_knight + I2HandKnight(HAND_B);
- list1[ 6] = f_hand_silver + I2HandSilver(HAND_W);
- list1[ 7] = e_hand_silver + I2HandSilver(HAND_B);
- list1[ 8] = f_hand_gold + I2HandGold(HAND_W);
- list1[ 9] = e_hand_gold + I2HandGold(HAND_B);
- list1[10] = f_hand_bishop + I2HandBishop(HAND_W);
- list1[11] = e_hand_bishop + I2HandBishop(HAND_B);
- list1[12] = f_hand_rook + I2HandRook(HAND_W);
- list1[13] = e_hand_rook + I2HandRook(HAND_B);
-
score += kkp[sq_bk0][sq_wk0][ kkp_hand_pawn + I2HandPawn(HAND_B) ];
score += kkp[sq_bk0][sq_wk0][ kkp_hand_lance + I2HandLance(HAND_B) ];
score += kkp[sq_bk0][sq_wk0][ kkp_hand_knight + I2HandKnight(HAND_B) ];
n2 = 0;
bb = BB_BPAWN;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WPAWN;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BLANCE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WLANCE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BKNIGHT;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WKNIGHT;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BSILVER;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WSILVER;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BTGOLD;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WTGOLD;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BBISHOP;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WBISHOP;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WHORSE;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BROOK;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WROOK;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
n2 = 0;
bb = BB_BDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
}
bb = BB_WDRAGON;
- while ( BBToU(bb) ) {
+ while ( BBTest(bb) ) {
sq = FirstOne( bb );
Xor( sq, bb );
for ( i = 0; i < n2; i++ ) { list1[nlist-i-1] = list2[i]; }
assert( nlist <= 52 );
- *pscore += score;
+
+ *pscore = score;
return nlist;
}
+
+
+static int CONV doapc( const tree_t * restrict ptree, int pc, int sq,
+ const int list0[52], const int list1[52], int nlist )
+{
+ int i, sum;
+ int index_b = aikpp[15+pc] + sq;
+ int index_w = aikpp[15-pc] + Inv(sq);
+ int sq_bk = SQ_BKING;
+ int sq_wk = Inv(SQ_WKING);
+
+ sum = 0;
+ for( i = 0; i < 14; i++ )
+ {
+ sum += PcPcOnSq( sq_bk, index_b, list0[i] );
+ sum -= PcPcOnSq( sq_wk, index_w, list1[i] );
+ }
+
+ for( i = 14; i < nlist; i++ )
+ {
+ sum += PcPcOnSqAny( sq_bk, index_b, list0[i] );
+ sum -= PcPcOnSqAny( sq_wk, index_w, list1[i] );
+ }
+
+ if ( pc > 0 )
+ {
+ sq_bk = SQ_BKING;
+ sq_wk = SQ_WKING;
+ sum += kkp[sq_bk][sq_wk][ aikkp[pc] + sq ];
+ }
+ else {
+ sq_bk = Inv(SQ_WKING);
+ sq_wk = Inv(SQ_BKING);
+ sum -= kkp[sq_bk][sq_wk][ aikkp[-pc] + Inv(sq) ];
+ }
+
+ return sum;
+}
+
+
+static int CONV
+doacapt( const tree_t * restrict ptree, int pc, int turn, int hand_index,
+ const int list0[52], const int list1[52], int nlist )
+{
+ int i, sum, sq_bk, sq_wk, index_b, index_w;
+
+ index_b = 2*(pc-1) + 1 - turn;
+ index_w = 2*(pc-1) + turn;
+ sq_bk = SQ_BKING;
+ sq_wk = Inv(SQ_WKING);
+
+ sum = 0;
+ for( i = 14; i < nlist; i++ )
+ {
+ sum += PcPcOnSq( sq_bk, list0[i], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[i], list1[index_w] );
+ }
+
+ for( i = 0; i <= 2*(pc-1); i++ )
+ {
+ sum += PcPcOnSq( sq_bk, list0[index_b], list0[i] );
+ sum -= PcPcOnSq( sq_wk, list1[index_w], list1[i] );
+ }
+
+ for( i += 1; i < 14; i++ )
+ {
+ sum += PcPcOnSq( sq_bk, list0[i], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[i], list1[index_w] );
+ }
+
+ if ( turn )
+ {
+ sum += PcPcOnSq( sq_bk, list0[index_w], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[index_w], list1[index_w] );
+ sq_bk = SQ_BKING;
+ sq_wk = SQ_WKING;
+ sum += kkp[sq_bk][sq_wk][ aikkp_hand[pc] + hand_index ];
+ }
+ else {
+ sum += PcPcOnSq( sq_bk, list0[index_b], list0[index_b] );
+ sum -= PcPcOnSq( sq_wk, list1[index_b], list1[index_w] );
+ sq_bk = Inv(SQ_WKING);
+ sq_wk = Inv(SQ_BKING);
+ sum -= kkp[sq_bk][sq_wk][ aikkp_hand[pc] + hand_index ];
+ }
+
+ return sum;
+}
+
+
+#if defined(INANIWA_SHIFT)
+static int
+inaniwa_score( const tree_t * restrict ptree )
+{
+ int score;
+
+ if ( ! inaniwa_flag ) { return 0; }
+
+ score = 0;
+ if ( inaniwa_flag == 2 ) {
+
+ if ( BOARD[B9] == -knight ) { score += 700 * FV_SCALE; }
+ if ( BOARD[H9] == -knight ) { score += 700 * FV_SCALE; }
+
+ if ( BOARD[A7] == -knight ) { score += 700 * FV_SCALE; }
+ if ( BOARD[C7] == -knight ) { score += 400 * FV_SCALE; }
+ if ( BOARD[G7] == -knight ) { score += 400 * FV_SCALE; }
+ if ( BOARD[I7] == -knight ) { score += 700 * FV_SCALE; }
+
+ if ( BOARD[B5] == -knight ) { score += 700 * FV_SCALE; }
+ if ( BOARD[D5] == -knight ) { score += 100 * FV_SCALE; }
+ if ( BOARD[F5] == -knight ) { score += 100 * FV_SCALE; }
+ if ( BOARD[H5] == -knight ) { score += 700 * FV_SCALE; }
+
+ if ( BOARD[E3] == pawn ) { score += 200 * FV_SCALE; }
+ if ( BOARD[E4] == pawn ) { score += 200 * FV_SCALE; }
+ if ( BOARD[E5] == pawn ) { score += 200 * FV_SCALE; }
+
+ } else {
+
+ if ( BOARD[B1] == knight ) { score -= 700 * FV_SCALE; }
+ if ( BOARD[H1] == knight ) { score -= 700 * FV_SCALE; }
+
+ if ( BOARD[A3] == knight ) { score -= 700 * FV_SCALE; }
+ if ( BOARD[C3] == knight ) { score -= 400 * FV_SCALE; }
+ if ( BOARD[G3] == knight ) { score -= 400 * FV_SCALE; }
+ if ( BOARD[I3] == knight ) { score -= 700 * FV_SCALE; }
+
+ if ( BOARD[B5] == knight ) { score -= 700 * FV_SCALE; }
+ if ( BOARD[D5] == knight ) { score -= 100 * FV_SCALE; }
+ if ( BOARD[F5] == knight ) { score -= 100 * FV_SCALE; }
+ if ( BOARD[H5] == knight ) { score -= 700 * FV_SCALE; }
+
+ if ( BOARD[E7] == -pawn ) { score -= 200 * FV_SCALE; }
+ if ( BOARD[E6] == -pawn ) { score -= 200 * FV_SCALE; }
+ if ( BOARD[E5] == -pawn ) { score -= 200 * FV_SCALE; }
+ }
+
+ return score;
+}
+#endif