## 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.

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

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.