From 044ad593b3c9fa8ab70f9b2ebfc2c36ce398eb5f Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Mon, 20 Jul 2009 09:56:21 +0100 Subject: [PATCH] Add Tord's polynomial material balance Use a polynomial weighted evaluation to calculate material value. This is far more flexible and elegant then applying a series of single euristic rules as before. Also correct a design issue in which we returned two values, one for middle game and one for endgame, while instead, because game phase is a function of board material itself, only one value should be calculated and used both for mid and end game. Verified it is equivalent to the tuning branch results with parameter values sampled after 40.000 games. After 999 games at 1+0 Mod vs Orig +277 =482 -240 51.85% 518.0/999 +13 ELO Signed-off-by: Marco Costalba --- src/evaluate.cpp | 4 +-- src/material.cpp | 66 +++++++++++++++++++++++++++++++----------------- src/material.h | 21 +++++---------- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 7a4176b7..ecc73b35 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -326,8 +326,8 @@ Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID) { // Probe the material hash table ei.mi = MaterialTable[threadID]->get_material_info(pos); - ei.mgValue += ei.mi->mg_value(); - ei.egValue += ei.mi->eg_value(); + ei.mgValue += ei.mi->material_value(); + ei.egValue += ei.mi->material_value(); // If we have a specialized evaluation function for the current material // configuration, call it and return diff --git a/src/material.cpp b/src/material.cpp index 3fc05db8..8380ab8f 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -40,7 +40,18 @@ namespace { const Value BishopPairMidgameBonus = Value(109); const Value BishopPairEndgameBonus = Value(97); - Key KNNKMaterialKey, KKNNMaterialKey; + // Polynomial material balance parameters + const Value RedundantQueenPenalty = Value(320); + const Value RedundantRookPenalty = Value(554); + const int LinearCoefficients[6] = { 1709, -137, -1185, -166, 141, 59 }; + + const int QuadraticCoefficientsSameColor[][6] = { + { 0, 0, 0, 0, 0, 0 }, { 33, -6, 0, 0, 0, 0 }, { 29, 269, -12, 0, 0, 0 }, + { 0, 19, -4, 0, 0, 0 }, { -35, -10, 40, 95, 50, 0 }, { 52, 23, 78, 144, -11, -33 } }; + + const int QuadraticCoefficientsOppositeColor[][6] = { + { 0, 0, 0, 0, 0, 0 }, { -5, 0, 0, 0, 0, 0 }, { -33, 23, 0, 0, 0, 0 }, + { 17, 25, -3, 0, 0, 0 }, { 10, -2, -19, -67, 0, 0 }, { 69, 64, -41, 116, 137, 0 } }; // Unmapped endgame evaluation and scaling functions, these // are accessed direcly and not through the function maps. @@ -50,6 +61,8 @@ namespace { ScalingFunction ScaleKQKRP(WHITE), ScaleKRPKQ(BLACK); ScalingFunction ScaleKPsK(WHITE), ScaleKKPs(BLACK); ScalingFunction ScaleKPKPw(WHITE), ScaleKPKPb(BLACK); + + Key KNNKMaterialKey, KKNNMaterialKey; } @@ -261,10 +274,10 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { // Evaluate the material balance - Color c; + const int bishopsPair_count[2] = { pos.piece_count(WHITE, BISHOP) > 1, pos.piece_count(BLACK, BISHOP) > 1 }; + Color c, them; int sign; - Value egValue = Value(0); - Value mgValue = Value(0); + int matValue = 0; for (c = WHITE, sign = 1; c <= BLACK; c++, sign = -sign) { @@ -291,30 +304,37 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { } } - // Bishop pair - if (pos.piece_count(c, BISHOP) >= 2) - { - mgValue += sign * BishopPairMidgameBonus; - egValue += sign * BishopPairEndgameBonus; - } - - // Knights are stronger when there are many pawns on the board. The - // formula is taken from Larry Kaufman's paper "The Evaluation of Material - // Imbalances in Chess": + // Redundancy of major pieces, formula based on Kaufman's paper + // "The Evaluation of Material Imbalances in Chess" // http://mywebpages.comcast.net/danheisman/Articles/evaluation_of_material_imbalance.htm - mgValue += sign * Value(pos.piece_count(c, KNIGHT)*(pos.piece_count(c, PAWN)-5)*16); - egValue += sign * Value(pos.piece_count(c, KNIGHT)*(pos.piece_count(c, PAWN)-5)*16); - - // Redundancy of major pieces, again based on Kaufman's paper: if (pos.piece_count(c, ROOK) >= 1) + matValue -= sign * ((pos.piece_count(c, ROOK) - 1) * RedundantRookPenalty + pos.piece_count(c, QUEEN) * RedundantQueenPenalty); + + // Second-degree polynomial material imbalance by Tord Romstad + // + // We use NO_PIECE_TYPE as a place holder for the bishop pair "extended piece", + // this allow us to be more flexible in defining bishop pair bonuses. + them = opposite_color(c); + for (PieceType pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; pt1++) { - Value v = Value((pos.piece_count(c, ROOK) - 1) * 32 + pos.piece_count(c, QUEEN) * 16); - mgValue -= sign * v; - egValue -= sign * v; + int c1, c2, c3; + c1 = sign * (pt1 != NO_PIECE_TYPE ? pos.piece_count(c, pt1) : bishopsPair_count[c]); + if (!c1) + continue; + + matValue += c1 * LinearCoefficients[pt1]; + + for (PieceType pt2 = NO_PIECE_TYPE; pt2 <= pt1; pt2++) + { + c2 = (pt2 != NO_PIECE_TYPE ? pos.piece_count(c, pt2) : bishopsPair_count[c]); + c3 = (pt2 != NO_PIECE_TYPE ? pos.piece_count(them, pt2) : bishopsPair_count[them]); + matValue += c1 * c2 * QuadraticCoefficientsSameColor[pt1][pt2]; + matValue += c1 * c3 * QuadraticCoefficientsOppositeColor[pt1][pt2]; + } } } - mi->mgValue = int16_t(mgValue); - mi->egValue = int16_t(egValue); + + mi->value = int16_t(matValue / 16); return mi; } diff --git a/src/material.h b/src/material.h index 7730a4c9..5fa2e678 100644 --- a/src/material.h +++ b/src/material.h @@ -51,8 +51,7 @@ class MaterialInfo { public: MaterialInfo() : key(0) { clear(); } - Value mg_value() const; - Value eg_value() const; + Value material_value() const; ScaleFactor scale_factor(const Position& pos, Color c) const; int space_weight() const; bool specialized_eval_exists() const; @@ -62,8 +61,7 @@ private: inline void clear(); Key key; - int16_t mgValue; - int16_t egValue; + int16_t value; uint8_t factor[2]; EndgameEvaluationFunctionBase* evaluationFunction; EndgameScalingFunctionBase* scalingFunction[2]; @@ -102,17 +100,12 @@ private: //// Inline functions //// -/// MaterialInfo::mg_value and MaterialInfo::eg_value simply returns the -/// material balance evaluation for the middle game and the endgame. +/// MaterialInfo::material_value simply returns the material balance +/// evaluation that is independent from game phase. -inline Value MaterialInfo::mg_value() const { +inline Value MaterialInfo::material_value() const { - return Value(mgValue); -} - -inline Value MaterialInfo::eg_value() const { - - return Value(egValue); + return Value(value); } @@ -121,7 +114,7 @@ inline Value MaterialInfo::eg_value() const { inline void MaterialInfo::clear() { - mgValue = egValue = 0; + value = 0; factor[WHITE] = factor[BLACK] = uint8_t(SCALE_FACTOR_NORMAL); evaluationFunction = NULL; scalingFunction[WHITE] = scalingFunction[BLACK] = NULL; -- 2.39.2