Repository: google-deepmind/open_spiel (language: python)

Issue:
Phantom Tic-Tac-Toe information state bug
Hey there, I was looking at the phantom tic-tac-toe implementation, specifically the information state tensor:

```cpp
void PhantomTTTState::InformationStateTensor(Player player,
                                             absl::Span<float> values) const {
  SPIEL_CHECK_GE(player, 0);
  SPIEL_CHECK_LT(player, num_players_);

  // First 27 bits encodes the player's view in the same way as TicTacToe.
  // Then the action sequence follows (one-hot encoded, per action).
  // Encoded in the same way as InformationStateAsString, so full sequences
  // which may contain action value 10 to represent "I don't know."
  const auto& player_view = player == 0 ? x_view_ : o_view_;
  SPIEL_CHECK_EQ(values.size(), kNumCells * kCellStates +
                                    kLongestSequence * (1 + kBitsPerAction));
  std::fill(values.begin(), values.end(), 0.);
  for (int cell = 0; cell < kNumCells; ++cell) {
    values[kNumCells * static_cast<int>(player_view[cell]) + cell] = 1.0;
  }

  // Now encode the sequence. Each (player, action) pair uses 11 bits:
  //   - first bit is the player taking the action (0 or 1)
  //   - next 10 bits is the one-hot encoded action (10 = "I don't know")
  int offset = kNumCells * kCellStates;
  for (const auto& player_with_action : action_sequence_) {
    if (player_with_action.first == player) {
      // Always include the observing player's actions.
      values[offset] = player_with_action.first;  // Player 0 or 1
      values[offset + 1 + player_with_action.second] = 1.0;
    } else if (obs_type_ == ObservationType::kRevealNumTurns) {
      // If the number of turns are revealed, then each of the other player's
      // actions will show up as unknowns.
      values[offset] = player_with_action.first;
      values[offset + 1 + 10] = 1.0;  // I don't know.
    } else {
      // Do not reveal anything about the number of actions taken by opponent.
      SPIEL_CHECK_EQ(obs_type_, ObservationType::kRevealNothing);
    }

    offset += (1 + kBitsPerAction);
  }
}
```

Firstly, `values[offset + 1 + 10] = 1.0;  // I don't know.` should be `1 + 9` I believe since actions range from 0-8 and not 1-9.

Second, we offset `offset += (1 + kBitsPerAction);` in any case. In the default case of `ObservationType::kRevealNothing`, I think we should only offset in the if and the else if, but now in the else (right now we always offset). 

For instance, with `ObservationType::kRevealNumTurns` we could get, for player 0's info string:

```bash
move 0: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
move 1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
move 2: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
move 3: [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
move 4: [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
move 5: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
```

(and you can see that the last "i don't know" action isn't set to 1, as per my previous point).

With `ObservationType::kRevealNothing`, we get:

```bash
move 0: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
move 1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
move 2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
move 3: [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
move 4: [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
move 5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
```

So well, we can still see the number of moves the opponent did by counting the lines of zeros. 


Discussion / hints:
I see that the problem is exactly the same in Dark Hex 3. Am I maybe missing something? 
I believe you're right (at least for both issues in Phantom TTT -- haven't looked at Dark Hex). Nice find.

Can you submit a PR fix? 

I think the information state size also be smaller then in the case of `kRevealNothing` (since its upper bound is smaller). And then we can put a check that the offset has reached the exactly the size of the container at the end of the function (like we do in other games).

If/when you're convinced that this is also an issue in Dark Hex, can you open another issue that refrers to this one? (Maybe also listing the code as you did here)

Fix patch:
diff --git a/open_spiel/games/dark_hex/dark_hex.cc b/open_spiel/games/dark_hex/dark_hex.cc
index 018199bb96..0e65c5b012 100644
--- a/open_spiel/games/dark_hex/dark_hex.cc
+++ b/open_spiel/games/dark_hex/dark_hex.cc
@@ -107,11 +107,18 @@ DarkHexState::DarkHexState(std::shared_ptr<const Game> game, int num_cols,
       game_version_(game_version),
       num_cols_(num_cols),
       num_rows_(num_rows),
-      num_cells_(num_cols * num_rows),
-      bits_per_action_(num_cells_ + 1),
-      longest_sequence_(num_cells_ * 2 - 1) {
+      num_cells_(num_cols * num_rows) {
   black_view_.resize(num_cols * num_rows, CellState::kEmpty);
   white_view_.resize(num_cols * num_rows, CellState::kEmpty);
+  if (obs_type == ObservationType::kRevealNothing) {
+    bits_per_action_ = num_cells_;
+    longest_sequence_ = num_cells_;
+  } else {
+    SPIEL_CHECK_EQ(obs_type_, ObservationType::kRevealNumTurns);
+    // Reserve 0 for the player and 10 as "I don't know."
+    bits_per_action_ = num_cells_ + 2;
+    longest_sequence_ = num_cells_ * 2 - 1;
+  }
 }
 
 void DarkHexState::DoApplyAction(Action move) {
@@ -218,7 +225,7 @@ void DarkHexState::InformationStateTensor(Player player,
   const auto& player_view = (player == 0 ? black_view_ : white_view_);
 
   SPIEL_CHECK_EQ(values.size(), num_cells_ * kCellStates +
-                                    longest_sequence_ * (1 + bits_per_action_));
+                                    longest_sequence_ * bits_per_action_);
   std::fill(values.begin(), values.end(), 0.);
   for (int cell = 0; cell < num_cells_; ++cell) {
     values[cell * kCellStates +
@@ -230,18 +237,25 @@ void DarkHexState::InformationStateTensor(Player player,
   for (const auto& player_with_action : action_sequence_) {
     if (player_with_action.first == player) {
       // Always include the observing player's actions.
-      values[offset] = player_with_action.first;
-      values[offset + 1 + player_with_action.second] = 1.0;
+      if (obs_type_ == ObservationType::kRevealNumTurns) {
+        values[offset] = player_with_action.first;  // Player 0 or 1
+        values[offset + 1 + player_with_action.second] = 1.0;
+      } else {
+        // Here we don't need to encode the player since we won't see opponent moves.
+        SPIEL_CHECK_EQ(obs_type_, ObservationType::kRevealNothing);
+        values[offset + player_with_action.second] = 1.0;
+      }
+      offset += bits_per_action_;
     } else if (obs_type_ == ObservationType::kRevealNumTurns) {
       // If the number of turns are revealed, then each of the other player's
       // actions will show up as unknowns. Here, num_cells_ is used to
       // encode "unknown".
       values[offset] = player_with_action.first;
       values[offset + 1 + num_cells_] = 1.0;
+      offset += bits_per_action_;
     } else {
       SPIEL_CHECK_EQ(obs_type_, ObservationType::kRevealNothing);
     }
-    offset += (1 + bits_per_action_);
   }
 }
 
@@ -290,14 +304,17 @@ DarkHexGame::DarkHexGame(const GameParameters& params, GameType game_type)
           ParameterValue<int>("num_cols", ParameterValue<int>("board_size"))),
       num_rows_(
           ParameterValue<int>("num_rows", ParameterValue<int>("board_size"))),
-      num_cells_(num_cols_ * num_rows_),
-      bits_per_action_(num_cells_ + 1),
-      longest_sequence_(num_cells_ * 2 - 1) {
+      num_cells_(num_cols_ * num_rows_) {
   std::string obs_type = ParameterValue<std::string>("obstype");
   if (obs_type == "reveal-nothing") {
     obs_type_ = ObservationType::kRevealNothing;
+    bits_per_action_ = num_cells_;
+    longest_sequence_ = num_cells_;
   } else if (obs_type == "reveal-numturns") {
     obs_type_ = ObservationType::kRevealNumTurns;
+    // Reserve 0 for the player and 10 as "I don't know."
+    bits_per_action_ = num_cells_ + 2;
+    longest_sequence_ = num_cells_ * 2 - 1;
   } else {
     SpielFatalError(absl::StrCat("Unrecognized observation type: ", obs_type));
   }
@@ -314,7 +331,7 @@ DarkHexGame::DarkHexGame(const GameParameters& params, GameType game_type)
 
 std::vector<int> DarkHexGame::InformationStateTensorShape() const {
   return {num_cells_ * kCellStates +
-          longest_sequence_ * (1 + bits_per_action_)};
+          longest_sequence_ * bits_per_action_};
 }
 
 std::vector<int> DarkHexGame::ObservationTensorShape() const {
diff --git a/open_spiel/games/dark_hex/dark_hex.h b/open_spiel/games/dark_hex/dark_hex.h
index 5c7891aad7..4fcc3b0399 100644
--- a/open_spiel/games/dark_hex/dark_hex.h
+++ b/open_spiel/games/dark_hex/dark_hex.h
@@ -125,8 +125,8 @@ class DarkHexState : public State {
   const int num_cols_;  // x
   const int num_rows_;  // y
   const int num_cells_;
-  const int bits_per_action_;
-  const int longest_sequence_;
+  int bits_per_action_;
+  int longest_sequence_;
 
   // Change this to _history on base class
   std::vector<std::pair<int, Action>> action_sequence_;
@@ -166,8 +166,8 @@ class DarkHexGame : public Game {
   const int num_cols_;
   const int num_rows_;
   const int num_cells_;
-  const int bits_per_action_;
-  const int longest_sequence_;
+  int bits_per_action_;
+  int longest_sequence_;
 };
 
 class ImperfectRecallDarkHexState : public DarkHexState {
diff --git a/open_spiel/games/phantom_ttt/phantom_ttt.cc b/open_spiel/games/phantom_ttt/phantom_ttt.cc
index 7bdc585d2c..6d4f8ea7a0 100644
--- a/open_spiel/games/phantom_ttt/phantom_ttt.cc
+++ b/open_spiel/games/phantom_ttt/phantom_ttt.cc
@@ -94,9 +94,21 @@ ImperfectRecallPTTTGame::ImperfectRecallPTTTGame(const GameParameters& params)
 
 PhantomTTTState::PhantomTTTState(std::shared_ptr<const Game> game,
                                  ObservationType obs_type)
-    : State(game), state_(game), obs_type_(obs_type) {
+    : State(game),
+      state_(game),
+      obs_type_(obs_type) {
   std::fill(begin(x_view_), end(x_view_), CellState::kEmpty);
   std::fill(begin(o_view_), end(o_view_), CellState::kEmpty);
+  if (obs_type_ == ObservationType::kRevealNumTurns) {
+    // Reserve 0 for the player and 10 as "I don't know."
+    bits_per_action_ = kNumCells + 2;
+    // Longest sequence is 17 moves, e.g. 0011223344556677889
+    longest_sequence_ = 2 * kNumCells - 1;
+  } else {
+    SPIEL_CHECK_EQ(obs_type_, ObservationType::kRevealNothing);
+    bits_per_action_ = kNumCells;
+    longest_sequence_ = kNumCells;
+  }
 }
 
 void PhantomTTTState::DoApplyAction(Action move) {
@@ -193,7 +205,7 @@ void PhantomTTTState::InformationStateTensor(Player player,
   // which may contain action value 10 to represent "I don't know."
   const auto& player_view = player == 0 ? x_view_ : o_view_;
   SPIEL_CHECK_EQ(values.size(), kNumCells * kCellStates +
-                                    kLongestSequence * (1 + kBitsPerAction));
+                                    longest_sequence_ * bits_per_action_);
   std::fill(values.begin(), values.end(), 0.);
   for (int cell = 0; cell < kNumCells; ++cell) {
     values[kNumCells * static_cast<int>(player_view[cell]) + cell] = 1.0;
@@ -206,19 +218,25 @@ void PhantomTTTState::InformationStateTensor(Player player,
   for (const auto& player_with_action : action_sequence_) {
     if (player_with_action.first == player) {
       // Always include the observing player's actions.
-      values[offset] = player_with_action.first;  // Player 0 or 1
-      values[offset + 1 + player_with_action.second] = 1.0;
+      if (obs_type_ == ObservationType::kRevealNumTurns) {
+        values[offset] = player_with_action.first;  // Player 0 or 1
+        values[offset + 1 + player_with_action.second] = 1.0;
+      } else {
+        // Here we don't need to encode the player since we won't see opponent moves.
+        SPIEL_CHECK_EQ(obs_type_, ObservationType::kRevealNothing);
+        values[offset + player_with_action.second] = 1.0;
+      }
+      offset += bits_per_action_;
     } else if (obs_type_ == ObservationType::kRevealNumTurns) {
       // If the number of turns are revealed, then each of the other player's
       // actions will show up as unknowns.
       values[offset] = player_with_action.first;
-      values[offset + 1 + 10] = 1.0;  // I don't know.
+      values[offset + 1 + kNumCells] = 1.0;  // I don't know.
+      offset += bits_per_action_;
     } else {
       // Do not reveal anything about the number of actions taken by opponent.
       SPIEL_CHECK_EQ(obs_type_, ObservationType::kRevealNothing);
     }
-
-    offset += (1 + kBitsPerAction);
   }
 }
 
@@ -283,8 +301,14 @@ PhantomTTTGame::PhantomTTTGame(const GameParameters& params, GameType game_type)
   std::string obs_type = ParameterValue<std::string>("obstype");
   if (obs_type == "reveal-nothing") {
     obs_type_ = ObservationType::kRevealNothing;
+    bits_per_action_ = kNumCells;
+    longest_sequence_ = kNumCells;
   } else if (obs_type == "reveal-numturns") {
     obs_type_ = ObservationType::kRevealNumTurns;
+    // Reserve 0 for the player and 10 as "I don't know."
+    bits_per_action_ = kNumCells + 2;
+    // Longest sequence is 17 moves, e.g. 0011223344556677889
+    longest_sequence_ = 2 * kNumCells - 1;
   } else {
     SpielFatalError(absl::StrCat("Unrecognized observation type: ", obs_type));
   }
@@ -292,16 +316,16 @@ PhantomTTTGame::PhantomTTTGame(const GameParameters& params, GameType game_type)
 
 std::vector<int> PhantomTTTGame::InformationStateTensorShape() const {
   // Enc
-  return {1, kNumCells * kCellStates + kLongestSequence * (1 + kBitsPerAction)};
+  return {1, kNumCells * kCellStates + longest_sequence_ * bits_per_action_};
 }
 
 std::vector<int> PhantomTTTGame::ObservationTensorShape() const {
   if (obs_type_ == ObservationType::kRevealNothing) {
     return {kNumCells * kCellStates};
   } else if (obs_type_ == ObservationType::kRevealNumTurns) {
-    return {kNumCells * kCellStates + kLongestSequence};
+    return {kNumCells * kCellStates + longest_sequence_};
   } else {
-    SpielFatalError("Uknown observation type");
+    SpielFatalError("Unknown observation type");
   }
 }
 
diff --git a/open_spiel/games/phantom_ttt/phantom_ttt.h b/open_spiel/games/phantom_ttt/phantom_ttt.h
index df1ac0a0e3..77df2fd46b 100644
--- a/open_spiel/games/phantom_ttt/phantom_ttt.h
+++ b/open_spiel/games/phantom_ttt/phantom_ttt.h
@@ -45,10 +45,6 @@ namespace phantom_ttt {
 
 inline constexpr const char* kDefaultObsType = "reveal-nothing";
 
-// Longest sequence is 17 moves, e.g. 0011223344556677889
-inline constexpr int kLongestSequence = 2 * tic_tac_toe::kNumCells - 1;
-inline constexpr int kBitsPerAction = 10;  // Reserve 9 as "I don't know."
-
 enum class ObservationType {
   kRevealNothing,
   kRevealNumTurns,
@@ -88,6 +84,9 @@ class PhantomTTTState : public State {
 
   tic_tac_toe::TicTacToeState state_;
   ObservationType obs_type_;
+  int bits_per_action_;
+  int longest_sequence_;
+
   // TODO(author2): Use the base class history_ instead.
   std::vector<std::pair<int, Action>> action_sequence_;
   std::array<tic_tac_toe::CellState, tic_tac_toe::kNumCells> x_view_;
@@ -119,13 +118,17 @@ class PhantomTTTGame : public Game {
   // These will depend on the obstype parameter.
   std::vector<int> InformationStateTensorShape() const override;
   std::vector<int> ObservationTensorShape() const override;
-  int MaxGameLength() const override { return kLongestSequence; }
+  int MaxGameLength() const override { 
+    return tic_tac_toe::kNumCells * 2 - 1;
+  }
 
   ObservationType obs_type() const { return obs_type_; }
 
  private:
   std::shared_ptr<const tic_tac_toe::TicTacToeGame> game_;
   ObservationType obs_type_;
+  int bits_per_action_;
+  int longest_sequence_;
 };
 
 // Implements the FOE abstraction from Lanctot et al. '12


Test patch:
diff --git a/open_spiel/integration_tests/playthroughs/dark_hex(num_rows=5,num_cols=3).txt b/open_spiel/integration_tests/playthroughs/dark_hex(num_rows=5,num_cols=3).txt
index f78a799b12..08a9aeba15 100644
--- a/open_spiel/integration_tests/playthroughs/dark_hex(num_rows=5,num_cols=3).txt
+++ b/open_spiel/integration_tests/playthroughs/dark_hex(num_rows=5,num_cols=3).txt
@@ -24,9 +24,9 @@ NumPlayers() = 2
 MinUtility() = -1.0
 MaxUtility() = 1.0
 UtilitySum() = 0.0
-InformationStateTensorShape() = [628]
+InformationStateTensorShape() = [360]
 InformationStateTensorLayout() = TensorLayout.CHW
-InformationStateTensorSize() = 628
+InformationStateTensorSize() = 360
 ObservationTensorShape() = [135]
 ObservationTensorLayout() = TensorLayout.CHW
 ObservationTensorSize() = 135
@@ -47,8 +47,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 0
 InformationStateString(0) = "...\n...\n...\n...\n...\n0\n"
 InformationStateString(1) = "...\n...\n...\n...\n...\n0\n"
-InformationStateTensor(0): binvec(628, 0x804020100804020100804020100804020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x804020100804020100804020100804020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x80402010080402010080402010080402000000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(1): binvec(360, 0x80402010080402010080402010080402000000000000000000000000000000000000000000000000000000000)
 ObservationString(0) = "...\n...\n...\n...\n..."
 ObservationString(1) = "...\n...\n...\n...\n..."
 ObservationTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -75,8 +75,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 1
 InformationStateString(0) = "x..\n...\n...\n...\n...\n1\n0,0 "
 InformationStateString(1) = "...\n...\n...\n...\n...\n1\n"
-InformationStateTensor(0): binvec(628, 0x404020100804020100804020100804020800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x804020100804020100804020100804020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40402010080402010080402010080402100000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(1): binvec(360, 0x80402010080402010080402010080402000000000000000000000000000000000000000000000000000000000)
 ObservationString(0) = "x..\n...\n...\n...\n..."
 ObservationString(1) = "...\n...\n...\n...\n..."
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -103,8 +103,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 0
 InformationStateString(0) = "x..\n...\n...\n...\n...\n2\n0,0 "
 InformationStateString(1) = "...\n...\n...\n...\n..o\n2\n1,14 "
-InformationStateTensor(0): binvec(628, 0x404020100804020100804020100804020800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x804020100804020100804020100804040000080010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40402010080402010080402010080402100000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(1): binvec(360, 0x80402010080402010080402010080404000040000000000000000000000000000000000000000000000000000)
 ObservationString(0) = "x..\n...\n...\n...\n..."
 ObservationString(1) = "...\n...\n...\n...\n..o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -131,8 +131,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 1
 InformationStateString(0) = "x..\n..x\n...\n...\n...\n3\n0,0 0,5 "
 InformationStateString(1) = "...\n...\n...\n...\n..o\n3\n1,14 "
-InformationStateTensor(0): binvec(628, 0x404020100802020100804020100804020800000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x804020100804020100804020100804040000080010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40402010080202010080402010080402100001000000000000000000000000000000000000000000000000000)
+InformationStateTensor(1): binvec(360, 0x80402010080402010080402010080404000040000000000000000000000000000000000000000000000000000)
 ObservationString(0) = "x..\n..x\n...\n...\n..."
 ObservationString(1) = "...\n...\n...\n...\n..o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -159,8 +159,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 0
 InformationStateString(0) = "x..\n..x\n...\n...\n...\n4\n0,0 0,5 "
 InformationStateString(1) = "...\n...\n...\n..o\n..o\n4\n1,14 1,11 "
-InformationStateTensor(0): binvec(628, 0x404020100802020100804020100804020800000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x804020100804020100804020200804040000080010000200200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40402010080202010080402010080402100001000000000000000000000000000000000000000000000000000)
+InformationStateTensor(1): binvec(360, 0x80402010080402010080402020080404000040040000000000000000000000000000000000000000000000000)
 ObservationString(0) = "x..\n..x\n...\n...\n..."
 ObservationString(1) = "...\n...\n...\n..o\n..o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -195,8 +195,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 1
 InformationStateString(0) = "x..\n.xx\n...\n..o\n..o\n7\n0,0 0,5 0,14 0,11 0,4 "
 InformationStateString(1) = "...\n...\n...\n..o\n..o\n7\n1,14 1,11 "
-InformationStateTensor(0): binvec(628, 0x404020100402020100804020200804040800000000100000000002000802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x804020100804020100804020200804040000080010000200200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40402010040202010080402020080404100001000001001010000000000000000000000000000000000000000)
+InformationStateTensor(1): binvec(360, 0x80402010080402010080402020080404000040040000000000000000000000000000000000000000000000000)
 ObservationString(0) = "x..\n.xx\n...\n..o\n..o"
 ObservationString(1) = "...\n...\n...\n..o\n..o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯
@@ -263,8 +263,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 0
 InformationStateString(0) = "xo.\n.xx\n.x.\no.o\nxxo\n18\n0,0 0,5 0,14 0,11 0,4 0,13 0,12 0,7 0,1 0,9 "
 InformationStateString(1) = ".o.\n.x.\noxo\no.o\n..o\n18\n1,14 1,11 1,8 1,6 1,1 1,4 1,7 1,9 "
-InformationStateTensor(0): binvec(628, 0x408020100402020080808020200402040800000000100000000002000802000000000040000000200000010000000000000004000002000000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x808020100404040081008020200804040000080010000200200000000000002010000008100000028000000084004040200800000000000000000000000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40802010040202008080802020040204100001000001001010000010004010080000100000000000000000000)
+InformationStateTensor(1): binvec(360, 0x80802010040404008100802020080404000040040040020080002000080004000000000000000000000000000)
 ObservationString(0) = "xo.\n.xx\n.x.\no.o\nxxo"
 ObservationString(1) = ".o.\n.x.\noxo\no.o\n..o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯
@@ -299,8 +299,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 1
 InformationStateString(0) = "xo.\n.xx\n.x.\noxo\nxxo\n21\n0,0 0,5 0,14 0,11 0,4 0,13 0,12 0,7 0,1 0,9 0,10 "
 InformationStateString(1) = "xo.\n.x.\noxo\noxo\n..o\n21\n1,14 1,11 1,8 1,6 1,1 1,4 1,7 1,9 1,10 1,0 "
-InformationStateTensor(0): binvec(628, 0x408020100402020080808010200402040800000000100000000002000802000000000040000000200000010000000000000004000002000080000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(628, 0x408020100404040081008010200804040000080010000200200000000000002010000008100000028000000084004040200800000000000002004180000000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40802010040202008080801020040204100001000001001010000010004010080000100010000000000000000)
+InformationStateTensor(1): binvec(360, 0x40802010040404008100801020080404000040040040020080002000080004000420000000000000000000000)
 ObservationString(0) = "xo.\n.xx\n.x.\noxo\nxxo"
 ObservationString(1) = "xo.\n.x.\noxo\noxo\n..o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯
@@ -339,8 +339,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = -4
 InformationStateString(0) = "xoo\nXxx\n.xo\noxo\nxxo\n25\n0,0 0,5 0,14 0,11 0,4 0,13 0,12 0,7 0,1 0,9 0,10 0,2 0,8 0,3 "
 InformationStateString(1) = "xoo\n.x.\noxo\noxo\n..o\n25\n1,14 1,11 1,8 1,6 1,1 1,4 1,7 1,9 1,10 1,0 1,2 "
-InformationStateTensor(0): binvec(628, 0x408040010402020081008010200402040800000000100000000002000802000000000040000000200000010000000000000004000002000080000000000000080000100100000000000000000000)
-InformationStateTensor(1): binvec(628, 0x408040100404040081008010200804040000080010000200200000000000002010000008100000028000000084004040200800000000000002004180009000000000000000000000000000000000)
+InformationStateTensor(0): binvec(360, 0x40804001040202008100801020040204100001000001001010000010004010080000100010200001004000000)
+InformationStateTensor(1): binvec(360, 0x40804010040404008100801020080404000040040040020080002000080004000420001000000000000000000)
 ObservationString(0) = "xoo\nXxx\n.xo\noxo\nxxo"
 ObservationString(1) = "xoo\n.x.\noxo\noxo\n..o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯
diff --git a/open_spiel/integration_tests/playthroughs/dark_hex_ir(board_size=3).txt b/open_spiel/integration_tests/playthroughs/dark_hex_ir(board_size=3).txt
index f9d876ee1e..fbb89363c1 100644
--- a/open_spiel/integration_tests/playthroughs/dark_hex_ir(board_size=3).txt
+++ b/open_spiel/integration_tests/playthroughs/dark_hex_ir(board_size=3).txt
@@ -24,9 +24,9 @@ NumPlayers() = 2
 MinUtility() = -1.0
 MaxUtility() = 1.0
 UtilitySum() = 0.0
-InformationStateTensorShape() = [268]
+InformationStateTensorShape() = [162]
 InformationStateTensorLayout() = TensorLayout.CHW
-InformationStateTensorSize() = 268
+InformationStateTensorSize() = 162
 ObservationTensorShape() = [81]
 ObservationTensorLayout() = TensorLayout.CHW
 ObservationTensorSize() = 81
@@ -45,8 +45,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 0
 InformationStateString(0) = "P0 ...\n...\n..."
 InformationStateString(1) = "P1 ...\n...\n..."
-InformationStateTensor(0): binvec(268, 0x804020100804020100800000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(268, 0x804020100804020100800000000000000000000000000000000000000000000000)
+InformationStateTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+InformationStateTensor(1): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n...\n..."
 ObservationString(1) = "...\n...\n..."
 ObservationTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -71,8 +71,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 1
 InformationStateString(0) = "P0 ...\n.x.\n..."
 InformationStateString(1) = "P1 ...\n...\n..."
-InformationStateTensor(0): binvec(268, 0x804020100404020100802000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(268, 0x804020100804020100800000000000000000000000000000000000000000000000)
+InformationStateTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+InformationStateTensor(1): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n.x.\n..."
 ObservationString(1) = "...\n...\n..."
 ObservationTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -97,8 +97,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 0
 InformationStateString(0) = "P0 ...\n.x.\n..."
 InformationStateString(1) = "P1 ...\n...\n..o"
-InformationStateTensor(0): binvec(268, 0x804020100404020100802000000000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(268, 0x804020100804020101000080400000000000000000000000000000000000000000)
+InformationStateTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+InformationStateTensor(1): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n.x.\n..."
 ObservationString(1) = "...\n...\n..o"
 ObservationTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -123,8 +123,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 1
 InformationStateString(0) = "P0 ...\n.x.\nx.."
 InformationStateString(1) = "P1 ...\n...\n..o"
-InformationStateTensor(0): binvec(268, 0x804020100404010100802000002000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(268, 0x804020100804020101000080400000000000000000000000000000000000000000)
+InformationStateTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+InformationStateTensor(1): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n.x.\nx.."
 ObservationString(1) = "...\n...\n..o"
 ObservationTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -149,8 +149,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 1
 InformationStateString(0) = "P0 ...\n.x.\nx.."
 InformationStateString(1) = "P1 ...\n...\nx.o"
-InformationStateTensor(0): binvec(268, 0x804020100404010100802000002000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(268, 0x804020100804010101000080400204000000000000000000000000000000000000)
+InformationStateTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+InformationStateTensor(1): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n.x.\nx.."
 ObservationString(1) = "...\n...\nx.o"
 ObservationTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -175,8 +175,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = 0
 InformationStateString(0) = "P0 ...\n.x.\nx.."
 InformationStateString(1) = "P1 ...\n..o\nx.o"
-InformationStateTensor(0): binvec(268, 0x804020100404010100802000002000000000000000000000000000000000000000)
-InformationStateTensor(1): binvec(268, 0x804020100808010101000080400204410000000000000000000000000000000000)
+InformationStateTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+InformationStateTensor(1): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n.x.\nx.."
 ObservationString(1) = "...\n..o\nx.o"
 ObservationTensor(0): ◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
@@ -213,8 +213,8 @@ IsSimultaneousNode() = False
 CurrentPlayer() = -4
 InformationStateString(0) = "P0 x..\nXxo\nx.."
 InformationStateString(1) = "P1 .o.\n..o\nx.o"
-InformationStateTensor(0): binvec(268, 0x404020010408010100802000002000000400000080400000000000000000000000)
-InformationStateTensor(1): binvec(268, 0x808020100808010101000080400204410001400000000000000000000000000000)
+InformationStateTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+InformationStateTensor(1): ◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "x..\nXxo\nx.."
 ObservationString(1) = ".o.\n..o\nx.o"
 ObservationTensor(0): ◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯
diff --git a/open_spiel/integration_tests/playthroughs/phantom_ttt.txt b/open_spiel/integration_tests/playthroughs/phantom_ttt.txt
index 8cd1219929..4c6379ec48 100644
--- a/open_spiel/integration_tests/playthroughs/phantom_ttt.txt
+++ b/open_spiel/integration_tests/playthroughs/phantom_ttt.txt
@@ -24,9 +24,9 @@ NumPlayers() = 2
 MinUtility() = -1.0
 MaxUtility() = 1.0
 UtilitySum() = 0.0
-InformationStateTensorShape() = [1, 214]
+InformationStateTensorShape() = [1, 108]
 InformationStateTensorLayout() = TensorLayout.CHW
-InformationStateTensorSize() = 214
+InformationStateTensorSize() = 108
 ObservationTensorShape() = [27]
 ObservationTensorLayout() = TensorLayout.CHW
 ObservationTensorSize() = 27
@@ -46,9 +46,9 @@ CurrentPlayer() = 0
 InformationStateString(0) = "...\n...\n...\n"
 InformationStateString(1) = "...\n...\n...\n"
 InformationStateTensor(0):
-◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 InformationStateTensor(1):
-◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n...\n..."
 ObservationString(1) = "...\n...\n..."
 ObservationTensor(0): ◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
@@ -74,9 +74,9 @@ CurrentPlayer() = 1
 InformationStateString(0) = "...\n...\nx..\n0,6 "
 InformationStateString(1) = "...\n...\n...\n"
 InformationStateTensor(0):
-◉◉◉◉◉◉◯◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◯◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 InformationStateTensor(1):
-◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n...\nx.."
 ObservationString(1) = "...\n...\n..."
 ObservationTensor(0): ◉◉◉◉◉◉◯◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯
@@ -102,9 +102,9 @@ CurrentPlayer() = 0
 InformationStateString(0) = "...\n...\nx..\n0,6 "
 InformationStateString(1) = "...\n...\n.o.\n1,7 "
 InformationStateTensor(0):
-◉◉◉◉◉◉◯◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◯◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 InformationStateTensor(1):
-◉◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n...\nx.."
 ObservationString(1) = "...\n...\n.o."
 ObservationTensor(0): ◉◉◉◉◉◉◯◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯
@@ -130,9 +130,9 @@ CurrentPlayer() = 1
 InformationStateString(0) = "...\n...\nx.x\n0,6 0,8 "
 InformationStateString(1) = "...\n...\n.o.\n1,7 "
 InformationStateTensor(0):
-◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 InformationStateTensor(1):
-◉◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n...\nx.x"
 ObservationString(1) = "...\n...\n.o."
 ObservationTensor(0): ◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉
@@ -158,9 +158,9 @@ CurrentPlayer() = 1
 InformationStateString(0) = "...\n...\nx.x\n0,6 0,8 "
 InformationStateString(1) = "...\n...\n.ox\n1,7 1,8 "
 InformationStateTensor(0):
-◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 InformationStateTensor(1):
-◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n...\nx.x"
 ObservationString(1) = "...\n...\n.ox"
 ObservationTensor(0): ◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉
@@ -186,9 +186,9 @@ CurrentPlayer() = 0
 InformationStateString(0) = "...\n...\nx.x\n0,6 0,8 "
 InformationStateString(1) = "..o\n...\n.ox\n1,7 1,8 1,2 "
 InformationStateTensor(0):
-◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 InformationStateTensor(1):
-◉◉◯◉◉◉◉◯◯◯◯◉◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◉◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◯◉◉◉◉◯◯◯◯◉◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "...\n...\nx.x"
 ObservationString(1) = "..o\n...\n.ox"
 ObservationTensor(0): ◉◉◉◉◉◉◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◉
@@ -234,9 +234,9 @@ CurrentPlayer() = -4
 InformationStateString(0) = "x.o\nx..\nxox\n0,6 0,8 0,3 0,7 0,2 0,0 "
 InformationStateString(1) = "..o\n..o\nxox\n1,7 1,8 1,2 1,6 1,5 "
 InformationStateTensor(0):
-◯◉◯◯◉◉◯◯◯◯◯◉◯◯◯◯◉◯◉◯◯◉◯◯◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◯◉◯◯◉◉◯◯◯◯◯◉◯◯◯◯◉◯◉◯◯◉◯◯◉◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◉◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◉◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 InformationStateTensor(1):
-◉◉◯◉◉◯◯◯◯◯◯◉◯◯◉◯◉◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◉◯◉◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◉◯◯◯◉◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
+◉◉◯◉◉◯◯◯◯◯◯◉◯◯◉◯◉◯◯◯◯◯◯◯◉◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◉◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯
 ObservationString(0) = "x.o\nx..\nxox"
 ObservationString(1) = "..o\n..o\nxox"
 ObservationTensor(0): ◯◉◯◯◉◉◯◯◯◯◯◉◯◯◯◯◉◯◉◯◯◉◯◯◉◯◉