Endgame-Analyzer/src/game_interface.cpp

129 lines
3.2 KiB
C++
Raw Normal View History

#include "myassert.h"
2023-11-11 12:40:36 +01:00
2023-11-15 23:07:39 +01:00
#include "game_interface.h"
2023-11-16 16:20:04 +01:00
namespace Hanabi
{
2023-11-11 12:40:36 +01:00
2024-01-14 18:04:27 +01:00
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);
}
2023-11-16 16:20:04 +01:00
std::ostream & operator<<(std::ostream & os, HanabiStateIF const & hanabi_state)
{
hanabi_state.print(os);
return os;
}
2023-11-16 16:20:04 +01:00
Game::Game(std::unique_ptr<HanabiStateIF> state, Hanabi::GameInfo game_info) :
GameInfo(std::move(game_info)), state(std::move(state)), 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.
2023-11-16 16:20:04 +01:00
if (not this->actions.empty())
{
switch (this->actions.back().type)
{
2023-11-11 22:32:30 +01:00
case ActionType::vote_terminate:
case ActionType::vote_terminate_players:
case ActionType::end_game:
this->actions.pop_back();
2023-11-16 16:20:04 +01:00
default:;
2023-11-11 22:32:30 +01:00
}
}
}
unsigned Game::cur_turn() const
{
return next_action + 1;
}
unsigned Game::num_turns() const
{
return actions.size();
}
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());
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);
}
2023-11-11 12:40:36 +01:00
Action const & action = actions[next_action];
std::uint8_t index;
2023-11-16 16:20:04 +01:00
switch (action.type)
{
2023-11-11 12:40:36 +01:00
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:
2023-11-16 16:20:04 +01:00
case Hanabi::ActionType::end_game:;
2023-11-11 12:40:36 +01:00
}
++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;
2023-11-16 16:20:04 +01:00
if (cur_turn >= turn)
{
for (size_t i = 0; i < cur_turn - turn; i++)
{
2023-11-11 22:32:30 +01:00
revert_turn();
}
2023-11-16 16:20:04 +01:00
}
else
{
while (next_action < actions.size() and next_action + 1 < turn)
{
2023-11-11 22:32:30 +01:00
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-16 16:20:04 +01:00
while (state->draw_pile_size() > draw_pile_break and next_action < actions.size())
{
2023-11-11 22:32:30 +01:00
make_turn();
2023-11-11 12:40:36 +01:00
}
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)))
2023-11-16 16:20:04 +01:00
{
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
}
}