From 6e8bd8bf2d77eeb4414b6e533559dbda1f0211c9 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sat, 1 Nov 2008 11:38:30 +0100 Subject: [PATCH] Final touches to material.cpp No functional changes, altough a bit of code reshuffle. Signed-off-by: Marco Costalba --- src/main.cpp | 1 - src/material.cpp | 81 ++++++++++++++++++++---------------------------- src/material.h | 56 ++++++++++++++++++--------------- 3 files changed, 65 insertions(+), 73 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7b675d34..9d2e1ef2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,7 +59,6 @@ int main(int argc, char *argv[]) { init_uci_options(); Position::init_zobrist(); Position::init_piece_square_tables(); - MaterialInfo::init(); MovePicker::init_phase_table(); init_eval(1); init_bitbases(); diff --git a/src/material.cpp b/src/material.cpp index 10daaeb5..9f0fb9ed 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -39,29 +39,33 @@ namespace { Key KNNKMaterialKey, KKNNMaterialKey; - struct ScalingInfo - { - Color col; - ScalingFunction* fun; - }; - } //// //// Classes //// + +/// See header for a class description. It is declared here to avoid +/// to include in the header file. + class EndgameFunctions { public: EndgameFunctions(); - EndgameEvaluationFunction* getEEF(Key key); - ScalingInfo getESF(Key key); + EndgameEvaluationFunction* getEEF(Key key) const; + ScalingFunction* getESF(Key key, Color* c) const; private: void add(Key k, EndgameEvaluationFunction* f); void add(Key k, Color c, ScalingFunction* f); + struct ScalingInfo + { + Color col; + ScalingFunction* fun; + }; + std::map EEFmap; std::map ESFmap; }; @@ -71,19 +75,6 @@ private: //// Functions //// -/// MaterialInfo::init() is called during program initialization. It -/// precomputes material hash keys for a few basic endgames, in order -/// to make it easy to recognize such endgames when they occur. - -void MaterialInfo::init() { - - typedef Key ZM[2][8][16]; - const ZM& z = Position::zobMaterial; - - KNNKMaterialKey = z[WHITE][KNIGHT][1] ^ z[WHITE][KNIGHT][2]; - KKNNMaterialKey = z[BLACK][KNIGHT][1] ^ z[BLACK][KNIGHT][2]; -} - /// Constructor for the MaterialInfoTable class @@ -126,7 +117,7 @@ void MaterialInfoTable::clear() { /// is stored there, so we don't have to recompute everything when the /// same material configuration occurs again. -MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) { +MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { Key key = pos.get_material_key(); int index = key & (size - 1); @@ -136,7 +127,7 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) { // have analysed this material configuration before, and we can simply // return the information we found the last time instead of recomputing it. if (mi->key == key) - return mi; + return mi; // Clear the MaterialInfo object, and set its key mi->clear(); @@ -146,8 +137,8 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) { // KNN vs K is a draw. if (key == KNNKMaterialKey || key == KKNNMaterialKey) { - mi->factor[WHITE] = mi->factor[BLACK] = 0; - return mi; + mi->factor[WHITE] = mi->factor[BLACK] = 0; + return mi; } // Let's look if we have a specialized evaluation function for this @@ -177,10 +168,12 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) { // if we decide to add more special cases. We face problems when there // are several conflicting applicable scaling functions and we need to // decide which one to use. - ScalingInfo si = funcs->getESF(key); - if (si.fun != NULL) + Color c; + ScalingFunction* sf; + + if ((sf = funcs->getESF(key, &c)) != NULL) { - mi->scalingFunction[si.col] = si.fun; + mi->scalingFunction[c] = sf; return mi; } @@ -229,7 +222,6 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) { // Evaluate the material balance - Color c; int sign; Value egValue = Value(0); Value mgValue = Value(0); @@ -281,17 +273,16 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) { egValue -= sign * v; } } - mi->mgValue = int16_t(mgValue); mi->egValue = int16_t(egValue); return mi; } -/// EndgameFunctions members definition. This helper class is used to -/// store the maps of end game and scaling functions that MaterialInfoTable -/// will query for each key. The maps are constant, and are populated only -/// at construction. Being per thread avoids to use locks to access them. +/// EndgameFunctions member definitions. This class is used to store the maps +/// of end game and scaling functions that MaterialInfoTable will query for +/// each key. The maps are constant and are populated only at construction, +/// but are per-thread instead of globals to avoid expensive locks. EndgameFunctions::EndgameFunctions() { @@ -343,22 +334,18 @@ void EndgameFunctions::add(Key k, Color c, ScalingFunction* f) { ESFmap.insert(std::pair(k, s)); } -EndgameEvaluationFunction* EndgameFunctions::getEEF(Key key) { - - EndgameEvaluationFunction* f = NULL; - std::map::iterator it(EEFmap.find(key)); - if (it != EEFmap.end()) - f = it->second; +EndgameEvaluationFunction* EndgameFunctions::getEEF(Key key) const { - return f; + std::map::const_iterator it(EEFmap.find(key)); + return (it != EEFmap.end() ? it->second : NULL); } -ScalingInfo EndgameFunctions::getESF(Key key) { +ScalingFunction* EndgameFunctions::getESF(Key key, Color* c) const { - ScalingInfo si = {WHITE, NULL}; - std::map::iterator it(ESFmap.find(key)); - if (it != ESFmap.end()) - si = it->second; + std::map::const_iterator it(ESFmap.find(key)); + if (it == ESFmap.end()) + return NULL; - return si; + *c = it->second.col; + return it->second.fun; } diff --git a/src/material.h b/src/material.h index 45972958..4ebd78fd 100644 --- a/src/material.h +++ b/src/material.h @@ -35,7 +35,7 @@ //// /// MaterialInfo is a class which contains various information about a -/// material configuration. It contains a material balance evaluation, +/// 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. @@ -51,11 +51,9 @@ class MaterialInfo { public: Value mg_value() const; Value eg_value() const; - ScaleFactor scale_factor(const Position &pos, Color c) const; + ScaleFactor scale_factor(const Position& pos, Color c) const; bool specialized_eval_exists() const; - Value evaluate(const Position &pos) const; - - static void init(); + Value evaluate(const Position& pos) const; private: void clear(); @@ -64,20 +62,22 @@ private: int16_t mgValue; int16_t egValue; uint8_t factor[2]; - EndgameEvaluationFunction *evaluationFunction; - ScalingFunction *scalingFunction[2]; + EndgameEvaluationFunction* evaluationFunction; + ScalingFunction* scalingFunction[2]; }; -/// Stores the endgame evaluation functions maps. Should be per thread -/// because STL is not thread safe and locks are expensive. +/// EndgameFunctions class stores the endgame evaluation functions std::map. +/// Because STL library is not thread safe even for read access, the maps, +/// although with identical content, are replicated for each thread. This +/// is faster then using locks with an unique set of global maps. class EndgameFunctions; -/// The MaterialInfoTable class represents a pawn hash table. It is basically +/// The MaterialInfoTable class represents a pawn hash table. It is basically /// just an array of MaterialInfo objects and a few methods for accessing these -/// objects. The most important method is get_material_info, which looks up a +/// objects. The most important method is get_material_info, which looks up a /// position in the table and returns a pointer to a MaterialInfo object. class MaterialInfoTable { @@ -86,11 +86,11 @@ public: MaterialInfoTable(unsigned numOfEntries); ~MaterialInfoTable(); void clear(); - MaterialInfo *get_material_info(const Position &pos); + MaterialInfo* get_material_info(const Position& pos); private: unsigned size; - MaterialInfo *entries; + MaterialInfo* entries; EndgameFunctions* funcs; }; @@ -103,10 +103,12 @@ private: /// material balance evaluation for the middle game and the endgame. inline Value MaterialInfo::mg_value() const { + return Value(mgValue); } inline Value MaterialInfo::eg_value() const { + return Value(egValue); } @@ -115,6 +117,7 @@ inline Value MaterialInfo::eg_value() const { /// with all slots at their default values. inline void MaterialInfo::clear() { + mgValue = egValue = 0; factor[WHITE] = factor[BLACK] = uint8_t(SCALE_FACTOR_NORMAL); evaluationFunction = NULL; @@ -125,16 +128,17 @@ inline void MaterialInfo::clear() { /// MaterialInfo::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 -/// 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 +/// 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 MaterialInfo::scale_factor(const Position &pos, Color c) - const { - if(scalingFunction[c] != NULL) { - ScaleFactor sf = scalingFunction[c]->apply(pos); - if(sf != SCALE_FACTOR_NONE) - return sf; +inline ScaleFactor MaterialInfo::scale_factor(const Position& pos, Color c) const { + + if (scalingFunction[c] != NULL) + { + ScaleFactor sf = scalingFunction[c]->apply(pos); + if (sf != SCALE_FACTOR_NONE) + return sf; } return ScaleFactor(factor[c]); } @@ -145,15 +149,17 @@ inline ScaleFactor MaterialInfo::scale_factor(const Position &pos, Color c) /// or if the normal evaluation function should be used. inline bool MaterialInfo::specialized_eval_exists() const { + return evaluationFunction != NULL; } -/// MaterialInfo::evaluate applies a specialized evaluation function to a -/// given position object. It should only be called when -/// this->specialized_eval_exists() returns 'true'. +/// MaterialInfo::evaluate applies a specialized evaluation function +/// to a given position object. It should only be called when +/// specialized_eval_exists() returns 'true'. + +inline Value MaterialInfo::evaluate(const Position& pos) const { -inline Value MaterialInfo::evaluate(const Position &pos) const { return evaluationFunction->apply(pos); } -- 2.39.2