Slots

January 14, 2011

We begin by defining the images on the wheels of the slot machines and displaying instructions to the user:

(define wheel #("BAR" "BELL" "ORANGE" "LEMON" "PLUM" "CHERRY"))

(define (display-instructions)
  (display "WELCOME TO THE CASINO") (newline)
  (display "BET IN INCREMENTS OF $1 FROM $1 TO $100") (newline)
  (display "BET $0 WHEN YOU ARE FINISHED") (newline))

Pull emulates a single pull on the handle, with a bet of n dollars. The three wheels are spun and displayed, then the five possible outcomes are tested, a message is displayed to the user, and the gain or loss on the pull is returned:

(define (pull n)
  (let ((x (randint 6)) (y (randint 6)) (z (randint 6)))
    (display (vector-ref wheel x)) (display " ")
    (display (vector-ref wheel y)) (display " ")
    (display (vector-ref wheel z)) (newline)
    (cond ((= x y z 0)
            (let ((d (* 101 n)))
              (display "***JACKPOT***") (newline)
              (display "YOU WIN $") (display d) (newline) d))
          ((= x y z)
            (let ((d (* 11 n)))
              (display "***TOP DOLLAR***") (newline)
              (display "YOU WIN $") (display d) (newline) d))
          ((or (= x y 0) (= x z 0) (= y z 0))
            (let ((d (* 6 n)))
              (display "***DOUBLE BAR***") (newline)
              (display "YOU WIN $") (display d) (newline) d))
          ((or (= x y) (= x z) (= y z))
            (let ((d (* 3 n)))
              (display "***DOUBLE***") (newline)
              (display "YOU WIN $") (display d) (newline) d))
          (else (display "YOU LOSE $") (display n) (newline) (- n)))))

Play manages a game. It displays instructions, then repeatedly gets a bet, error-checks the input, pulls the handle, and reports status. When the user places a $o bet it displays the final status:

(define (play)
  (display-instructions)
  (display "ENTER YOUR BET: ")
  (let loop ((bet (read)) (purse 0))
    (cond ((or (not (integer? bet)) (negative? bet))
            (display "ENTER YOUR BET: ")
            (loop (read) purse))
          ((< 100 bet)
            (display "HOUSE LIMIT $100") (newline)
            (display "ENTER YOUR BET: ") (loop (read) purse))
          ((<= 1 bet 100)
            (let* ((p (pull bet)) (purse (+ p purse)))
              (cond ((positive? purse)
                      (display "YOU HAVE $") (display purse))
                    ((negative? purse)
                      (display "YOU OWE $") (display (- purse)))
                    (else (display "YOU ARE EVEN")))
              (newline) (display "ENTER YOUR BET: ")
              (loop (read) purse)))
          ((negative? purse)
            (display "PLACE $") (display (- purse))
            (display " ON THE KEYBOARD") (newline))
          ((positive? purse)
            (display "COLLECT $") (display purse)
            (display " FROM THE CASHIER") (newline))
          (else (display "YOU BROKE EVEN") (newline)))))

Here’s a sample game:

> (play)
WELCOME TO THE CASINO
BET IN INCREMENTS OF $1 FROM $1 TO $10
BET $0 WHEN YOU ARE FINISHED
ENTER YOUR BET: 10
BAR PLUM LEMON
YOU LOSE $10
YOU OWE $10
ENTER YOUR BET: 10
BELL ORANGE ORANGE
***DOUBLE***
YOU WIN $30
YOU HAVE $20
ENTER YOUR BET: 10
BAR BAR CHERRY
***DOUBLE BAR***
YOU WIN $60
YOU HAVE $80
ENTER YOUR BET: 10
ORANGE ORANGE BAR
***DOUBLE***
YOU WIN $30
YOU HAVE $110
ENTER YOUR BET: 10
LEMON PLUM ORANGE
YOU LOSE $10
YOU HAVE $100
ENTER YOUR BET: 10
BELL LEMON BELL
***DOUBLE***
YOU WIN $30
YOU HAVE $130
ENTER YOUR BET: 10
CHERRY LEMON PLUM
YOU LOSE $10
YOU HAVE $120
ENTER YOUR BET: 0
COLLECT $120 FROM THE CASHIER

We used randint from the Standard Prelude. You can run the program at http://programmingpraxis.codepad.org/A8iRnYpJ.

Advertisement

Pages: 1 2 3 4

6 Responses to “Slots”

  1. […] today’s Programming Praxis exercise, our goal is to create a game that simulates a slot machine. […]

  2. My Haskell solution (see http://bonsaicode.wordpress.com/2011/01/14/programming-praxis-slots/ for a version with comments):

    import Control.Monad
    import Data.List
    import System.Random
    import Text.Printf
    import Text.Read.HT
    
    pull :: Int -> IO Int
    pull n = do ws <- replicateM 3 $ randomRIO (0,5)
                putStrLn . unwords $ map (wheel !!) ws
                result . group $ sort ws where
        wheel = words "BAR BELL ORANGE LEMON PLUM CHERRY"                
        result [[0,0,0]] = win "JACKPOT" 101
        result [_]       = win "TOP DOLLAR" 11
        result [[0,0],_] = win "DOUBLE BAR" 6
        result [_,_]     = win "DOUBLE" 3
        result _         = printf "YOU LOSE $%d\n" n >> return (-n)
        win msg d = printf "***%s***\nYOU WIN $%d\n" msg (n*d) >> return (n*d)
    
    prompt :: IO Int
    prompt = do putStr "ENTER YOUR BET: "
                maybe prompt check . maybeRead =<< getLine where
        check bet | bet < 0   = prompt
                  | bet > 100 = putStrLn "HOUSE LIMIT $100" >> prompt
                  | otherwise = return bet
    
    main :: IO ()
    main = instructions >> loop 0 where
        instructions = putStrLn "WELCOME TO THE CASINO\n\
            \BET IN INCREMENTS OF $1 FROM $1 TO $100\n\
            \BET $0 WHEN YOU ARE FINISHED"
        loop purse = prompt >>= \bet -> if bet == 0 then quit purse
            else fmap (+ purse) (pull bet) >>= \n -> status n >> loop n
        status n | n > 0     = printf "YOU HAVE $%d\n" n
                 | n < 0     = printf "YOU OWE $%d\n" (-n)
                 | otherwise = putStrLn "YOU ARE EVEN"
        quit total | total > 0 = printf "COLLECT $%d FROM THE CASHIER\n" total
                   | total < 0 = printf "PLACE $%d ON THE KEYBOARD\n" (-total)
                   | otherwise = putStrLn "YOU BROKE EVEN"
    
  3. Graham said

    My Python solution. Like the Haskell above, I factored out the _win
    procedure. I'm not terribly happy with the maze of ifs and elifs my code grew
    into, but it'll do.

    #!/usr/bin/env python
    from random import randrange
    WHEEL = ["BAR", "BELL", "ORANGE", "LEMON", "PLUM", "CHERRY"]

    def display_instructions():
    print "WELCOME TO THE CASINO"
    print "BET IN INCREMENTS OF $1 FROM $1 TO $100"
    print "BET $0 WHEN YOU ARE FINISHED"
    return

    def pull(n):

    def _win(msg, d):
    print "***{0}***".format(msg)
    print "YOU WIN ${0}".format(n * d)
    return n * d

    x, y, z = randrange(6), randrange(6), randrange(6)
    print WHEEL[x], WHEEL[y], WHEEL[z]
    if x == y == z == 0:
    return _win("JACKPOT", 101)
    elif x == y == z:
    return _win("TOP DOLLAR", 11)
    elif x == y == 0 or x == z == 0 or y == z == 0:
    return _win("DOUBLE BAR", 6)
    elif x == y or x == z or y == z:
    return _win("DOUBLE", 3)
    else:
    print "YOU LOSE ${0}".format(n)
    return -n

    def play():
    display_instructions()
    bet, purse = 1, 0
    while bet != 0:
    bet = raw_input("ENTER YOUR BET:\t")
    try:
    bet = int(bet)
    except ValueError:
    continue
    if bet > 100:
    print "HOUSE LIMIT $100"
    continue
    elif 1 <= bet <= 100:
    purse += pull(bet)
    if purse > 0:
    print "YOU HAVE ${0}".format(purse)
    elif purse < 0:
    print "YOU OWE ${0}".format(-purse)
    else:
    print "YOU ARE EVEN"
    if purse < 0:
    print "PLACE ${0} ON THE KEYBOARD".format(-purse)
    elif purse > 0:
    print "COLLECT ${0} FROM THE CASHIER".format(purse)
    else:
    print "YOU BROKE EVEN"
    return

    if __name__ == "__main__":
    play()

  4. Graham said

    Oh no! I had a couple typos (messed up closing the code tag, and extra ” in ) in the comment above. Apologies!

  5. uberlazy said

    Waddling through old code is fun, but I feel this exercise isn’t all it could have been. Slot machines are based on interesting statistical models that keep the game addictive while ensuring the House wins. In that vein, I modified the original task and created a weighted slot machine. I know it doesn’t earn me brownie points, but I hope someone finds it interesting or fun.

    I also took the betting out of it so I can just hit the spin key mindlessly, like on a real machine :)

    http://paste.lisp.org/display/119226

  6. uberlazy said

    … incidentally, selecting a random wheel stop is a variant of the algorithm for selecting fortunes from the exercise #192.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: