Slots

Description of the page content

Conversion of Slots to several programming languages.

Tags:

This program has been converted to 15 programming languages.

Original

Origin of slots.bas:

Slots, by Fred Mirabelle and Bob Harper, 1978.

Creative Computing's BASIC Games.

- https://www.atariarchives.org/basicgames/showpage.php?page=149
- http://vintage-basic.net/games.html
- http://vintage-basic.net/bcg/slots.bas

10 PRINT TAB(30);"SLOTS"
20 PRINT TAB(15);"CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY"
30 PRINT: PRINT: PRINT
100 REM PRODUCED BY FRED MIRABELLE AND BOB HARPER ON JAN 29, 1973
110 REM IT SIMULATES THE SLOT MACHINE.
120 PRINT "YOU ARE IN THE H&M CASINO,IN FRONT OF ONE OF OUR"
130 PRINT "ONE-ARM BANDITS. BET FROM $1 TO $100."
140 PRINT "TO PULL THE ARM, PUNCH THE RETURN KEY AFTER MAKING YOUR BET."
150 LET P=0
160 PRINT: PRINT"YOUR BET";
170 INPUT M
180 IF M>100 THEN 860
190 IF M<1 THEN 880
200 M=INT(M)
210 GOSUB 1270
220 PRINT
230 LET X=INT(6*RND(1)+1)
240 LET Y=INT(6*RND(1)+1)
250 LET Z=INT(6*RND(1)+1)
260 PRINT
270 IF X=1 THEN 910
280 IF X=2 THEN 930
290 IF X=3 THEN 950
300 IF X=4 THEN 970
310 IF X=5 THEN 990
320 IF X=6 THEN 1010
330 IF Y=1 THEN 1030
340 IF Y=2 THEN 1050
350 IF Y=3 THEN 1070
360 IF Y=4 THEN 1090
370 IF Y=5 THEN 1110
380 IF Y=6 THEN 1130
390 IF Z=1 THEN 1150
400 IF Z=2 THEN 1170
410 IF Z=3 THEN 1190
420 IF Z=4 THEN 1210
430 IF Z=5 THEN 1230
440 IF Z=6 THEN 1250
450 IF X=Y THEN 600
460 IF X=Z THEN 630
470 IF Y=Z THEN 650
480 PRINT
490 PRINT "YOU LOST."
500 LET P=P-M
510 PRINT "YOUR STANDINGS ARE $"P
520 PRINT "AGAIN";
530 INPUT A$
540 IF A$="Y" THEN 160
550 PRINT
560 IF P<0 THEN 670
570 IF P=0 THEN 690
580 IF P>0 THEN 710
590 GOTO 1350
600 IF Y=Z THEN 730
610 IF Y=1 THEN 820
620 GOTO 1341
630 IF Z=1 THEN 820
640 GOTO 470
650 IF Z=1 THEN 820
660 GOTO 1341
670 PRINT "PAY UP!  PLEASE LEAVE YOUR MONEY ON THE TERMINAL."
680 GOTO 1350
690 PRINT"HEY, YOU BROKE EVEN."
700 GOTO 1350
710 PRINT "COLLECT YOUR WINNINGS FROM THE H&M CASHIER."
720 GOTO 1350
730 IF Z=1 THEN 780
740 PRINT: PRINT"**TOP DOLLAR**"
750 PRINT "YOU WON!"
760 P=(((10*M)+M)+P)
770 GOTO 510
780 PRINT:PRINT"***JACKPOT***"
790 PRINT "YOU WON!"
800 P=(((100*M)+M)+P)
810 GOTO 510
820 PRINT:PRINT"*DOUBLE BAR*"
830 PRINT"YOU WON!"
840 P=(((5*M)+M)+P)
850 GOTO 510
860 PRINT"HOUSE LIMITS ARE $100"
870 GOTO 160
880 PRINT"MINIMUM BET IS $1"
890 GOTO 160
900 GOTO 220
910 PRINT"BAR";:GOSUB 1310
920 GOTO 330
930 PRINT"BELL";:GOSUB 1310
940 GOTO 330
950 PRINT"ORANGE";:GOSUB 1310
960 GOTO 330
970 PRINT"LEMON";:GOSUB 1310
980 GOTO 330
990 PRINT"PLUM";:GOSUB 1310
1000 GOTO 330
1010 PRINT"CHERRY";:GOSUB 1310
1020 GOTO 330
1030 PRINT" BAR";:GOSUB 1310
1040 GOTO 390
1050 PRINT" BELL";:GOSUB 1310
1060 GOTO 390
1070 PRINT" ORANGE";:GOSUB 1310
1080 GOTO 390
1090 PRINT" LEMON";:GOSUB 1310
1100 GOTO 390
1110 PRINT" PLUM";:GOSUB 1310
1120 GOTO 390
1130 PRINT" CHERRY";:GOSUB 1310
1140 GOTO 390
1150 PRINT" BAR"
1160 GOTO 450
1170 PRINT" BELL"
1180 GOTO 450
1190 PRINT" ORANGE"
1200 GOTO 450
1210 PRINT" LEMON"
1220 GOTO 450
1230 PRINT" PLUM"
1240 GOTO 450
1250 PRINT" CHERRY"
1260 GOTO 450
1270 FOR Q4=1 TO 10
1280 PRINT CHR$(7);
1290 NEXT Q4
1300 RETURN
1310 FOR T8=1 TO 5
1320 PRINT CHR$(7);
1330 NEXT T8
1340 RETURN
1341 PRINT: PRINT "DOUBLE!!"
1342 PRINT"YOU WON!"
1343 P=(((2*M)+M)+P)
1344 GOTO 510
1350 STOP
9999 END

In Arturo

; Slots

; Original version in BASIC:
;   By Fred Mirabelle and Bob Harper, 1973-01-29.
;   Creative Computing's BASIC Games, 1978.
;   - https://www.atariarchives.org/basicgames/showpage.php?page=149
;   - http://vintage-basic.net/games.html
;   - http://vintage-basic.net/bcg/slots.bas

; This version in Arturo:
;   Copyright (c) 2023, Marcos Cruz (programandala.net)
;   SPDX-License-Identifier: Fair
;
; Written in 2023-10.
;
; Last modified: 20251205T0052+0100.

image: array [ "BAR", "BELL", "ORANGE", "LEMON ", "PLUM", "CHERRY" ]
images: size image
firstImage: 0
lastImage: sub images 1
barPosition: firstImage

imageMaxSize: 0
loop image 'i [
    if greater? size i imageMaxSize [ let 'imageMaxSize size i ]
]

reel: array [ 0 0 0 ]
reels: size reel
firstReel: 0
lastReel: sub reels 1

minBet: 1
maxBet: 100

printCredits: function [ ] [
    clear
    print "Slots"
    print "A slot machine simulation.\n"
    print "Original version in BASIC:"
    print "    Creative computing (Morristown, New Jersey, USA)."
    print "    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    input "Press Enter for instructions. "
]

printInstructions: function [ ] [
    clear
    print "You are in the H&M casino, in front of one of our"
    print render "one-arm bandits. Bet from |minBet| to |maxBet| USD (or 0 to quit).\n"
    input "Press Enter to start. "
]

won: function [ prize bet ] [
    case [ prize ]
        when? [ equal?   2 ] [ print "DOUBLE!"        ]
        when? [ equal?   5 ] [ print "*DOUBLE BAR*"   ]
        when? [ equal?  10 ] [ print "**TOP DOLLAR**" ]
        when? [ equal? 100 ] [ print "***JACKPOT***"  ]
        else [ ]
    print "You won!"
    mul bet add prize 1
]

showStandings: function [ usd ] [
    print render "Your standings are |usd| USD."
]

; Print the given image in its proper color.
printImage: function [ n ] [
    img: render "[ |pad .center image\[n] imageMaxSize| ] "
    case [ n ]
        when? [ equal? 0 ] [ prints color       #white  img ]
        when? [ equal? 1 ] [ prints color       #cyan   img ]
        when? [ equal? 2 ] [ prints color       #yellow img ]
        when? [ equal? 3 ] [ prints color .bold #yellow img ]
        when? [ equal? 4 ] [ prints color .bold #white  img ]
        when? [ equal? 5 ] [ prints color .bold #red    img ]
        else [ ]
]

; Print the reels.
printReels: function [ ] [
    goto 0 0
    loop reel 'n [ printImage n ]
    print ""
]

; Init the reels with random images.
initReels: function [ ] [
    loop .with: 'i reel [ ] [ set reel i random firstImage lastImage ]
]

turnReels: function [ ] [
    initReels
    printReels
]

; Return the seconds since the Unix epoch (1970-01-01 00:00:00 UTC).
epochSeconds: function [ ] [
    to :integer now
]

spinReels: function [ ] [
    durationInSeconds: 2
    cursor false
    let 'firstSecond epochSeconds
    while [ less? sub epochSeconds firstSecond durationInSeconds ]
    [ turnReels ]
    cursor true
]

; Read an integer and return it; if the input is not a valid integer,
; return a zero instead.
inputInteger: function [ ] [
    try? [ to :integer input "" ] else [ 0 ]
]

play: function [ ] [
    standings: 0
    equals: 0
    betting: true
    playing: true
    initReels
    while [ playing ] [ ; play loop
        while [ and? playing betting ] [ ; bet loop
            clear
            printReels
            prints "Your bet (or 0 to quit): "
            bet: inputInteger
            case [ bet ]
                when? [ less? maxBet ] [
                    print render "House limits are |maxBet| USD."
                    input "Press Enter to try again. "
                ]
                when? [ greater? minBet ] [
                    confirm: input "Type \"q\" to confirm you want to quit. "
                    if equal? confirm "q" [
                        ; XXX TODO break
                        betting: false
                        playing: false
                    ]
                ]
                else [ betting: false ] ; XXX TODO break
        ] ; bet loop
        if playing [
            clear
            spinReels
            bars: 0
            loop range firstReel lastReel 'i [
                add 'bars to :integer equal? reel\[i] barPosition
            ]
            case [ size unique reel ] ; number of different images
                when? [ equal? 1 ] [
                    if? equal? bars 3 [ add 'standings won 100 bet ]
                    else [ add 'standings won 10 bet ]
                ]
                when? [ equal? 2 ] [
                    if? equal? bars 2 [ add 'standings won 5 bet ]
                    else [ add 'standings won 2 bet ]
                ]
                else [
                    print "You lost."
                    sub 'standings bet
                ]
            showStandings standings
            input "Press Enter to continue. "
            betting: true
        ]
    ] ; play loop
    showStandings standings
    case [ standings ]
        when? [ greater? 0 ] [
            print "Pay up!  Please leave your money on the terminal."
        ]
        when? [ equal? 0 ] [
            print "Hey, you broke even."
        ]
        when? [ less? 0 ] [
            print "Collect your winnings from the H&M cashier."
        ]
        else [ ]
]

printCredits
printInstructions
play

In C#

// Slots
// A slot machine simulation.

// Original version in BASIC:
//  By Fred Mirabelle and Bob Harper, 1973-01-29.
//  Creative Computing's BASIC Games.
//  - https://www.atariarchives.org/basicgames/showpage.php?page=149
//  - http://vintage-basic.net/games.html
//  - http://vintage-basic.net/bcg/slots.bas

// This version in C#:
//  Copyright (c) 2024, Marcos Cruz (programandala.net)
//  SPDX-License-Identifier: Fair
//
// Written in 2024-12-22/24.
//
// Last modified: 20251205T1549+0100.

using System;
using System.Diagnostics;

class Slots
{
    static string[] image = {" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"};
    const int BAR = 0; // position of "BAR" in `image`.
    static ConsoleColor[] color =
    {
        ConsoleColor.White,
        ConsoleColor.DarkCyan,
        ConsoleColor.DarkYellow,
        ConsoleColor.Yellow,
        ConsoleColor.White,
        ConsoleColor.Red };
    const int MAX_BET = 100;
    const int MIN_BET = 1;

    static void PressEnter(string prompt)
    {
        Console.Write(prompt);
        Console.ReadLine();
    }

    static void PrintCredits()
    {
        Console.Clear();
        Console.WriteLine("Slots");
        Console.WriteLine("A slot machine simulation.\n");
        Console.WriteLine("Original version in BASIC:");
        Console.WriteLine("    Creative computing (Morristown, New Jersey, USA).");
        Console.WriteLine("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n");
        Console.WriteLine("This version in C#:");
        Console.WriteLine("    Copyright (c) 2024, Marcos Cruz (programandala.net)");
        Console.WriteLine("    SPDX-License-Identifier: Fair\n");
        PressEnter("Press Enter for instructions.");
    }

    static void PrintInstructions()
    {
        Console.Clear();
        Console.WriteLine("You are in the H&M casino, in front of one of our");
        Console.WriteLine($"one-arm bandits. Bet from {MIN_BET} to {MAX_BET} USD (or 0 to quit).\n");
        PressEnter("Press Enter to start.");
    }

    static int Won(int prize, int bet)
    {
        switch (prize)
        {
            case   2: Console.WriteLine("DOUBLE!"); break;
            case   5: Console.WriteLine("*DOUBLE BAR*"); break;
            case  10: Console.WriteLine("**TOP DOLLAR**"); break;
            case 100: Console.WriteLine("***JACKPOT***"); break;
        }
        Console.WriteLine("You won!");
        return (prize + 1) * bet;
    }

    static void ShowStandings(int usd)
    {
        Console.WriteLine($"Your standings are {usd} USD.");
    }

    static void PrintReels(int[] reel)
    {
        ConsoleColor currentBackgroundColor = Console.BackgroundColor;
        ConsoleColor currentForegroundColor = Console.ForegroundColor;
        Console.SetCursorPosition(0, 0);
        foreach (int r in reel)
        {
            Console.ForegroundColor = color[r];
            Console.Write($"[{image[r]}] ");
        }
        Console.BackgroundColor = currentBackgroundColor;
        Console.ForegroundColor = currentForegroundColor;
        Console.WriteLine("");
    }

    static void InitReels(ref int[] reel)
    {
        Random rand = new Random();
        int images = image.Length;
        for (int i = 0; i < reel.Length; i++)
        {
            reel[i] = rand.Next(images);
        }
    }

    static void SpinReels(ref int[] reel)
    {
        const int MILLISECONDS = 2000;
        Console.CursorVisible = false;
        Stopwatch timer = new Stopwatch();
        timer.Start();
        while(timer.ElapsedMilliseconds < MILLISECONDS)
        {
            InitReels(ref reel);
            PrintReels(reel);
        }
        Console.CursorVisible = true;
    }

    // Return the number of equals and bars in the given array.
    //
    static (int, int) Prize(int[] reel)
    {
        int equals = 0;
        int bars = 0;

        for (int i = 0; i < reel.Length; i++)
        {
            for (int j = i + 1; j < reel.Length; j++)
            {
                equals +=  Convert.ToInt32(reel[i] == reel[j]);
            }
        }
        if (equals > 0 && equals < reel.Length)
        {
            equals++;
        }

        foreach (int i in reel)
        {
            bars += Convert.ToInt32(i == BAR);
        }
        return (equals, bars);
    }

    static string GetString(string prompt)
    {
        Console.Write(prompt);
        return Console.ReadLine();
    }

    static int GetInteger(string prompt)
    {
        int n = 0;

        while (true)
        {
            try
            {
                n = Int32.Parse(GetString(prompt));
                break;
            }
            catch { }
        }

        return n;
    }

    static void Play()
    {
        int standings = 0;
        int bet = 0;
        int[] reel = {0, 0, 0};
        int equals = 0;
        int bars = 0;

        InitReels(ref reel);

        while (true) { // play loop

            while (true) { // bet loop
                Console.Clear();
                PrintReels(reel);
                bet = GetInteger("Your bet (or 0 to quit): ");
                if (bet > MAX_BET)
                {
                    Console.WriteLine($"House limits are {MAX_BET} USD.");
                    PressEnter("Press Enter to try again.");
                }
                else if (bet < MIN_BET)
                {
                    Console.WriteLine("Type \"q\" to confirm you want to quit.");
                    string confirm = Console.ReadLine().ToLower();
                    if (confirm == "q")
                    {
                        goto showStandings;
                    }
                }
                else
                {
                    break; // bet loop
                };
            };

            Console.Clear();
            SpinReels(ref reel);
            (equals, bars) = Prize(reel);

            switch (equals)
            {
                case 3:
                    if (bars == 3)
                    {
                        standings += Won(100, bet);
                    }
                    else
                    {
                        standings += Won(10, bet);
                    };
                    break;
                case 2:
                    if (bars == 2)
                    {
                        standings += Won(5, bet);
                    }
                    else
                    {
                        standings += Won(2, bet);
                    }
                    break;
                default:
                    Console.WriteLine("You lost.");
                    standings -= bet;
                    break;
            };

            ShowStandings(standings);
            PressEnter("Press Enter to continue.");
        }; // play loop

        showStandings:

        ShowStandings(standings);
        if (standings < 0)
            Console.WriteLine("Pay up!  Please leave your money on the terminal.");
        else if (standings == 0)
            Console.WriteLine("Hey, you broke even.");
        else if (standings > 0)
            Console.WriteLine("Collect your winnings from the H&M cashier.");
    }

    static void Main()
    {
        PrintCredits();
        PrintInstructions();
        Play();
    }
}

In Chapel

// Slots
//  A slot machine simulation.

// Original version in BASIC:
//  Creative Computing (Morristown, New Jersey, USA).
//  Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

// This version in Chapel:
//  Copyright (c) 2025, Marcos Cruz (programandala.net)
//  SPDX-License-Identifier: Fair
//
// Written on 2025-04-07.
//
// Last modified: 20250407T1916+0200.

// Modules {{{1
// =============================================================================

import IO;
import Random;
import Time;

// Terminal {{{1
// =============================================================================

const BLACK = 0;
const RED = 1;
const GREEN = 2;
const YELLOW = 3;
const BLUE = 4;
const MAGENTA = 5;
const CYAN = 6;
const WHITE = 7;
const DEFAULT = 9;

const STYLE_OFF = 20;
const FOREGROUND = 30;
const BACKGROUND = 40;
const BRIGHT = 60;

const NORMAL_STYLE = 0;

proc moveCursorHome() {
    write("\x1B[H");
}

proc hideCursor() {
    write("\x1B[?25l");
}

proc showCursor() {
    write("\x1B[?25h");
}

proc setStyle(style: int) {
    writef("\x1B[%im", style);
}

proc resetAttributes() {
    setStyle(NORMAL_STYLE);
}

proc eraseScreen() {
    write("\x1B[2J");
}

proc clearScreen() {
    eraseScreen();
    resetAttributes();
    moveCursorHome();
}

// Data {{{1
// =============================================================================

param REELS = 3;
param IMAGES = 6;

var images: range = 0 ..< IMAGES;

const image: [images] string = [
    " BAR  ",
    " BELL ",
    "ORANGE",
    "LEMON ",
    " PLUM ",
    "CHERRY"
];

const BAR = 0; // position of "BAR" in `image`.

const color: [0 .. 5] int = [
    FOREGROUND + WHITE,
    FOREGROUND + CYAN,
    FOREGROUND + YELLOW,
    FOREGROUND + BRIGHT + YELLOW,
    FOREGROUND + BRIGHT + WHITE,
    FOREGROUND + BRIGHT + RED
];

param MAX_BET = 100;
param MIN_BET = 1;

// User input {{{1
// =============================================================================

proc acceptString(prompt: string): string {
    write(prompt);
    IO.stdout.flush();
    return IO.readLine().strip();
}

// Print the given prompt, accept a string from the user. If the typed string
// is a valid integer return it; otherwise return 0.
//
proc acceptInteger(prompt: string): int {
    var result: int;
    var s: string = acceptString(prompt);
    try {
        result = (s): int;
    }
    catch exc {
        result = 0;
    }
    return result;
}

// Credits and instructions {{{1
// =============================================================================

proc printCredits() {
    clearScreen();
    writeln("Slots");
    writeln("A slot machine simulation.\n");
    writeln("Original version in BASIC:");
    writeln("    Creative computing (Morristown, New Jersey, USA).");
    writeln("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n");
    writeln("This version in Chapel:");
    writeln("    Copyright (c) 2025, Marcos Cruz (programandala.net)");
    writeln("    SPDX-License-Identifier: Fair\n");
    acceptString("Press Enter for instructions. ");
}

proc printInstructions() {
    clearScreen();
    writeln("You are in the H&M casino, in front of one of our");
    writef("one-arm bandits. Bet from %i to %i USD (or 0 to quit).\n\n",
        MIN_BET, MAX_BET);
    acceptString("Press Enter to start. ");
}

// Game {{{1
// =============================================================================

proc won(prize: int, bet: int): int {
    select prize {
        when 2 do writeln("DOUBLE!");
        when 5 do writeln("*DOUBLE BAR*");
        when 10 do writeln("**TOP DOLLAR**");
        when 100 do writeln("***JACKPOT***");
    }
    writeln("You won!");
    return (prize + 1) * bet;
}

proc showStandings(usd: int) {
    writef("Your standings are %i USD.\n", usd);
}

proc printReels(reel: [] int) {
    moveCursorHome();
    for r in reel {
        setStyle(color[r]);
        writef("[%s] ", image[r]);
    }
    setStyle(NORMAL_STYLE);
    writeln("");
}

var rsInt = new Random.randomStream(int);

proc initReels(ref reel: [] int) {
    var images: int = (image.size): int;
    for i in 0 ..< reel.size {
        reel[i] = rsInt.next(0, images - 1);
    }
}

proc spinReels(ref reel: [] int) {
    const SECONDS = 2;
    hideCursor();
    var startSecond: int = Time.timeSinceEpoch().seconds;
    var currentSecond: int;
    do {
        initReels(reel);
        printReels(reel);
        currentSecond = Time.timeSinceEpoch().seconds;
    } while currentSecond - startSecond <= SECONDS;
    showCursor();
}

proc play() {

    var standings: int = 0;
    var bet: int = 0;
    var reel: [0 ..< REELS] int;

    initReels(reel);

    label playLoop while true {

        label betLoop while true {
            clearScreen();
            printReels(reel);
            bet = acceptInteger("Your bet (or 0 to quit): ");
            if bet > MAX_BET {
                writef("House limits are %i USD.\n", MAX_BET);
                acceptString("Press Enter to try again. ");
            } else if bet < MIN_BET {
                var confirmation: string =
                    acceptString("Type \"q\" to confirm you want to quit. ");
                if confirmation == "q" || confirmation == "Q" {
                    break playLoop;
                }
            } else {
                break betLoop;
            } // bet check

        } // bet loop

        clearScreen();
        spinReels(reel);

        var bars: int = reel.count(BAR);
        var equals: int;
        for image in images {
            equals = max(equals, reel.count(image));
        }

        select equals {
            when 3 {
                if bars == 3 {
                    standings += won(100, bet);
                } else {
                    standings += won(10, bet);
                }
            }
            when 2 {
                if bars == 2 {
                    standings += won(5, bet);
                } else {
                    standings += won(2, bet);
                }
            }
            otherwise {
                writeln("You lost.");
                standings -= bet;
            }
        } // prize check

        showStandings(standings);
        acceptString("Press Enter to continue. ");

    } // play loop

    showStandings(standings);

    if standings < 0 {
        writeln("Pay up!  Please leave your money on the terminal.");
    } else if standings > 0 {
        writeln("Collect your winnings from the H&M cashier.");
    } else {
        writeln("Hey, you broke even.");
    }

}

// Main {{{1
// =============================================================================

proc main() {
    printCredits();
    printInstructions();
    play();
}

In Crystal

# Slots
#   A slot machine simulation.

# Original version in BASIC:
#   Creative Computing (Morristown, New Jersey, USA).
#   Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

# This version in Crystal:
#   Copyright (c) 2023, Marcos Cruz (programandala.net)
#   SPDX-License-Identifier: Fair
#
# Written in 2023-09.
#
# Last modified: 20250407T2050+0200.

# Config {{{1
# ==============================================================================

REELS   = 3
IMAGE   = [" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"]
IMAGES  = IMAGE.size
BAR     =   0 # position of "BAR" in `IMAGE`.
MIN_BET =   1
MAX_BET = 100

# Terminal {{{1
# ==============================================================================

# Screen colors
BLACK   = 0
RED     = 1
GREEN   = 2
YELLOW  = 3
BLUE    = 4
MAGENTA = 5
CYAN    = 6
WHITE   = 7
DEFAULT = 9

# Screen attributes
NORMAL = 0

# Screen color offsets
FOREGROUND = +30
BRIGHT     = +60

# Moves the cursor to the home position.
def home
  print "\e[H"
end

# Clears the screen and moves the cursor to the home position.
def clear
  print "\e[2J"
  home
end

def set_color(color : Int)
  print "\e[#{color}m"
end

def set_attribute(attr : Int)
  print "\e[0;#{attr}m"
end

def hide_cursor
  print "\e[?25l"
end

def show_cursor
  print "\e[?25h"
end

# User Input {{{1
# ==============================================================================

# Prompts the user to enter a command and returns it.
def command(prompt = "> ") : String
  s = nil
  while s.is_a?(Nil)
    print prompt
    s = gets
  end
  s
end

# Prints the given prompt, waits until the user enters a integer and returns it.
# If the input is not a valid integer, returns zero instead.
def get_integer_or_0(prompt : String) : Int
  while true
    print prompt
    begin
      return gets.not_nil!.to_i
      break
    rescue
      return 0
    end
  end
end

# Prints the given prompt and waits until the user enters an empty string.
def press_enter(prompt : String)
  until command(prompt) == ""
  end
end

# Credits and instructions {{{1
# ==============================================================================

def print_credits
  clear
  puts "Slots"
  puts "A slot machine simulation.\n"
  puts "Original version in BASIC:"
  puts "    Creative computing (Morristown, New Jersey, USA)."
  puts "    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n"
  puts "This version in Crystal:"
  puts "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
  puts "    SPDX-License-Identifier: Fair\n"
  press_enter("Press Enter for instructions. ")
end

def print_instructions
  clear
  puts "You are in the H&M casino, in front of one of our"
  puts "one-arm bandits. Bet from #{MIN_BET} to #{MAX_BET} USD (or 0 to quit).\n"
  press_enter("Press Enter to start. ")
end

# Main {{{1
# ==============================================================================

def won(prize : Int, bet : Int) : Int
  case prize
  when   2; puts "DOUBLE!"
  when   5; puts "*DOUBLE BAR*"
  when  10; puts "**TOP DOLLAR**"
  when 100; puts "***JACKPOT***"
  end
  puts "You won!"
  return (prize + 1) * bet
end

def show_standings(usd : Int)
  puts "Your standings are #{usd} USD."
end

def print_reels(reel : Array(Int))
  home

  color = [
    FOREGROUND + WHITE,
    FOREGROUND + CYAN,
    FOREGROUND + YELLOW,
    FOREGROUND + BRIGHT + YELLOW,
    FOREGROUND + BRIGHT + WHITE,
    FOREGROUND + BRIGHT + RED,
  ]

  reel.each do |r|
    set_color(color[r])
    print "[#{IMAGE[r]}] "
  end

  set_attribute(NORMAL)
  puts
end

def init_reels(reel : Array(Int))
  reel.each_index do |i|
    reel[i] = rand(IMAGES)
  end
end

SPINS = 24000

def spin_reels(reel : Array(Int))
  hide_cursor
  SPINS.times do
    reel.each_index do |i|
      reel[i] = rand(IMAGES)
    end
    print_reels(reel)
  end
  show_cursor
end

def prize(reel : Array(Int)) : Tuple
  # XXX TODO rewrite, make the counting independent from the number of reels
  equals = 0 # number of equals in the 3 reels
  bars = 0   # number of bars in the 3 reels
  case
  when reel[0] == reel[1] && reel[1] == reel[2]
    equals = 3
  when reel[0] == reel[1] || reel[1] == reel[2] || reel[0] == reel[2]
    equals = 2
  end
  (0...REELS).each do |i|
    bars += reel[i] == BAR ? 1 : 0
  end
  return equals, bars
end

def play
  standings = 0
  reel = [0, 0, 0]
  equals = 0
  bars = 0
  init_reels(reel)
  betting = true
  playing = true
  while playing
    bet = 0
    while playing && betting
      clear
      print_reels(reel)
      bet = get_integer_or_0("Your bet (or 0 to quit): ")
      case
      when bet > MAX_BET
        puts "House limits are #{MAX_BET} USD."
        press_enter("Press Enter to try again. ")
      when bet < MIN_BET
        if command("Type \"q\" to confirm you want to quit: ") == "q"
          playing = false
          betting = false
        end
      else
        betting = false
      end # bet check
    end   # betting
    if playing
      clear
      spin_reels(reel)
      equals, bars = prize(reel)
      case
      when equals == REELS
        if bars == REELS
          standings += won(100, bet)
        else
          standings += won(10, bet)
        end
      when equals == 2
        if bars == 2
          standings += won(5, bet)
        else
          standings += won(2, bet)
        end
      else
        puts "You lost."
        standings -= bet
      end # prize check
      show_standings(standings)
      press_enter("Press Enter to continue. ")
      betting = true
    end
  end # play loop
  show_standings(standings)
  case
  when standings < 0
    puts "Pay up!  Please leave your money on the terminal."
  when standings == 0
    puts "Hey, you broke even."
  when standings > 0
    puts "Collect your winnings from the H&M cashier."
  end
end

print_credits
print_instructions
play

In D

// Slots
//     A slot machine simulation.

// Original version in BASIC:
//     Creative Computing (Morristown, New Jersey, USA).
//     Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

// This version in D:
//     Copyright (c) 2025, Marcos Cruz (programandala.net)
//     SPDX-License-Identifier: Fair
//
// Written on 2025-03-24.
//
// Last modified: 20251220T0632+0100.

module slots;

// Terminal {{{1
// =============================================================================

enum BLACK = 0;
enum RED = 1;
enum GREEN = 2;
enum YELLOW = 3;
enum BLUE = 4;
enum MAGENTA = 5;
enum CYAN = 6;
enum WHITE = 7;
enum DEFAULT = 9;

enum STYLE_OFF = 20;
enum FOREGROUND = 30;
enum BACKGROUND = 40;
enum BRIGHT = 60;

enum NORMAL_STYLE = 0;

void moveCursorHome()
{
    import std.stdio : write;

    write("\x1B[H");
}

void hideCursor()
{
    import std.stdio : write;

    write("\x1B[?25l");
}

void showCursor()
{
    import std.stdio : write;

    write("\x1B[?25h");
}

void setStyle(int style)
{
    import std.stdio : writef;

    writef("\x1B[%dm", style);
}

void resetAttributes()
{
    setStyle(NORMAL_STYLE);
}

void eraseScreen()
{
    import std.stdio : write;

    write("\x1B[2J");
}

void clearScreen()
{
    eraseScreen();
    resetAttributes();
    moveCursorHome();
}

// Data {{{1
// =============================================================================

enum REELS = 3;

string[] image = [" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"];
enum BAR = 0; // position of "BAR" in `image`.
const(int[]) color = [
    FOREGROUND + WHITE,
    FOREGROUND + CYAN,
    FOREGROUND + YELLOW,
    FOREGROUND + BRIGHT + YELLOW,
    FOREGROUND + BRIGHT + WHITE,
    FOREGROUND + BRIGHT + RED ];
enum MAX_BET = 100;
enum MIN_BET = 1;

// User input {{{1
// =============================================================================

string acceptString(string prompt)
{
    import std.stdio : readln;
    import std.stdio : write;
    import std.string : strip;

    write(prompt);
    return strip(readln());
}

/// Print the given prompt, accept a string from the user. If the typed string
/// is a valid integer return it; otherwise return 0.

int acceptInteger(string prompt)
{
    import std.conv : to;

    int result;
    string s = acceptString(prompt);
    try
    {
        result = to!int(s);
    }
    catch (Exception exc)
    {
        result = 0;
    }
    return result;
}

// Credits and instructions {{{1
// =============================================================================

void printCredits()
{
    import std.stdio : writeln;

    clearScreen();
    writeln("Slots");
    writeln("A slot machine simulation.\n");
    writeln("Original version in BASIC:");
    writeln("    Creative computing (Morristown, New Jersey, USA).");
    writeln("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n");
    writeln("This version in D:");
    writeln("    Copyright (c) 2025, Marcos Cruz (programandala.net)");
    writeln("    SPDX-License-Identifier: Fair\n");
    acceptString("Press Enter for instructions. ");
}

void printInstructions()
{
    import std.stdio : writefln;
    import std.stdio : writeln;

    clearScreen();
    writeln("You are in the H&M casino, in front of one of our");
    writefln("one-arm bandits. Bet from %d to %d USD (or 0 to quit).\n",
        MIN_BET, MAX_BET);
    acceptString("Press Enter to start. ");
}

// Game {{{1
// =============================================================================

int won(int prize, int bet)
{
    import std.stdio : writeln;

    final switch (prize)
    {
        case 2:
            writeln("DOUBLE!");
            break;
        case 5:
            writeln("*DOUBLE BAR*");
            break;
        case 10:
            writeln("**TOP DOLLAR**");
            break;
        case 100:
            writeln("***JACKPOT***");
    }
    writeln("You won!");
    return (prize + 1) * bet;
}

void showStandings(int usd)
{
    import std.stdio : writefln;

    writefln("Your standings are %d USD.", usd);
}

void printReels(int[REELS] reel)
{
    import std.stdio : writef;
    import std.stdio : writeln;

    moveCursorHome();
    foreach (int r; reel)
    {
        setStyle(color[r]);
        writef("[%s] ", image[r]);
    }
    setStyle(NORMAL_STYLE);
    writeln();
}

void initReels(ref int[REELS] reel)
{
    import std.random : uniform;

    int images = cast(int)(image.length);
    foreach (int i; 0 .. reel.length)
    {
        reel[i] = uniform(0, images);
    }
}

void spinReels(ref int[REELS] reel)
{
    import core.time : MonoTime;

    int SECONDS = 2;
    hideCursor();
    auto startTime = MonoTime.currTime;
    long startSecond = (startTime - MonoTime.zero).total!"seconds";
    long currentSecond;
    do
    {
        initReels(reel);
        printReels(reel);
        auto currentTime = MonoTime.currTime;
        currentSecond = (currentTime - MonoTime.zero).total!"seconds";
    } while (currentSecond - startSecond <= SECONDS);
    showCursor();
}

void play()
{
    import std.algorithm.iteration : uniq;
    import std.algorithm.searching : count;
    import std.algorithm.sorting : sort;
    import std.stdio : writefln;
    import std.stdio : writeln;

    int standings = 0;
    int bet = 0;
    int[REELS] reel;

    initReels(reel);

    playLoop: while (true)
    {

        betLoop: while (true)
        {
            clearScreen();
            printReels(reel);
            bet = acceptInteger("Your bet (or 0 to quit): ");
            if (bet > MAX_BET)
            {
                writefln("House limits are %d USD.", MAX_BET);
                acceptString("Press Enter to try again. ");
            }
            else if (bet < MIN_BET)
            {
                string confirmation = acceptString("Type \"q\" to confirm you want to quit. ");
                if (confirmation == "q" || confirmation == "Q")
                {
                    break playLoop;
                }
            }
            else
            {
                break betLoop;
            } // bet check

        } // bet loop

        clearScreen();
        spinReels(reel);
        int equals = REELS - cast(int)(reel[0 .. REELS].sort().uniq.count);
        equals += cast(int)(equals > 0);
        int bars = cast(int)(count(reel[0 .. REELS], BAR));

        switch (equals)
        {
            case 3:
                if (bars == 3)
                {
                    standings += won(100, bet);
                }
                else
                {
                    standings += won(10, bet);
                }
                break;
            case 2:
                if (bars == 2)
                {
                    standings += won(5, bet);
                }
                else
                {
                    standings += won(2, bet);
                }
                break;
            default:
                writeln("You lost.");
                standings -= bet;
        } // prize check

        showStandings(standings);
        acceptString("Press Enter to continue. ");

    } // play loop

    showStandings(standings);

    if (standings < 0)
    {
        writeln("Pay up!  Please leave your money on the terminal.");
    }
    else if (standings > 0)
    {
        writeln("Collect your winnings from the H&M cashier.");
    }
    else
    {
        writeln("Hey, you broke even.");
    }

}

// Main {{{1
// =============================================================================

void main()
{
    printCredits();
    printInstructions();
    play();
}

In Go

/*
Slots
    A slot machine simulation.

Original version in BASIC:
    Creative Computing (Morristown, New Jersey, USA).
    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

This version in Go:
    Copyright (c) 2025, Marcos Cruz (programandala.net)
    SPDX-License-Identifier: Fair

Written on 2025-01-06/07, 2025-04-07.

Last modified: 20250407T2100+0200.
*/

package main

import "fmt"
import "math/rand"
import "strconv"
import "time"

const reels = 3

const blackColor = 0
const redColor = 1
const greenColor = 2
const yellowColor = 3
const blueColor = 4
const magentaColor = 5
const cyanColor = 6
const whiteColor = 7
const defaultColor = 9

const normalAttributes = 0

const foreground = +30
const background = +40
const bright = +60

func clearScreen() {
    fmt.Print("\x1B[0;0H\x1B[2J")
}

func moveCursorHome() {
    fmt.Print("\x1B[H")
}

func hideCursor() {
    fmt.Print("\x1B[?25l")
}

func showCursor() {
    fmt.Print("\x1B[?25h")
}

func setColor(color int) {
    fmt.Printf("\x1B[%vm", color)
}

const defaultInk = foreground + whiteColor
const inputInk = foreground + bright + greenColor
const instructionsInk = foreground + yellowColor
const titleInk = foreground + bright + redColor

var image = []string{" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"}
var reel [reels]int

const bar int = 0 // position of "BAR" in `image`.
var color = []int{
    foreground + whiteColor,
    foreground + cyanColor,
    foreground + yellowColor,
    foreground + bright + yellowColor,
    foreground + bright + whiteColor,
    foreground + bright + redColor}

const maxBet int = 100
const minBet int = 1

func printCredits() {

    clearScreen()
    fmt.Println("Slots")
    fmt.Println("A slot machine simulation.\n")
    fmt.Println("\nOriginal version in BASIC:")
    fmt.Println("    Creative computing (Morristown, New Jersey, USA).")
    fmt.Println("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n")
    fmt.Println("\nThis version in Go:")
    fmt.Println("    Copyright (c) 2025, Marcos Cruz (programandala.net)")
    fmt.Println("    SPDX-License-Identifier: Fair\n")
    pressEnter("Press Enter for instructions.")

}

func printInstructions() {

    clearScreen()
    fmt.Println("You are in the H&M casino, in front of one of our")
    fmt.Printf(
        "one-arm bandits. Bet from %v to %v USD (or 0 to quit).\n\n",
        minBet, maxBet)
    pressEnter("Press Enter to start.")

}

func won(prize int, bet int) int {

    switch prize {
    case 2:
        fmt.Println("DOUBLE!")
    case 5:
        fmt.Println("*DOUBLE BAR*")
    case 10:
        fmt.Println("**TOP DOLLAR**")
    case 100:
        fmt.Println("***JACKPOT***")
    }
    fmt.Println("You won!")
    return (prize + 1) * bet

}

func showStandings(usd int) {

    fmt.Printf("Your standings are %v USD.\n", usd)

}

func printReels() {

    moveCursorHome()
    for _, r := range reel {
        setColor(color[r])
        fmt.Printf("[%v] ", image[r])
    }
    setColor(normalAttributes)
    fmt.Println("")

}

func initReels() {

    var images = len(image)
    for i := range reel {
        reel[i] = rand.Intn(images)
    }

}

func spinReels() {

    const seconds time.Duration = 2
    var firstSecond = time.Now()
    var lastSecond = firstSecond.Add(time.Second * seconds)
    hideCursor()
    for time.Now().Before(lastSecond) {
        initReels()
        printReels()
    }
    showCursor()

}

// Return the number of equals and bars in the given `reel` array.
func prize() (int, int) {

    var equals = 0
    for first := 0; first < len(reel); first++ {
        for second := first + 1; second < len(reel); second++ {
            if reel[first] == reel[second] {
                equals++
            }
        }
    }
    if equals > 0 && equals < len(reel) {
        equals++
    }

    var bars = 0
    for i := 0; i < len(reel); i++ {
        if reel[i] == bar {
            bars++
        }
    }

    return equals, bars

}

// Print the given prompt and wait until the user enters a string.
func inputString(prompt string) string {

    setColor(inputInk)
    defer setColor(defaultInk)
    fmt.Print(prompt)
    var s = ""
    fmt.Scanf("%s", &s)
    return s

}

// Print the given prompt and wait until the user presses Enter.
func pressEnter(prompt string) {

    inputString(prompt)

}

// Print the given prompt and wait until the user enters an integer.
func inputInt(prompt string) int {

    var number int64
    var err error
    setColor(inputInk)
    defer setColor(defaultInk)
    for {
        number, err = strconv.ParseInt(inputString(prompt), 10, 0)
        if err == nil {
            break
        } else {
            fmt.Println("Integer expected.")
        }
    }
    return int(number)

}

func play() {

    rand.Seed(time.Now().UTC().UnixNano())

    var standings = 0
    var bet = 0
    var equals = 0
    var bars = 0
    initReels()
playLoop:
    for {
    betLoop:
        for {
            clearScreen()
            printReels()
            bet = inputInt("Your bet (or 0 to quit): ")
            switch {
            case bet > maxBet:
                fmt.Printf("House limits are %v USD.\n", maxBet)
                pressEnter("Press Enter to try again.")
            case bet < minBet:
                if confirm := inputString("Type \"q\" to confirm you want to quit. "); confirm == "q" {
                    break playLoop
                }
            default:
                break betLoop
            } // bet check
        } // bet loop
        clearScreen()
        spinReels()
        equals, bars = prize()
        switch equals {
        case 3:
            if bars == 3 {
                standings += won(100, bet)
            } else {
                standings += won(10, bet)
            }
        case 2:
            if bars == 2 {
                standings += won(5, bet)
            } else {
                standings += won(2, bet)
            }
        default:
            fmt.Println("You lost.")
            standings -= bet
        } // prize check
        showStandings(standings)
        pressEnter("Press Enter to continue.")
    } // play loop
    showStandings(standings)
    switch {
    case standings < 0:
        fmt.Println("Pay up!  Please leave your money on the terminal.")
    case standings == 0:
        fmt.Println("Hey, you broke even.")
    case standings > 0:
        fmt.Println("Collect your winnings from the H&M cashier.")
    }

}

func main() {

    printCredits()
    printInstructions()
    play()

}

In Hare

// Slots
//      A slot machine simulation.
//
// Original version in BASIC:
//      Creative Computing (Morristown, New Jersey, USA).
//      Produced by Fred Mirabelle and Bob Harper on 1973-01-29.
//
// This version in Hare:
//      Copyright (c) 2025, Marcos Cruz (programandala.net)
//      SPDX-License-Identifier: Fair
//
// Written on 2025-02-15, 2025-04-07.
//
// Last modified: 20260213T1645+0100.

// Modules {{{1
// =============================================================================

use bufio;
use fmt;
use math::random;
use os;
use strconv;
use strings;
use time;

// Terminal {{{1
// =============================================================================

def BLACK = 0;
def RED = 1;
def GREEN = 2;
def YELLOW = 3;
def BLUE = 4;
def MAGENTA = 5;
def CYAN = 6;
def WHITE = 7;
def DEFAULT = 9;

def STYLE_OFF = 20;
def FOREGROUND = 30;
def BACKGROUND = 40;
def BRIGHT = 60;

def NORMAL_STYLE = 0;

fn move_cursor_home() void = {
        fmt::print("\x1B[H")!;
};

fn hide_cursor() void = {
        fmt::print("\x1B[?25l")!;
};

fn show_cursor() void = {
        fmt::print("\x1B[?25h")!;
};

fn set_style(style: int) void = {
        fmt::printf("\x1B[{}m", style)!;
};

fn reset_attributes() void = {
        set_style(NORMAL_STYLE);
};

fn erase_screen() void = {
        fmt::print("\x1B[2J")!;
};

fn clear_screen() void = {
        erase_screen();
        reset_attributes();
        move_cursor_home();
};

// Data {{{1
// =============================================================================

def REELS = 3;

const image: [_]str = [" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"];
def BAR = 0; // position of "BAR" in `image`.
const color: [_]int = [
        FOREGROUND + WHITE,
        FOREGROUND + CYAN,
        FOREGROUND + YELLOW,
        FOREGROUND + BRIGHT + YELLOW,
        FOREGROUND + BRIGHT + WHITE,
        FOREGROUND + BRIGHT + RED ];
def MAX_BET = 100;
def MIN_BET = 1;

// User input {{{1
// =============================================================================

fn print_prompt(prompt: str = "") void = {
        fmt::print(prompt)!;
        bufio::flush(os::stdout)!;
};

fn accept_string(prompt: str = "") str = {
        print_prompt(prompt);
        const buffer = match (bufio::read_line(os::stdin)!) {
                case let buffer: []u8 =>
                        yield buffer;
                case =>
                        return "";
                };
        defer free(buffer);
        return strings::dup(strings::fromutf8(buffer)!)!;
};

fn press_enter(prompt: str) void = {
        free(accept_string(prompt));
};

fn accept_integer() (int | ...strconv::error) = {
        const s = accept_string();
        defer free(s);
        return strconv::stoi(s);
};

fn prompted_integer(prompt: str) (int | ...strconv::error) = {
        fmt::print(prompt)!;
        bufio::flush(os::stdout)!;
        return accept_integer();
};

fn prompted_integer_or_0(prompt: str) int = {
        match (prompted_integer(prompt)) {
        case let i: int =>
                return i;
        case =>
                return 0;
        };
};

// Credits and instructions {{{1
// =============================================================================

fn print_credits() void = {
        clear_screen();
        fmt::println("Slots")!;
        fmt::println("A slot machine simulation.\n")!;
        fmt::println("Original version in BASIC:")!;
        fmt::println("    Creative computing (Morristown, New Jersey, USA).")!;
        fmt::println("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n")!;
        fmt::println("This version in Hare:")!;
        fmt::println("    Copyright (c) 2025, Marcos Cruz (programandala.net)")!;
        fmt::println("    SPDX-License-Identifier: Fair\n")!;
        press_enter("Press Enter for instructions. ");
};

fn print_instructions() void = {
        clear_screen();
        fmt::println("You are in the H&M casino, in front of one of our")!;
        fmt::printf("one-arm bandits. Bet from {} to {} USD (or 0 to quit).\n\n",
                MIN_BET, MAX_BET)!;
        press_enter("Press Enter to start. ");
};

// Game {{{1
// =============================================================================

fn won(prize: int, bet: int) int = {
        switch (prize) {
        case   2 => fmt::println("DOUBLE!")!;
        case   5 => fmt::println("*DOUBLE BAR*")!;
        case  10 => fmt::println("**TOP DOLLAR**")!;
        case 100 => fmt::println("***JACKPOT***")!;
        case     => void ;
        };
        fmt::println("You won!")!;
        return (prize + 1) * bet;
};

fn show_standings(usd: int) void = {
        fmt::printfln("Your standings are {} USD.", usd)!;
};

fn print_reels(reel: *[REELS]int) void = {
        move_cursor_home();
        for (let r .. reel) {
                set_style(color[r]);
                fmt::printf("[{}] ", image[r])!;
        };
        set_style(NORMAL_STYLE);
        fmt::println("")!;
};

fn init_reels(reel: *[REELS]int) void = {
        let images = (len(image)): int;
        for (let i = 0; i < len(reel): int; i += 1) {
                reel[i] = random::u32n(&rand, images: u32): int;
        };
};

fn spin_reels(reel: *[REELS]int) void = {
        def DURATION_IN_SECONDS = 2;
        hide_cursor();
        let first_second = time::now(time::clock::MONOTONIC).sec;
        for ((time::now(time::clock::MONOTONIC).sec - first_second) < DURATION_IN_SECONDS) {
                init_reels(reel);
                print_reels(reel);
        };
        show_cursor();
};

fn bool_to_int(flag: bool) int = {
        return if (flag) 1 else 0;
};

// Return the number of equals and bars in the given `reel` array.
//
fn prize(reel: *[REELS]int) (int, int) = {
        // Count the number of equals
        let equals: int = 0;
        for (let first = 0; first < len(reel): int; first += 1) {
                for (let second = first + 1; second < len(reel): int; second += 1) {
                        equals += bool_to_int(reel[first] == reel[second]);
                };
        };
        equals += bool_to_int(equals > 0 && equals < len(reel): int);

        // Count the number of bars
        let bars: int = 0;
        for (let i = 0; i < len(reel): int; i += 1) {
                bars += bool_to_int(reel[i] == BAR);
        };

        return (equals, bars);
};

fn play() void = {
        let standings = 0;
        let bet = 0;
        let reel: [REELS]int = [0, 0, 0];
        let equals = 0;
        let bars = 0;
        init_reels(&reel);
        for :play_loop (true) {
                for :bet_loop (true) {
                        clear_screen();
                        print_reels(&reel);
                        bet = prompted_integer_or_0("Your bet (or 0 to quit): ");
                        if (bet > MAX_BET) {
                                fmt::printfln("House limits are {} USD.", MAX_BET)!;
                                press_enter("Press Enter to try again. ");
                        } else if (bet < MIN_BET) {
                                let confirmation = accept_string("Type \"q\" to confirm you want to quit. ");
                                defer free(confirmation);
                                if (confirmation == "q" || confirmation == "Q") {
                                        break :play_loop;
                                };
                        } else {
                                break :bet_loop;
                        }; // bet check
                }; // bet loop
                clear_screen();
                spin_reels(&reel);
                let prize_details = prize(&reel);
                equals = prize_details.0;
                bars = prize_details.1;
                switch (equals) {
                case 3 =>
                        if (bars == 3) {
                                standings += won(100, bet);
                        } else {
                                standings += won(10, bet);
                        };
                case 2 =>
                        if (bars == 2) {
                                standings += won(5, bet);
                        } else {
                                standings += won(2, bet);
                        };
                case =>
                        fmt::println("You lost.")!;
                        standings -= bet;
                }; // prize check
                show_standings(standings);
                press_enter("Press Enter to continue. ");
        }; // play loop
        show_standings(standings);
        if (standings < 0) {
                fmt::println("Pay up!  Please leave your money on the terminal.")!;
        } else if (standings > 0) {
                fmt::println("Collect your winnings from the H&M cashier.")!;
        } else {
                fmt::println("Hey, you broke even.")!;
        };
};

// Main {{{1
// =============================================================================

let rand: random::random = 0;

fn randomize() void = {
        rand = random::init(time::now(time::clock::MONOTONIC).sec: u64);
};

fn init() void = {
        randomize();
};

export fn main() void = {
        init();
        print_credits();
        print_instructions();
        play();
};

In Janet

# Slots
#   A slot machine simulation.

# Original version in BASIC:
#   Creative Computing (Morristown, New Jersey, USA).
#   Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

# This version in Janet:
#   Copyright (c) 2025, Marcos Cruz (programandala.net)
#   SPDX-License-Identifier: Fair
#
# Written on 2025-12-27.
#
# Last modified: 20251227T2048+0100.

# Terminal {{{1
# ==============================================================================

# Screen colors
(def black 0)
(def red 1)
(def green 2)
(def yellow 3)
(def blue 4)
(def magenta 5)
(def cyan 6)
(def white 7)
(def default-color 9)

# Screen attributes
(def normal 0)

# Screen color offsets
(def foreground +30)
(def bright +60)

(defn move-cursor-home []
  (prin "\e[H"))

(defn clear-screen []
  (prin "\e[2J")
  (move-cursor-home))

(defn set-color [color]
  (prin "\e[" color "m")
)

(defn set-attribute [attr]
  (prin "\e[0;" attr "m")
)

(defn hide-cursor []
  (prin "\e[?25l"))

(defn show-cursor []
  (prin "\e[?25h"))

# Config {{{1
# ==============================================================================

(def reels 3)
(def image [" BAR  " " BELL " "ORANGE" "LEMON " " PLUM " "CHERRY"])
(def images (length image))
(def bar 0) # position of "BAR" in `image`.
(def min-bet 1)
(def max-bet 100)
(def input-color (+ green foreground))
(def ordinary-color (+ default-color foreground))

# User Input {{{1
# ==============================================================================

(defn command [&opt prompt-text]
  (default prompt-text "> ")
  (set-color input-color)
  (defer (set-color ordinary-color)
    (do
      (prin prompt-text)
      (flush)
      (string/trim (getline)))))

(defn get-integer-or-0 [prompt-text]
  (def number (scan-number (command prompt-text)))
  (if number
    (math/trunc number)
    0))

(defn press-enter [prompt-text]
  (while (not= (command prompt-text) "")) (break))

# Credits and instructions {{{1
# ==============================================================================

(defn print-credits []
  (clear-screen)
  (print "Slots")
  (print "A slot machine simulation.\n")
  (print "Original version in BASIC:")
  (print "    Creative computing (Morristown, New Jersey, USA).")
  (print "    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n")
  (print "This version in Janet:")
  (print "    Copyright (c) 2025, Marcos Cruz (programandala.net)")
  (print "    SPDX-License-Identifier: Fair\n")
  (press-enter "Press Enter for instructions. "))

(defn print-instructions []
  (clear-screen)
  (print "You are in the H&M casino, in front of one of our")
  (print "one-arm bandits. Bet from " min-bet " to " max-bet " USD (or 0 to quit).\n")
  (press-enter "Press Enter to start. "))

# Main {{{1
# ==============================================================================

(defn won [prize bet]
  (case prize
      2 (print "DOUBLE!")
      5 (print "*DOUBLE BAR*")
     10 (print "**TOP DOLLAR**")
    100 (print "***JACKPOT***"))
  (print "You won!")
  (* bet (+ prize 1)))

(defn show-standings [usd]
  (print "Your standings are " usd " USD."))

(def image-color [
  (+ foreground white)
  (+ foreground cyan)
  (+ foreground yellow)
  (+ foreground bright yellow)
  (+ foreground bright white)
  (+ foreground bright red)])

(defn print-reels [reel]
  (move-cursor-home)
  (each r reel
    (set-color (image-color r))
    (prin "[" (get image r) "] "))
  (set-attribute normal)
  (print))

(def random-number-generator (math/rng (os/time)))

(defn random-image []
  (math/rng-int random-number-generator images))

(defn init-reels [reel]
  (eachk i reel
    (put reel i (random-image))))

(defn spin-reels [reel]
  (def spins 24000)
  (hide-cursor)
  (for _ 0 spins
    (eachk i reel
      (put reel i (random-image)))
    (print-reels reel))
  (show-cursor))

(defn prize [reel]
  (def duplicates (- (length reel) (length (distinct reel))))
  (def equals
    (if (= duplicates 0)
      duplicates
      (+ 1 duplicates)))
  (def bars (length (filter |(= $ bar) reel)))
  [equals bars])

(defn play []
  (var standings 0)
  (var reel @[0 0 0])
  (init-reels reel)
  (var betting true)
  (var playing true)
  (while playing
    (var bet 0)
    (while (and playing betting)
      (clear-screen)
      (print-reels reel)
      (set bet (get-integer-or-0 "Your bet (or 0 to quit): "))
      (cond
        (> bet max-bet)
          (do
            (print "House limits are " max-bet " USD.")
            (press-enter "Press Enter to try again. "))
        (< bet min-bet)
          (when (= "q" (command "Type \"q\" to confirm you want to quit: "))
            (set playing false)
            (set betting false))
        (set betting false)))
    (when playing
      (clear-screen)
      (spin-reels reel)
      (def [equals bars] (prize reel))
      (cond
        (= equals reels)
          (if (= bars reels)
            (+= standings (won 100 bet))
            (+= standings (won 10 bet)))
        (= equals 2)
          (if (= bars 2)
            (+= standings (won 5 bet))
            (+= standings (won 2 bet)))
        (do
          (print "You lost.")
          (-= standings bet)))
      (show-standings standings)
      (press-enter "Press Enter to continue. ")
      (set betting true)))
  (show-standings standings)
  (cond
    (< standings 0)
      (print "Pay up!  Please leave your money on the terminal.")
    (= standings 0)
      (print "Hey, you broke even.")
    (> standings 0)
      (print "Collect your winnings from the H&M cashier.")))

(defn main [& args]
  (print-credits)
  (print-instructions)
  (play))

In Julia

# Slots
#   A slot machine simulation.

# Original version in BASIC:
#   Creative Computing (Morristown, New Jersey, USA).
#   Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

# This version in Julia:
#   Copyright (c) 2024, Marcos Cruz (programandala.net)
#   SPDX-License-Identifier: Fair
#
# Written on 2024-07-04.
#
# Last modified: 20240704T1731+0200.

# Config {{{1
# ==============================================================================

const REELS   = 3
const IMAGE   = [" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"]
const IMAGES  = length(IMAGE)
const BAR     =   1 # position of "BAR" in `IMAGE`.
const MIN_BET =   1
const MAX_BET = 100

# Terminal {{{1
# ==============================================================================

# Screen colors
const BLACK   = 0
const RED     = 1
const GREEN   = 2
const YELLOW  = 3
const BLUE    = 4
const MAGENTA = 5
const CYAN    = 6
const WHITE   = 7
const DEFAULT = 9

# Screen attributes
const NORMAL = 0

# Screen color offsets
const FOREGROUND = +30
const BRIGHT     = +60

# Move the cursor to the home position.
function home()
    print("\e[H")
end

# Clear the screen and move the cursor to the home position.
function clear_screen()
    print("\e[2J")
    home()
end

function set_color(color::Int)
    print("\e[$(color)m")
end

function set_attribute(attr::Int)
    print("\e[0;$(attr)m")
end

function hide_cursor()
    print("\e[?25l")
end

function show_cursor()
    print("\e[?25h")
end

# User Input {{{1
# ==============================================================================

# Prompt the user to enter a command and return it.
function command(prompt = "> ")::String
    print(prompt)
    return readline()
end

# Print the given prompt, waits until the user enter a integer and return it.
# If the input is not a valid integer, return zero instead.
function get_integer_or_0(prompt::String)::Int
    print(prompt)
    n = tryparse(Int, readline())
    if isnothing(n)
        return 0
    else
        return n
    end
end

# Print the given prompt and wait until the user enters an empty string.
function press_enter(prompt::String)
    while command(prompt) != ""
    end
end

# Credits and instructions {{{1
# ==============================================================================

function print_credits()
    clear_screen()
    println("Slots")
    println("A slot machine simulation.\n")
    println("Original version in BASIC:")
    println("    Creative computing (Morristown, New Jersey, USA).")
    println("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n")
    println("This version in Julia:")
    println("    Copyright (c) 2024, Marcos Cruz (programandala.net)")
    println("    SPDX-License-Identifier: Fair\n")
    press_enter("Press Enter for instructions. ")
end

function print_instructions()
    clear_screen()
    println("You are in the H&M casino, in front of one of our")
    println("one-arm bandits. Bet from $(MIN_BET) to $(MAX_BET) USD (or 0 to quit).\n")
    press_enter("Press Enter to start. ")
end

# Main {{{1
# ==============================================================================

function won(prize::Int, bet::Int)::Int
    if     prize ==   2; println("DOUBLE!")
    elseif prize ==   5; println("*DOUBLE BAR*")
    elseif prize ==  10; println("**TOP DOLLAR**")
    elseif prize == 100; println("***JACKPOT***")
    end
    println("You won!")
    return (prize + 1) * bet
end

function show_standings(usd::Int)
    println("Your standings are $usd USD.")
end

function print_reels(reel::Array{Int})
    home()

    color = [
        FOREGROUND + WHITE,
        FOREGROUND + CYAN,
        FOREGROUND + YELLOW,
        FOREGROUND + BRIGHT + YELLOW,
        FOREGROUND + BRIGHT + WHITE,
        FOREGROUND + BRIGHT + RED,
    ]

    for r in reel
        set_color(color[r])
        print("[$(IMAGE[r])] ")
    end

    set_attribute(NORMAL)
    println()
end

function init_reels(reel::Array{Int})
    for i in 1 : REELS
        reel[i] = rand(1 : IMAGES)
    end
end

const SPINS = 24000

function spin_reels(reel::Array{Int})
    hide_cursor()
    for _ in 1 : SPINS
        for i in 1 : REELS
            reel[i] = rand(1 : IMAGES)
        end
        print_reels(reel)
    end
    show_cursor()
end

function prize(reel::Array{Int})::Tuple
    equals = 0
    bars = 0
    for i in 1 : IMAGES
        repeated = count(==(i), reel)
        if repeated > 1
            equals = max(equals, repeated)
        end
        if i == BAR
            bars = repeated
        end
    end
    return equals, bars
end

function play()
    standings = 0
    reel = [0, 0, 0]
    equals = 0
    bars = 0
    init_reels(reel)
    betting = true
    playing = true
    while playing
        bet = 0
        while playing && betting
            clear_screen()
            print_reels(reel)
            bet = get_integer_or_0("Your bet (or 0 to quit): ")
            if bet > MAX_BET
                println("House limits are $(MAX_BET) USD.")
                press_enter("Press Enter to try again. ")
            elseif bet < MIN_BET
                if command("Type \"q\" to confirm you want to quit: ") == "q"
                    playing = false
                    betting = false
                end
            else
                betting = false
            end # bet check
        end # betting
        if playing
            clear_screen()
            spin_reels(reel)
            equals, bars = prize(reel)
            if equals == REELS
                if bars == REELS
                    standings += won(100, bet)
                else
                    standings += won(10, bet)
                end
            elseif equals == 2
                if bars == 2
                    standings += won(5, bet)
                else
                    standings += won(2, bet)
                end
            else
                println("You lost.")
                standings -= bet
            end # prize check
            show_standings(standings)
            press_enter("Press Enter to continue. ")
            betting = true
        end
    end # play loop
    show_standings(standings)
    if standings < 0
        println("Pay up!  Please leave your money on the terminal.")
    elseif standings == 0
        println("Hey, you broke even.")
    elseif standings > 0
        println("Collect your winnings from the H&M cashier.")
    end
end

print_credits()
print_instructions()
play()

In Kotlin

/*
Slots
    A slot machine simulation.

Original version in BASIC:
    Creative Computing (Morristown, New Jersey, USA).
    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

This version in Kotlin:
    Copyright (c) 2023, Marcos Cruz (programandala.net)
    SPDX-License-Identifier: Fair

Written in 2023-10.

Last modified: 20250519T0009+0200.
*/

import kotlin.time.*

// Terminal {{{1
// =============================================================

const val BLACK = 0
const val RED = 1
const val GREEN = 2
const val YELLOW = 3
const val BLUE = 4
const val MAGENTA = 5
const val CYAN = 6
const val WHITE = 7
const val DEFAULT = 9

const val FOREGROUND = +30
const val BRIGHT = +60

const val NORMAL = 0

// Move the cursor to the top left position of the terminal.
fun moveCursorHome() {
    print("\u001B[H")
}

// Clear the terminal and move the cursor to the top left position.
fun clear() {
    print("\u001B[2J")
    moveCursorHome()
}

// Make the cursor invisible.
fun hideCursor() {
    print("\u001B[?25l")
}

// Make the cursor visible.
fun showCursor() {
    print("\u001B[?25h")
}

// Set the color.
fun setColor(color: Int) {
    print("\u001B[${color}m")
}

// Set the attribute.
fun setAttribute(attr: Int) {
    print("\u001B[0;${attr}m")
}

// Global variables and constants {{{1
// =============================================================

var image = arrayOf<String>(" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY")
const val BAR = 0 // position of "BAR" in `image`.
var color = arrayOf<Int>(
    WHITE + FOREGROUND,
    CYAN + FOREGROUND,
    YELLOW + FOREGROUND,
    BRIGHT + YELLOW + FOREGROUND,
    BRIGHT + WHITE + FOREGROUND,
    BRIGHT + RED + FOREGROUND )
const val MAX_BET = 100
const val MIN_BET = 1

var reel = mutableListOf<Int>(0, 0, 0)

// User input {{{1
// =============================================================

fun pressEnter(prompt: String) {
    print(prompt)
    readln()
}

// Accept and return a valid integer, or zero.
fun getNumber(prompt: String): Int {
    try {
        print(prompt)
        return readln().toInt()
    }
    catch (e: Exception) { return 0 }
}

// Credits, instructions {{{1
// =============================================================

fun printCredits() {
    clear()
    println("Slots")
    println("A slot machine simulation.\n")
    println("Original version in BASIC:")
    println("    Creative computing (Morristown, New Jersey, USA).")
    println("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n")
    println("This version in Kotlin:")
    println("    Copyright (c) 2023, Marcos Cruz (programandala.net)")
    println("    SPDX-License-Identifier: Fair\n")
    pressEnter("Press Enter for instructions.")
}

fun printInstructions() {
    clear()
    println("You are in the H&M casino, in front of one of our")
    println("one-arm bandits. Bet from $MIN_BET to $MAX_BET USD (or 0 to quit).\n")
    pressEnter("Press Enter to start.")
}

// Main {{{1
// =============================================================

fun won(prize: Int, bet: Int): Int {
    when (prize) {
        2 -> println("DOUBLE!")
        5 -> println("*DOUBLE BAR*")
        10 -> println("**TOP DOLLAR**")
        100 -> println("***JACKPOT***")
    }
    println("You won!")
    return (prize + 1) * bet
}

fun showStandings(dollars: Int) {
    println("Your standings are $dollars USD.")
}

fun printReels() {
    moveCursorHome()
    for (r in reel) {
        setColor(color[r])
        print("[${image[r]}]")
    }
    setAttribute(NORMAL)
    println("")
}

fun initReels() {
    for (i in reel.indices) {
        reel[i] = image.indices.random()
    }
}

fun spinReels() {
    val duration: Duration = 2.toDuration(DurationUnit.SECONDS)
    val timeSource = TimeSource.Monotonic
    val startTime = timeSource.markNow()
    hideCursor()
    do {
        initReels()
        printReels()
        var currentTime = timeSource.markNow()
    } while ((currentTime - startTime) < duration)
    showCursor()
}

fun play() {
    var bet: Int
    var standings = 0
    initReels()
    playLoop@ while (true) {
        betLoop@ while (true) {
            clear()
            printReels()
            bet = getNumber("Your bet (or 0 to quit): ")
            when (true) {
                (bet > MAX_BET) -> {
                    println("House limits are $MAX_BET USD.")
                    pressEnter("Press Enter to try again.")
                }
                (bet < MIN_BET) -> {
                    println("Type \"q\" to confirm you want to quit.")
                    var confirm = readln()
                    if (confirm.lowercase() == "q") {
                        break@playLoop
                    }
                }
                else -> break@betLoop
            } // bet check
        } // bet loop
        clear()
        spinReels()
        var bars = 0 // counter
        for (i in reel.indices) {
            bars += if (reel[i] == BAR) 1 else 0
        }
        when (reel.distinct().count()) {
            1 ->
                if (bars == 3) {
                    standings += won(100, bet)
                } else {
                    standings += won(10, bet)
                }
            2 ->
                if (bars == 2) {
                    standings += won(5, bet)
                } else {
                    standings += won(2, bet)
                }
            else -> {
                println("You lost.")
                standings -= bet
            }
        } // prize check
        showStandings(standings)
        pressEnter("Press Enter to continue.")
    } // play loop
    showStandings(standings)
    when {
        (standings < 0) ->
            println("Pay up!  Please leave your money on the terminal.")
        (standings == 0) ->
            println("Hey, you broke even.")
        (standings > 0) ->
            println("Collect your winnings from the H&M cashier.")
    }
}

fun main() {
    printCredits()
    printInstructions()
    play()
}

In Nim

#[
Slots
  A slot machine simulation.

Original version in BASIC:
  Creative Computing (Morristown, New Jersey, USA).
  Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

This version in Nim:
  Copyright (c) 2025, Marcos Cruz (programandala.net)
  SPDX-License-Identifier: Fair

Written on 2025-01-21.

Last modified: 20250404T0159+0200.
]#

import std/monotimes
import std/random
import std/sequtils
import std/strutils
import std/terminal
import std/times
import std/unicode

const reels = 3
const images = 6
const image: array[images, string] = [" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"]
const bar = 0 # position of "BAR" in `image`.
const colors = images

type ImageColor = tuple [
  foreground: ForegroundColor,
  bright: bool,
  ]

var color: array[colors, ImageColor] = [
  (fgWhite, false),
  (fgCyan, false),
  (fgYellow, false),
  (fgYellow, true),
  (fgWhite, true),
  (fgRed, true),
  ]

const maxBet = 100
const minBet = 1

proc cursorHome() =
  setCursorPos(0, 0)

proc clearScreen() =
  eraseScreen()
  cursorHome()

proc pressEnter(prompt: string) =
  write(stdout, prompt)
  discard readLine(stdin)

proc printCredits() =
  clearScreen()
  writeLine(stdout, "Slots")
  writeLine(stdout, "A slot machine simulation.\n")
  writeLine(stdout, "Original version in BASIC:")
  writeLine(stdout, "    Creative computing (Morristown, New Jersey, USA).")
  writeLine(stdout, "    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n")
  writeLine(stdout, "This version in Nim:")
  writeLine(stdout, "    Copyright (c) 2025, Marcos Cruz (programandala.net)")
  writeLine(stdout, "    SPDX-License-Identifier: Fair\n")
  pressEnter("Press Enter for instructions.")

proc printInstructions() =
  clearScreen()
  writeLine(stdout, "You are in the H&M casino, in front of one of our")
  write(stdout, "one-arm bandits. Bet from ", minBet, " to ", maxBet, " USD (or 0 to quit).\n\n")
  pressEnter("Press Enter to start.")

proc won(prize: int, bet: int): int =
  case prize:
  of   2: writeLine(stdout, "DOUBLE!")
  of   5: writeLine(stdout, "*DOUBLE BAR*")
  of  10: writeLine(stdout, "**TOP DOLLAR**")
  of 100: writeLine(stdout, "***JACKPOT***")
  else: discard
  writeLine(stdout, "You won!")
  result = (prize + 1) * bet

proc showStandings(usd: int) =
  writeLine(stdout, "Your standings are ", usd, " USD.")

proc printReels(reel: array[reels, int]) =
  cursorHome()
  for r in reel:
    write(stdout, ansiForegroundColorCode(color[r].foreground, color[r].bright))
    write(stdout, "[", image[r], "] ")
  resetAttributes(stdout)
  writeLine(stdout, "")

proc initReels(reel: var array[reels, int]) =
  for i in 0 ..< reels:
    reel[i] = rand(0 ..< images)

proc spinReels(reel: var array[reels, int]) =
  const milliseconds = 1500
  hideCursor()
  var start = getMonoTime()
  while inMilliseconds(getMonoTime() - start) < milliseconds:
    initReels(reel)
    printReels(reel)
  showCursor()

# Return the number of equals and bars in the given `reel` array.
#
proc prize(reel: array[reels, int]): (int, int) =
  var equals = reels - len(deduplicate(reel, isSorted = false))
  equals += int(equals > 0)
  var bars = count(reel, bar)
  result = (equals, bars)

proc readIntOrZero(prompt: string): int =
  while true:
    try:
      write(stdout, prompt)
      result = parseInt(readLine(stdin))
      break
    except ValueError:
      result = 0

proc play() =

  var standings = 0
  var bet = 0
  var reel: array[reels, int] = [1, 2, 3]
  var equals = 0
  var bars = 0

  initReels(reel)

  block playing:
    while true: # play loop

      while true: # bet loop

        clearScreen()
        printReels(reel)
        bet = readIntOrZero("Your bet (or 0 to quit): ")

        if bet > maxBet:
            writeLine(stdout, "House limits are ", maxBet, " USD.")
            pressEnter("Press Enter to try again.")
        elif bet < minBet:
            writeLine(stdout, "Type \"q\" to confirm you want to quit.")
            if toLower(readLine(stdin)) == "q":
              break playing
        else:
            break # bet loop

        # end of bet check

      clearScreen()
      spinReels(reel)
      (equals, bars) = prize(reel)
      case equals:
      of 3:
          if bars == 3:
            standings += won(100, bet)
          else:
            standings += won(10, bet)
      of 2:
          if bars == 2:
            standings += won(5, bet)
          else:
            standings += won(2, bet)
      else:
          writeLine(stdout, "You lost.")
          standings -= bet
      showStandings(standings)
      pressEnter("Press Enter to continue.")

      # end of bet loop

    # end of play loop

  # end of play block

  showStandings(standings)
  if standings < 0:
      writeLine(stdout, "Pay up!  Please leave your money on the terminal.")
  elif standings == 0:
      writeLine(stdout, "Hey, you broke even.")
  else:
      writeLine(stdout, "Collect your winnings from the H&M cashier.")

printCredits()
printInstructions()
play()

In Odin

/*
Slots
    A slot machine simulation.

Original version in BASIC:
    Creative Computing (Morristown, New Jersey, USA).
    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

This version in Odin:
    Copyright (c) 2023, 2024, 2025, Marcos Cruz (programandala.net)
    SPDX-License-Identifier: Fair

Written in 2023-09/10, 2024-04, 2024-05, 2024-12, 2025-04.

Last modified: 20250407T2030+0200.
*/

package slots

import "../lib/anodino/src/read"
import "../lib/anodino/src/term"
import "core:fmt"
import "core:math/rand"
import "core:time"

image   := []string{" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"}
BAR     :: 0 // position of "BAR" in `image`.
color   := []int{
    term.FOREGROUND + term.WHITE,
    term.FOREGROUND + term.CYAN,
    term.FOREGROUND + term.YELLOW,
    term.FOREGROUND + term.BRIGHT + term.YELLOW,
    term.FOREGROUND + term.BRIGHT + term.WHITE,
    term.FOREGROUND + term.BRIGHT + term.RED }
MAX_BET :: 100
MIN_BET :: 1

press_enter :: proc(prompt : string) {

    fmt.print(prompt)
    s, _ := read.a_string()
    delete(s)

}

print_credits :: proc() {

    term.clear_screen()
    fmt.println("Slots")
    fmt.println("A slot machine simulation.\n")
    fmt.println("Original version in BASIC:")
    fmt.println("    Creative computing (Morristown, New Jersey, USA).")
    fmt.println("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n")
    fmt.println("This version in Odin:")
    fmt.println("    Copyright (c) 2023, Marcos Cruz (programandala.net)")
    fmt.println("    SPDX-License-Identifier: Fair\n")
    press_enter("Press Enter for instructions.")

}

print_instructions :: proc() {

    term.clear_screen()
    fmt.println("You are in the H&M casino, in front of one of our")
    fmt.printf(
        "one-arm bandits. Bet from %v to %v USD (or 0 to quit).\n\n",
        MIN_BET, MAX_BET)
    press_enter("Press Enter to start.")

}

won :: proc(prize : int, bet : int) -> int {

    switch prize {
        case   2 : fmt.println("DOUBLE!")
        case   5 : fmt.println("*DOUBLE BAR*")
        case  10 : fmt.println("**TOP DOLLAR**")
        case 100 : fmt.println("***JACKPOT***")
    }
    fmt.println("You won!")
    return (prize + 1) * bet

}

show_standings :: proc(usd : int) {

    fmt.printfln("Your standings are %v USD.", usd)

}

print_reels :: proc(reel : ^[]int) {

    term.move_cursor_home()
    for r in reel {
        term.set_color(color[r])
        fmt.printf("[%v] ", image[r])
    }
    term.set_attribute(term.NORMAL)
    fmt.println("")

}

init_reels :: proc(reel : ^[]int) {

    images := len(image)
    for _, i in reel {
        reel[i] = int(rand.int31_max(i32(images)))
    }

}

spin_reels :: proc(reel : ^[]int) {

    DURATION_IN_SECONDS :: 2
    term.hide_cursor()
    first_second := time.to_unix_seconds(time.now())
    for (time.to_unix_seconds(time.now()) - first_second) < DURATION_IN_SECONDS {
        init_reels(reel)
        print_reels(reel)
    }
    term.show_cursor()

}

// Return the number of equals and bars in the given `reel` array.
//
prize :: proc(reel : ^[]int) -> (equals : int, bars : int) {

    for i in 0 ..< len(image) {
        count := 0;
        for r in 0 ..< len(reel) {
            count += int(reel[r] == i)
        }
        equals = max(equals, count)
    }

    for r in 0 ..< len(reel) {
        bars += int(reel[r] == BAR)
    }

    return equals, bars

}

play :: proc() {

    standings := 0
    bet := 0
    reel := []int{0, 0, 0}
    equals := 0
    bars := 0
    init_reels(&reel)
    play_loop: for {
        bet_loop: for {
            term.clear_screen()
            print_reels(&reel)
            fmt.print("Your bet (or 0 to quit): ")
            bet = read.an_int_or_0()
            switch {
                case bet > MAX_BET :
                    fmt.printfln("House limits are %v USD.", MAX_BET)
                    press_enter("Press Enter to try again.")
                case bet < MIN_BET :
                    fmt.println("Type \"q\" to confirm you want to quit.")
                    confirm, _ := read.a_string()
                    defer delete(confirm)
                    if confirm == "q" {
                        break play_loop
                    }
                case :
                    break bet_loop
            } // bet check
        } // bet loop
        term.clear_screen()
        spin_reels(&reel)
        equals, bars = prize(&reel)
        switch equals {
            case 3 :
                if bars == 3 {
                    standings += won(100, bet)
                } else {
                    standings += won(10, bet)
                }
            case 2 :
                if bars == 2 {
                    standings += won(5, bet)
                } else {
                    standings += won(2, bet)
                }
            case :
                fmt.println("You lost.")
                standings -= bet
        } // prize check
        show_standings(standings)
        press_enter("Press Enter to continue.")
    } // play loop
    show_standings(standings)
    switch {
        case standings < 0 :
            fmt.println("Pay up!  Please leave your money on the terminal.")
        case standings == 0 :
            fmt.println("Hey, you broke even.")
        case standings > 0 :
            fmt.println("Collect your winnings from the H&M cashier.")
    }

}

main :: proc() {

    print_credits()
    print_instructions()
    play()

}

In Pike

#!/usr/bin/env pike

// Slots
//  A slot machine simulation.

// Original version in BASIC:
//  Creative Computing (Morristown, New Jersey, USA).
//  Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

// This version in Pike:
//  Copyright (c) 2025, Marcos Cruz (programandala.net)
//  SPDX-License-Identifier: Fair
//
// Written on 2025-03-11.
//
// Last modified: 20250324T2051+0100.

// Terminal {{{1
// =============================================================================

constant BLACK = 0;
constant RED = 1;
constant GREEN = 2;
constant YELLOW = 3;
constant BLUE = 4;
constant MAGENTA = 5;
constant CYAN = 6;
constant WHITE = 7;
constant DEFAULT = 9;

constant STYLE_OFF = 20;
constant FOREGROUND = 30;
constant BACKGROUND = 40;
constant BRIGHT = 60;

constant NORMAL_STYLE = 0;

void move_cursor_home() {
    write("\x1B[H");
}

void hide_cursor() {
    write("\x1B[?25l");
}

void show_cursor() {
    write("\x1B[?25h");
}

void set_style(int style) {
    write("\x1B[%dm", style);
}

void reset_attributes() {
    set_style(NORMAL_STYLE);
}

void erase_screen() {
    write("\x1B[2J");
}

void clear_screen() {
    erase_screen();
    reset_attributes();
    move_cursor_home();
}

// Data {{{1
// =============================================================================

constant REELS = 3;

array(string) image = ({" BAR  ", " BELL ", "ORANGE", "LEMON ", " PLUM ", "CHERRY"});
constant BAR = 0; // position of "BAR" in `image`.
array(int) color = ({
    FOREGROUND + WHITE,
    FOREGROUND + CYAN,
    FOREGROUND + YELLOW,
    FOREGROUND + BRIGHT + YELLOW,
    FOREGROUND + BRIGHT + WHITE,
    FOREGROUND + BRIGHT + RED });
constant MAX_BET = 100;
constant MIN_BET = 1;

// User input {{{1
// =============================================================================

string accept_string(string prompt) {
    write(prompt);
    return Stdio.stdin->gets();
}

int accept_integer(string prompt) {
    // NB The casting accepts any valid integer at the start of the string
    // and ignores the rest;  if no valid integer is found at the start of
    // the string, zero is returned.
    return (int) accept_string(prompt);
}

// Credits and instructions {{{1
// =============================================================================

void print_credits() {
    clear_screen();
    write("Slots\n");
    write("A slot machine simulation.\n\n");
    write("Original version in BASIC:\n");
    write("    Creative computing (Morristown, New Jersey, USA).\n");
    write("    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n\n");
    write("This version in Pike:\n");
    write("    Copyright (c) 2025, Marcos Cruz (programandala.net)\n");
    write("    SPDX-License-Identifier: Fair\n\n");
    accept_string("Press Enter for instructions. ");
}

void print_instructions() {
    clear_screen();
    write("You are in the H&M casino, in front of one of our\n");
    write("one-arm bandits. Bet from %d to %d USD (or 0 to quit).\n\n",
        MIN_BET, MAX_BET);
    accept_string("Press Enter to start. ");
}

// Game {{{1
// =============================================================================

int won(int prize, int bet) {
    switch (prize) {
        case 2:
            write("DOUBLE!\n");
            break;
        case 5:
            write("*DOUBLE BAR*\n");
            break;
        case 10:
            write("**TOP DOLLAR**\n");
            break;
        case 100:
            write("***JACKPOT***\n");
    }
    write("You won!\n");
    return (prize + 1) * bet;
}

void show_standings(int usd) {
    write("Your standings are %d USD.\n", usd);
}

void print_reels(array(int) reel) {
    move_cursor_home();
    foreach (reel, int r) {
        set_style(color[r]);
        write("[%s] ", image[r]);
    }
    set_style(NORMAL_STYLE);
    write("\n");
}

void init_reels(array(int) reel) {
    int images = (sizeof(image));
    for (int i = 0; i < sizeof(reel); i += 1) {
        reel[i] = random(images);
    }
}

void spin_reels(array(int) reel) {
    constant DURATION_IN_SECONDS = 2;
    hide_cursor();
    int first_second = time();
    while (time() - first_second < DURATION_IN_SECONDS) {
        init_reels(reel);
        print_reels(reel);
    }
    show_cursor();
}

void play() {

    int standings = 0;
    int bet = 0;
    array(int) reel = allocate(REELS);
    int equals = 0;
    int bars = 0;

    init_reels(reel);

    play_loop: while (true) {

        bet_loop: while (true) {
            clear_screen();
            print_reels(reel);
            bet = accept_integer("Your bet (or 0 to quit): ");
            if (bet > MAX_BET) {
                write("House limits are %d USD.\n", MAX_BET);
                accept_string("Press Enter to try again. ");
            } else if (bet < MIN_BET) {
                string confirmation = accept_string("Type \"q\" to confirm you want to quit. ");
                if (confirmation == "q" || confirmation == "Q") {
                    break play_loop;
                }
            } else {
                break bet_loop;
            } // bet check

        } // bet loop

        clear_screen();
        spin_reels(reel);
        equals = sizeof(reel) - sizeof(Array.uniq(reel));
        equals += (equals > 0);
        bars = Array.count(reel, BAR);

        switch (equals) {
            case 3:
                if (bars == 3) {
                    standings += won(100, bet);
                } else {
                    standings += won(10, bet);
                }
                break;
            case 2:
                if (bars == 2) {
                    standings += won(5, bet);
                } else {
                    standings += won(2, bet);
                }
                break;
            default:
                write("You lost.\n");
                standings -= bet;
        } // prize check

        show_standings(standings);
        accept_string("Press Enter to continue. ");

    } // play loop

    show_standings(standings);

    if (standings < 0) {
        write("Pay up!  Please leave your money on the terminal.\n");
    } else if (standings > 0) {
        write("Collect your winnings from the H&M cashier.\n");
    } else {
        write("Hey, you broke even.\n");
    }

}

// Main {{{1
// =============================================================================

void main() {
    print_credits();
    print_instructions();
    play();
}

In Raku

# Slots
#   A slot machine simulation.
#
# Original version in BASIC:
#   Creative Computing (Morristown, New Jersey, USA).
#   Produced by Fred Mirabelle and Bob Harper on 1973-01-29.
#
# This version in Raku:
#   Copyright (c) 2024, Marcos Cruz (programandala.net)
#   SPDX-License-Identifier: Fair
#
# Written in 2024-12.
#
# Last modified: 20241211T1519+0100.

# Terminal {{{1
# ==============================================================

constant $BLACK = 0;
constant $RED = 1;
constant $GREEN = 2;
constant $YELLOW = 3;
constant $BLUE = 4;
constant $MAGENTA = 5;
constant $CYAN = 6;
constant $WHITE = 7;
constant $DEFAULT = 9;

constant $STYLE_OFF = +20;
constant $FOREGROUND = +30;
constant $BACKGROUND = +40;
constant $BRIGHT = +60;

constant $NORMAL = 0;
constant $RESET_ALL = $NORMAL;
constant $BOLD = 1;
constant $DIM = 2;
constant $ITALIC = 3;
constant $UNDERLINE = 4;
constant $UNDERSCORE = $UNDERLINE;
constant $BLINK = 5;
constant $OVERLINE = 6;
constant $RAPID_BLINK = $OVERLINE;
constant $INVERT = 7;
constant $REVERSE = $INVERT;
constant $HIDDEN = 8;
constant $CROSSED_OUT = 9;
constant $STRIKE = $CROSSED_OUT;

constant $NO_STYLE = $STYLE_OFF;

# Move the cursor to the home position.
sub move_cursor_home {

    print "\e[H";

}

# Erase the screen.
sub erase_screen {

    print "\e[2J";

}

# Reset the attributes.
sub reset_attributes {

    set_color($RESET_ALL);

}

# Erase the screen, reset the attributes and move the cursor to the home position.
sub clear_screen {

    erase_screen;
    reset_attributes;
    move_cursor_home;

}

# Set the color.
sub set_color(Int $color) {

    print "\e[{$color}m";

}

# Set the attribute.
sub set_attribute(Int $attr) {

    print "\e[0;{$attr}m";

}

# Make the cursor invisible.
sub hide_cursor {

    print "\e[?25l";

}

# Make the cursor visible.
sub show_cursor {

    print "\e[?25h";

}

# Globals {{{1
# ==============================================================

constant @image = (' BAR  ', ' BELL ', 'ORANGE', 'LEMON ', ' PLUM ', 'CHERRY');
constant $BAR = 0; # position of "BAR" in `image`.

constant @color = (
    $FOREGROUND + $WHITE,
    $FOREGROUND + $CYAN,
    $FOREGROUND + $YELLOW,
    $FOREGROUND + $BRIGHT + $YELLOW,
    $FOREGROUND + $BRIGHT + $WHITE,
    $FOREGROUND + $BRIGHT + $RED);

constant $MAX_BET = 100;
constant $MIN_BET = 1;

# Info {{{1
# ==============================================================

sub print_credits {

    clear_screen;
    put 'Slots';
    put "A slot machine simulation.\n";
    put 'Original version in BASIC:';
    put '    Creative computing (Morristown, New Jersey, USA).';
    put "    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n";
    put 'This version in Raku:';
    put '    Copyright (c) 2024, Marcos Cruz (programandala.net)';
    put "    SPDX-License-Identifier: Fair\n";
    prompt 'Press Enter for instructions.';

}

sub print_instructions {

    clear_screen;
    put 'You are in the H&M casino, in front of one of our';
    put "one-arm bandits. Bet from $MIN_BET to $MAX_BET USD (or 0 to quit).\n\n";
    prompt 'Press Enter to start.';

}

# Main {{{1
# ==============================================================

sub won(Int $prize, Int $bet --> Int) {

    given $prize {
        when 2  { put 'DOUBLE!' };
        when 5  { put '*DOUBLE BAR*' };
        when 10  { put '**TOP DOLLAR**' };
        when 100  { put '***JACKPOT***' };
    };
    put 'You won!';
    return ($prize + 1) * $bet;

}

sub show_standings(Int $usd) {

    print "Your standings are $usd USD.\n";

}

sub print_reels(@reel) {

    move_cursor_home;
    for @reel -> $r {
        set_color(@color[$r]);
        print "[@image[$r]]";
    }
    set_attribute($NORMAL);
    put '';

}

sub init_reels(@reel) {

    my $images = @image.elems;
    for 0 ..^ @reel.elems -> $i {
        @reel[$i] = (0 ..^ $images).pick;
    }

}

sub spin_reels(@reel) {

    constant $SECONDS = 2;
    my $first_second = now;

    hide_cursor;
    while (now - $first_second) < $SECONDS {
        init_reels(@reel);
        print_reels(@reel);
        sleep 0.1
    }
    show_cursor;

}

# Return the number of repeated elements in the given list.
#
sub repeated(@list) {

    my $count = @list.repeated.elems;
    return $count > 0 ?? $count + 1 !! 0;

}

# Return the number of equals and bars in the given `reel` array.
#
sub prize(@reel) {

    my $equals = repeated(@reel);
    my $bars = repeated(grep $BAR, @reel);
    return ($equals, $bars);

}

sub prompt_number(Str $prompt --> Int) {

    my Int $n;

    loop {
        try {
            $n = (+prompt $prompt).Int;
            CATCH {
                default {
                    return 0;
                }
            }
        }
        last;
    }
    return $n;

}

sub play {

    my $standings = 0;
    my $bet = 0;
    my @reel = (0, 0, 0);
    my $equals = 0;
    my $bars = 0;

    init_reels(@reel);

    PLAY: loop {

        BET: loop {
            clear_screen;
            print_reels(@reel);
            $bet = prompt_number('Your bet (or 0 to quit): ');
            if $bet > $MAX_BET {
                print "House limits are $MAX_BET USD.\n";
                prompt 'Press Enter to try again.';
            } elsif $bet < $MIN_BET  {
                if (prompt "Type \"q\" to confirm you want to quit.").lc eq 'q' {
                    last PLAY;
                }
            } else {
                last BET;
            }
        }

        clear_screen;
        spin_reels(@reel);
        ($equals, $bars) = prize(@reel);

        given $equals {
            when 3  {
                if $bars == 3 {
                    $standings += won(100, $bet);
                } else {
                    $standings += won(10, $bet);
                }
            }
            when 2  {
                if $bars == 2 {
                    $standings += won(5, $bet);
                } else {
                    $standings += won(2, $bet);
                }
            }
            default {
                put 'You lost.';
                $standings -= $bet;
            }
        } # prize check
        show_standings($standings);
        prompt 'Press Enter to continue.';
    } # play loop

    show_standings($standings);

    if $standings < 0  {
        put 'Pay up!  Please leave your money on the terminal.';
    } elsif $standings == 0  {
        put 'Hey, you broke even.';
    } elsif $standings > 0  {
        put 'Collect your winnings from the H&M cashier.';
    }

}

print_credits;
print_instructions;
play;

In V

/*
Slots
    A slot machine simulation.

Original version in BASIC:
    Creative Computing (Morristown, New Jersey, USA).
    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.

This version in V:
    Copyright (c) 2023, Marcos Cruz (programandala.net)
    SPDX-License-Identifier: Fair

Last modified 20250406T0123+0200.
*/
import arrays
import os
import rand
import readline
import strconv
import term

const image = [' BAR  ', ' BELL ', 'ORANGE', 'LEMON ', ' PLUM ', 'CHERRY']
const bar = 0 // position of 'BAR' in `image`.

const images = image.len

const max_bet = 100
const min_bet = 1

fn utf8_keypress() rune {
    mut rl := readline.Readline{}
    rl.enable_raw_mode_nosig()
    defer {
        rl.disable_raw_mode()
    }
    return term.utf8_getchar() or { ` ` }
}

fn press(this string) rune {
    print('Press ${this}')
    return utf8_keypress()
}

fn credits() {
    term.clear()
    println('Slots')
    println('A slot machine simulation.\n')
    println('Original version in BASIC:')
    println('    Creative computing (Morristown, New Jersey, USA).')
    println('    Produced by Fred Mirabelle and Bob Harper on 1973-01-29.\n')
    println('This version in V:')
    println('    Copyright (c) 2023, Marcos Cruz (programandala.net)')
    println('    SPDX-License-Identifier: Fair\n')
    _ = press('any key for instructions. ')
}

fn instructions() {
    term.clear()
    println('You are in the H&M casino, in front of one of our')
    println('one-arm bandits. Bet from ${min_bet} to ${max_bet} USD (or 0 to quit).\n')
    _ = press('any key to start. ')
}

fn won(prize int, bet int) int {
    match prize {
        2 { println('DOUBLE!') }
        5 { println('*DOUBLE BAR*') }
        10 { println('**TOP DOLLAR**') }
        100 { println('***JACKPOT***') }
        else {}
    }
    println('You won!')
    return (prize + 1) * bet
}

fn show_standings(usd int) {
    println('Your standings are ${usd} USD.')
}

fn home() {
    term.set_cursor_position(x: 0, y: 0)
}

fn display_reels(reel []int) {
    color := [
        term.white,
        term.cyan,
        term.yellow,
        term.bright_yellow,
        term.bright_white,
        term.bright_red,
    ]
    home()
    for i in reel {
        print('[${color[i](image[i])}] ')
    }
    println('')
}

fn reel_image(default int) int {
    return rand.intn(images) or { default }
}

fn init_reels(mut reel []int) {
    for i, _ in reel {
        reel[i] = reel_image(i)
    }
}

fn spin_reels(mut reel []int) {
    term.hide_cursor()
    for spin := 0; spin < 24000; spin += 1 {
        for i, _ in reel {
            reel[i] = reel_image(i)
        }
        display_reels(reel)
    }
    term.show_cursor()
}

fn play() {
    mut standings := 0
    mut bet := 0
    mut reel := [0, 0, 0]
    init_reels(mut reel)
    play: for {
        for {
            term.clear()
            display_reels(reel)
            bet = strconv.atoi(os.input('Your bet (or 0 to quit): ')) or { 0 }
            match true {
                bet > max_bet {
                    println('House limits are ${max_bet} USD.')
                    _ = press('any key to try again. ')
                }
                bet < min_bet {
                    if press('"q" to confirm you want to quit. ') == `q` {
                        break play
                    }
                }
                else {
                    break
                }
            } // bet match
        } // bet loop
        term.clear()
        spin_reels(mut reel)
        equals := arrays.uniq_all_repeated(reel.sorted()).len
        bars := reel.count(it == bar)
        match true {
            equals == 3 {
                if bars == 3 {
                    standings += won(100, bet)
                } else {
                    standings += won(10, bet)
                }
            }
            equals == 2 {
                if bars == 2 {
                    standings += won(5, bet)
                } else {
                    standings += won(2, bet)
                }
            }
            else {
                println('You lost.')
                standings -= bet
            }
        } // prize match
        show_standings(standings)
        _ = press('any key to continue.')
    } // play loop
    show_standings(standings)
    match true {
        standings < 0 {
            println('Pay up!  Please leave your money on the terminal.')
        }
        standings == 0 {
            println('Hey, you broke even.')
        }
        standings > 0 {
            println('Collect your winnings from the H&M cashier.')
        }
        else {}
    }
}

fn main() {
    credits()
    instructions()
    play()
}

Related pages

Basics off
Metaproject about the "Basics of…" projects.

External related links