Skip to content

Commit 1450fdf

Browse files
lanctotamyssnippet
authored andcommitted
feat(core): add MaxSerializationLength to Game API for fixed-size state buffers
1 parent faa5f90 commit 1450fdf

File tree

7 files changed

+37
-1
lines changed

7 files changed

+37
-1
lines changed

open_spiel/games/chess/chess.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,5 +592,17 @@ int ChessGame::MaxChanceOutcomes() const {
592592
}
593593
}
594594

595+
int ChessGame::MaxSerializationLength() const {
596+
// "FEN: " + fen + "\n" + StrJoin(history, "\n") + "\n"
597+
// Max FEN length is approximately 100 characters.
598+
// Max history length is MaxHistoryLength().
599+
// Each action is up to 5 digits (NumDistinctActions() ~ 4674).
600+
int max_fen_len = 100;
601+
int max_history_len = MaxHistoryLength();
602+
int max_action_len = 5; // log10(4674) + 1
603+
return std::strlen("FEN: ") + max_fen_len + 1 +
604+
max_history_len * (max_action_len + 1) + 1;
605+
}
606+
595607
} // namespace chess
596608
} // namespace open_spiel

open_spiel/games/chess/chess.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ class ChessGame : public Game {
269269
std::unique_ptr<State> DeserializeState(
270270
const std::string& str) const override;
271271

272+
int MaxSerializationLength() const override;
273+
272274
bool IsChess960() const { return chess960_; }
273275

274276
std::string Chess960LookupFEN(int index) const {

open_spiel/games/tic_tac_toe/tic_tac_toe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ class TicTacToeGame : public Game {
169169
}
170170
int MaxGameLength() const override { return kNumCells; }
171171
std::string ActionToString(Player player, Action action_id) const override;
172+
int MaxSerializationLength() const override { return 19; }
172173
};
173174

174175
CellState PlayerToState(Player player);

open_spiel/python/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ endif()
2727
include_directories (../pybind11_abseil ../../pybind11/include)
2828
set(PYTHON_BINDINGS ${PYTHON_BINDINGS}
2929
pybind11/algorithms_infostate_tree.cc
30-
pybind11/algorithms_infostate_tree.tcc
30+
pybind11/algorithms_infostate_tree_templates.h
3131
pybind11/algorithms_infostate_tree.h
3232
pybind11/algorithms_corr_dist.cc
3333
pybind11/algorithms_corr_dist.h

open_spiel/python/pybind11/pyspiel.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ PYBIND11_MODULE(pyspiel, m) {
455455
.def("policy_tensor_shape", &Game::PolicyTensorShape)
456456
.def("deserialize_state", &Game::DeserializeState)
457457
.def("max_game_length", &Game::MaxGameLength)
458+
.def("max_serialization_length", &Game::MaxSerializationLength)
458459
.def("action_to_string", &Game::ActionToString)
459460
.def("max_chance_nodes_in_history", &Game::MaxChanceNodesInHistory)
460461
.def("max_move_number", &Game::MaxMoveNumber)

open_spiel/spiel.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,19 @@ std::unique_ptr<State> Game::DeserializeState(const std::string& str) const {
505505
return state;
506506
}
507507

508+
int Game::MaxSerializationLength() const {
509+
// Default implementation assumes the default serialization format:
510+
// history actions joined by \n, each action as decimal number.
511+
// Games that override State::Serialize must override this method.
512+
int num_actions = NumDistinctActions();
513+
int max_action_digits = 1;
514+
if (num_actions > 1) {
515+
max_action_digits = static_cast<int>(std::log10(num_actions - 1)) + 1;
516+
}
517+
int max_history_length = MaxHistoryLength();
518+
return max_history_length * (max_action_digits + 1) + 1;
519+
}
520+
508521
std::string SerializeGameAndState(const Game& game, const State& state) {
509522
std::string str = "";
510523

open_spiel/spiel.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,13 @@ class Game : public std::enable_shared_from_this<Game> {
969969
// State::Serialize (i.e. that method should also be overridden).
970970
virtual std::unique_ptr<State> DeserializeState(const std::string& str) const;
971971

972+
// The maximum length of the string returned by State::Serialize() for any
973+
// state in this game. This is useful for allocating fixed-size buffers when
974+
// working with vectorized game states.
975+
// The default implementation assumes the default serialization format.
976+
// Games that override State::Serialize must override this method.
977+
virtual int MaxSerializationLength() const;
978+
972979
// The maximum length of any one game (in terms of number of decision nodes
973980
// visited in the game tree). For a simultaneous action game, this is the
974981
// maximum number of joint decisions. In a turn-based game, this is the

0 commit comments

Comments
 (0)