Card Game Extension (alpha release)

I still don’t understand how you find the hand that its going to play

Almost all of the blocks for determining the poker hand is in the DeterminePokerHand function. Outside of that, an important helper function is called CountNumOfAKind, and it looks at the selected cards and counts how many “X of a kind” is in those cards, and something is counted only if the number of cards in that rank match X exactly. so a hand of “A,A,A,9,8” would not contain a “2 of a kind” even though it has 2 aces, but it would contain one “3 of a kind”.

Looking back at DeterminePokerHand, From top to bottom, here is what the code blocks generally mean:

  1. Setup the EvaluateCardRanks array. It just stores the rank of the selected cards for other sections of the code to use - it’s not strictly necessary, but it’s easier than looking through the entire player hand and pick out the selected cards again every time I want to look through them.CountNumOfAKind, the helper function, uses the array as well.
  2. Check if 5 cards are selected:
    1. If the hand is made out of 5 cards, check to see if the 5 cards form a flush. We can do that by grabbing the suit of the first selected card, then just checking if the rest of the selected cards have the exact suit. We store this in HasFlush.
    2. We also check a 5 card hand for straights. We do this by first looking through the selected cards once and figure out which rank is the smallest, then loop through the cards 4 more times, trying to see if a card exist where the rank is the next number. We store the result in HasStraight.
    3. If the hand has less than 5 cards (and since the game doesn’t have jokers yet), we can safely rule out flushes and straights. We set both of those to false.
  3. Once we know whether the selected cards has a flush/straight, and we can count exactly how many X of a kind are in the selected cards, the rest is easy, just make checks against the criteria for a specific hand, starting from the highest scoring one:
  • the selected cards form a “Flush 5” if it HasFlush and CountNumOfAKind(5) returns 1.
  • “Flush House” is formed by HasFlush, CountNumOfAKind(3) returns 1, and CountNumOfAKind(2) returns 1
  • etc, etc.

A small wrinkle about Balatro specifically is that it is picky about which cards score for points, so there are additional logic involved in flagging specific cards for scoring:

  1. 5 card poker hands are easy, just flag them all for scoring.
  2. “4 of a Kind”, “3 of a Kind”, “Two Pairs”, “Pair” are trickier - I need to find the cards that forms the “X of a kind” again, and mark them for scoring.
  3. “High Card” actually requires its own code, since only the highest ranked card in the poker hand scores. The code is actually not completely right, by the way - the code only looks for the first card that scores the highest, when in reality it needs to check for rank as well (K > Q > J > 10 even though they score 10 chips). This matters when the cards are modified in the real Balatro game.
3 Likes

very nice you added the secret hands as I checked the function in the project

2 Likes

why does this make so many duplicates

1 Like


There are two problems in this block:

  1. You are assigning values to the Rank attribute twice. There’s currently no checks against this, but it is not something you’re supposed to do.
  2. The add card block looks at each list and adds all combinations of items between the lists. So by having 5 items on the first list and 35 items on the second list we are adding 5*35 = 175 cards into the deck.

Here is how the block is meant to be used. I’ve replicated the blocks for how the playing cards are created:

That first block creates all possible combinations between 4 suits and 13 ranks, so the cards that gets added to the deck would be Ace of Hearts, 2 of Hearts, 3 of Hearts… all the way to King of Hearts, then Ace of Spades, 2 of Spades… in this exact order. If I break that block further so I’m creating one card at a time, the logic looks like this:

Looking back at the blocks further above, notice how I have to add the suit colors (red/black) by looking through the deck again. It is tempting to try and add SuitColor to the list of combinations and do this, but this is wrong:

The block would add all combinations between the suits, the ranks, and the suit colors, Meaning you’ll now be adding, in order, a red Ace of Hearts, a black Ace of Hearts, a red 2 of Hearts, a black 2 of Hearts… creating 4x13x2 = 104 cards, including combinations that you don’t want.

If the attributes that you put in the cards are highly unique (TCG cards tend to do this), you are unfortunately going to have to add those cards to the deck one at a time, like so:

2 Likes

I just want to say that this is the smartest thing I’ve seen this extension used for.

3 Likes

I was gonna use this for my JJK game, but it doesn’t work too well, so I’d rather use the mini menu extension. I will use it for my RPG and survival games, tho

1 Like

Random question just out of curiosity would this extension be able to make the library of ruina card combat system. If you don’t know how it works just look up library of ruina gameplay and you’ll see. This is just out of curiosity and I’m not planning to make a game like that

1 Like

The short answer is no.

The extension can help you manage data that’s encoded on the cards, allow you to draw unique cards based on those data so you don’t need to create unique art for every card in the game, and help handle basic things like selecting cards and moving them between deck/hand/discard.

Outside of that, you’ll have to manually write blocks that enforces the rules of the game, whether it is targeting, damage calculation, determining where the cards go to, etc.

1 Like

oh ok that makes sense