diff --git a/include/game_state.h b/include/game_state.h index b9ee2a5..eba388d 100644 --- a/include/game_state.h +++ b/include/game_state.h @@ -382,6 +382,8 @@ private: void incr_turn(); void decr_turn(); + void check_draw_pile_integrity() const; + static constexpr uint8_t no_endgame = std::numeric_limits::max(); static constexpr player_t draw_pile = num_players; static constexpr player_t trash_or_play_stack = num_players + 1; diff --git a/include/game_state.hpp b/include/game_state.hpp index 9dbded4..b939d6c 100644 --- a/include/game_state.hpp +++ b/include/game_state.hpp @@ -1,4 +1,5 @@ #include +#include #include "myassert.h" #include "game_state.h" @@ -164,6 +165,26 @@ namespace Hanabi { } } + template + void HanabiState::check_draw_pile_integrity() const + { + if (not _relative_representation.initialized) + { + return; + } + if (_draw_pile.size() >= 2) { + auto copy = _draw_pile; + copy.sort([](CardMultiplicity const & card1, CardMultiplicity const & card2){ + return card1.card.rank < card2.card.rank or (card1.card.rank == card2.card.rank and card1.card.suit < card2.card.suit); + }); + auto before = copy.begin(); + for(auto it = std::next(copy.begin()); it != copy.end(); ++it) { + ASSERT(before->card != it->card); + ++before; + } + } + } + template bool HanabiState::is_playable(const Hanabi::Card &card) const { return card.rank == _stacks[card.suit] - 1; @@ -186,6 +207,7 @@ namespace Hanabi { template unsigned long HanabiState::play_and_potentially_update(hand_index_t index) { + check_draw_pile_integrity(); ASSERT(index < _hands[_turn].size()); const Card played_card = _hands[_turn][index]; if (!is_playable(played_card)) { @@ -208,6 +230,7 @@ namespace Hanabi { const unsigned long multiplicity = draw(index); incr_turn(); + check_draw_pile_integrity(); return multiplicity; } @@ -218,6 +241,7 @@ namespace Hanabi { template unsigned long HanabiState::discard_and_potentially_update(hand_index_t index) { + check_draw_pile_integrity(); ASSERT(index < _hands[_turn].size()); ASSERT(_num_clues != max_num_clues); @@ -229,6 +253,7 @@ namespace Hanabi { _actions_log.emplace(ActionType::discard, discarded_card, index); incr_turn(); + check_draw_pile_integrity(); return multiplicity; } @@ -449,6 +474,7 @@ namespace Hanabi { template void HanabiState::revert_play() { + check_draw_pile_integrity(); const BacktrackAction last_action = _actions_log.top(); _actions_log.pop(); ASSERT(last_action.action_type == ActionType::play); @@ -463,10 +489,12 @@ namespace Hanabi { _stacks[last_action.discarded.suit]++; } _score--; + check_draw_pile_integrity(); } template void HanabiState::revert_discard() { + check_draw_pile_integrity(); const BacktrackAction last_action = _actions_log.top(); _actions_log.pop(); @@ -479,6 +507,7 @@ namespace Hanabi { _pace++; revert_draw(last_action.index, last_action.discarded); + check_draw_pile_integrity(); } template @@ -793,6 +822,7 @@ namespace Hanabi { revert_action(); } else { unsigned sum_of_multiplicities = 0; + [[maybe_unused]] const auto pile = _draw_pile; for(size_t i = 0; i < _draw_pile.size(); i++) { const unsigned long multiplicity = do_action(); sum_of_multiplicities += multiplicity;