From 31d4f0b73430677e79873beef16830dc07857ddd Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sun, 21 Dec 2008 16:26:36 +0100 Subject: [PATCH] Merge space weigth evaluation fromGlaurung 2.2 Is a new evaluation rule that gives bonus in midgame to the side that has more space behind pawns for its minor pieces. Signed-off-by: Marco Costalba --- src/evaluate.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++---- src/material.cpp | 12 ++++++++ src/material.h | 12 ++++++++ src/ucioption.cpp | 1 + 4 files changed, 95 insertions(+), 6 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 3e396af3..9c35a0db 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -52,6 +52,7 @@ namespace { int WeightPassedPawnsMidgame = 0x100; int WeightPassedPawnsEndgame = 0x100; int WeightKingSafety[2] = { 0x100, 0x100 }; + int WeightSpace; // Internal evaluation weights. These are applied on top of the evaluation // weights read from UCI parameters. The purpose is to be able to change @@ -65,6 +66,7 @@ namespace { const int WeightPassedPawnsEndgameInternal = 0x100; const int WeightKingSafetyInternal = 0x100; const int WeightKingOppSafetyInternal = 0x100; + const int WeightSpaceInternal = 0x30; // Visually better to define tables constants typedef Value V; @@ -203,6 +205,19 @@ namespace { ((1ULL << SQ_A8) | (1ULL << SQ_H8)) }; + // The SpaceMask[color] contains area of the board which is consdered by + // the space evaluation. In the middle game, each side is given a bonus + // based on how many squares inside this area are safe and available for + // friendly minor pieces. + const Bitboard SpaceMask[2] = { + (1ULL<kingside_storm_value(WHITE) - ei.pi->queenside_storm_value(BLACK); + + // Evaluate space for both sides + if (ei.mi->space_weight() > 0) + { + evaluate_space(pos, WHITE, ei); + evaluate_space(pos, BLACK, ei); + } } // Mobility @@ -414,7 +437,7 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) { ei.egValue += apply_weight(ei.egMobility, WeightMobilityEndgame); // If we don't already have an unusual scale factor, check for opposite - // colored bishop endgames, and use a lower scale for those: + // colored bishop endgames, and use a lower scale for those if ( phase < PHASE_MIDGAME && pos.opposite_colored_bishops() && ( (factor[WHITE] == SCALE_FACTOR_NORMAL && ei.egValue > Value(0)) @@ -527,6 +550,7 @@ void read_weights(Color us) { WeightKingSafety[us] = weight_option("Cowardice", WeightKingSafetyInternal); WeightKingSafety[them] = weight_option("Aggressiveness", WeightKingOppSafetyInternal); + WeightSpace = weight_option("Space", WeightSpaceInternal); init_safety(); } @@ -1101,14 +1125,54 @@ namespace { } - // apply_weight applies an evaluation weight to a value. + // evaluate_space() computes the space evaluation for a given side. The + // space evaluation is a simple bonus based on the number of safe squares + // available for minor pieces on the central four files on ranks 2--4. Safe + // squares one, two or three squares behind a friendly pawn are counted + // twice. Finally, the space bonus is scaled by a weight taken from the + // material hash table. + + void evaluate_space(const Position &pos, Color us, EvalInfo &ei) { + + Color them = opposite_color(us); + + // Find the safe squares for our pieces inside the area defined by + // SpaceMask[us]. A square is unsafe it is attacked by an enemy + // pawn, or if it is undefended and attacked by an enemy piece. + + Bitboard safeSquares = + SpaceMask[us] & ~pos.pawns(us) & ~ei.attacked_by(them, PAWN) + & ~(~ei.attacked_by(us) & ei.attacked_by(them)); + + // Find all squares which are at most three squares behind some friendly + // pawn. + Bitboard behindFriendlyPawns = pos.pawns(us); + if(us == WHITE) { + behindFriendlyPawns |= (behindFriendlyPawns >> 8); + behindFriendlyPawns |= (behindFriendlyPawns >> 16); + } + else { + behindFriendlyPawns |= (behindFriendlyPawns << 8); + behindFriendlyPawns |= (behindFriendlyPawns << 16); + } + + int space = + count_1s_max_15(safeSquares) + + count_1s_max_15(behindFriendlyPawns & safeSquares); + + ei.mgValue += Sign[us] * + apply_weight(Value(space * ei.mi->space_weight()), WeightSpace); + } + + + // apply_weight() applies an evaluation weight to a value inline Value apply_weight(Value v, int w) { return (v*w) / 0x100; } - // scale_by_game_phase interpolates between a middle game and an endgame + // scale_by_game_phase() interpolates between a middle game and an endgame // score, based on game phase. It also scales the return value by a // ScaleFactor array. diff --git a/src/material.cpp b/src/material.cpp index 11fd3c9b..44700f81 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -237,6 +237,18 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { } } + // Compute the space weight + if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= + 2*QueenValueMidgame + 4*RookValueMidgame + 2*KnightValueMidgame) + { + int minorPieceCount = pos.piece_count(WHITE, KNIGHT) + + pos.piece_count(BLACK, KNIGHT) + + pos.piece_count(WHITE, BISHOP) + + pos.piece_count(BLACK, BISHOP); + + mi->spaceWeight = minorPieceCount * minorPieceCount; + } + // Evaluate the material balance int sign; diff --git a/src/material.h b/src/material.h index 4ebd78fd..5fbe6405 100644 --- a/src/material.h +++ b/src/material.h @@ -52,6 +52,7 @@ public: Value mg_value() const; Value eg_value() const; ScaleFactor scale_factor(const Position& pos, Color c) const; + int space_weight() const; bool specialized_eval_exists() const; Value evaluate(const Position& pos) const; @@ -64,6 +65,7 @@ private: uint8_t factor[2]; EndgameEvaluationFunction* evaluationFunction; ScalingFunction* scalingFunction[2]; + uint8_t spaceWeight; }; @@ -120,6 +122,7 @@ inline void MaterialInfo::clear() { mgValue = egValue = 0; factor[WHITE] = factor[BLACK] = uint8_t(SCALE_FACTOR_NORMAL); + spaceWeight = 0; evaluationFunction = NULL; scalingFunction[WHITE] = scalingFunction[BLACK] = NULL; } @@ -144,6 +147,15 @@ inline ScaleFactor MaterialInfo::scale_factor(const Position& pos, Color c) cons } +/// MaterialInfo::space_weight() simply returns the weight for the space +/// evaluation for this material configuration. + +inline int MaterialInfo::space_weight() const { + + return spaceWeight; +} + + /// MaterialInfo::specialized_eval_exists decides whether there is a /// specialized evaluation function for the current material configuration, /// or if the normal evaluation function should be used. diff --git a/src/ucioption.cpp b/src/ucioption.cpp index fa2a0cab..c777383e 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -85,6 +85,7 @@ namespace { o.push_back(Option("Pawn Structure (Endgame)", 100, 0, 200)); o.push_back(Option("Passed Pawns (Middle Game)", 100, 0, 200)); o.push_back(Option("Passed Pawns (Endgame)", 100, 0, 200)); + o.push_back(Option("Space", 100, 0, 200)); o.push_back(Option("Aggressiveness", 100, 0, 200)); o.push_back(Option("Cowardice", 100, 0, 200)); o.push_back(Option("King Safety Curve", "Quadratic", COMBO)); -- 2.39.2