Lance Reinsmith, M.D. is a radiologist and programming hobbyist who lives and works in San Antonio, TX. Dr. Reinsmith is no better at playing dreidel than random chance would indicate.
Dreidel is a game commonly played during the celebration of the Hanukkah holiday. Each player starts with a bank of coins and takes turns spinning a four-sided top. The results of the spins dictate how the game progresses. For more information, check out the Wikipedia entry on dreidel.
To summarize, each player usually antes one coin into the pot to start and when the pot is empty. If a player rolls a:
- נ (nun), the player does nothing.
- ג (gimel), the player gets everything in the pot.
- ה (hey), the player gets half of the coins in the pot. If there are an odd number of coins in the pot, the player takes half the pot rounded up to the nearest whole number.
- ש (shin), the player adds one to three coins to the pot. (For historical and geographic purposes, some dreidels have a פ (pey) instead of a shin, but this has the same function.)
This article reviews how to write a simple dreidel simulation script using Python. It assumes you have intermediate familiarity with Python 3, including classes, list comprehension, lambda functions, and type hinting.
To spin the dreidel, we’ll need to define our dreidel faces and import the choice method from the random module.
Most dreidel games involve about 4–6 players with a starting bank of about 10 coins. Let’s set some constants for our game:
Of course, you can change these.
I’ll eventually want the console output to be color-coded for better readability. The colorama package helps simplify this in Python. Install using:
Appending colorama color codes to strings can get quite busy and cumbersome; but, we can simplify this using lists and/or variables with short names:
This way, we can reference the list by an index and append that to the string. If this sounds confusing, it will be more clear below.
We’ll now construct a Player class to serve as a blueprint for each player in the game.
This init method assigns a name and starting bank to the Player. It also assigns a color using a modulus to rotate through the list of colors defined above. (The double underscores before and after “init” make this a “dunder” function — which usually means a class function run internally and not intended to be called de novo.)
Next, we create a simple method to determine if a player is bankrupt which returns a boolean based on their bank. It returns True if the patient’s bank is zero or less.
Then, we create an ante method which takes in a parameter of the ante_amount. (This defaults to the amount defined above.) It first checks if the player is bankrupt. If so, it returns 0 to the pot. If the player is not bankrupt, it then checks if the player has enough to ante up. If so, the ante is deducted from the player’s bank and returned to the pot. If not, the player pays its residual to the pot and the player’s bank goes to zero.
Next, it’s time to spin! The turn method takes in the current pot as a parameter. A random choice of the faces is made. Based on this, the player’s bank and the pot are adjusted. The method returns the spin and the final pot value as a tuple.
There are a few things to point out here:
- (pot+1) // 2 makes sure the player gets half of the pot rounded up to the nearest whole number
- The SHIN_PENALTY is defined above. If the player cannot pay this, it adds the residual amount in their bank to the pot and sets their bank to zero.
Finally, we make a string representation for the Player for completeness sake. The entire class is shown here:
We then make a function to check all of the players in the game to see if there is a winner:
This can be a bit tricky if you’re not used to the map function and lambda functions. The function takes in a list of Players as a parameter, each Player with an is_bankrupt() method. It then maps the is_bankrupt() method over all of the Players and calculates the sum of the results. Since is_bankrupt() returns 0 for a bankrupted player, a sum of 1 means there is only a single non-bankrupt player.
Finally, we need to set up the game:
This function appears complex, so we’ll break it down step-by-step.
The function accepts the number of players (num_players) and starting bank amount for each player (starting_bank) as parameters. These default to 4 and 10 by default.
Next, the group of Players is constructed using list comprehension. While doing so, the index of the for loop is used to assign a rotating color to the Player. (I use “_” as an index variable, but you could use “I” or anything else.)
The pot and spin_count are then reset to zero.
Next, the script enters a loop where each player takes turns. Prior to each turn, the function checks if the pot is zero. If so, everyone needs to ante (see ante method above) if they can. It then checks for a winner by passing the list of Players to the check_for_winner function defined above.
If there is a winner, it loops through the players to find the winner and prints a message in white (by prepending the text with the w variable defined with the colors) declaring the game stats, the winner name, and the number of spins it took to complete the game. The game is then over.
If no one has won, it then checks if the current player is bankrupt. If not, the player takes their turn spinning and the pot is updated and spin count increased. The function then prints a message to the console in the player’s color (by prepending the text with the player.color value) specifying who has spun, what the result is, and the new values of their pot and the bank.
It’s now time to tell the script to set up and play the game if the script is run:
That’s it! If you like this, try adjusting the parameters to see how the game changes. Or, try playing a real game of dreidel with friends or family! Here is the entire script.