Module by zero error in operator '%'

Godot Version

4.1.3.stable

Question

Hi there!

I am trying to make blackjack in Godot, and have got the following code setup from a tutorial setting up decks linked here: https://www.youtube.com/watch?v=e4irC98Aits

I have only changed a few variable names and added some loops. However, I keep getting an error on line 31 as the title says. Looking at the stack variables, the current_deck seems to have a size of 0, but if I add a breakpoint on this line, the stack says it has a size of 52 (as intended). Here is my code:

extends Node

var full_deck = [
	"2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "10C", "JC", "QC", "KC", "AC",
	"2D", "3D", "4D", "5D", "6D", "7D", "8D", "9D", "10D", "JD", "QD", "KD", "AD",
	"2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "10H", "JH", "QH", "KH", "AH",
	"2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "10S", "JS", "QS", "KS", "AS"
]

var current_deck = []

@onready var player = $"../Player"
@onready var dealer = $"../Dealer"

func _ready():
	deal_cards()

func deal_cards():
	current_deck = full_deck.duplicate(true)
	print(current_deck)
	var player_cards = []
	var dealer_cards = []
	while player_cards.size() != 2:
		player_cards = [_new_card()]
	while dealer_cards.size() != 2:
		dealer_cards = [_new_card()]
	print(player_cards)
	print(dealer_cards)
	
func _new_card():
	var card = current_deck[randi() % current_deck.size()]
	current_deck.erase(card)
	return card

Any ideas on why this may be occurring? Thank you.

Your current code do:

# while player_cards has less than 2 cards:
while player_cards.size() != 2:
    # set player_cards to a new array containing next drawn card
    player_cards = [_new_card()]

player_cards will never have more than one card as you are always resetting it to a new array with only one entry.
So the while loops infinitely, and at some point, deck will be empty because you are removing the drawn cards from it with:

current_deck.erase(card)

When deck is empty, the modulo/zero error happen in this line:

var card = current_deck[randi() % current_deck.size()]

What you want to do is:

# Add a drawn card to the existing player_cards array
player_cards.append(_new_card())

You would probably also need to add a protection for when the deck will actually be empty in normal gameplay:

func _new_card():
    if current_deck.size() == 0:
        print("No more cards in the deck !")
        return null
    var card = current_deck[randi() % current_deck.size()]
    current_deck.erase(card)
    return card
1 Like

Thank you very much!