parse actions from hanab.live

This commit is contained in:
Maximilian Keßler 2023-08-05 13:04:51 +02:00
parent 452c028f72
commit 52f114b020
Signed by: max
GPG key ID: BCC5A619923C0BA5
3 changed files with 62 additions and 12 deletions

View file

@ -29,6 +29,33 @@ namespace Hanabi {
return card;
}
Action tag_invoke(boost::json::value_to_tag<Action>, 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<ActionType>(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<Hanabi::Card> parse_deck(const boost::json::value& deck_json) {
return deck;
}
std::vector<Hanabi::Action> parse_actions(const boost::json::value& action_json) {
return boost::json::value_to<std::vector<Hanabi::Action>>(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<int, const char*> game_spec) {
}
}();
const std::vector<Hanabi::Card> deck = parse_deck(game.at("deck"));
const std::vector<Hanabi::Action> 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;

View file

@ -102,9 +102,25 @@ private:
std::array<std::array<std::array<player_t, max_card_duplicity>, 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<Card>& 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);

View file

@ -68,13 +68,13 @@ namespace Hanabi {
}
template<size_t num_suits, player_t num_players, size_t hand_size, uint8_t max_draw_pile_size>
Action HanabiState<num_suits, num_players, hand_size, max_draw_pile_size>::clue() {
BacktrackAction HanabiState<num_suits, num_players, hand_size, max_draw_pile_size>::clue() {
assert(_num_clues > 0);
--_num_clues;
incr_turn();
return Action{ActionType::clue, {}, {}};
return BacktrackAction{ActionType::clue, {}, {}};
}
template<size_t num_suits, player_t num_players, size_t hand_size, uint8_t max_draw_pile_size>
@ -90,7 +90,7 @@ namespace Hanabi {
}
template<std::size_t num_suits, player_t num_players, std::size_t hand_size, uint8_t max_draw_pile_size>
Action HanabiState<num_suits, num_players, hand_size, max_draw_pile_size>::play(
BacktrackAction HanabiState<num_suits, num_players, hand_size, max_draw_pile_size>::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<std::size_t num_suits, player_t num_players, std::size_t hand_size, uint8_t max_draw_pile_size>
Action HanabiState<num_suits, num_players, hand_size, max_draw_pile_size>::discard(
BacktrackAction HanabiState<num_suits, num_players, hand_size, max_draw_pile_size>::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<std::size_t num_suits, player_t num_players, std::size_t hand_size, uint8_t max_draw_pile_size>
void HanabiState<num_suits, num_players, hand_size, max_draw_pile_size>::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;
}
}