mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
Introduce namespace Material
And retire old struct MaterialTable simplifying the code. No functional change.
This commit is contained in:
parent
52bbf372bb
commit
231f62baf7
6 changed files with 72 additions and 104 deletions
|
@ -36,7 +36,7 @@ namespace {
|
||||||
struct EvalInfo {
|
struct EvalInfo {
|
||||||
|
|
||||||
// Pointers to material and pawn hash table entries
|
// Pointers to material and pawn hash table entries
|
||||||
MaterialEntry* mi;
|
Material::Entry* mi;
|
||||||
PawnEntry* pi;
|
PawnEntry* pi;
|
||||||
|
|
||||||
// attackedBy[color][piece type] is a bitboard representing all squares
|
// 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;
|
Score score, mobilityWhite, mobilityBlack;
|
||||||
|
|
||||||
Key key = pos.key();
|
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
|
// 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
|
// 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);
|
score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo);
|
||||||
|
|
||||||
// Probe the material hash table
|
// 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();
|
score += ei.mi->material_value();
|
||||||
|
|
||||||
// If we have a specialized evaluation function for the current material
|
// If we have a specialized evaluation function for the current material
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm> // For std::min
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -81,18 +81,54 @@ namespace {
|
||||||
&& pos.piece_count(Them, PAWN) >= 1;
|
&& pos.piece_count(Them, PAWN) >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// imbalance() calculates imbalance comparing piece count of each
|
||||||
|
/// piece type for both colors.
|
||||||
|
|
||||||
|
template<Color Us>
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
/// 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
|
/// 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.
|
/// 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();
|
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
|
// If e->key matches the position's material hash key, it means that we
|
||||||
// have analysed this material configuration before, and we can simply
|
// have analysed this material configuration before, and we can simply
|
||||||
|
@ -100,10 +136,10 @@ MaterialEntry* MaterialTable::probe(const Position& pos) {
|
||||||
if (e->key == key)
|
if (e->key == key)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
memset(e, 0, sizeof(MaterialEntry));
|
memset(e, 0, sizeof(Entry));
|
||||||
e->key = key;
|
e->key = key;
|
||||||
e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL;
|
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
|
// Let's look if we have a specialized evaluation function for this
|
||||||
// particular material configuration. First we look for a fixed
|
// 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
|
/// Material::game_phase() calculates the phase given the current
|
||||||
/// piece type for both colors.
|
|
||||||
|
|
||||||
template<Color Us>
|
|
||||||
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
|
|
||||||
/// position. Because the phase is strictly a function of the material, it
|
/// position. Because the phase is strictly a function of the material, it
|
||||||
/// is stored in MaterialEntry.
|
/// 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);
|
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
|
: npm <= EndgameLimit ? PHASE_ENDGAME
|
||||||
: Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
|
: Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Material
|
||||||
|
|
|
@ -25,31 +25,26 @@
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
const int MaterialTableSize = 8192;
|
namespace Material {
|
||||||
|
|
||||||
/// MaterialEntry is a class which contains various information about a
|
/// Material::Entry contains various information about a material configuration.
|
||||||
/// material configuration. It contains a material balance evaluation,
|
/// It contains a material balance evaluation, a function pointer to a special
|
||||||
/// a function pointer to a special endgame evaluation function (which in
|
/// endgame evaluation function (which in most cases is NULL, meaning that the
|
||||||
/// most cases is NULL, meaning that the standard evaluation function will
|
/// standard evaluation function will be used), and "scale factors".
|
||||||
/// be used), and "scale factors" for black and white.
|
|
||||||
///
|
///
|
||||||
/// The scale factors are used to scale the evaluation score up or down.
|
/// 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
|
/// 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.
|
/// of 4, which will result in scores of absolute value less than one pawn.
|
||||||
|
|
||||||
class MaterialEntry {
|
struct Entry {
|
||||||
|
|
||||||
friend struct MaterialTable;
|
Score material_value() const { return make_score(value, value); }
|
||||||
|
int space_weight() const { return spaceWeight; }
|
||||||
public:
|
Phase game_phase() const { return gamePhase; }
|
||||||
Score material_value() const;
|
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;
|
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;
|
Key key;
|
||||||
int16_t value;
|
int16_t value;
|
||||||
uint8_t factor[COLOR_NB];
|
uint8_t factor[COLOR_NB];
|
||||||
|
@ -59,55 +54,24 @@ private:
|
||||||
Phase gamePhase;
|
Phase gamePhase;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef HashTable<Entry, 8192> Table;
|
||||||
|
|
||||||
/// The MaterialTable class represents a material hash table. The most important
|
Entry* probe(const Position& pos, Table& entries, Endgames& endgames);
|
||||||
/// method is probe(), which returns a pointer to a MaterialEntry object.
|
Phase game_phase(const Position& pos);
|
||||||
|
|
||||||
struct MaterialTable {
|
/// Material::scale_factor takes a position and a color as input, and
|
||||||
|
|
||||||
MaterialEntry* probe(const Position& pos);
|
|
||||||
static Phase game_phase(const Position& pos);
|
|
||||||
template<Color Us> static int imbalance(const int pieceCount[][PIECE_TYPE_NB]);
|
|
||||||
|
|
||||||
HashTable<MaterialEntry, MaterialTableSize> entries;
|
|
||||||
Endgames endgames;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// MaterialEntry::scale_factor takes a position and a color as input, and
|
|
||||||
/// returns a scale factor for the given color. We have to provide the
|
/// 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
|
/// 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
|
/// 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
|
/// the position. For instance, in KBP vs K endgames, a scaling function
|
||||||
/// which checks for draws with rook pawns and wrong-colored bishops.
|
/// which checks for draws with rook pawns and wrong-colored bishops.
|
||||||
|
|
||||||
inline ScaleFactor MaterialEntry::scale_factor(const Position& pos, Color c) const {
|
inline ScaleFactor Entry::scale_factor(const Position& pos, Color c) const {
|
||||||
|
|
||||||
if (!scalingFunction[c])
|
return !scalingFunction[c] || (*scalingFunction[c])(pos) == SCALE_FACTOR_NONE
|
||||||
return ScaleFactor(factor[c]);
|
? ScaleFactor(factor[c]) : (*scalingFunction[c])(pos);
|
||||||
|
|
||||||
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 Phase MaterialEntry::game_phase() const {
|
|
||||||
return gamePhase;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool MaterialEntry::specialized_eval_exists() const {
|
|
||||||
return evaluationFunction != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !defined(MATERIAL_H_INCLUDED)
|
#endif // !defined(MATERIAL_H_INCLUDED)
|
||||||
|
|
|
@ -919,7 +919,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||||
|
|
||||||
// Prefetch pawn and material hash tables
|
// Prefetch pawn and material hash tables
|
||||||
prefetch((char*)thisThread->pawnTable.entries[st->pawnKey]);
|
prefetch((char*)thisThread->pawnTable.entries[st->pawnKey]);
|
||||||
prefetch((char*)thisThread->materialTable.entries[st->materialKey]);
|
prefetch((char*)thisThread->materialTable[st->materialKey]);
|
||||||
|
|
||||||
// Update incremental scores
|
// Update incremental scores
|
||||||
st->psqScore += psq_delta(piece, from, to);
|
st->psqScore += psq_delta(piece, from, to);
|
||||||
|
|
|
@ -208,7 +208,7 @@ void Search::think() {
|
||||||
if (Options["Contempt Factor"] && !Options["UCI_AnalyseMode"])
|
if (Options["Contempt Factor"] && !Options["UCI_AnalyseMode"])
|
||||||
{
|
{
|
||||||
int cf = Options["Contempt Factor"] * PawnValueMg / 100; // From centipawns
|
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);
|
||||||
DrawValue[~RootColor] = VALUE_DRAW + Value(cf);
|
DrawValue[~RootColor] = VALUE_DRAW + Value(cf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,8 @@ public:
|
||||||
|
|
||||||
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
|
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
|
||||||
Eval::Table evalTable;
|
Eval::Table evalTable;
|
||||||
MaterialTable materialTable;
|
Material::Table materialTable;
|
||||||
|
Endgames endgames;
|
||||||
PawnTable pawnTable;
|
PawnTable pawnTable;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
int maxPly;
|
int maxPly;
|
||||||
|
|
Loading…
Add table
Reference in a new issue