119 lines
No EOL
2.9 KiB
C++
119 lines
No EOL
2.9 KiB
C++
#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<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 (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;
|
|
}
|
|
} |