add cli command to dump id parts
This commit is contained in:
parent
012b73879f
commit
b1c1f41c6e
3 changed files with 85 additions and 17 deletions
|
@ -220,6 +220,8 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] virtual std::optional<probability_t> lookup() const = 0;
|
[[nodiscard]] virtual std::optional<probability_t> lookup() const = 0;
|
||||||
[[nodiscard]] virtual std::uint64_t unique_id() const = 0;
|
[[nodiscard]] virtual std::uint64_t unique_id() const = 0;
|
||||||
|
[[nodiscard]] virtual std::pair<std::vector<std::uint64_t>, std::vector<Card>> dump_unique_id_parts() const = 0;
|
||||||
|
|
||||||
virtual std::vector<std::pair<Action, std::optional<probability_t>>> get_reasonable_actions() = 0;
|
virtual std::vector<std::pair<Action, std::optional<probability_t>>> get_reasonable_actions() = 0;
|
||||||
virtual std::vector<std::pair<CardMultiplicity, std::optional<probability_t>>> possible_next_states(hand_index_t index, bool play) = 0;
|
virtual std::vector<std::pair<CardMultiplicity, std::optional<probability_t>>> possible_next_states(hand_index_t index, bool play) = 0;
|
||||||
|
|
||||||
|
@ -264,8 +266,9 @@ public:
|
||||||
void init_backtracking_information() final;
|
void init_backtracking_information() final;
|
||||||
probability_t evaluate_state() final;
|
probability_t evaluate_state() final;
|
||||||
|
|
||||||
std::optional<probability_t> lookup() const;
|
[[nodiscard]] std::optional<probability_t> lookup() const final;
|
||||||
std::uint64_t unique_id() const final;
|
[[nodiscard]] std::uint64_t unique_id() const final;
|
||||||
|
[[nodiscard]] std::pair<std::vector<std::uint64_t>, std::vector<Card>> dump_unique_id_parts() const final;
|
||||||
|
|
||||||
std::vector<std::pair<Action, std::optional<probability_t>>> get_reasonable_actions() final;
|
std::vector<std::pair<Action, std::optional<probability_t>>> get_reasonable_actions() final;
|
||||||
std::vector<std::pair<CardMultiplicity, std::optional<probability_t>>> possible_next_states(hand_index_t index, bool play) final;
|
std::vector<std::pair<CardMultiplicity, std::optional<probability_t>>> possible_next_states(hand_index_t index, bool play) final;
|
||||||
|
|
|
@ -816,6 +816,55 @@ namespace Hanabi {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
|
||||||
|
std::pair<std::vector<std::uint64_t>, std::vector<Card>> HanabiState<num_suits, num_players, hand_size>::dump_unique_id_parts() const {
|
||||||
|
std::vector<std::uint64_t> ret;
|
||||||
|
std::vector<Card> cards;
|
||||||
|
|
||||||
|
// encode all positions of cards that started in draw pile
|
||||||
|
ASSERT(_relative_representation.card_positions_draw.size() == _relative_representation.good_cards_draw.size());
|
||||||
|
for(size_t i = 0; i < _relative_representation.card_positions_draw.size(); i++) {
|
||||||
|
for(player_t player : _relative_representation.card_positions_draw[i]) {
|
||||||
|
// We normalize here: If a card is already played, then the positions of its other copies
|
||||||
|
// do not matter, so we can just pretend that they are all in the trash already.
|
||||||
|
// The resulting states will be equivalent.
|
||||||
|
if (!is_trash(_relative_representation.good_cards_draw[i])) {
|
||||||
|
ret.push_back(player);
|
||||||
|
} else {
|
||||||
|
ret.push_back(trash_or_play_stack);
|
||||||
|
}
|
||||||
|
cards.push_back(_relative_representation.good_cards_draw[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode number of clues
|
||||||
|
ret.push_back(_num_clues);
|
||||||
|
|
||||||
|
// we can encode draw pile size and extra turn in one metric, since we only have extra turns if draw pile is empty
|
||||||
|
const std::uint8_t draw_pile_size_and_extra_turns = [this]() -> uint8_t {
|
||||||
|
if(_endgame_turns_left == no_endgame) {
|
||||||
|
return _weighted_draw_pile_size + num_players;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return _endgame_turns_left;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
ret.push_back(draw_pile_size_and_extra_turns);
|
||||||
|
|
||||||
|
// encode positions of cards that started in hands
|
||||||
|
ret.push_back(_relative_representation.card_positions_hands.to_ulong());
|
||||||
|
|
||||||
|
ret.push_back(_turn);
|
||||||
|
|
||||||
|
// The id is unique now, since for all relevant cards, we know their position (including if they are played),
|
||||||
|
// the number of clues, the draw pile size and whose turn it is.
|
||||||
|
// This already uniquely determines the current players position, assuming that we never discard good cards
|
||||||
|
// (and only play them)
|
||||||
|
|
||||||
|
return {ret, cards};
|
||||||
|
}
|
||||||
|
|
||||||
template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
|
template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
|
||||||
const std::unordered_map<unsigned long, probability_t>& HanabiState<num_suits, num_players, hand_size>::position_tablebase() const {
|
const std::unordered_map<unsigned long, probability_t>& HanabiState<num_suits, num_players, hand_size>::position_tablebase() const {
|
||||||
return _position_tablebase;
|
return _position_tablebase;
|
||||||
|
|
|
@ -29,19 +29,20 @@ namespace Hanabi {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static std::array<std::string, 12> cli_commands = {
|
constexpr static std::array<std::string, 13> cli_commands = {
|
||||||
"play",
|
"play",
|
||||||
"clue",
|
"clue",
|
||||||
"discard",
|
"discard",
|
||||||
"id",
|
"opt",
|
||||||
"state",
|
"state",
|
||||||
|
"id",
|
||||||
"revert",
|
"revert",
|
||||||
"actions",
|
"actions",
|
||||||
"evaluate",
|
"evaluate",
|
||||||
"help",
|
"help",
|
||||||
"quit",
|
"quit",
|
||||||
"initials",
|
"set-initials",
|
||||||
"opt",
|
"dump-id-parts",
|
||||||
};
|
};
|
||||||
|
|
||||||
char * cli_commands_generator(const char *text, int state) {
|
char * cli_commands_generator(const char *text, int state) {
|
||||||
|
@ -152,16 +153,31 @@ namespace Hanabi {
|
||||||
add_history(prompt.c_str());
|
add_history(prompt.c_str());
|
||||||
|
|
||||||
if (prompt.starts_with("help")) {
|
if (prompt.starts_with("help")) {
|
||||||
std::cout << "state: print information on current game state." << std::endl;
|
std::cout << "state: print information on current game state." << std::endl;
|
||||||
std::cout << "clue: give a clue." << std::endl;
|
std::cout << "clue: give a clue." << std::endl;
|
||||||
std::cout << "play <card>: play specified card." << std::endl;
|
std::cout << "play <card>: play specified card." << std::endl;
|
||||||
std::cout << "discard: discard trash from hand." << std::endl;
|
std::cout << "discard: discard trash from hand." << std::endl;
|
||||||
std::cout << "opt: take optimal action. In case of ties, prefers plays and discards in that order." << std::endl;
|
std::cout << "opt: take optimal action. In case of ties, prefers plays and discards in that order." << std::endl;
|
||||||
std::cout << "revert <turns>: revert specified number of turns (default 1)." << std::endl;
|
std::cout << "revert <turns>: revert specified number of turns (default 1)." << std::endl;
|
||||||
std::cout << "actions: display list of reasonable actions to take and their winning chances." << std::endl;
|
std::cout << "actions: display list of reasonable actions to take and their winning chances." << std::endl;
|
||||||
std::cout << "evaluate: evaluate current game state recursively. Potentially runtime-expensive." << std::endl;
|
std::cout << "evaluate: evaluate current game state recursively. Potentially runtime-expensive." << std::endl;
|
||||||
std::cout << "id: display id of state. Has no inherent meaning, useful for debugging." << std::endl;
|
std::cout << "set-initials <chars>: Set initials for the suits." << std::endl;
|
||||||
std::cout << "quit: Quit this interactive shell." << std::endl;
|
std::cout << "quit: Quit this interactive shell." << std::endl;
|
||||||
|
std::cout << "id: display id of state. Has no inherent meaning, useful for debugging." << std::endl;
|
||||||
|
std::cout << "dump-id-parts: Dump parts used to calculate the id of the state as well as the cards associated to them." << std::endl;
|
||||||
|
std::cout << "help: Display this help message." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prompt.starts_with("dump-id-parts")) {
|
||||||
|
for (const auto val: game->dump_unique_id_parts().first) {
|
||||||
|
std::cout << val << ", ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
for (const auto card: game->dump_unique_id_parts().second) {
|
||||||
|
std::cout << card << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +187,7 @@ namespace Hanabi {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prompt.starts_with("initials")) {
|
if (prompt.starts_with("set-initials")) {
|
||||||
if (prompt.length() < 12) {
|
if (prompt.length() < 12) {
|
||||||
std::cout << "At least 3 initials need to be specified" << std::endl;
|
std::cout << "At least 3 initials need to be specified" << std::endl;
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in a new issue