Skip to content

Instantly share code, notes, and snippets.

@lancereinsmith
Created December 13, 2020 19:36
Show Gist options
  • Save lancereinsmith/361d9e375ca038240bed0d8385e0f258 to your computer and use it in GitHub Desktop.
Save lancereinsmith/361d9e375ca038240bed0d8385e0f258 to your computer and use it in GitHub Desktop.
# dreidel.py
from random import choice
from colorama import Fore
FACES = ["Nun", "Gimel", "Hey", "Shin"]
NUM_PLAYERS = 6
STARTING_BANK = 10
ANTE_AMOUNT = 1
SHIN_PENALTY = 3
c = [Fore.RED, Fore.GREEN, Fore.BLUE, Fore.YELLOW, Fore.MAGENTA, Fore.CYAN]
w = Fore.WHITE
class Player(object):
def __init__(self, player_name: str, starting_bank: int, color_key: int) -> None:
self.player_name = player_name
self.bank = starting_bank
self.color = c[color_key % len(c)]
def is_bankrupt(self) -> bool:
"""Checks if player is bankrupt. Returns True if bank is zero or less."""
return self.bank <= 0
def ante(self, ante_amount: int = ANTE_AMOUNT) -> int:
"""Antes the player into the pot. Returns amount anted.
Keyword arguments:
ante_amount -- amount each player must ante (default set above)
"""
if self.is_bankrupt():
return 0
if self.bank < ante_amount:
money_left = self.bank
self.bank = 0
return money_left
else:
self.bank -= ante_amount
return ante_amount
def turn(self, pot: int) -> tuple:
"""Player spins dreidel and win/loss calculated.
Returns tuple of spin and final pot value.
Keyword arguments:
pot -- starting pot value
"""
spin = choice(FACES)
if spin == "Nun":
return spin, pot
elif spin == "Gimel":
self.bank += pot
return spin, 0
elif spin == "Hey":
half_rounded_up = (pot + 1) // 2
self.bank += half_rounded_up
return spin, pot - half_rounded_up
else:
if self.bank > SHIN_PENALTY:
self.bank -= SHIN_PENALTY
return spin, pot + SHIN_PENALTY
else:
money_left = self.bank
self.bank = 0
return spin, pot + money_left
def __repr__(self) -> str:
if self.is_bankrupt():
return f"{self.color}{self.player_name} is bankrupt."
else:
return f"{self.color}{self.player_name} has a bank of {self.bank}."
def check_for_winner(players) -> bool:
"""Checks all players for a single winner. Returns True if there is a winner.
Keyword arguments:
players -- list of player objects
"""
return sum(map(lambda x: not x.is_bankrupt(), players)) == 1
def play_game(num_players: int = 4, starting_bank: int = 10) -> None:
"""Plays the dreidel game.
Keyword arguments:
ante_amount -- amount each player must ante (default set above)
"""
players = [Player(f"Player {_ + 1}", starting_bank, _) for _ in range(num_players)]
pot = 0
spin_count = 0
while True:
for player in players:
if pot == 0:
pot = sum(map(lambda x: x.ante(), players))
print(f"{w}** Everyone must ante! The pot is now {pot}. **")
if check_for_winner(players):
for player in players:
if player.bank > 0:
winner = player.player_name
print(
f"\n{w}For a game with {num_players} players and a starting bank of {starting_bank}, it took {spin_count} spins for {winner} to win."
)
return
if not player.is_bankrupt():
spin, pot = player.turn(pot)
spin_count += 1
print(
f"{player.color}{player.player_name} spun {spin} and now has a bank of {player.bank}. The pot is now {pot}."
)
if __name__ == "__main__":
play_game(num_players=NUM_PLAYERS, starting_bank=STARTING_BANK)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment