Skip to content

Instantly share code, notes, and snippets.

@markjamesm
Last active August 6, 2021 15:11
Show Gist options
  • Save markjamesm/23aa62652064b837588f44ca634c7824 to your computer and use it in GitHub Desktop.
Save markjamesm/23aa62652064b837588f44ca634c7824 to your computer and use it in GitHub Desktop.
Functional Programming with Python — Building a Simple Slot Machine
# Copyright 2021 Mark-James McDougall and licensed under the MIT License.
# This is an example of a single reel slot machine written with a functional
# programming paradigm using python.
# Once started, the machine will keep running until a jackpot condition is
# hit (three matching numbers), and it will also keep track of the number
# of times two matching numbers come up.
# Example output:
# Jackpot!
# Number of spins to hit the jackpot: 562
# Number of two of a kinds hit: 82
import numpy as np
from enum import Enum
# Enum in place of union type to keep track of the spin state.
class SpinState(Enum):
START = 0
JACKPOT = 1
TWO_OF_A_KIND = 2
LOSS = 3
# Generates a spin for a single slot machine line.
# This is technically an impure function because random numbers are
# being generated within the function and this results in a different
# result given the same parameters.
def spin_wheel(symbols_amount: int) -> list[int]:
spin = (list(np.random.randint(low=1, high=symbols_amount+1, size=3)))
return spin
# Notice that the functions below are pure with no side effects.
# We're also making use of optional types for type safety.
def win_condition_check(spin: list[int]) -> SpinState:
# This is an if expression and not an if statement because all
# paths evaluate to a value (SpinState).
if len(set(spin)) < 2:
return SpinState.JACKPOT
elif len(spin) != len(set(spin)):
return SpinState.TWO_OF_A_KIND
else:
return SpinState.LOSS
# The game_simulation runs until a jackpot condition is reached.
# This is a recursive method which uses accumulators to manage state in a functional way
# as opposed to creating side effects by using class attributes.
def game_simulation(spin_result: SpinState, jackpot_count: int, two_of_a_kind_count: int) -> (SpinState, int, int):
# A typical slot machine might display three spinning reels
# with about 20 symbols. For simplicity's sake, lets model a single reel.
wheel_spin = spin_wheel(20)
spin_result = win_condition_check(wheel_spin)
# Another if expression which returns a triple once the jackpot is hit, otherwise
# make a recursive function call and increment our accumulators.
if spin_result == SpinState.JACKPOT:
return spin_result, jackpot_count, two_of_a_kind_count
elif spin_result == SpinState.TWO_OF_A_KIND:
return game_simulation(spin_result, jackpot_count + 1, two_of_a_kind_count + 1)
elif spin_result == SpinState.START:
return game_simulation(spin_result, jackpot_count, two_of_a_kind_count)
else:
new_spin = SpinState.LOSS
return game_simulation(new_spin, jackpot_count + 1, two_of_a_kind_count)
# Entrypoint
if __name__ == '__main__':
# Pass the initial states to the game_simulation.
game_round = game_simulation(SpinState.START, 0, 0)
print(f"Jackpot!\nNumber of spins to hit the jackpot: {game_round[1]}\nNumber of two of a kinds hit: {game_round[2]}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment