store bits for starting hand cards in central bitse
This commit is contained in:
parent
8001483ddd
commit
9cc852a96d
2 changed files with 22 additions and 18 deletions
|
@ -37,13 +37,14 @@ constexpr size_t max_card_duplicity = 3;
|
||||||
constexpr player_t draw_pile = -1;
|
constexpr player_t draw_pile = -1;
|
||||||
constexpr player_t trash_or_play_stack = -2;
|
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 std::array<std::string, 6> suit_initials{"r", "y", "g", "b", "p", "t"};
|
constexpr std::array<std::string, 6> suit_initials{"r", "y", "g", "b", "p", "t"};
|
||||||
|
|
||||||
struct Card {
|
struct Card {
|
||||||
suit_t suit;
|
suit_t suit;
|
||||||
rank_t rank;
|
rank_t rank;
|
||||||
bool was_in_initial_hand;
|
uint8_t local_index_among_good_starting_hand_cards;
|
||||||
bool initial_trash;
|
bool initial_trash;
|
||||||
|
|
||||||
Card &operator++();
|
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
|
// 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
|
|
||||||
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
|
// This will indicate whether cards that were in hands initially still are in hands
|
||||||
std::array<boost::container::static_vector<Card, hand_size>, num_players> _good_cards_in_initial_draw_pile;
|
std::bitset<num_players * hand_size> _card_positions_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{};
|
||||||
|
|
|
@ -218,9 +218,9 @@ namespace Hanabi {
|
||||||
if constexpr(update_card_positions) {
|
if constexpr(update_card_positions) {
|
||||||
const Card discarded = _hands[_turn][index];
|
const Card discarded = _hands[_turn][index];
|
||||||
if (!discarded.initial_trash) {
|
if (!discarded.initial_trash) {
|
||||||
if (discarded.was_in_initial_hand) {
|
if (discarded.local_index_among_good_starting_hand_cards != not_in_starting_hand) {
|
||||||
ASSERT(_card_positions_hands[_turn][index] == true);
|
ASSERT(_card_positions_hands[discarded.local_index_among_good_starting_hand_cards] == true);
|
||||||
_card_positions_hands[_turn][index] = false;
|
_card_positions_hands[discarded.local_index_among_good_starting_hand_cards] = false;
|
||||||
} else {
|
} else {
|
||||||
auto replaced_card_it = std::ranges::find(_card_positions_draw[discarded], _turn);
|
auto replaced_card_it = std::ranges::find(_card_positions_draw[discarded], _turn);
|
||||||
ASSERT(replaced_card_it != _card_positions_draw[discarded].end());
|
ASSERT(replaced_card_it != _card_positions_draw[discarded].end());
|
||||||
|
@ -290,9 +290,9 @@ namespace Hanabi {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!discarded_card.initial_trash) {
|
if (!discarded_card.initial_trash) {
|
||||||
if (discarded_card.was_in_initial_hand) {
|
if (discarded_card.local_index_among_good_starting_hand_cards != not_in_starting_hand) {
|
||||||
ASSERT(_card_positions_hands[_turn][index] == false);
|
ASSERT(_card_positions_hands[discarded_card.local_index_among_good_starting_hand_cards] == false);
|
||||||
_card_positions_hands[_turn][index] = true;
|
_card_positions_hands[discarded_card.local_index_among_good_starting_hand_cards] = true;
|
||||||
} else {
|
} else {
|
||||||
auto hand_card_it = std::ranges::find(_card_positions_draw[discarded_card], trash_or_play_stack);
|
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());
|
ASSERT(hand_card_it != _card_positions_draw[discarded_card].end());
|
||||||
|
@ -309,7 +309,7 @@ namespace Hanabi {
|
||||||
const Card trash = [this]() -> Card {
|
const Card trash = [this]() -> Card {
|
||||||
for(suit_t suit = 0; suit < num_suits; suit++) {
|
for(suit_t suit = 0; suit < num_suits; suit++) {
|
||||||
if(_stacks[suit] < starting_card_rank) {
|
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};
|
return {0,0};
|
||||||
|
@ -328,7 +328,7 @@ namespace Hanabi {
|
||||||
_draw_pile.clear();
|
_draw_pile.clear();
|
||||||
for(suit_t suit = 0; suit < num_suits; suit++) {
|
for(suit_t suit = 0; suit < num_suits; suit++) {
|
||||||
for(rank_t rank = 0; rank < starting_card_rank; rank++) {
|
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();
|
_card_positions_draw[card].clear();
|
||||||
if (nums_in_draw_pile[card] > 0) {
|
if (nums_in_draw_pile[card] > 0) {
|
||||||
_draw_pile.push_back({card, nums_in_draw_pile[card]});
|
_draw_pile.push_back({card, nums_in_draw_pile[card]});
|
||||||
|
@ -340,22 +340,27 @@ 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.was_in_initial_hand = true;
|
|
||||||
card.initial_trash = is_trash(card);
|
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(!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
|
// This card is already in hand, so just replace the second copy by some trash
|
||||||
card = trash;
|
card = trash;
|
||||||
} else {
|
} 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>
|
template<suit_t num_suits, player_t num_players, hand_index_t hand_size>
|
||||||
|
|
Loading…
Reference in a new issue