Thunderjack! HTML5 Game Update: Recycling the Deck

Hey there,

Now that you’ve got most of the core gameplay completed, this article is about managing the deck of cards.

Each round of play draws cards from the deck. Just before each new round is started, all cards involved in play are moved to a discard pile. Cards in this pile cannot be used again until the deck is recycled.

Eventually, the deck will run out of cards. This is not good, especially considering it would happen in the middle of a game, while cards are being dealt. The process of recycling the deck starts after all the in-play cards have been discarded.

In the video, for the sake of brevity, the deck will recycled after one round. But in a real game, you’d want more cards to be played before the deck recycles. The discard pile is formed just to the left of the dealer’s hand. At the end of the round, after all the cards are discarded, they are then moved back into the deck. Afterwards, the deck is shuffled, and the next round begins.

But before you get into recycling the deck, let’s first go over discarding the cards.

Discarding the cards

At the end of each round, the game discards all players’ and dealer’s cards by moving them from their hands into the discard pile.

Just like the deck was defined as a DeckDataprototype, the discard pile can use the same prototype:

discardDeckData = new Thunderjack.DeckData();

The discard pile can be treated just like the deck, because cards will be added to and removed from it.

Note: The deck functions as a stack (LIFO – last in, first out), meaning that the cards added to the deck are removed in the reverse order in which they were added. The last card to be added (last in) is the first one to be removed (first out).

As mentioned, at the end of each round, all the cards in play are moved to the discard pile. The DeckData prototype currently does not have a way to add cards to it as needed, so here’s a function to add to the prototype to do that:

pushCardData
Thunderjack.DeckData.prototype.pushCardData = function(cardData) {
  this._cardsData.push(cardData);
};

When moving discarding all the cards, some pseudo code looks like this:

for each player in the game {
  discardPlayerCards (player)
}

discardPlayerCards (dealer) //don't forget the dealer
...
discardPlayerCards (player) {
  for each cardData in player's hand {
    remove cardData from hand
    add cardData to discardDeckData //using discardDeckData.pushCardData()
  }
}

Recycling the deck

Recycling is made of three steps:

1). Decide if the deck should be recycled. If so, proceed to step 2. Otherwise, begin the next round.
2). Move all cards from the discard pile back into the deck.
3). Shuffle the deck.

Once all the in-play cards have been discarded, we call this function:

handleDiscardCardsComplete
GamePlay.prototype._handleDiscardCardsComplete = function() {
  if (this._shouldRecycleDeck()) {
    this._recycleDeck();
  }
  
  this._beginRound();
};

Let’s start with the first step:

1). Decide if the deck should be recycled. If so, proceed to step 2. Otherwise, beGin the next round.

After all the cards have been discarded, you check the deck to see if it has few enough cards to be recycled. We’ll pick a hard number (you can make it a percentage of maximum number of cards in the deck).

The handleDiscardCardsComplete function should be called after all the cards have been discarded. It will first decide if the deck should be recycled. It so, it goes ahead wit hit. Otherwise, the next round begins.

shouldRecycleDeck
GamePlay.prototype._shouldRecycleDeck = function() {
  if (this._discardDeckData.getLength() === 0) {
    //shouldn't recycle deck if no cards have been discarded
    return(false);
  }
  
  var RECYCLE_DECK_THRESHOLD = 15;
  return(this._deckData.getLength() < RECYCLE_DECK_THRESHOLD);
};

This function determines if the deck should be recycled. The threshold is 15 cards. If the deck contains less than 15 cards, it should be recycled.

Note: Having a threshold of 15 cards is quite low, and can be risky, especially if you are playing three hands. Each hand can hold six cards max. That said, the max number of cards used in a game is 7 x 6 = 42 cards (three player hands with six cards each (3 x 6) + three split hands with six cards each (3 x 6) + one dealer hand of six cards (1 x 6). So, you have: 3 x 6 + 3 x 6 + 6 = 42.

It is unlikely that a single game would use this many cards, but there is the chance that the number of cards used in the game would completely empty the deck. You can reduce this from happening by increasing the threshold. A way to guarantee that it will never happen is to use more than one deck, and increase the threshold to 43 (not a typo: you want the deck to be recycled if there are less than 43; or you could change the comparison operator from < to <= and use 42 as the threshold).

Now you know if the deck should be recycled or not. (Let’s assume so, we you can move on to step 2! 😛 )

2). Move all cards from the discard pile back into the deck.

Going back to the handleDiscardCardsComplete, we’re assuming that shouldRecycleDeck returned true. So we’re now start the recycle process with this function:

recycleDeck
GamePlay.prototype._recycleDeck = function() {
  //move all cards from the discard pile to the deck
  var cardData = this._discardDeckData.popCardData();
  while (cardData !== null) {
    this._deckData.pushCardData(cardData);
    cardData = this._discardDeckData.popCardData();
  }
};

This function starts by “popping” (removing) the last card from the discard pile and storing it in the cardData variable.

Next it starts a while loop. As long as there are cards in the discard pile, the loop will do the following:

  1. Add the card data to the deck
  2. Pop the next card from the discard pile.

After the last card has been removed from the discard pile and popCardData is called when there are no cards left, cardData will be set to null.

Remember that the functions being called on the deckData and discardDeckData have been defined on the DeckData prototype.

3). Shuffle the deck.

Finally, after all the cards have been moved back into the deck, it is shuffled by calling the shuffle function.

You can do this by adding one more line at the bottom of your recycleDeck function:

GamePlay.prototype._recycleDeck = function() {
  ...
  this._deckData.shuffle();
};

Recycling the deck is now complete, and the game begins with the next round.

If you have any questions for me about anything I’ve discussed so far, feel free to ask in the comments below.

Also, if you’re looking to hire a coder to build your next card game, get in touch with me by e-mailing me at cartrell@gameplaycoder.com.

That’s it for this post, guys. Thanks, and talk to you later.

– C. out.