From 231f62baf7b6d9cee18bf7e85bed0fc9b78eed73 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sun, 16 Dec 2012 12:00:54 +0100 Subject: [PATCH 1/1] Introduce namespace Material And retire old struct MaterialTable simplifying the code. No functional change. --- src/evaluate.cpp | 7 ++-- src/material.cpp | 90 +++++++++++++++++++++++++----------------------- src/material.h | 72 ++++++++++---------------------------- src/position.cpp | 2 +- src/search.cpp | 2 +- src/thread.h | 3 +- 6 files changed, 72 insertions(+), 104 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index f27c04ec..4765094a 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -36,7 +36,7 @@ namespace { struct EvalInfo { // Pointers to material and pawn hash table entries - MaterialEntry* mi; + Material::Entry* mi; PawnEntry* pi; // attackedBy[color][piece type] is a bitboard representing all squares @@ -367,7 +367,8 @@ Value do_evaluate(const Position& pos, Value& margin) { Score score, mobilityWhite, mobilityBlack; Key key = pos.key(); - Eval::Entry* e = pos.this_thread()->evalTable[key]; + Thread* th = pos.this_thread(); + Eval::Entry* e = th->evalTable[key]; // If e->key matches the position's hash key, it means that we have analysed // this node before, and we can simply return the information we found the last @@ -391,7 +392,7 @@ Value do_evaluate(const Position& pos, Value& margin) { score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo); // Probe the material hash table - ei.mi = pos.this_thread()->materialTable.probe(pos); + ei.mi = Material::probe(pos, th->materialTable, th->endgames); score += ei.mi->material_value(); // If we have a specialized evaluation function for the current material diff --git a/src/material.cpp b/src/material.cpp index 073bef81..72240867 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -17,7 +17,7 @@ along with this program. If not, see . */ -#include +#include // For std::min #include #include @@ -81,18 +81,54 @@ namespace { && pos.piece_count(Them, PAWN) >= 1; } + /// imbalance() calculates imbalance comparing piece count of each + /// piece type for both colors. + + template + int imbalance(const int pieceCount[][PIECE_TYPE_NB]) { + + const Color Them = (Us == WHITE ? BLACK : WHITE); + + int pt1, pt2, pc, v; + int value = 0; + + // Redundancy of major pieces, formula based on Kaufman's paper + // "The Evaluation of Material Imbalances in Chess" + if (pieceCount[Us][ROOK] > 0) + value -= RedundantRookPenalty * (pieceCount[Us][ROOK] - 1) + + RedundantQueenPenalty * pieceCount[Us][QUEEN]; + + // Second-degree polynomial material imbalance by Tord Romstad + for (pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; pt1++) + { + pc = pieceCount[Us][pt1]; + if (!pc) + continue; + + v = LinearCoefficients[pt1]; + + for (pt2 = NO_PIECE_TYPE; pt2 <= pt1; pt2++) + v += QuadraticCoefficientsSameColor[pt1][pt2] * pieceCount[Us][pt2] + + QuadraticCoefficientsOppositeColor[pt1][pt2] * pieceCount[Them][pt2]; + + value += pc * v; + } + return value; + } + } // namespace +namespace Material { -/// MaterialTable::probe() takes a position object as input, looks up a MaterialEntry +/// Material::probe() takes a position object as input, looks up a MaterialEntry /// object, and returns a pointer to it. If the material configuration is not /// already present in the table, it is computed and stored there, so we don't /// have to recompute everything when the same material configuration occurs again. -MaterialEntry* MaterialTable::probe(const Position& pos) { +Entry* probe(const Position& pos, Table& entries, Endgames& endgames) { Key key = pos.material_key(); - MaterialEntry* e = entries[key]; + Entry* e = entries[key]; // If e->key matches the position's material hash key, it means that we // have analysed this material configuration before, and we can simply @@ -100,10 +136,10 @@ MaterialEntry* MaterialTable::probe(const Position& pos) { if (e->key == key) return e; - memset(e, 0, sizeof(MaterialEntry)); + memset(e, 0, sizeof(Entry)); e->key = key; e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL; - e->gamePhase = MaterialTable::game_phase(pos); + e->gamePhase = game_phase(pos); // Let's look if we have a specialized evaluation function for this // particular material configuration. First we look for a fixed @@ -226,47 +262,11 @@ MaterialEntry* MaterialTable::probe(const Position& pos) { } -/// MaterialTable::imbalance() calculates imbalance comparing piece count of each -/// piece type for both colors. - -template -int MaterialTable::imbalance(const int pieceCount[][PIECE_TYPE_NB]) { - - const Color Them = (Us == WHITE ? BLACK : WHITE); - - int pt1, pt2, pc, v; - int value = 0; - - // Redundancy of major pieces, formula based on Kaufman's paper - // "The Evaluation of Material Imbalances in Chess" - if (pieceCount[Us][ROOK] > 0) - value -= RedundantRookPenalty * (pieceCount[Us][ROOK] - 1) - + RedundantQueenPenalty * pieceCount[Us][QUEEN]; - - // Second-degree polynomial material imbalance by Tord Romstad - for (pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; pt1++) - { - pc = pieceCount[Us][pt1]; - if (!pc) - continue; - - v = LinearCoefficients[pt1]; - - for (pt2 = NO_PIECE_TYPE; pt2 <= pt1; pt2++) - v += QuadraticCoefficientsSameColor[pt1][pt2] * pieceCount[Us][pt2] - + QuadraticCoefficientsOppositeColor[pt1][pt2] * pieceCount[Them][pt2]; - - value += pc * v; - } - return value; -} - - -/// MaterialTable::game_phase() calculates the phase given the current +/// Material::game_phase() calculates the phase given the current /// position. Because the phase is strictly a function of the material, it /// is stored in MaterialEntry. -Phase MaterialTable::game_phase(const Position& pos) { +Phase game_phase(const Position& pos) { Value npm = pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK); @@ -274,3 +274,5 @@ Phase MaterialTable::game_phase(const Position& pos) { : npm <= EndgameLimit ? PHASE_ENDGAME : Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit)); } + +} // namespace Material diff --git a/src/material.h b/src/material.h index 89f8f556..c88094cf 100644 --- a/src/material.h +++ b/src/material.h @@ -25,31 +25,26 @@ #include "position.h" #include "types.h" -const int MaterialTableSize = 8192; +namespace Material { -/// MaterialEntry is a class which contains various information about a -/// material configuration. It contains a material balance evaluation, -/// a function pointer to a special endgame evaluation function (which in -/// most cases is NULL, meaning that the standard evaluation function will -/// be used), and "scale factors" for black and white. +/// Material::Entry contains various information about a material configuration. +/// It contains a material balance evaluation, a function pointer to a special +/// endgame evaluation function (which in most cases is NULL, meaning that the +/// standard evaluation function will be used), and "scale factors". /// /// The scale factors are used to scale the evaluation score up or down. /// For instance, in KRB vs KR endgames, the score is scaled down by a factor /// of 4, which will result in scores of absolute value less than one pawn. -class MaterialEntry { +struct Entry { - friend struct MaterialTable; - -public: - Score material_value() const; + Score material_value() const { return make_score(value, value); } + int space_weight() const { return spaceWeight; } + Phase game_phase() const { return gamePhase; } + bool specialized_eval_exists() const { return evaluationFunction != NULL; } + Value evaluate(const Position& p) const { return (*evaluationFunction)(p); } ScaleFactor scale_factor(const Position& pos, Color c) const; - int space_weight() const; - Phase game_phase() const; - bool specialized_eval_exists() const; - Value evaluate(const Position& pos) const; -private: Key key; int16_t value; uint8_t factor[COLOR_NB]; @@ -59,55 +54,24 @@ private: Phase gamePhase; }; +typedef HashTable Table; -/// The MaterialTable class represents a material hash table. The most important -/// method is probe(), which returns a pointer to a MaterialEntry object. - -struct MaterialTable { - - MaterialEntry* probe(const Position& pos); - static Phase game_phase(const Position& pos); - template static int imbalance(const int pieceCount[][PIECE_TYPE_NB]); - - HashTable entries; - Endgames endgames; -}; - +Entry* probe(const Position& pos, Table& entries, Endgames& endgames); +Phase game_phase(const Position& pos); -/// MaterialEntry::scale_factor takes a position and a color as input, and +/// Material::scale_factor takes a position and a color as input, and /// returns a scale factor for the given color. We have to provide the /// position in addition to the color, because the scale factor need not /// to be a constant: It can also be a function which should be applied to /// the position. For instance, in KBP vs K endgames, a scaling function /// which checks for draws with rook pawns and wrong-colored bishops. -inline ScaleFactor MaterialEntry::scale_factor(const Position& pos, Color c) const { - - if (!scalingFunction[c]) - return ScaleFactor(factor[c]); - - ScaleFactor sf = (*scalingFunction[c])(pos); - return sf == SCALE_FACTOR_NONE ? ScaleFactor(factor[c]) : sf; -} - -inline Value MaterialEntry::evaluate(const Position& pos) const { - return (*evaluationFunction)(pos); -} - -inline Score MaterialEntry::material_value() const { - return make_score(value, value); -} - -inline int MaterialEntry::space_weight() const { - return spaceWeight; -} +inline ScaleFactor Entry::scale_factor(const Position& pos, Color c) const { -inline Phase MaterialEntry::game_phase() const { - return gamePhase; + return !scalingFunction[c] || (*scalingFunction[c])(pos) == SCALE_FACTOR_NONE + ? ScaleFactor(factor[c]) : (*scalingFunction[c])(pos); } -inline bool MaterialEntry::specialized_eval_exists() const { - return evaluationFunction != NULL; } #endif // !defined(MATERIAL_H_INCLUDED) diff --git a/src/position.cpp b/src/position.cpp index 37b5c049..0c19d820 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -919,7 +919,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI // Prefetch pawn and material hash tables prefetch((char*)thisThread->pawnTable.entries[st->pawnKey]); - prefetch((char*)thisThread->materialTable.entries[st->materialKey]); + prefetch((char*)thisThread->materialTable[st->materialKey]); // Update incremental scores st->psqScore += psq_delta(piece, from, to); diff --git a/src/search.cpp b/src/search.cpp index 654efb32..292faf04 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -208,7 +208,7 @@ void Search::think() { if (Options["Contempt Factor"] && !Options["UCI_AnalyseMode"]) { int cf = Options["Contempt Factor"] * PawnValueMg / 100; // From centipawns - cf = cf * MaterialTable::game_phase(RootPos) / PHASE_MIDGAME; // Scale down with phase + cf = cf * Material::game_phase(RootPos) / PHASE_MIDGAME; // Scale down with phase DrawValue[ RootColor] = VALUE_DRAW - Value(cf); DrawValue[~RootColor] = VALUE_DRAW + Value(cf); } diff --git a/src/thread.h b/src/thread.h index 6c3c18af..64a56ccb 100644 --- a/src/thread.h +++ b/src/thread.h @@ -110,7 +110,8 @@ public: SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD]; Eval::Table evalTable; - MaterialTable materialTable; + Material::Table materialTable; + Endgames endgames; PawnTable pawnTable; size_t idx; int maxPly; -- 2.39.2