diff --git a/game_state.h b/game_state.h index 3544438..bfd1d88 100644 --- a/game_state.h +++ b/game_state.h @@ -34,8 +34,6 @@ using state_t = std::uint32_t; constexpr rank_t starting_card_rank = 5; constexpr suit_t max_suit_index = 5; constexpr size_t max_card_duplicity = 3; -constexpr player_t draw_pile = -1; -constexpr player_t trash_or_play_stack = -2; constexpr clue_t max_num_clues = 8; constexpr uint8_t not_in_starting_hand = std::numeric_limits::max(); @@ -200,6 +198,12 @@ private: void incr_turn(); void decr_turn(); + 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; + + std::uint64_t unique_id() const; + player_t _turn{}; clue_t _num_clues{}; std::uint8_t _weighted_draw_pile_size{}; @@ -208,13 +212,12 @@ private: std::list _draw_pile{}; std::uint8_t _endgame_turns_left{}; - static constexpr uint8_t no_endgame = std::numeric_limits::max(); - // This will save the card positions of all cards that are in the draw pile when we start backtracking CardArray> _card_positions_draw; // This will indicate whether cards that were in hands initially still are in hands std::bitset _card_positions_hands; + size_t _num_useful_cards_in_starting_hands; // further statistics that we might want to keep track of uint8_t _pace{}; diff --git a/game_state.hpp b/game_state.hpp index e040f01..727d8e2 100644 --- a/game_state.hpp +++ b/game_state.hpp @@ -69,8 +69,12 @@ namespace Hanabi { _hands(), _draw_pile(), _endgame_turns_left(no_endgame), + _card_positions_draw(), + _card_positions_hands(), + _num_useful_cards_in_starting_hands(0), _pace(deck.size() - 5 * num_suits - num_players * (hand_size - 1)), - _score(0) { + _score(0), + _enumerated_states(0) { std::ranges::fill(_stacks, starting_card_rank); for(const Card& card: deck) { _draw_pile.push_back({card, 1}); @@ -340,7 +344,6 @@ namespace Hanabi { } // Prepare cards in hands - uint8_t local_index_among_good_starting_hand_cards = 0; for(player_t player = 0; player < num_players; player++) { for(Card& card : _hands[player]) { card.initial_trash = is_trash(card); @@ -351,8 +354,8 @@ namespace Hanabi { // This card is already in hand, so just replace the second copy by some trash card = trash; } else { - card.local_index_among_good_starting_hand_cards = local_index_among_good_starting_hand_cards; - local_index_among_good_starting_hand_cards++; + card.local_index_among_good_starting_hand_cards = _num_useful_cards_in_starting_hands; + _num_useful_cards_in_starting_hands++; good_cards_in_hand.push_back(card); } @@ -360,7 +363,9 @@ namespace Hanabi { } } _card_positions_hands.reset(); - _card_positions_hands.flip(); + for(size_t i = 0; i < _num_useful_cards_in_starting_hands; i++) { + _card_positions_hands[i] = true; + } } template @@ -480,4 +485,10 @@ namespace Hanabi { return best_probability; } + template + std::uint64_t HanabiState::unique_id() const { + unsigned long id = _card_positions_hands.to_ulong(); + return id; + } + } // namespace Hanabi \ No newline at end of file