store bits for starting hand cards in central bitse

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

View file

@ -37,13 +37,14 @@ 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<uint8_t>::max();
constexpr std::array<std::string, 6> suit_initials{"r", "y", "g", "b", "p", "t"};
struct Card {
suit_t suit;
rank_t rank;
bool was_in_initial_hand;
uint8_t local_index_among_good_starting_hand_cards;
bool initial_trash;
Card &operator++();
@ -211,11 +212,9 @@ private:
// 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;
// This will indicate whether cards that were in hands initially still are in hands
std::array<std::bitset<hand_size>, num_players> _card_positions_hands;
// A list of cards (set up once upon initialization) of all good cards that were in starting hands
std::array<boost::container::static_vector<Card, hand_size>, num_players> _good_cards_in_initial_draw_pile;
// This will indicate whether cards that were in hands initially still are in hands
std::bitset<num_players * hand_size> _card_positions_hands;
// further statistics that we might want to keep track of
uint8_t _pace{};

View file

@ -218,9 +218,9 @@ namespace Hanabi {
if constexpr(update_card_positions) {
const Card discarded = _hands[_turn][index];
if (!discarded.initial_trash) {
if (discarded.was_in_initial_hand) {
ASSERT(_card_positions_hands[_turn][index] == true);
_card_positions_hands[_turn][index] = false;
if (discarded.local_index_among_good_starting_hand_cards != not_in_starting_hand) {
ASSERT(_card_positions_hands[discarded.local_index_among_good_starting_hand_cards] == true);
_card_positions_hands[discarded.local_index_among_good_starting_hand_cards] = false;
} else {
auto replaced_card_it = std::ranges::find(_card_positions_draw[discarded], _turn);
ASSERT(replaced_card_it != _card_positions_draw[discarded].end());
@ -290,9 +290,9 @@ namespace Hanabi {
}
if (!discarded_card.initial_trash) {
if (discarded_card.was_in_initial_hand) {
ASSERT(_card_positions_hands[_turn][index] == false);
_card_positions_hands[_turn][index] = true;
if (discarded_card.local_index_among_good_starting_hand_cards != not_in_starting_hand) {
ASSERT(_card_positions_hands[discarded_card.local_index_among_good_starting_hand_cards] == false);
_card_positions_hands[discarded_card.local_index_among_good_starting_hand_cards] = true;
} else {
auto hand_card_it = std::ranges::find(_card_positions_draw[discarded_card], trash_or_play_stack);
ASSERT(hand_card_it != _card_positions_draw[discarded_card].end());
@ -309,7 +309,7 @@ namespace Hanabi {
const Card trash = [this]() -> Card {
for(suit_t suit = 0; suit < num_suits; suit++) {
if(_stacks[suit] < starting_card_rank) {
return {suit, starting_card_rank - 1, false, true};
return {suit, starting_card_rank - 1, not_in_starting_hand, true};
}
}
return {0,0};
@ -328,7 +328,7 @@ namespace Hanabi {
_draw_pile.clear();
for(suit_t suit = 0; suit < num_suits; suit++) {
for(rank_t rank = 0; rank < starting_card_rank; rank++) {
Card card {suit, rank, false, is_trash(card)};
Card card {suit, rank, not_in_starting_hand, is_trash(card)};
_card_positions_draw[card].clear();
if (nums_in_draw_pile[card] > 0) {
_draw_pile.push_back({card, nums_in_draw_pile[card]});
@ -340,22 +340,27 @@ 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.was_in_initial_hand = true;
card.initial_trash = is_trash(card);
// Needed to check for dupes in same hand
boost::container::static_vector<Card, hand_size> good_cards_in_hand;
if(!is_trash(card)) {
if(std::count(_good_cards_in_initial_draw_pile[player].begin(), _good_cards_in_initial_draw_pile[player].end(), card) > 0) {
if(std::count(good_cards_in_hand.begin(), good_cards_in_hand.end(), card) > 0) {
// This card is already in hand, so just replace the second copy by some trash
card = trash;
} else {
_good_cards_in_initial_draw_pile[player].push_back(card);
card.local_index_among_good_starting_hand_cards = local_index_among_good_starting_hand_cards;
local_index_among_good_starting_hand_cards++;
good_cards_in_hand.push_back(card);
}
}
}
_card_positions_hands[player].reset();
_card_positions_hands[player].flip();
}
_card_positions_hands.reset();
_card_positions_hands.flip();
}
template<suit_t num_suits, player_t num_players, hand_index_t hand_size>