diff --git a/src/evaluate.cpp b/src/evaluate.cpp
index f27c04ec..4765094a 100644
--- a/src/evaluate.cpp
+++ b/src/evaluate.cpp
@@ -36,7 +36,7 @@ namespace {
struct EvalInfo {
// Pointers to material and pawn hash table entries
- MaterialEntry* mi;
+ Material::Entry* mi;
PawnEntry* pi;
// 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;
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
// 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);
// 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();
// If we have a specialized evaluation function for the current material
diff --git a/src/material.cpp b/src/material.cpp
index 073bef81..72240867 100644
--- a/src/material.cpp
+++ b/src/material.cpp
@@ -17,7 +17,7 @@
along with this program. If not, see .
*/
-#include
+#include // For std::min
#include
#include
@@ -81,18 +81,54 @@ namespace {
&& pos.piece_count(Them, PAWN) >= 1;
}
+ /// imbalance() calculates imbalance comparing piece count of each
+ /// piece type for both colors.
+
+ template
+ 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 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
/// 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.
-MaterialEntry* MaterialTable::probe(const Position& pos) {
+Entry* probe(const Position& pos, Table& entries, Endgames& endgames) {
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
// have analysed this material configuration before, and we can simply
@@ -100,10 +136,10 @@ MaterialEntry* MaterialTable::probe(const Position& pos) {
if (e->key == key)
return e;
- memset(e, 0, sizeof(MaterialEntry));
+ memset(e, 0, sizeof(Entry));
e->key = key;
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
// 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
-/// piece type for both colors.
-
-template
-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
+/// Material::game_phase() calculates the phase given the current
/// position. Because the phase is strictly a function of the material, it
/// 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);
@@ -274,3 +274,5 @@ Phase MaterialTable::game_phase(const Position& pos) {
: npm <= EndgameLimit ? PHASE_ENDGAME
: Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
}
+
+} // namespace Material
diff --git a/src/material.h b/src/material.h
index 89f8f556..c88094cf 100644
--- a/src/material.h
+++ b/src/material.h
@@ -25,31 +25,26 @@
#include "position.h"
#include "types.h"
-const int MaterialTableSize = 8192;
+namespace Material {
-/// MaterialEntry is a class which contains various information about a
-/// 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.
+/// Material::Entry contains various information about a 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".
///
/// 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
/// of 4, which will result in scores of absolute value less than one pawn.
-class MaterialEntry {
+struct Entry {
- friend struct MaterialTable;
-
-public:
- Score material_value() const;
+ Score material_value() const { return make_score(value, value); }
+ int space_weight() const { return spaceWeight; }
+ Phase game_phase() const { return gamePhase; }
+ 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;
- int space_weight() const;
- Phase game_phase() const;
- bool specialized_eval_exists() const;
- Value evaluate(const Position& pos) const;
-private:
Key key;
int16_t value;
uint8_t factor[COLOR_NB];
@@ -59,55 +54,24 @@ private:
Phase gamePhase;
};
+typedef HashTable Table;
-/// The MaterialTable class represents a material hash table. The most important
-/// method is probe(), which returns a pointer to a MaterialEntry object.
+Entry* probe(const Position& pos, Table& entries, Endgames& endgames);
+Phase game_phase(const Position& pos);
-struct MaterialTable {
-
- MaterialEntry* probe(const Position& pos);
- static Phase game_phase(const Position& pos);
- template static int imbalance(const int pieceCount[][PIECE_TYPE_NB]);
-
- HashTable entries;
- Endgames endgames;
-};
-
-
-/// MaterialEntry::scale_factor takes a position and a color as input, and
+/// Material::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
/// 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 MaterialEntry::scale_factor(const Position& pos, Color c) const {
+inline ScaleFactor Entry::scale_factor(const Position& pos, Color c) const {
- if (!scalingFunction[c])
- return ScaleFactor(factor[c]);
-
- ScaleFactor sf = (*scalingFunction[c])(pos);
- return sf == SCALE_FACTOR_NONE ? ScaleFactor(factor[c]) : sf;
+ return !scalingFunction[c] || (*scalingFunction[c])(pos) == SCALE_FACTOR_NONE
+ ? ScaleFactor(factor[c]) : (*scalingFunction[c])(pos);
}
-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)
diff --git a/src/position.cpp b/src/position.cpp
index 37b5c049..0c19d820 100644
--- a/src/position.cpp
+++ b/src/position.cpp
@@ -919,7 +919,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
// Prefetch pawn and material hash tables
prefetch((char*)thisThread->pawnTable.entries[st->pawnKey]);
- prefetch((char*)thisThread->materialTable.entries[st->materialKey]);
+ prefetch((char*)thisThread->materialTable[st->materialKey]);
// Update incremental scores
st->psqScore += psq_delta(piece, from, to);
diff --git a/src/search.cpp b/src/search.cpp
index 654efb32..292faf04 100644
--- a/src/search.cpp
+++ b/src/search.cpp
@@ -208,7 +208,7 @@ void Search::think() {
if (Options["Contempt Factor"] && !Options["UCI_AnalyseMode"])
{
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);
}
diff --git a/src/thread.h b/src/thread.h
index 6c3c18af..64a56ccb 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -110,7 +110,8 @@ public:
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
Eval::Table evalTable;
- MaterialTable materialTable;
+ Material::Table materialTable;
+ Endgames endgames;
PawnTable pawnTable;
size_t idx;
int maxPly;