diff --git a/Makefile b/Makefile index 1f0a673..6429762 100644 --- a/Makefile +++ b/Makefile @@ -124,13 +124,14 @@ else # ifeq ($(build),dev) # fen.c #CPPFLAGS += -DDEBUG_FEN # FEN decoding # hash / TT - #CPPFLAGS += -DZOBRIST_VERIFY # double chk zobrist + #CPPFLAGS += -DZOBRIST_VERIFY # incr. zobrist check #CPPFLAGS += -DPERFT_MOVE_HISTORY # perft, keep prev moves # attack.c #CPPFLAGS += -DDEBUG_ATTACK_ATTACKERS # sq_attackers #CPPFLAGS += -DDEBUG_ATTACK_PINNERS # sq_pinners details # eval.c eval-simple.c - CPPFLAGS += -DDEBUG_EVAL # eval + CPPFLAGS += -DDEBUG_EVAL # eval + CPPFLAGS += -DPHASE_VERIFY # incr. phase check # old unused flags #CPPFLAGS += -DDEBUG_POS # position.c diff --git a/src/eval-defs.c b/src/eval-defs.c index 62332ac..8055a2a 100644 --- a/src/eval-defs.c +++ b/src/eval-defs.c @@ -22,6 +22,10 @@ //#include "eval-simple.h" //#include "eval.h" +phase_t piece_phase[PIECE_TYPE_NB] = { + 0, P_PHASE, N_PHASE, B_PHASE, R_PHASE, Q_PHASE, 0 +}; + /* eval parameters definition. */ static const struct ev_params ev_param_def [EV_PARAMS_NB] = { /* type setable def min max name */ diff --git a/src/eval-defs.h b/src/eval-defs.h index bd3881c..18ed3b5 100644 --- a/src/eval-defs.h +++ b/src/eval-defs.h @@ -36,18 +36,24 @@ enum { Q_PHASE = 4, ALL_PHASE = P_PHASE*16 + N_PHASE*4 + B_PHASE*4 + R_PHASE*4 + Q_PHASE*2 }; +extern phase_t piece_phase[PIECE_TYPE_NB]; + +static inline phase_t pt_phase(piece_type_t pt) +{ + return piece_phase[pt]; +} /* max pieces eval is 9*QUEEN_VALUE + 2*ROOK_VALUE + 2*BISHOP_VALUE * + 2*KNIGHT_VALUE which is (for a pawn valued at 100) well less than 15,000. */ #define EVAL_MAX (SHRT_MAX) /* 32767 */ #define EVAL_MIN (-EVAL_MAX) - +#define EVAL_DRAW 0 #define EVAL_INV EVAL_MIN #define EVAL_MATE 30000 -/* eval parameters */ +/* engine parameters */ enum { WT_MAT, WT_PST, diff --git a/src/eval.c b/src/eval.c index 9f2fb64..1d09a3f 100644 --- a/src/eval.c +++ b/src/eval.c @@ -19,6 +19,50 @@ #include "position.h" #include "eval.h" #include "eval-simple.h" +#include "hist.h" + +/** + * calc_phase - calculate position phase + * @pos: &position + * + * This function should be calculated when a new position is setup, or as + * a verification of an incremental one. + * Note: phase is *not* clamped, to avoid update errors. + * + * @return: phase value + */ +phase_t calc_phase(pos_t *pos) +{ + int phase = ALL_PHASE; + for (piece_type_t pt = PAWN; pt < KING; ++pt) + phase -= piece_phase[pt] * popcount64(pos->bb[WHITE][pt] | pos->bb[BLACK][pt]); +# ifdef DEBUG_PHASE + printf("calc phase:%d\n", phase); +# endif + return phase; +} + +/** + * phase_verify() - verify position phase. + * @pos: &position + * + * Verify that position phase is correct (a full recalculation is performed). + * This function is inactive if PHASE_VERIFY is not set. + * + * @return: True if phase key is OK, no return otherwise. + */ +#ifdef PHASE_VERIFY +bool phase_verify(pos_t *pos) +{ + phase_t verif = calc_phase(pos); + if (pos->phase != verif) { + warn(true, "warn phase=%d verif=%d\n", pos->phase, verif); + hist_print(pos); + bug_on(pos->phase != verif); + } + return true; +} +#endif /** * calc_phase - calculate position phase @@ -30,7 +74,7 @@ * * @return: */ -phase_t calc_phase(pos_t *pos) +__unused static phase_t calc_phase2(pos_t *pos) { int phase = ALL_PHASE; phase -= P_PHASE * popcount64(pos->bb[WHITE][PAWN] | pos->bb[BLACK][PAWN]); @@ -41,7 +85,7 @@ phase_t calc_phase(pos_t *pos) phase = max(phase, 0); # ifdef DEBUG_EVAL - printf("calc phase:%d\n", phase); + printf("calc phase:%d verif=%d\n", phase, calc_phase(pos)); # endif return phase; } diff --git a/src/eval.h b/src/eval.h index 2c2185a..ded6422 100644 --- a/src/eval.h +++ b/src/eval.h @@ -20,6 +20,11 @@ #include "eval-defs.h" phase_t calc_phase(pos_t *pos); +#ifdef PHASE_VERIFY +bool phase_verify(pos_t *pos); +#else +#define phase_verify(p) true +#endif eval_t eval_mobility(pos_t *pos, bool color); eval_t eval_square_control(pos_t *pos, bool color); diff --git a/src/hash.c b/src/hash.c index 989005a..15c489d 100644 --- a/src/hash.c +++ b/src/hash.c @@ -97,12 +97,11 @@ hkey_t zobrist_calc(pos_t *pos) * @pos: &position * * Verify that position Zobrist key matches a full Zobrist calculation. - * This function cannot be called if ZOBRIST_VERIFY is not set. + * This function is inactive if ZOBRIST_VERIFY is not set. * - * @return: True if Zobrist key is OK. + * @return: True if Zobrist key is OK, no return otherwise. */ #ifdef ZOBRIST_VERIFY - bool zobrist_verify(pos_t *pos) { hkey_t diff, key = zobrist_calc(pos); diff --git a/src/move-do.c b/src/move-do.c index c64cd5a..819afa3 100644 --- a/src/move-do.c +++ b/src/move-do.c @@ -79,16 +79,21 @@ pos_t *move_do(pos_t *pos, const move_t move, state_t *state) if (is_promotion(move)) { bug_on(sq_rank(to) != sq_rel_rank(RANK_8, us)); - new_piece = MAKE_PIECE(move_promoted(move), us); + piece_t promoted = move_promoted(move); + new_piece = MAKE_PIECE(promoted, us); + pos->phase += pt_phase(PAWN) - pt_phase(promoted); } if (captured != EMPTY) { pos->ply50 = 0; - bug_on(pos->board[to] == EMPTY || COLOR(pos->captured) != them); + pos->phase += pt_phase(PIECE(captured)); + + bug_on(COLOR(captured) != them); key ^= zobrist_pieces[captured][to]; pos_clr_sq(pos, to); /* clear square */ } else if (is_castle(move)) { /* handle rook move */ square_t rookfrom, rookto; + if (to > from) { rookfrom = sq_rel(H1, us); rookto = sq_rel(F1, us); @@ -105,6 +110,7 @@ pos_t *move_do(pos_t *pos, const move_t move, state_t *state) pos->ply50 = 0; if (from + up + up == to) { /* if pawn double push, set e.p. */ square_t ep = from + up; + if (bb_pawn_attacks[us][ep] & pos->bb[them][PAWN]) { pos->en_passant = ep; key ^= zobrist_ep[EP_ZOBRIST_IDX(pos->en_passant)]; @@ -112,6 +118,8 @@ pos_t *move_do(pos_t *pos, const move_t move, state_t *state) } else if (is_enpassant(move)) { /* clear grabbed pawn */ square_t grabbed = to - up; piece_t pc = pos->board[grabbed]; + + pos->phase += pt_phase(PAWN); key ^= zobrist_pieces[pc][grabbed]; pos_clr_sq(pos, grabbed); } @@ -155,7 +163,12 @@ pos_t *move_do(pos_t *pos, const move_t move, state_t *state) pos->key = key; pos->repcount = pos_repcount(pos); + + /* consistency checks. + * Checks done only if compiled with '-DZOBRIST_VERIFY' or '-DPHASE_VERIFY' + */ zobrist_verify(pos); + phase_verify(pos); return pos; } diff --git a/src/position.c b/src/position.c index 40da984..deb09a2 100644 --- a/src/position.c +++ b/src/position.c @@ -185,8 +185,8 @@ bitboard_t pos_checkers(const pos_t *pos, const color_t color) * pos_repcount() - return position repetition count. * @pos: &position to search * - * Attention: positions before (and including) root position repcount is - * decreased by one. See do_moves() in uci.c. + * Attention: positions before (and including) root position repcount are + * already decreased by one. See do_moves() in uci.c. * * @return: The number of repetitions in history, zero otherwise. */