From 52f114b020633cfc4a41a54a4dd22b54ebc57cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Sat, 5 Aug 2023 13:04:51 +0200 Subject: [PATCH] parse actions from hanab.live --- download.h | 32 ++++++++++++++++++++++++++++++++ game_state.h | 26 +++++++++++++++++++++----- game_state.hpp | 16 +++++++++------- 3 files changed, 62 insertions(+), 12 deletions(-) diff --git a/download.h b/download.h index 6d374cc..ad28813 100644 --- a/download.h +++ b/download.h @@ -29,6 +29,33 @@ namespace Hanabi { return card; } + Action tag_invoke(boost::json::value_to_tag, boost::json::value const &jv) { + Hanabi::Action action{}; + uint8_t type; + boost::json::object const &obj = jv.as_object(); + + extract(obj, action.target, "target"); + extract(obj, type, "type"); + + action.type = static_cast(type); + switch (action.type) { + case ActionType::color_clue: + case ActionType::rank_clue: + action.type = ActionType::clue; + break; + case ActionType::end_game: + case ActionType::vote_terminate: + action.type = ActionType::end_game; + break; + case ActionType::play: + case ActionType::discard: + break; + default: + throw std::runtime_error("Invalid game format, could not parse action type " + std::to_string(type)); + } + return action; + } + void tag_invoke(boost::json::value_from_tag, boost::json::value &jv, Hanabi::Card const &card) { jv = {{"suitIndex", card.suit}, {"rank", card.rank}}; } @@ -51,6 +78,10 @@ std::vector parse_deck(const boost::json::value& deck_json) { return deck; } +std::vector parse_actions(const boost::json::value& action_json) { + return boost::json::value_to>(action_json); +} + boost::json::object download_game_json(int game_id) { std::string request_str = "https://hanab.live/export/" + std::to_string(game_id); cpr::Response r = cpr::Get(cpr::Url(request_str)); @@ -79,6 +110,7 @@ void get_game(std::variant game_spec) { } }(); const std::vector deck = parse_deck(game.at("deck")); + const std::vector actions = parse_actions(game.at("actions")); const unsigned num_players = game.at("players").as_array().size(); std::cout << deck.size() << std::endl; std::cout << num_players; diff --git a/game_state.h b/game_state.h index 7e3fc01..25105a3 100644 --- a/game_state.h +++ b/game_state.h @@ -102,9 +102,25 @@ private: std::array, starting_card_rank>, num_suits> _card_positions; }; -enum class ActionType { discard, clue, play }; +enum class ActionType { + play = 0, + discard = 1, + clue = 2, + color_clue = 2, + rank_clue = 3, + end_game = 4, + vote_terminate = 10, +}; +/** + * Action type for replay format of hanab.live + */ struct Action { + ActionType type{}; + uint8_t target; +}; + +struct BacktrackAction { ActionType type{}; Card discarded{}; std::uint8_t index{}; @@ -116,17 +132,17 @@ public: HanabiState() = default; explicit HanabiState(const std::vector& deck); - Action clue(); + BacktrackAction clue(); /** * Plays a card from current hand, drawing top card of draw pile and rotating draw pile * @param index of card in hand to be played */ - Action play(std::uint8_t index); + BacktrackAction play(std::uint8_t index); - Action discard(std::uint8_t index); + BacktrackAction discard(std::uint8_t index); - void revert(const Action &action); + void revert(const BacktrackAction &action); void draw(std::uint8_t index); diff --git a/game_state.hpp b/game_state.hpp index 019fc77..72cc186 100644 --- a/game_state.hpp +++ b/game_state.hpp @@ -68,13 +68,13 @@ namespace Hanabi { } template - Action HanabiState::clue() { + BacktrackAction HanabiState::clue() { assert(_num_clues > 0); --_num_clues; incr_turn(); - return Action{ActionType::clue, {}, {}}; + return BacktrackAction{ActionType::clue, {}, {}}; } template @@ -90,7 +90,7 @@ namespace Hanabi { } template - Action HanabiState::play( + BacktrackAction HanabiState::play( std::uint8_t index) { assert(index < _hands[_turn].size()); const Card card = _hands[_turn][index]; @@ -98,7 +98,7 @@ namespace Hanabi { --_stacks[card.suit]; - Action ret{ActionType::play, _hands[_turn][index], index}; + BacktrackAction ret{ActionType::play, _hands[_turn][index], index}; if (card.rank == 0) { // update clues if we played the last card of a stack @@ -112,14 +112,14 @@ namespace Hanabi { } template - Action HanabiState::discard( + BacktrackAction HanabiState::discard( std::uint8_t index) { assert(index < _hands[_turn].size()); assert(_num_clues != max_num_clues); _num_clues++; - Action ret{ActionType::discard, _hands[_turn][index], index}; + BacktrackAction ret{ActionType::discard, _hands[_turn][index], index}; draw(index); incr_turn(); @@ -189,7 +189,7 @@ namespace Hanabi { template void HanabiState::revert( - const Action &action) { + const BacktrackAction &action) { decr_turn(); switch (action.type) { case ActionType::clue: @@ -207,6 +207,8 @@ namespace Hanabi { } revert_draw(action.index, action.discarded); _stacks[action.discarded.suit]++; + default: + break; } }