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;
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);
: 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];
}