add integrity check for draw pile

This commit is contained in:
Maximilian Keßler 2023-11-11 11:44:37 +01:00
parent 59709e2375
commit b6a2dfb855
Signed by: max
GPG key ID: BCC5A619923C0BA5
2 changed files with 32 additions and 0 deletions

View file

@ -382,6 +382,8 @@ private:
void incr_turn(); void incr_turn();
void decr_turn(); void decr_turn();
void check_draw_pile_integrity() const;
static constexpr uint8_t no_endgame = std::numeric_limits<uint8_t>::max(); static constexpr uint8_t no_endgame = std::numeric_limits<uint8_t>::max();
static constexpr player_t draw_pile = num_players; static constexpr player_t draw_pile = num_players;
static constexpr player_t trash_or_play_stack = num_players + 1; static constexpr player_t trash_or_play_stack = num_players + 1;

View file

@ -1,4 +1,5 @@
#include <algorithm> #include <algorithm>
#include <iostream>
#include "myassert.h" #include "myassert.h"
#include "game_state.h" #include "game_state.h"
@ -164,6 +165,26 @@ namespace Hanabi {
} }
} }
template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
void HanabiState<num_suits, num_players, hand_size>::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<suit_t num_suits, player_t num_players, hand_index_t hand_size> template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
bool HanabiState<num_suits, num_players, hand_size>::is_playable(const Hanabi::Card &card) const { bool HanabiState<num_suits, num_players, hand_size>::is_playable(const Hanabi::Card &card) const {
return card.rank == _stacks[card.suit] - 1; return card.rank == _stacks[card.suit] - 1;
@ -186,6 +207,7 @@ namespace Hanabi {
template<suit_t num_suits, player_t num_players, hand_index_t hand_size> template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
unsigned long HanabiState<num_suits, num_players, hand_size>::play_and_potentially_update(hand_index_t index) { unsigned long HanabiState<num_suits, num_players, hand_size>::play_and_potentially_update(hand_index_t index) {
check_draw_pile_integrity();
ASSERT(index < _hands[_turn].size()); ASSERT(index < _hands[_turn].size());
const Card played_card = _hands[_turn][index]; const Card played_card = _hands[_turn][index];
if (!is_playable(played_card)) { if (!is_playable(played_card)) {
@ -208,6 +230,7 @@ namespace Hanabi {
const unsigned long multiplicity = draw(index); const unsigned long multiplicity = draw(index);
incr_turn(); incr_turn();
check_draw_pile_integrity();
return multiplicity; return multiplicity;
} }
@ -218,6 +241,7 @@ namespace Hanabi {
template<suit_t num_suits, player_t num_players, hand_index_t hand_size> template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
unsigned long HanabiState<num_suits, num_players, hand_size>::discard_and_potentially_update(hand_index_t index) { unsigned long HanabiState<num_suits, num_players, hand_size>::discard_and_potentially_update(hand_index_t index) {
check_draw_pile_integrity();
ASSERT(index < _hands[_turn].size()); ASSERT(index < _hands[_turn].size());
ASSERT(_num_clues != max_num_clues); ASSERT(_num_clues != max_num_clues);
@ -229,6 +253,7 @@ namespace Hanabi {
_actions_log.emplace(ActionType::discard, discarded_card, index); _actions_log.emplace(ActionType::discard, discarded_card, index);
incr_turn(); incr_turn();
check_draw_pile_integrity();
return multiplicity; return multiplicity;
} }
@ -449,6 +474,7 @@ namespace Hanabi {
template<suit_t num_suits, player_t num_players, hand_index_t hand_size> template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
void void
HanabiState<num_suits, num_players, hand_size>::revert_play() { HanabiState<num_suits, num_players, hand_size>::revert_play() {
check_draw_pile_integrity();
const BacktrackAction last_action = _actions_log.top(); const BacktrackAction last_action = _actions_log.top();
_actions_log.pop(); _actions_log.pop();
ASSERT(last_action.action_type == ActionType::play); ASSERT(last_action.action_type == ActionType::play);
@ -463,10 +489,12 @@ namespace Hanabi {
_stacks[last_action.discarded.suit]++; _stacks[last_action.discarded.suit]++;
} }
_score--; _score--;
check_draw_pile_integrity();
} }
template<suit_t num_suits, player_t num_players, hand_index_t hand_size> template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
void HanabiState<num_suits, num_players, hand_size>::revert_discard() { void HanabiState<num_suits, num_players, hand_size>::revert_discard() {
check_draw_pile_integrity();
const BacktrackAction last_action = _actions_log.top(); const BacktrackAction last_action = _actions_log.top();
_actions_log.pop(); _actions_log.pop();
@ -479,6 +507,7 @@ namespace Hanabi {
_pace++; _pace++;
revert_draw(last_action.index, last_action.discarded); revert_draw(last_action.index, last_action.discarded);
check_draw_pile_integrity();
} }
template<suit_t num_suits, player_t num_players, hand_index_t hand_size> template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
@ -793,6 +822,7 @@ namespace Hanabi {
revert_action(); revert_action();
} else { } else {
unsigned sum_of_multiplicities = 0; unsigned sum_of_multiplicities = 0;
[[maybe_unused]] const auto pile = _draw_pile;
for(size_t i = 0; i < _draw_pile.size(); i++) { for(size_t i = 0; i < _draw_pile.size(); i++) {
const unsigned long multiplicity = do_action(); const unsigned long multiplicity = do_action();
sum_of_multiplicities += multiplicity; sum_of_multiplicities += multiplicity;