2023-11-11 22:32:30 +01:00
|
|
|
#include <iostream>
|
|
|
|
#include <utility>
|
2023-11-11 12:40:36 +01:00
|
|
|
#include "game_state.h"
|
|
|
|
|
|
|
|
namespace Hanabi {
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
// 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:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-12 18:32:19 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-11-12 17:30:44 +01:00
|
|
|
bool Game::holds_state()
|
|
|
|
{
|
|
|
|
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
|
|
|
}
|
2023-11-11 22:32:30 +01:00
|
|
|
|
|
|
|
|
2023-11-11 12:40:36 +01:00
|
|
|
}
|