From 341f26b2d404dc03917d7a09f30be4504cb75af5 Mon Sep 17 00:00:00 2001 From: Fabian Fichter Date: Mon, 29 Mar 2021 12:38:49 +0200 Subject: [PATCH] Better document piece value calculation No functional change. --- src/psqt.cpp | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/psqt.cpp b/src/psqt.cpp index bdbc91a..e5a4a4e 100644 --- a/src/psqt.cpp +++ b/src/psqt.cpp @@ -143,13 +143,13 @@ void init(const Variant* v) { if (v->blastOnCapture) score += make_score(mg_value(score) * 3 / 2, eg_value(score)); } - - // Scale slider piece values with board size + const PieceInfo* pi = pieceMap.find(pt)->second; bool isSlider = pi->sliderQuiet.size() || pi->sliderCapture.size() || pi->hopperQuiet.size() || pi->hopperCapture.size(); bool isPawn = !isSlider && pi->stepsQuiet.size() && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](Direction d) { return d < SOUTH / 2; }); bool isSlowLeaper = !isSlider && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](Direction d) { return dist(d) > 1; }); + // Scale slider piece values with board size if (isSlider) { constexpr int lc = 5; @@ -171,21 +171,28 @@ void init(const Variant* v) { eg_value(score) * 4700 / (3500 + mg_value(score))); } + // Piece values saturate earlier in drop variants if (v->capturesToHand || v->twoBoards) score = make_score(mg_value(score) * 7000 / (7000 + mg_value(score)), eg_value(score) * 7000 / (7000 + eg_value(score))); + // In variants where checks are prohibited, strong pieces are less mobile, so limit their value else if (!v->checking) score = make_score(std::min(mg_value(score), Value(1800)) / 2, std::min(eg_value(score), Value(1800)) * 3 / 5); + // Adjust piece values for atomic captures else if (v->blastOnCapture) score = make_score(mg_value(score) * 7000 / (7000 + mg_value(score)), eg_value(score)); + // With check counting, strong pieces are even more dangerous else if (v->checkCounting) score = make_score(mg_value(score) * (20000 + mg_value(score)) / 22000, eg_value(score) * (20000 + eg_value(score)) / 21000); + // In variants such as horde where all pieces need to be captured, weak pieces such as pawns are more useful else if ( v->extinctionValue == -VALUE_MATE && v->extinctionPieceCount == 0 && v->extinctionPieceTypes.find(ALL_PIECES) != v->extinctionPieceTypes.end()) score += make_score(0, std::max(KnightValueEg - PieceValue[EG][pt], VALUE_ZERO) / 20); + // The strongest piece of a variant usually has some dominance, such as rooks in Makruk and Xiangqi. + // This does not apply to drop variants. else if (pt == strongestPiece) score += make_score(std::max(QueenValueMg - PieceValue[MG][pt], VALUE_ZERO) / 20, std::max(QueenValueEg - PieceValue[EG][pt], VALUE_ZERO) / 20); @@ -229,18 +236,21 @@ void init(const Variant* v) { : isSlider ? make_score(5, 5) * (2 * f + std::max(std::min(r, Rank(v->maxRank - r)), RANK_1) - v->maxFile - 1) : isPawn ? make_score(5, 5) * (2 * f - v->maxFile) : make_score(10, 10) * (1 + isSlowLeaper) * (f + std::max(std::min(r, Rank(v->maxRank - r)), RANK_1) - v->maxFile / 2)); + // Add a penalty for unpromoted soldiers if (pt == SOLDIER && r < v->soldierPromotionRank) psq[pc][s] -= score * (v->soldierPromotionRank - r) / (4 + f); + // Corners are valuable in othello if (v->enclosingDrop == REVERSI) { if (f == FILE_A && (r == RANK_1 || r == v->maxRank)) psq[pc][s] += make_score(1000, 1000); } + // In atomic variants pieces are "self-defending" and should therefore be pushed forward if (v->blastOnCapture) psq[pc][s] += make_score(40, 0) * (r - v->maxRank / 2); psq[~pc][rank_of(s) <= v->maxRank ? flip_rank(s, v->maxRank) : s] = -psq[pc][s]; } - // pieces in pocket + // Pieces in hand psq[ pc][SQ_NONE] = score + make_score(35, 10) * (1 + !isSlider); psq[~pc][SQ_NONE] = -psq[pc][SQ_NONE]; } -- 1.7.0.4