From 7b7a9485d6d36b246b8eb3f278570e52d929aa51 Mon Sep 17 00:00:00 2001 From: AliceRoselia <63040919+AliceRoselia@users.noreply.github.com> Date: Fri, 14 Nov 2025 17:18:29 +0100 Subject: [PATCH] Simplify indexing Removes 1 function (from_to) from the Move type, change them to simpler raw. Remove the "and" use in the correction history structure calculation. Adjust the indexing. Passed simplification STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 42880 W: 11327 L: 11113 D: 20440 Ptnml(0-2): 161, 4852, 11212, 5042, 173 https://tests.stockfishchess.org/tests/view/690593b8ea4b268f1fac1e8a Passed simplification LTC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 43560 W: 11276 L: 11079 D: 21205 Ptnml(0-2): 17, 4679, 12197, 4864, 23 https://tests.stockfishchess.org/tests/view/6906f819ea4b268f1fac216b closes https://github.com/official-stockfish/Stockfish/pull/6391 Bench: 2523092 --- src/history.h | 27 +++++++++++---------------- src/movepick.cpp | 8 ++++---- src/search.cpp | 12 ++++++------ src/types.h | 2 -- 4 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/history.h b/src/history.h index 445d54181..a605ae417 100644 --- a/src/history.h +++ b/src/history.h @@ -33,32 +33,28 @@ namespace Stockfish { -constexpr int PAWN_HISTORY_SIZE = 8192; // has to be a power of 2 -constexpr int CORRECTION_HISTORY_SIZE = 32768; // has to be a power of 2 +constexpr int PAWN_HISTORY_SIZE = 8192; // has to be a power of 2 +constexpr int UINT_16_HISTORY_SIZE = std::numeric_limits::max() + 1; constexpr int CORRECTION_HISTORY_LIMIT = 1024; constexpr int LOW_PLY_HISTORY_SIZE = 5; static_assert((PAWN_HISTORY_SIZE & (PAWN_HISTORY_SIZE - 1)) == 0, "PAWN_HISTORY_SIZE has to be a power of 2"); -static_assert((CORRECTION_HISTORY_SIZE & (CORRECTION_HISTORY_SIZE - 1)) == 0, +static_assert((UINT_16_HISTORY_SIZE & (UINT_16_HISTORY_SIZE - 1)) == 0, "CORRECTION_HISTORY_SIZE has to be a power of 2"); inline int pawn_history_index(const Position& pos) { return pos.pawn_key() & (PAWN_HISTORY_SIZE - 1); } -inline int pawn_correction_history_index(const Position& pos) { - return pos.pawn_key() & (CORRECTION_HISTORY_SIZE - 1); -} +inline uint16_t pawn_correction_history_index(const Position& pos) { return pos.pawn_key(); } -inline int minor_piece_index(const Position& pos) { - return pos.minor_piece_key() & (CORRECTION_HISTORY_SIZE - 1); -} +inline uint16_t minor_piece_index(const Position& pos) { return pos.minor_piece_key(); } template -inline int non_pawn_index(const Position& pos) { - return pos.non_pawn_key(c) & (CORRECTION_HISTORY_SIZE - 1); +inline uint16_t non_pawn_index(const Position& pos) { + return pos.non_pawn_key(c); } // StatsEntry is the container of various numerical statistics. We use a class @@ -102,12 +98,11 @@ using Stats = MultiArray, Sizes...>; // during the current search, and is used for reduction and move ordering decisions. // It uses 2 tables (one for each color) indexed by the move's from and to squares, // see https://www.chessprogramming.org/Butterfly_Boards -using ButterflyHistory = Stats; +using ButterflyHistory = Stats; // LowPlyHistory is addressed by play and move's from and to squares, used // to improve move ordering near the root -using LowPlyHistory = - Stats; +using LowPlyHistory = Stats; // CapturePieceToHistory is addressed by a move's [piece][to][captured piece type] using CapturePieceToHistory = Stats; @@ -139,7 +134,7 @@ namespace Detail { template struct CorrHistTypedef { - using type = Stats; + using type = Stats; }; template<> @@ -155,7 +150,7 @@ struct CorrHistTypedef { template<> struct CorrHistTypedef { using type = - Stats; + Stats; }; } diff --git a/src/movepick.cpp b/src/movepick.cpp index 0b18cf565..7de11fa1f 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -158,7 +158,7 @@ ExtMove* MovePicker::score(MoveList& ml) { else if constexpr (Type == QUIETS) { // histories - m.value = 2 * (*mainHistory)[us][m.from_to()]; + m.value = 2 * (*mainHistory)[us][m.raw()]; m.value += 2 * (*pawnHistory)[pawn_history_index(pos)][pc][to]; m.value += (*continuationHistory[0])[pc][to]; m.value += (*continuationHistory[1])[pc][to]; @@ -176,7 +176,7 @@ ExtMove* MovePicker::score(MoveList& ml) { if (ply < LOW_PLY_HISTORY_SIZE) - m.value += 8 * (*lowPlyHistory)[ply][m.from_to()] / (1 + ply); + m.value += 8 * (*lowPlyHistory)[ply][m.raw()] / (1 + ply); } else // Type == EVASIONS @@ -185,9 +185,9 @@ ExtMove* MovePicker::score(MoveList& ml) { m.value = PieceValue[capturedPiece] + (1 << 28); else { - m.value = (*mainHistory)[us][m.from_to()] + (*continuationHistory[0])[pc][to]; + m.value = (*mainHistory)[us][m.raw()] + (*continuationHistory[0])[pc][to]; if (ply < LOW_PLY_HISTORY_SIZE) - m.value += (*lowPlyHistory)[ply][m.from_to()]; + m.value += (*lowPlyHistory)[ply][m.raw()]; } } } diff --git a/src/search.cpp b/src/search.cpp index b88c428e2..7404b939c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -824,7 +824,7 @@ Value Search::Worker::search( if (((ss - 1)->currentMove).is_ok() && !(ss - 1)->inCheck && !priorCapture) { int evalDiff = std::clamp(-int((ss - 1)->staticEval + ss->staticEval), -200, 156) + 58; - mainHistory[~us][((ss - 1)->currentMove).from_to()] << evalDiff * 9; + mainHistory[~us][((ss - 1)->currentMove).raw()] << evalDiff * 9; if (!ttHit && type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION) pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq] << evalDiff * 14; @@ -1066,7 +1066,7 @@ moves_loop: // When in check, search starts here if (history < -4312 * depth) continue; - history += 76 * mainHistory[us][move.from_to()] / 32; + history += 76 * mainHistory[us][move.raw()] / 32; // (*Scaler): Generally, a lower divisor scales well lmrDepth += history / 3220; @@ -1196,7 +1196,7 @@ moves_loop: // When in check, search starts here ss->statScore = 803 * int(PieceValue[pos.captured_piece()]) / 128 + captureHistory[movedPiece][move.to_sq()][type_of(pos.captured_piece())]; else - ss->statScore = 2 * mainHistory[us][move.from_to()] + ss->statScore = 2 * mainHistory[us][move.raw()] + (*contHist[0])[movedPiece][move.to_sq()] + (*contHist[1])[movedPiece][move.to_sq()]; @@ -1414,7 +1414,7 @@ moves_loop: // When in check, search starts here update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, scaledBonus * 400 / 32768); - mainHistory[~us][((ss - 1)->currentMove).from_to()] << scaledBonus * 220 / 32768; + mainHistory[~us][((ss - 1)->currentMove).raw()] << scaledBonus * 220 / 32768; if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION) pawnHistory[pawn_history_index(pos)][pos.piece_on(prevSq)][prevSq] @@ -1862,10 +1862,10 @@ void update_quiet_histories( const Position& pos, Stack* ss, Search::Worker& workerThread, Move move, int bonus) { Color us = pos.side_to_move(); - workerThread.mainHistory[us][move.from_to()] << bonus; // Untuned to prevent duplicate effort + workerThread.mainHistory[us][move.raw()] << bonus; // Untuned to prevent duplicate effort if (ss->ply < LOW_PLY_HISTORY_SIZE) - workerThread.lowPlyHistory[ss->ply][move.from_to()] << bonus * 761 / 1024; + workerThread.lowPlyHistory[ss->ply][move.raw()] << bonus * 761 / 1024; update_continuation_histories(ss, pos.moved_piece(move), move.to_sq(), bonus * 955 / 1024); diff --git a/src/types.h b/src/types.h index 46aa16a03..a2171b638 100644 --- a/src/types.h +++ b/src/types.h @@ -448,8 +448,6 @@ class Move { return Square(data & 0x3F); } - constexpr int from_to() const { return data & 0xFFF; } - constexpr MoveType type_of() const { return MoveType(data & (3 << 14)); } constexpr PieceType promotion_type() const { return PieceType(((data >> 12) & 3) + KNIGHT); }