X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fmaterial.cpp;h=57cf05cadac8b36e1f056a47d62635c93110aae8;hp=9195880af4ccf5ffadd1abba7a226567007013b0;hb=0d69ac33ff1b0258c9b18dca48f7b8b40fab5713;hpb=3ed603cd64624d27de3f3f6e8f4e5dfccaaed420 diff --git a/src/material.cpp b/src/material.cpp index 9195880a..57cf05ca 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -1,7 +1,7 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Copyright (C) 2004-2008 Tord Romstad (Glaurung author) - Copyright (C) 2008 Marco Costalba + Copyright (C) 2008-2009 Marco Costalba Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,12 +23,12 @@ //// #include -#include #include #include #include "material.h" +using std::string; //// //// Local definitions @@ -36,13 +36,23 @@ namespace { + // Values modified by Joona Kiiski const Value BishopPairMidgameBonus = Value(109); const Value BishopPairEndgameBonus = Value(97); Key KNNKMaterialKey, KKNNMaterialKey; + // Unmapped endgame evaluation and scaling functions, these + // are accessed direcly and not through the function maps. + EvaluationFunction EvaluateKmmKm(WHITE); + EvaluationFunction EvaluateKXK(WHITE), EvaluateKKX(BLACK); + ScalingFunction ScaleKBPK(WHITE), ScaleKKBP(BLACK); + ScalingFunction ScaleKQKRP(WHITE), ScaleKRPKQ(BLACK); + ScalingFunction ScaleKPsK(WHITE), ScaleKKPs(BLACK); + ScalingFunction ScaleKPKPw(WHITE), ScaleKPKPb(BLACK); } + //// //// Classes //// @@ -53,24 +63,28 @@ namespace { class EndgameFunctions { + typedef EndgameEvaluationFunctionBase EF; + typedef EndgameScalingFunctionBase SF; + public: EndgameFunctions(); - EndgameEvaluationFunctionBase* getEEF(Key key) const; - EndgameScalingFunctionBase* getESF(Key key, Color* c) const; + ~EndgameFunctions(); + template T* get(Key key) const; private: - void add(const std::string& keyCode, EndgameEvaluationFunctionBase* f); - void add(const std::string& keyCode, Color c, EndgameScalingFunctionBase* f); - Key buildKey(const std::string& keyCode); + template void add(const string& keyCode); - struct ScalingInfo - { - Color col; - EndgameScalingFunctionBase* fun; - }; + static Key buildKey(const string& keyCode); + static const string swapColors(const string& keyCode); - std::map EEFmap; - std::map ESFmap; + std::map EEFmap; + std::map ESFmap; + + // Maps accessing functions for const and non-const references + template const std::map& map() const { return EEFmap; } + template<> const std::map& map() const { return ESFmap; } + template std::map& map() { return EEFmap; } + template<> std::map& map() { return ESFmap; } }; @@ -90,9 +104,8 @@ MaterialInfoTable::MaterialInfoTable(unsigned int numOfEntries) { { std::cerr << "Failed to allocate " << (numOfEntries * sizeof(MaterialInfo)) << " bytes for material hash table." << std::endl; - exit(EXIT_FAILURE); + Application::exit_with_failure(); } - clear(); } @@ -100,17 +113,8 @@ MaterialInfoTable::MaterialInfoTable(unsigned int numOfEntries) { MaterialInfoTable::~MaterialInfoTable() { - delete [] entries; delete funcs; -} - - -/// MaterialInfoTable::clear() clears a material hash table by setting -/// all entries to 0. - -void MaterialInfoTable::clear() { - - memset(entries, 0, size * sizeof(MaterialInfo)); + delete [] entries; } @@ -147,19 +151,19 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { // Let's look if we have a specialized evaluation function for this // particular material configuration. First we look for a fixed // configuration one, then a generic one if previous search failed. - if ((mi->evaluationFunction = funcs->getEEF(key)) != NULL) + if ((mi->evaluationFunction = funcs->get(key)) != NULL) return mi; else if ( pos.non_pawn_material(BLACK) == Value(0) && pos.piece_count(BLACK, PAWN) == 0 - && pos.non_pawn_material(WHITE) >= RookValueEndgame) + && pos.non_pawn_material(WHITE) >= RookValueMidgame) { mi->evaluationFunction = &EvaluateKXK; return mi; } else if ( pos.non_pawn_material(WHITE) == Value(0) && pos.piece_count(WHITE, PAWN) == 0 - && pos.non_pawn_material(BLACK) >= RookValueEndgame) + && pos.non_pawn_material(BLACK) >= RookValueMidgame) { mi->evaluationFunction = &EvaluateKKX; return mi; @@ -185,15 +189,14 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { // material configuration. Is there a suitable scaling function? // // The code below is rather messy, and it could easily get worse later, - // if we decide to add more special cases. We face problems when there + // 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. - Color c; EndgameScalingFunctionBase* sf; - if ((sf = funcs->getESF(key, &c)) != NULL) + if ((sf = funcs->get(key)) != NULL) { - mi->scalingFunction[c] = sf; + mi->scalingFunction[sf->color()] = sf; return mi; } @@ -254,6 +257,7 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { // Evaluate the material balance + Color c; int sign; Value egValue = Value(0); Value mgValue = Value(0); @@ -314,43 +318,42 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { /// 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. +/// but are per-thread instead of globals to avoid expensive locks needed +/// because std::map is not guaranteed to be thread-safe even if accessed +/// only for a lookup. EndgameFunctions::EndgameFunctions() { KNNKMaterialKey = buildKey("KNNK"); KKNNMaterialKey = buildKey("KKNN"); - add("KPK", &EvaluateKPK); - add("KKP", &EvaluateKKP); - add("KBNK", &EvaluateKBNK); - add("KKBN", &EvaluateKKBN); - add("KRKP", &EvaluateKRKP); - add("KPKR", &EvaluateKPKR); - add("KRKB", &EvaluateKRKB); - add("KBKR", &EvaluateKBKR); - add("KRKN", &EvaluateKRKN); - add("KNKR", &EvaluateKNKR); - add("KQKR", &EvaluateKQKR); - add("KRKQ", &EvaluateKRKQ); - add("KBBKN", &EvaluateKBBKN); - add("KNKBB", &EvaluateKNKBB); - - add("KNPK", WHITE, &ScaleKNPK); - add("KKNP", BLACK, &ScaleKKNP); - add("KRPKR", WHITE, &ScaleKRPKR); - add("KRKRP", BLACK, &ScaleKRKRP); - add("KBPKB", WHITE, &ScaleKBPKB); - add("KBKBP", BLACK, &ScaleKBKBP); - add("KBPKN", WHITE, &ScaleKBPKN); - add("KNKBP", BLACK, &ScaleKNKBP); - add("KRPPKRP", WHITE, &ScaleKRPPKRP); - add("KRPKRPP", BLACK, &ScaleKRPKRPP); - add("KRPPKRP", WHITE, &ScaleKRPPKRP); - add("KRPKRPP", BLACK, &ScaleKRPKRPP); + add >("KPK"); + add >("KBNK"); + add >("KRKP"); + add >("KRKB"); + add >("KRKN"); + add >("KQKR"); + add >("KBBKN"); + + add >("KNPK"); + add >("KRPKR"); + add >("KBPKB"); + add >("KBPPKB"); + add >("KBPKN"); + add >("KRPPKRP"); + add >("KRPPKRP"); +} + +EndgameFunctions::~EndgameFunctions() { + + for (std::map::iterator it = EEFmap.begin(); it != EEFmap.end(); ++it) + delete (*it).second; + + for (std::map::iterator it = ESFmap.begin(); it != ESFmap.end(); ++it) + delete (*it).second; } -Key EndgameFunctions::buildKey(const std::string& keyCode) { +Key EndgameFunctions::buildKey(const string& keyCode) { assert(keyCode.length() > 0 && keyCode[0] == 'K'); assert(keyCode.length() < 8); @@ -371,29 +374,25 @@ Key EndgameFunctions::buildKey(const std::string& keyCode) { return Position(s.str()).get_material_key(); } -void EndgameFunctions::add(const std::string& keyCode, EndgameEvaluationFunctionBase* f) { +const string EndgameFunctions::swapColors(const string& keyCode) { - EEFmap.insert(std::pair(buildKey(keyCode), f)); + // Build corresponding key for the opposite color: "KBPKN" -> "KNKBP" + size_t idx = keyCode.find("K", 1); + return keyCode.substr(idx) + keyCode.substr(0, idx); } -void EndgameFunctions::add(const std::string& keyCode, Color c, EndgameScalingFunctionBase* f) { +template +void EndgameFunctions::add(const string& keyCode) { - ScalingInfo s = {c, f}; - ESFmap.insert(std::pair(buildKey(keyCode), s)); -} + typedef typename T::Base F; -EndgameEvaluationFunctionBase* EndgameFunctions::getEEF(Key key) const { - - std::map::const_iterator it(EEFmap.find(key)); - return (it != EEFmap.end() ? it->second : NULL); + map().insert(std::pair(buildKey(keyCode), new T(WHITE))); + map().insert(std::pair(buildKey(swapColors(keyCode)), new T(BLACK))); } -EndgameScalingFunctionBase* EndgameFunctions::getESF(Key key, Color* c) const { - - std::map::const_iterator it(ESFmap.find(key)); - if (it == ESFmap.end()) - return NULL; +template +T* EndgameFunctions::get(Key key) const { - *c = it->second.col; - return it->second.fun; + std::map::const_iterator it(map().find(key)); + return (it != map().end() ? it->second : NULL); }