#include "myassert.h" #include "game_interface.h" namespace Hanabi { std::ostream &operator<<(std::ostream &os, HanabiStateIF const &hanabi_state) { hanabi_state.print(os); return os; } Game::Game(std::unique_ptr state, std::vector actions, std::vector deck): state(std::move(state)), actions(std::move(actions)), deck(std::move(deck)), next_action(0) { // If there is a 'Null' action that only signals the game's end, we want to get rid of it now, // as this will mess with our moves. if(not this->actions.empty()) { switch(this->actions.back().type) { case ActionType::vote_terminate: case ActionType::vote_terminate_players: case ActionType::end_game: this->actions.pop_back(); default: ; } } } unsigned Game::cur_turn() const { return next_action + 1; } void Game::make_turn() { ASSERT(next_action < actions.size()); Card const next_draw = deck[deck.size() - state->draw_pile_size()]; state->rotate_next_draw(next_draw); Action const & action = actions[next_action]; std::uint8_t index; switch(action.type) { case Hanabi::ActionType::color_clue: case Hanabi::ActionType::rank_clue: state->give_clue(); break; case Hanabi::ActionType::discard: index = state->find_card_in_hand(action.card); ASSERT(index != std::uint8_t(-1)); state->discard(index); break; case Hanabi::ActionType::play: index = state->find_card_in_hand(action.card); ASSERT(index != std::uint8_t(-1)); state->play(index); break; case Hanabi::ActionType::vote_terminate_players: case Hanabi::ActionType::vote_terminate: case Hanabi::ActionType::end_game: ; } ++next_action; } void Game::revert_turn() { state->revert(); --next_action; } bool Game::goto_turn(size_t turn) { size_t const cur_turn = next_action + 1; if (cur_turn >= turn) { for(size_t i = 0; i < cur_turn - turn; i++) { revert_turn(); } } else { while(next_action < actions.size() and next_action + 1 < turn) { make_turn(); } } return next_action + 1 == turn; } bool Game::holds_state() const { return state != nullptr; } bool Game::goto_draw_pile_size(size_t draw_pile_break) { while (state->draw_pile_size() > draw_pile_break and next_action < actions.size()) { make_turn(); } while(state->draw_pile_size() < draw_pile_break or (state->draw_pile_size() == draw_pile_break and state->last_action_type() == ActionType::clue)) { revert_turn(); } return state->draw_pile_size() == draw_pile_break; } }