store number of useful cards in starting hands

This commit is contained in:
Maximilian Keßler 2023-08-07 11:48:39 +02:00
parent 9cc852a96d
commit 0100e8c987
Signed by: max
GPG key ID: BCC5A619923C0BA5
2 changed files with 23 additions and 9 deletions

View file

@ -34,8 +34,6 @@ using state_t = std::uint32_t;
constexpr rank_t starting_card_rank = 5; constexpr rank_t starting_card_rank = 5;
constexpr suit_t max_suit_index = 5; constexpr suit_t max_suit_index = 5;
constexpr size_t max_card_duplicity = 3; 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 clue_t max_num_clues = 8;
constexpr uint8_t not_in_starting_hand = std::numeric_limits<uint8_t>::max(); constexpr uint8_t not_in_starting_hand = std::numeric_limits<uint8_t>::max();
@ -200,6 +198,12 @@ private:
void incr_turn(); void incr_turn();
void decr_turn(); void decr_turn();
static constexpr uint8_t no_endgame = std::numeric_limits<uint8_t>::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{}; player_t _turn{};
clue_t _num_clues{}; clue_t _num_clues{};
std::uint8_t _weighted_draw_pile_size{}; std::uint8_t _weighted_draw_pile_size{};
@ -208,13 +212,12 @@ private:
std::list<CardMultiplicity> _draw_pile{}; std::list<CardMultiplicity> _draw_pile{};
std::uint8_t _endgame_turns_left{}; std::uint8_t _endgame_turns_left{};
static constexpr uint8_t no_endgame = std::numeric_limits<uint8_t>::max();
// This will save the card positions of all cards that are in the draw pile when we start backtracking // This will save the card positions of all cards that are in the draw pile when we start backtracking
CardArray<num_suits, boost::container::static_vector<player_t, max_card_duplicity>> _card_positions_draw; CardArray<num_suits, boost::container::static_vector<player_t, max_card_duplicity>> _card_positions_draw;
// This will indicate whether cards that were in hands initially still are in hands // This will indicate whether cards that were in hands initially still are in hands
std::bitset<num_players * hand_size> _card_positions_hands; std::bitset<num_players * hand_size> _card_positions_hands;
size_t _num_useful_cards_in_starting_hands;
// further statistics that we might want to keep track of // further statistics that we might want to keep track of
uint8_t _pace{}; uint8_t _pace{};

View file

@ -69,8 +69,12 @@ namespace Hanabi {
_hands(), _hands(),
_draw_pile(), _draw_pile(),
_endgame_turns_left(no_endgame), _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)), _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); std::ranges::fill(_stacks, starting_card_rank);
for(const Card& card: deck) { for(const Card& card: deck) {
_draw_pile.push_back({card, 1}); _draw_pile.push_back({card, 1});
@ -340,7 +344,6 @@ namespace Hanabi {
} }
// Prepare cards in hands // Prepare cards in hands
uint8_t local_index_among_good_starting_hand_cards = 0;
for(player_t player = 0; player < num_players; player++) { for(player_t player = 0; player < num_players; player++) {
for(Card& card : _hands[player]) { for(Card& card : _hands[player]) {
card.initial_trash = is_trash(card); 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 // This card is already in hand, so just replace the second copy by some trash
card = trash; card = trash;
} else { } else {
card.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;
local_index_among_good_starting_hand_cards++; _num_useful_cards_in_starting_hands++;
good_cards_in_hand.push_back(card); good_cards_in_hand.push_back(card);
} }
@ -360,7 +363,9 @@ namespace Hanabi {
} }
} }
_card_positions_hands.reset(); _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<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>
@ -480,4 +485,10 @@ namespace Hanabi {
return best_probability; return best_probability;
} }
template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
std::uint64_t HanabiState<num_suits, num_players, hand_size>::unique_id() const {
unsigned long id = _card_positions_hands.to_ulong();
return id;
}
} // namespace Hanabi } // namespace Hanabi