Consider material density in king safety
authorFabian Fichter <ianfab@users.noreply.github.com>
Thu, 27 Aug 2020 20:45:45 +0000 (22:45 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Thu, 27 Aug 2020 20:55:58 +0000 (22:55 +0200)
Scale king danger of drop variants by material density
and thereby remove magic correction factors.

euroshogi STC
LLR: 2.97 (-2.94,2.94) [0.00,10.00]
Total: 2735 W: 1417 L: 1276 D: 42
http://www.variantfishtest.org:6543/tests/view/5f3fd4266e23db221d9e902e

euroshogi LTC
LLR: 2.95 (-2.94,2.94) [0.00,10.00]
Total: 1427 W: 760 L: 639 D: 28
http://www.variantfishtest.org:6543/tests/view/5f46e1076e23db221d9e9045

shogi STC
LLR: 2.95 (-2.94,2.94) [0.00,10.00]
Total: 6037 W: 3098 L: 2909 D: 30
http://www.variantfishtest.org:6543/tests/view/5f3fabca6e23db221d9e9013

shogi LTC
LLR: 2.98 (-2.94,2.94) [-10.00,5.00]
Total: 917 W: 487 L: 425 D: 5
http://www.variantfishtest.org:6543/tests/view/5f46b5236e23db221d9e9043

judkins STC
LLR: 2.96 (-2.94,2.94) [0.00,10.00]
Total: 2936 W: 1430 L: 1292 D: 214
http://www.variantfishtest.org:6543/tests/view/5f3fd48d6e23db221d9e9030

src/evaluate.cpp
src/material.cpp
src/material.h

index eba72b0..fcecece 100644 (file)
@@ -616,9 +616,10 @@ namespace {
     if (pos.king_type() == WAZIR)
         score += make_score(0, mg_value(score) / 2);
 
-    // For drop games, king danger is independent of game phase
+    // For drop games, king danger is independent of game phase, but dependent on material density
     if (pos.captures_to_hand() || pos.two_boards())
-        score = make_score(mg_value(score), mg_value(score)) * 2 / (2 + 16 / pos.max_rank() * !pos.shogi_doubled_pawn());
+        score = make_score(mg_value(score) * me->material_density() / 11000,
+                           mg_value(score) * me->material_density() / 11000);
 
     if (T)
         Trace::add(KING, Us, score);
index a01e24a..8afe7cc 100644 (file)
@@ -141,12 +141,14 @@ Entry* probe(const Position& pos) {
   Value npm   = Utility::clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
 
   // Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
-  if (pos.captures_to_hand())
+  if (pos.captures_to_hand() || pos.two_boards())
   {
       Value npm2 = VALUE_ZERO;
       for (PieceType pt : pos.piece_types())
           npm2 += (pos.count_in_hand(WHITE, pt) + pos.count_in_hand(BLACK, pt)) * PieceValue[MG][make_piece(WHITE, pt)];
       e->gamePhase = Phase(PHASE_MIDGAME * npm / std::max(int(npm + npm2), 1));
+      int countAll = pos.count_with_hand(WHITE, ALL_PIECES) + pos.count_with_hand(BLACK, ALL_PIECES);
+      e->materialDensity = (npm + npm2 + pos.count<PAWN>() * PawnValueMg) * countAll / ((pos.max_file() + 1) * (pos.max_rank() + 1));
   }
   else
       e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
index 9ab1d81..076f078 100644 (file)
@@ -41,6 +41,7 @@ struct Entry {
 
   Score imbalance() const { return make_score(value, value); }
   Phase game_phase() const { return gamePhase; }
+  int material_density() const { return materialDensity; }
   bool specialized_eval_exists() const { return evaluationFunction != nullptr; }
   Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); }
 
@@ -62,6 +63,7 @@ struct Entry {
   int16_t value;
   uint8_t factor[COLOR_NB];
   Phase gamePhase;
+  int materialDensity;
 };
 
 typedef HashTable<Entry, 8192> Table;