Couples’ Dreidel

During my first-ever game of dreidel this week, we agreed on a friendly variation in the rules. When someone was about to run out of chocolate coins and be knocked out of the game, couples could rescue each other with a “loan.” Eventually we put a stop to that, thinking that all this rescuing was making the game drag on.

For a definitive answer, I wrote a short Python script that simulates thousands of dreidel games, tallying how many turns are played. As it turns out, we were wrong. If you allow couples to win a joint victory, then games that allow rescuing actually end much faster. Couples defeat other couples and other single players faster than single players defeat each other, even though all players — coupled or not — still take separate turns. If you insist on having only one winner, making the couple break their alliance in the end and play out the game, the games get a little longer but the effect it not large. (I originally published a different conclusion about this last scenario.)

Simulating 10,000 6-player games. Each player start with 5 coins.

No couples: 112 minutes
One couple: 101 minutes
Two couples: 84 minutes
Three couples: 68 minutes

Disallow joint victories:
One couple: 114 minutes
Two couples: 121 minutes
Three couples: 127 minutes

The statistical error of these results is about one minute.
See the code.

#!/usr/bin/python

# How long does a game of dreidel take?
# How does that change when couples form "alliances" and help each other out?

import random
from numpy import average, round
from scipy.stats import stderr

def pay(i, coins, couples):
	"""Pay what is owed, or have your partner pay, or lose the game."""
	if coins[i] > 0:
		# Player can pay.
		coins[i] -= 1
		paid = True
	elif couples[i]:
		# Player has a partner.
		if coins[couples[i]] > 0:
			# That partner can afford a loan.
			coins[couples[i]] -= 1
			paid = True
		else:
			coins[i] = None # Player is out of the game.
			paid = False
	else:
		coins[i] = None # Player is out of the game.
		paid = False
	return coins, paid

def play_round(coins, couples, turn_counter, next_player):
	"""Simulate one round of the game, and count turns."""
	# Ante up.
	pot = 0
	for i in range(len(coins)):
		if coins[i] is not None:
			coins, paid = pay(i, coins, couples)
			if (paid): pot += 1

	# Take turns.
	while pot > 0:
		# List players in order, starting with whoever's turn it is.
		for i in map(lambda x: x % len(coins), range(next_player, next_player+len(coins))):
			if coins[i] is None:
				continue # Player is already out of the game.
			roll = random.choice(['nun', 'gimmel', 'hey', 'shin'])
			if roll is 'gimmel':
				coins[i] += pot
				pot = 0
			elif roll is 'hey':
				coins[i] += pot/2
				pot = pot - pot/2
			elif roll is 'shin':
				coins, paid = pay(i, coins, couples)
				if paid:
					pot += 1
			turn_counter += 1
			if pot is 0:
				next_player = i+1
				break

	return coins, turn_counter, next_player

def game(number_of_players, starting_money, couples, allow_joint_victory=True):
	"""Simulate a game, and count turns."""
	coins = number_of_players*[starting_money]
	turn_counter = 0
	next_player = 0

	# In the function call, couples may be specified as an explicit list with a seating arrangement.
	# Alternatively, the call may simply give the NUBMER of couples. They will be seated beside each other.
	if type(couples) is not list:
		number_of_couples = couples
		couples = number_of_players*[None]
		for i in range(number_of_couples):
			couples[2*i]=2*i+1
			couples[2*i+1]=2*i

	while True:
		# Check whether game has ended.
		winners = [i for i, c in enumerate(coins) if c is not None]
		if (len(winners) is 1): break # One winner.
		if (len(winners) is 2 and
			winners[0] == couples[winners[1]]):
				if (allow_joint_victory is True):
					break # Joint win.
				else:
					# End the alliance and play it out.
					couples = number_of_players*[None]

		coins, turn_counter, next_player = play_round(coins, couples, turn_counter, next_player)
	return turn_counter

def simulate_games(N, number_of_players, starting_money, number_of_couples, allow_joint_victory=True):
	"""Return average game duration of N simulated games."""
	TURNS_PER_MIN = 5 # estimated turns per minute, to interpret result
	outcomes = [game(number_of_players, starting_money, number_of_couples, allow_joint_victory) for x in range(N)]
	value = int(round(average(outcomes)/TURNS_PER_MIN))
	error = int(round(stderr(outcomes)/TURNS_PER_MIN))
	return str(value) + ' +/- ' + str(error) + ' minutes'

TRIALS = 10000
N_PLAYERS = 6
MONEY = 5

print 'Simulating 10,000 6-player games. Each player starts with 5 coins.'
print 'No couples:', simulate_games(TRIALS, N_PLAYERS, MONEY, 0)
print 'One couple:', simulate_games(TRIALS, N_PLAYERS, MONEY, 1)
print 'Two couples:', simulate_games(TRIALS, N_PLAYERS, MONEY, 2)
print 'Three couples:', simulate_games(TRIALS, N_PLAYERS, MONEY, 3)

print 'Disallow joint victories:'
print 'One couple:', simulate_games(TRIALS, N_PLAYERS, MONEY, 1, False)
print 'Two couples:', simulate_games(TRIALS, N_PLAYERS, MONEY, 2, False)
print 'Three couples:', simulate_games(TRIALS, N_PLAYERS, MONEY, 3, False)

Hide the code.


4 Responses to Couples’ Dreidel

  1. I have a couple of ‘scienfic’ questions to ask about this study.
    1) Did you look at mean squared error to see the robustness of your result? Having couple’s victory makes sense that it would decrease the time, but forcing the couple duke it out makes it seem like it should take longer. All games of dreidel will end with two people, but without couples victories you are limiting which pairs of people can be the last two.
    2) What is the seating effect of the couples? You currently have them sitting next to each other. I’m not sure how it would work out, but the way it currently stands is that if I roll “shim” then it’s easy for my partner to rescue my coin. On the other hand, if she doesn’t rescue my coin then it’s pretty unlikely I’ll get it back.
    3) It would also be interesting to ask how the game of dreidel changes with different dice. For example, instead of the current 4-sided die, you could have a 6-sided die with three “shin”s. I would imagine that it would both bankrupt people faster and that having couples would prolong the game in this case.

  2. 1) The statistical error is about one minute. However, puzzling about why “forcing the couple to duke it out” still shortens games prompted me to find a serious systematic error. In my code, each round began with the same player; in correct dreidel, each round resumes where the previous one left off. With that correction, couples’ games are only shorter if you allow joint victory. The world makes sense again.

    2) Seating has a very small effect on average game duration. But it might have a more pronounced effect on who wins.
    One couple, seated together: 101 +/- 1 minutes
    One couple, seated one seat apart: 101 +/- 1 minutes
    One couple, seated two seats apart: 103 +/- 1 minutes
    Disallow joint victories:
    One couple, seated together: 114 +/- 1 minutes
    One couple, seated one seat apart: 112 +/- 1 minutes
    One couple, seated two seats apart: 112 +/- 1 minutes

    3) I’ll come back to this one later.

  3. We usually played dreidel so that whenever somebody spun a gimmel, a consensus would end the game. No need for everybody to lose all their coins/m&ms/gelt/what-have-you. The game went faster, and everybody left feeling like a winner. Then again, we stopped playing dreidel when I was still in middle school, so maybe the rules for kids are different than the rules for adults.

  4. Interesting. We allowed people to quit with their winnings at any point, but in practice stubbornness kept everybody in for awhile. Consensus would be a better rule.

    For the six-sided die Brendan proposed, I find much shorter games overall. Contrary to his expectation, forming couples still shortens games. The benefit of having a team cash reservoir remains significant.
    No couples: 51 minutes
    One couple: 45 minutes
    Two couples: 40 minutes

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>