Coding a card game - Excluding certain numbers from *rand

Hi everyone!

As a hobby project, I’m coding a mini gambling/card-game that I invented, similar to blackjack. You can play the current demo here, but I wanted to add a more complex mechanic and I’m not sure how to do the coding that it would entail.

Would welcome all the help I can get!! Or even just thoughts on the mechanics!

Basic rules of the game

  1. There are 8 types of cards (peasant all the way up to Pope), each with a different score. There are also special “pairings” that give you special scores (e.g. King with Queen, two peasants, all royals etc.)
  2. You place a starting bid. So does your opponent.
  3. You draw a card, your opponent draws a card. You can add to your original bid, if you want.
  4. You draw another card. Your opponent draws another card.
  5. You tally up the scores of both your cards. The person with the highest score wins.

Help
Right now, I’m using a random number generator to generate what cards are drawn. Each card is assigned a number from 1 to 8. (Peasant = 1, Jester = 2 etc.)

Like blackjack, the game would be so much cooler if there’s a fixed number of each type of card in the deck, so that getting one of them would affect the chances of getting another one of them in the next draw. E.g. if there are only 2 cards of each type in a deck, and you get a peasant, then you can tell that the probability of getting another peasant is lower.

However, I’m not sure how to code this - how do I craft a custom “list” for random number generator (beyond setting the min and max range) to exclude cards (i.e. “numbers”) that have been drawn before? More importantly, what’s the most elegant way to automate the updating of this list so that it isn’t super clunky?

What the code looks like currently
For now, to avoid the problem of dealing with differing probabilities (e.g. if there are only 2, or 3 of each type of card), I’ve said that there are 4 of each type in a deck. Meaning that you can get a King without there being a lower probability of getting a King again in your next draw (nor will your opponent’s likelihood of getting a King be affected).

This means the code is relatively straightforward:

*rand first_card_generator 0 8
*if first_card_generator = 1
  *set first_card "peasant"
  It's a [i]peasant[/i]. 1 point.
*if first_card_generator = 2
  *set first_card "jester"
  It's a [i]jester[/i]. 2 points.
*if first_card_generator = 3
  *set first_card "scholar"
  It's a [i]scholar[/i]. 3 points.
*if first_card_generator = 4
  *set first_card "marshall"
  It's a [i]marshall[/i]. 4 points.
*if first_card_generator = 5 
  *set first_card "chancellor"
  It's a [i]chancellor[/i]. 
*if first_card_generator = 6
  *set first_card "queen"
  It's a [i]queen[/i]. 6 points.
*if first_card_generator = 7
  *set first_card "king"
  It's a [i]king[/i].
*if first_card_generator = 8
  *set first_card "pope"
  It's a [i]pope[/i]. 8 points.

Thanks very much in advance :slight_smile:

2 Likes

What if you number each card in your deck, then force the random generator to redraw if it gets the same exact card it’s drawn before? Like, if you had two each of 8 cards in your deck:

*rand first_card generator 1 16
*if first_card_generator = 1 or first_card generator = 2
*set first_card “peasant”
It’s a peasant. 1 point.
[etc.]

*label second_draw
*rand second_card generator 1 16
*if second_card generator = first_card generator
*goto second_draw
*if second_card generator = 1 or second_card_generator = 2
*set second_card “peasant”
It’s a peasant. 1 point.

That way if it draws the “same” peasant card, it’ll reroll, dropping your chances of getting the same card twice, but if it draws the “other” peasant card, the player can still get a second peasant.

6 Likes

I think booleans are good for that, but you would have to add a subcategory for the cards, maybe elf, dwarf, orc, goblin or such. So you have 8*subcategory different cards.

I wlii try If I get some code running, might take some time.

2 Likes

@Amtelope Oh shoot, that’s a brilliant workaround, thank you!

Since the opponent is also drawing from the same deck, I suppose I’d apply this to the opponent’s draw:

One thing that gets me stuck though, for the player’s second card or the opponent’s second card, is that there’s a genuine possibility that there’s no way a certain card should be drawn (e.g. how to tell that a 1 & 2 should be linked), and I’ve just cracked my brain trying to think of a solution.

Edit: And then realised that the method actually DOES take care of the scenario where two of the same type of card have been drawn before (e.g. a 1 and a 2, both peasants):

Scenario of the third draw (i.e. player’s second draw:

*label third_draw
*rand third_card_generator 1 16
*if (third_card_generator = first_card generator) or (third_card_generator = second_card_generator)
*goto third_card_draw

Let’s say a 1 was drawn first, then a 2 was drawn (both peasants). If the third draw is a 1 (peasant), a re-draw will be forced. On the other hand, if the third draw is 2 (also a peasant), a re-draw will also be forced.

Which would hence always force a re-draw i.e. be rightly coded as an ‘impossible outcome’. (Right…?)

Cool!

@Kaelyn Ahh suits would also be an amazing idea, especially if it adds some flavor to the game. I will toy with this idea further…

Either way, it can also be combined with the above solution for flavor-text (e.g. 1 = Human peasant, 2 = elf peasant).

Thanks both :DD

P.S. I loved The Play’s the Thing. I’d been dreaming of a “play”/musical related thing ever since “A Player’s Heart”, and TPtT really scratched my itch!

2 Likes

Create an array of cards:

*create card_1_name "peasant" 
*create card_1_value 1
*create card_1_drawn false
... 

If you use suits, create them in sequence. For exemple:

*create card_1_name "peasant of hearts" 
... 
*create card_9_name "peasant of coins" 

Create a subroutine to pick a card. The subroutine should pick a number randomly from the number of cards in the deck. Check if the drawn flag is still false. Set the drawn flag to true. Return the selected number.

*create current_card 0

*label draw
*temp pick 0
*rand pick 1 8
*if not(card[pick]["drawn"]) 
	*set card[pick]["drawn"] true
	*set current_card pick
*else
	*gosub draw
*return
3 Likes

@burninglights That should work. It may get clunky if you have a lot of draws. At that point, one possible solution is to create “card_1,” “card_2” etc. variables to track whether a card has been drawn (set to false initially.)

In the code below, *set card[first_card_generator] true will *set card_(whatever the value of first_card_generator is) true. The value of the variable inside the brackets is rendered as “_value”.

So:

*rand first_card_generator 1 16
*if first_card_generator = 1 or first_card generator = 2
It’s a peasant. 1 point.
*set card[first_card_generator] true

*label second_draw
*rand second_card_generator 1 16
*if card[second_card_generator] = true
*goto second_draw
If second_card_generator = 1 or second_card_generator = 2
*set card[second_card_generator] true
It’s a peasant. 1 point.

That way you don’t have to compare a dozen draws to each other if your game is long. You can just check if the card that was just drawn has been used before or not.

EDIT: or use arrays as above …

2 Likes

@Amtelope and @cup_half_empty Wow thank you so much!! I hadn’t needed to use arrays before this, and your instructions/examples really helped me understand how to use them. Cheers! :slight_smile:

2 Likes

First, I usually recommend when trying to create a minigame inside your game to code dive into the HG title Missing Wings. Carlos included just about every variety of text-only game imaginable in that outing, including multiple card-based ones.

Second, I am too much of a coding dunce to follow everything that others have said here, but I did want to caution that it looks like you have text showing right after the *rand was run. That’s bad. Whenever running *rand I believe you need a page_break or choice between when the roll occurs and when the reader sees text for the result. Otherwise, when they go to the stat screen and then come back, it will reroll the result each time.

3 Likes

Oh interesting! Thanks for the shout!

I’ll also definitely check out Missing wings, thank you!

2 Likes

This topic was automatically closed 24 hours after the last reply. If you want to reopen your WiP, contact the moderators.