phase update in move_do(), new phase_verify(), rewrite calc_phase()

This commit is contained in:
2024-08-06 21:19:51 +02:00
parent aef14db3e4
commit fcd54b44ce
8 changed files with 85 additions and 13 deletions

View File

@@ -124,13 +124,14 @@ else # ifeq ($(build),dev)
# fen.c # fen.c
#CPPFLAGS += -DDEBUG_FEN # FEN decoding #CPPFLAGS += -DDEBUG_FEN # FEN decoding
# hash / TT # hash / TT
#CPPFLAGS += -DZOBRIST_VERIFY # double chk zobrist #CPPFLAGS += -DZOBRIST_VERIFY # incr. zobrist check
#CPPFLAGS += -DPERFT_MOVE_HISTORY # perft, keep prev moves #CPPFLAGS += -DPERFT_MOVE_HISTORY # perft, keep prev moves
# attack.c # attack.c
#CPPFLAGS += -DDEBUG_ATTACK_ATTACKERS # sq_attackers #CPPFLAGS += -DDEBUG_ATTACK_ATTACKERS # sq_attackers
#CPPFLAGS += -DDEBUG_ATTACK_PINNERS # sq_pinners details #CPPFLAGS += -DDEBUG_ATTACK_PINNERS # sq_pinners details
# eval.c eval-simple.c # eval.c eval-simple.c
CPPFLAGS += -DDEBUG_EVAL # eval CPPFLAGS += -DDEBUG_EVAL # eval
CPPFLAGS += -DPHASE_VERIFY # incr. phase check
# old unused flags # old unused flags
#CPPFLAGS += -DDEBUG_POS # position.c #CPPFLAGS += -DDEBUG_POS # position.c

View File

@@ -22,6 +22,10 @@
//#include "eval-simple.h" //#include "eval-simple.h"
//#include "eval.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. */ /* eval parameters definition. */
static const struct ev_params ev_param_def [EV_PARAMS_NB] = { static const struct ev_params ev_param_def [EV_PARAMS_NB] = {
/* type setable def min max name */ /* type setable def min max name */

View File

@@ -36,18 +36,24 @@ enum {
Q_PHASE = 4, Q_PHASE = 4,
ALL_PHASE = P_PHASE*16 + N_PHASE*4 + B_PHASE*4 + R_PHASE*4 + Q_PHASE*2 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 /* 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. * + 2*KNIGHT_VALUE which is (for a pawn valued at 100) well less than 15,000.
*/ */
#define EVAL_MAX (SHRT_MAX) /* 32767 */ #define EVAL_MAX (SHRT_MAX) /* 32767 */
#define EVAL_MIN (-EVAL_MAX) #define EVAL_MIN (-EVAL_MAX)
#define EVAL_DRAW 0
#define EVAL_INV EVAL_MIN #define EVAL_INV EVAL_MIN
#define EVAL_MATE 30000 #define EVAL_MATE 30000
/* eval parameters */ /* engine parameters */
enum { enum {
WT_MAT, WT_MAT,
WT_PST, WT_PST,

View File

@@ -19,6 +19,50 @@
#include "position.h" #include "position.h"
#include "eval.h" #include "eval.h"
#include "eval-simple.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 * calc_phase - calculate position phase
@@ -30,7 +74,7 @@
* *
* @return: * @return:
*/ */
phase_t calc_phase(pos_t *pos) __unused static phase_t calc_phase2(pos_t *pos)
{ {
int phase = ALL_PHASE; int phase = ALL_PHASE;
phase -= P_PHASE * popcount64(pos->bb[WHITE][PAWN] | pos->bb[BLACK][PAWN]); 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); phase = max(phase, 0);
# ifdef DEBUG_EVAL # ifdef DEBUG_EVAL
printf("calc phase:%d\n", phase); printf("calc phase:%d verif=%d\n", phase, calc_phase(pos));
# endif # endif
return phase; return phase;
} }

View File

@@ -20,6 +20,11 @@
#include "eval-defs.h" #include "eval-defs.h"
phase_t calc_phase(pos_t *pos); 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_mobility(pos_t *pos, bool color);
eval_t eval_square_control(pos_t *pos, bool color); eval_t eval_square_control(pos_t *pos, bool color);

View File

@@ -97,12 +97,11 @@ hkey_t zobrist_calc(pos_t *pos)
* @pos: &position * @pos: &position
* *
* Verify that position Zobrist key matches a full Zobrist calculation. * 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 #ifdef ZOBRIST_VERIFY
bool zobrist_verify(pos_t *pos) bool zobrist_verify(pos_t *pos)
{ {
hkey_t diff, key = zobrist_calc(pos); hkey_t diff, key = zobrist_calc(pos);

View File

@@ -79,16 +79,21 @@ pos_t *move_do(pos_t *pos, const move_t move, state_t *state)
if (is_promotion(move)) { if (is_promotion(move)) {
bug_on(sq_rank(to) != sq_rel_rank(RANK_8, us)); 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) { if (captured != EMPTY) {
pos->ply50 = 0; 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]; key ^= zobrist_pieces[captured][to];
pos_clr_sq(pos, to); /* clear square */ pos_clr_sq(pos, to); /* clear square */
} else if (is_castle(move)) { /* handle rook move */ } else if (is_castle(move)) { /* handle rook move */
square_t rookfrom, rookto; square_t rookfrom, rookto;
if (to > from) { if (to > from) {
rookfrom = sq_rel(H1, us); rookfrom = sq_rel(H1, us);
rookto = sq_rel(F1, 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; pos->ply50 = 0;
if (from + up + up == to) { /* if pawn double push, set e.p. */ if (from + up + up == to) { /* if pawn double push, set e.p. */
square_t ep = from + up; square_t ep = from + up;
if (bb_pawn_attacks[us][ep] & pos->bb[them][PAWN]) { if (bb_pawn_attacks[us][ep] & pos->bb[them][PAWN]) {
pos->en_passant = ep; pos->en_passant = ep;
key ^= zobrist_ep[EP_ZOBRIST_IDX(pos->en_passant)]; 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 */ } else if (is_enpassant(move)) { /* clear grabbed pawn */
square_t grabbed = to - up; square_t grabbed = to - up;
piece_t pc = pos->board[grabbed]; piece_t pc = pos->board[grabbed];
pos->phase += pt_phase(PAWN);
key ^= zobrist_pieces[pc][grabbed]; key ^= zobrist_pieces[pc][grabbed];
pos_clr_sq(pos, 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->key = key;
pos->repcount = pos_repcount(pos); pos->repcount = pos_repcount(pos);
/* consistency checks.
* Checks done only if compiled with '-DZOBRIST_VERIFY' or '-DPHASE_VERIFY'
*/
zobrist_verify(pos); zobrist_verify(pos);
phase_verify(pos);
return pos; return pos;
} }

View File

@@ -185,8 +185,8 @@ bitboard_t pos_checkers(const pos_t *pos, const color_t color)
* pos_repcount() - return position repetition count. * pos_repcount() - return position repetition count.
* @pos: &position to search * @pos: &position to search
* *
* Attention: positions before (and including) root position repcount is * Attention: positions before (and including) root position repcount are
* decreased by one. See do_moves() in uci.c. * already decreased by one. See do_moves() in uci.c.
* *
* @return: The number of repetitions in history, zero otherwise. * @return: The number of repetitions in history, zero otherwise.
*/ */