Endgame-Analyzer/src/game_interface.cpp

129 lines
3.2 KiB
C++

#include "myassert.h"
#include "game_interface.h"
namespace Hanabi
{
bool CardMultiplicity::operator==(Hanabi::CardMultiplicity const & other) const
{
return card == other.card && multiplicity == other.multiplicity;
}
bool CardMultiplicity::operator!=(Hanabi::CardMultiplicity const & other) const
{
return not (*this == other);
}
std::ostream & operator<<(std::ostream & os, HanabiStateIF const & hanabi_state)
{
hanabi_state.print(os);
return os;
}
Game::Game(std::unique_ptr<HanabiStateIF> state, Hanabi::GameInfo game_info) :
GameInfo(std::move(game_info)), state(std::move(state)), 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;
}
unsigned Game::num_turns() const
{
return actions.size();
}
void Game::make_turn()
{
ASSERT(next_action < actions.size());
size_t draw_pile_size = state->draw_pile_size();
if (draw_pile_size > 0) {
Card const next_draw = deck.at(deck.size() - 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 (next_action > 0 and (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;
}
}