Wrote some code to pick random cards from an expanding number of decks. Only "opening" a new deck when needed. If you ask for 13 random diamonds and 13 random spades then it will only use one deck. But if you request 14 random diamonds or 5 random kings then it will start using a second deck.

```
int MAX_DECKS = 10;
int16_t get_from_decks(bool *decks, int search_rank, int search_suit)
{
int start_rank = search_rank == -1 ? rand()%13 : search_rank;
int start_suit = search_suit == -1 ? rand()%4 : search_suit;
int rank, suit;
int deck = 0;
bool found = false;
while(deck < MAX_DECKS && !found) {
for(int rank_offset=0;
rank_offset < (search_rank == -1 ? 13 : 1) && !found;
rank_offset++) {
for(int suit_offset=0;
suit_offset < (search_suit == -1 ? 4 : 1) && !found;
suit_offset++) {
rank = (start_rank + rank_offset) % 13;
suit = (start_suit + suit_offset) % 4;
int idx = rank + suit * 13 + deck * 52;
if(decks[idx]) {
decks[idx] = false;
found = true;
}
}
}
deck++;
}
return rank + suit * 13;
}
```

The algorithm will always try to empty the previous decks even if new ones have been opened. So if the first deck has 1 remaining club, the second deck has 10 clubs and you request a random club then it will always return the last club from deck 1.

If you go past MAX_DECKS then the code returns cards that match the search criteria but without taking into account decks (so five random hearts could come up 5 aces).

The code isn't high performance. It just does a brute force search for a free card matching the criteria. A search three and/or meta data about remaining cards in the deck would make it faster but I only need it to process a limited set of cards (and only once during a file load).

Demo of function:

```
int most_copies(int *array) {
int copies = 0;
for(int i=0; array[i] != -1; i++) {
int count = 1;
for(int a=i+1; array[a] != -1; a++) {
if(array[i] == array[a]) {
count++;
}
}
copies = count > copies ? count : copies;
}
return copies;
}
int main (int argc, char const *argv[])
{
bool* decks = (bool*)malloc(sizeof(bool)*52*MAX_DECKS);
memset(decks, 1, sizeof(bool)*52*MAX_DECKS);
int *created_cards = (int*)malloc(sizeof(int)*100);
memset(created_cards, -1, sizeof(int)*100);
// Get 52 random cards (full deck)
for(int i=0; i<52; i++) {
created_cards[i] = get_from_decks(decks, -1, -1);
}
printf("Decks for 52 cards: %d\n", most_copies(created_cards));
// Get 60 random cards (full deck + 8 cards)
memset(decks, 1, sizeof(bool)*52*MAX_DECKS);
memset(created_cards, -1, sizeof(int)*100);
for(int i=0; i<60; i++) {
created_cards[i] = get_from_decks(decks, -1, -1);
}
printf("Decks for 60 cards: %d\n", most_copies(created_cards));
// Get 5 aces (2 decks):
memset(decks, 1, sizeof(bool)*52*MAX_DECKS);
memset(created_cards, -1, sizeof(int)*100);
for(int i=0; i<5; i++) {
created_cards[i] = get_from_decks(decks, 0, -1);
}
printf("Decks for 5 aces: %d\n", most_copies(created_cards));
// Get 27 diamonds (3 decks):
memset(decks, 1, sizeof(bool)*52*MAX_DECKS);
memset(created_cards, -1, sizeof(int)*100);
for(int i=0; i<27; i++) {
created_cards[i] = get_from_decks(decks, -1, 0);
}
printf("Decks for 27 diamonds: %d\n", most_copies(created_cards));
return 0;
}
```

Output:

```
Decks for 52 cards: 1
Decks for 60 cards: 2
Decks for 5 aces: 2
Decks for 27 diamonds: 3
```