Endgame-Analyzer/src/game_interface.cpp

100 lines
2.7 KiB
C++
Raw Normal View History

#include "game_interface.h"
#include "myassert.h"
2023-11-11 12:40:36 +01:00
namespace Hanabi {
std::ostream &operator<<(std::ostream &os, HanabiStateIF const &hanabi_state)
{
hanabi_state.print(os);
return os;
}
2023-11-11 22:32:30 +01:00
Game::Game(std::unique_ptr<HanabiStateIF> state, std::vector<Action> actions, std::vector<Card> deck):
state(std::move(state)), actions(std::move(actions)), deck(std::move(deck)), next_action(0)
2023-11-11 22:32:30 +01:00
{
// 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;
}
2023-11-11 12:40:36 +01:00
void Game::make_turn()
{
2023-11-11 13:29:55 +01:00
ASSERT(next_action < actions.size());
2023-11-11 12:40:36 +01:00
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();
2023-11-11 22:32:30 +01:00
--next_action;
2023-11-11 12:40:36 +01:00
}
2023-11-11 22:32:30 +01:00
bool Game::goto_turn(size_t turn)
2023-11-11 12:40:36 +01:00
{
2023-11-11 22:32:30 +01:00
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();
2023-11-11 12:40:36 +01:00
}
}
2023-11-11 22:32:30 +01:00
return next_action + 1 == turn;
2023-11-11 12:40:36 +01:00
}
bool Game::holds_state() const
{
return state != nullptr;
}
2023-11-11 22:32:30 +01:00
bool Game::goto_draw_pile_size(size_t draw_pile_break)
2023-11-11 12:40:36 +01:00
{
2023-11-11 22:32:30 +01:00
while (state->draw_pile_size() > draw_pile_break and next_action < actions.size()) {
make_turn();
2023-11-11 12:40:36 +01:00
}
2023-11-11 22:32:30 +01:00
while(state->draw_pile_size() < draw_pile_break or (state->draw_pile_size() == draw_pile_break and state->last_action_type() == ActionType::clue)) {
2023-11-11 12:40:36 +01:00
revert_turn();
}
2023-11-11 22:32:30 +01:00
return state->draw_pile_size() == draw_pile_break;
2023-11-11 12:40:36 +01:00
}
}