Basics of Arturo

Priskribo de la ĉi-paĝa enhavo

Konverto de malnovaj BASIC-programoj al Arturo por lerni la fundamentojn de ĉi-tiu lingvo.

Etikedoj:

3D Plot

; 3D Plot

; Original version in BASIC:
;   3-D Plot (by Mark Bramhall), 1978.
;   Creative Computing's BASIC Games.
;   - http://vintage-basic.net/games.html
;   - http://vintage-basic.net/bcg/3dplot.bas
;   - https://www.atariarchives.org/basicgames/showpage.php?page=167

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

SPACE: ` `
DOT: `*`
WIDTH: 56

; Display the credits and wait for a keypress.
printCredits: function [] [
    print "3D Plot\n"
    print "Original version in BASIC:"
    print "    Creative computing (Morristown, New Jersey, USA), ca. 1980.\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    input "Press Enter to start the program."
]

a: function [z] [
    mul 30 exp div (mul neg z z) 100
]

draw: function [] [
    x: neg 30
    while [not? greater? x 30] [
        line: array.of: WIDTH SPACE
        l: 0
        y1: mul 5 floor div sqrt(sub 900 (mul x x)) 5
        loop y1 .. (neg y1) .step: 5 'y [
            z: floor (add 25 sub a(sqrt(add mul x x mul y y)) (mul 0.7 y))
            if greater? z l [
                l: z
                line\[z]: DOT
            ]
        ] ; y loop
        loop 0 .. (sub WIDTH 1) 'pos [
            prints line\[pos]
        ]
        print ""
        add 'x 1.5
    ] ; x loop
]

clear
printCredits
clear
draw

Bagels

; Bagels

; Original version in BASIC:
;   D. Resek, P. Rowe, 1978.
;   Creative Computing's BASIC Games.
;   - http://vintage-basic.net/games.html
;   - http://vintage-basic.net/bcg/bagels.bas
;   - http://www.atariarchives.org/basicgames/showpage.php?page=9

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

; Clear the screen, print the credits and wait for a keypress.
printCredits: function [] [
    clear
    print "Bagels"
    print "Number guessing game\n"
    print "Original source unknown but suspected to be:"
    print "    Lawrence Hall of Science, U.C. Berkely.\n"
    print "Original version in BASIC:"
    print "    D. Resek, P. Rowe, 1978."
    print "    Creative computing (Morristown, New Jersey, USA), 1978.\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    input "Press Enter to read the instructions. "
]

; Clear the screen, print the instructions and wait for a keypress.
printInstructions: function [] [
    clear
    print "Bagels"
    print "Number guessing game\n"
    print "I am thinking of a three-digit number that has no two digits the same."
    print "Try to guess it and I will give you clues as follows:\n"
    print "   PICO   - one digit correct but in the wrong position"
    print "   FERMI  - one digit correct and in the right position"
    print "   BAGELS - no digits correct\n"
    input "Press Enter to start. "
]

DIGITS: 3

randomDigit: array [0 0 0]

; Return an integer array with random digits.
randomNumber: function [] [
    number: array []
    while [ less? size number DIGITS ] [
        digit: random 0 9
        if not? contains? number digit [
            append 'number digit
        ]
    ]
    number
]

; Print the given prompt and get a three-digit number from the user.
userInput: function [prompt] [
    userDigit: array []
    while [ less? size userDigit DIGITS ] [
        inputString: input prompt
        if? less? size inputString DIGITS [
            print ~"Remember it's a |DIGITS|-digit number."
        ] else [
            empty 'userDigit
            loop inputString 'char [
                if? contains? "0123456789" char [
                    digit: to :integer to :string char
                    if? contains? userDigit digit [
                        print "Remember my number has no two digits the same."
                        break
                    ] else [
                        append 'userDigit digit
                    ]
                ] else [
                    print "What?"
                    break
                ]
            ]
        ]
    ]
    userDigit
]

; Return `true` if the given string is "yes" or a synonym.
isYes: function [answer] [
    contains? ["ok", "yeah", "yes", "y"] answer
]

; Return `true` if the given string is "no" or a synonym.
isNo: function [answer] [
    contains? ["no", "nope", "n"] answer
]

; Print the given prompt, wait until the user enters a valid yes/no
; string, and return `true` for "yes" or `false` for "no".
yes: function [prompt] [
    answer: ""
    while [ not? or? isYes answer isNo answer ] [ answer: input prompt ]
    isYes answer
]

; Init and run the game loop.
play: function [] [
    maxTries: 20
    score: 0
    while [ true ] [
        clear
        computerNumber: randomNumber
        print "O.K.  I have a number in mind."
        loop range 1 maxTries [ 'guess ] [
            userNumber: userInput(~"Guess #|pad .with:`0` to :string guess 2 |: ")
            fermi: 0
            pico: 0
            loop range 0 sub DIGITS 1 [ 'i ] [
                loop range 0 sub DIGITS 1 [ 'j ] [
                    if equal? userNumber\[i] computerNumber\[j] [
                        if? equal? i j [ add 'fermi 1 ]
                        else           [ add 'pico  1 ]
                    ]
                ]
            ]
            prints repeat "PICO " pico
            prints repeat "FERMI " fermi
            if equal? add pico fermi 0 [ prints "BAGELS" ]
            print ""
            if equal? fermi DIGITS [ break ]
        ]
        if? equal? fermi DIGITS [
            print "You got it!!!"
            inc score
        ] else [
            print "Oh well."
            prints ~"That's |maxTries| guesses.  My number was "
            loop range 0 sub DIGITS 1 [ 'i ] [ prints computerNumber\[i] ]
            print "."
        ]
        if not? yes("Play again? ") [ break ]
    ]
    if notEqual? score 0 [
        print ~"A |score|-point bagels, buff!!"
    ]
    print "Hope you had fun.  Bye."
]

printCredits
printInstructions
play

Bug

; Bug

; Original version in BASIC:
;   Brian Leibowitz, 1978.
;   Creative Computing's BASIC Games.
;   - http://vintage-basic.net/games.html
;   - http://vintage-basic.net/bcg/bug.bas
;   - https://www.atariarchives.org/basicgames/showpage.php?page=30
;   - http://www.retroarchive.org/cpm/games/ccgames.zip

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

bugRecord: dictionary [
    body: false
    neck: false
    head: false
    feelers: 0
    feelerType: ' '
    tail: false
    legs: 0
]

playerRecord: dictionary [
    pronoun: ""
    possessive: ""
    bug: bugRecord
]

; Players.
computer: new playerRecord
computer\bug: new bugRecord
human: new playerRecord
human\bug: new bugRecord

; Bug body parts.
partNumber: dictionary [
    body: 1
    neck: 2
    head: 3
    feeler: 4
    tail: 5
    leg: 6
]

partName: array [
    ""
    "body"
    "neck"
    "head"
    "feeler"
    "tail"
    "leg"
]

; Bug body attributes.
bodyHeight: 2
feelerLength: 4
legLength: 2
maxFeelers: 2
maxLegs: 6
neckLength: 2

; Move the cursor up by the given number of rows (defaults to 1), without
; changing the column position.
cursorUp: function [ rows ] [
    prints render "\e[|rows|A"
]

; Erase the current line, without moving the cursor position.
eraseLine: function [ ] [
    prints "\e[2K"
]

; Move the cursor to the previous row, without changing the column position,
; and erase its line.
erasePreviousLine: function [ ] [
    cursorUp 1
    eraseLine
]

; Clear the screen, display the credits and wait for a keypress.
printCredits: function [ ] [
    clear
    print "Bug\n"
    print "Original version in BASIC:"
    print "    Brian Leibowitz, 1978."
    print "    Creative computing (Morristown, New Jersey, USA), 1978.\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    input "Press Enter to read the instructions. "
]

instructions: {:
The object is to finish your bug before I finish mine. Each number
stands for a part of the bug body.

I will roll the die for you, tell you what I rolled for you, what the
number stands for, and if you can get the part. If you can get the
part I will give it to you. The same will happen on my turn.

If there is a change in either bug I will give you the option of
seeing the pictures of the bugs. The numbers stand for parts as
follows:
:}

; Capitalize the first character of `s` and convert the rest of `s` to
; lowercase.
toCapital: function [ s ] [
    capitalize lower s
]

; ; Print a table with the bug parts' description.
printPartsTable: function [ ] [

    columns: 3
    columnWidth: 8
    columnSeparation: 2

    ; Headers
    header: [ "Number" "Part" "Quantity" ]
    loop range 0 sub columns 1  'i [
        prints pad .right header\[ i ] add columnWidth columnSeparation
    ]
    print ""

    ; Rulers
    loop range 1 columns 'i [
        prints repeat "-" columnWidth
        if? less? i columns [ prints repeat " " columnSeparation ]
    ]
    print ""

    ; Data
    partQuantity: array .of: add size partNumber 1 0
    partQuantity\[ partNumber\body ]: 1
    partQuantity\[ partNumber\neck ]: 1
    partQuantity\[ partNumber\head ]: 1
    partQuantity\[ partNumber\feeler ]: 2
    partQuantity\[ partNumber\tail ]: 1
    partQuantity\[ partNumber\leg ]: 6
    loop range partNumber\body partNumber\leg 'part [
        prints pad .right to :string part add columnWidth columnSeparation
        prints pad .right toCapital partName\[part] add columnWidth columnSeparation
        print partQuantity\[ part ]
    ]

]

; Clear the screen, print the instructions and wait for a keypress.
printInstructions: function [ ] [
    clear
    print "Bug"
    print instructions
    printPartsTable
    input "\nPress Enter to start. "
]

; Print a bug head.
printHead: function [ ] [
    print "        HHHHHHH"
    print "        H     H"
    print "        H O O H"
    print "        H     H"
    print "        H  V  H"
    print "        HHHHHHH"
]

; Print the given bug.
printBug: function [ bug ] [
    if greater? bug\feelers 0 [
        loop range 0 sub feelerLength 1  'i [
            prints "        "
            loop range 0 sub bug\feelers 1  'j [
                prints render " |bug\feelerType|"
            ]
            print ""
        ]
    ]
    if bug\head [
        printHead
    ]
    if bug\neck [
        loop range 0 sub neckLength 1  'i [
            print "          N N"
        ]
    ]
    if bug\body [
        print "     BBBBBBBBBBBB"
        loop range 0 sub bodyHeight 1  'i [
            print "     B          B"
        ]
        if bug\tail [
            print "TTTTTB          B"
        ]
        print "     BBBBBBBBBBBB"
    ]
    if greater? bug\legs 0 [
        loop range 0 sub legLength 1  'i [
            prints "    "
            loop range 0 sub bug\legs 1  'j [
                prints " L"
            ]
            print ""
        ]
    ]
    print ""
]

; Return `true` if the given bug is finished; otherwise return `false`.
isFinished?: function [ bug ] [
    and?
        and?
            equal? bug\feelers maxFeelers
            bug\tail
        equal? bug\legs maxLegs
]

; Return a random number from 1 to 6 (inclusive).
dice: function [ ] [
    random 1 6
]

; Array to convert a number to its equilavent text.
asText: [ "no" "a" "two" "three" "four" "five" "six" ]

; Return the proper plural ending depending of the given number.
pluralEnding: function [ n ] [
    if? greater? n 1 [ "s" ] else [ "" ]
]

; Return a string containing the given number and noun in their proper form.
plural: function [ noun number ] [
    render "|asText\[number]| |noun||pluralEnding number|"
]

; Add the given part to the given player's bug.
addPart: function [ part player ] [
    changed: false
    case [ part ]
    when? [ equal? partNumber\body ] [
        if? player\bug\body [
            print render ", but |player\pronoun| already have a body."
        ] else [
            print render "; |player\pronoun| now have a body:"
            player\bug\body: true
            changed: true
        ]
    ]
    when? [ equal? partNumber\neck ] [
        if? player\bug\neck [
            print render ", but |player\pronoun| you already have a neck."
        ] else [
            if? not? player\bug\body [
                print render ", but |player\pronoun| need a body first."
            ] else [
                print render "; |player\pronoun| now have a neck:"
                player\bug\neck: true
                changed: true
            ]
        ]
    ]
    when? [ equal? partNumber\head ] [
        if? player\bug\head [
            print render ", but |player\pronoun| already have a head."
        ] else [
            if? not? player\bug\neck [
                print render ", but |player\pronoun| need a a neck first."
            ] else [
                print render "; |player\pronoun| now have a head:"
                player\bug\head: true
                changed: true
            ]
        ]
    ]
    when? [ equal? partNumber\feeler ] [
        if? equal? player\bug\feelers maxFeelers [
            print render ", but |player\pronoun| have two feelers already."
        ] else [
            if? not? player\bug\head [
                print render ", but |player\pronoun| need a head first."
            ] else [
                player\bug\feelers: player\bug\feelers + 1
                prints render "; |player\pronoun| now have "
                prints plural "feeler" player\bug\feelers
                print ":"
                changed: true
            ]
        ]
    ]
    when? [ equal? partNumber\tail ] [
        if? player\bug\tail [
            print render ", but |player\pronoun| already have a tail."
        ] else [
            if? not? player\bug\body [
                print render ", but |player\pronoun| need a body first."
            ] else [
                print render "; |player\pronoun| now have a tail:"
                player\bug\tail: true
                changed: true
            ]
        ]
    ]
    when? [ equal? partNumber\leg ] [
        if? equal? player\bug\legs maxLegs [
            print render ", but |player\pronoun| have |asText\[maxLegs]| feet already."
        ] else [
            if? not? player\bug\body [
                print render ", but |player\pronoun| need a body first."
            ] else [
                player\bug\legs: player\bug\legs + 1
                prints render "; |player\pronoun| now have "
                prints plural "leg" player\bug\legs
                print ":"
                changed: true
            ]
        ]
    ]
    else [ ]
    changed
]

; Ask the user to press the Enter key, wait for the input, then erase the
; prompt text.
prompt: function [ ] [
    input "Press Enter to roll the dice. "
    erasePreviousLine
]

; Play one turn for the given player, rolling the dice and updating his bug.
turn: function [ player ] [
    prompt
    number: dice
    prints render "|toCapital player\pronoun| rolled a |number| (|partName\[number]|)"
    if addPart number player [
        print ""
        printBug player\bug
    ]
]

; Return `true` if both bugs are finished, otherwise return `false`.
tie?: function [ ] [
    and? isFinished? human\bug isFinished? computer\bug
]

; Print a message about the winner.
printWinner: function [ ] [
    if? tie? [
        print "Both of our bugs are finished in the same number of turns!"
    ] else [
        if? isFinished? human\bug [ prints human\possessive ]
        else [ prints computer\possessive ]
        print " bug is finished."
    ]
]

; Return `true` if any bug is finished; otherwise return `false`.
gameOver?: function [ ] [
    or? isFinished? human\bug isFinished? computer\bug
]

; Execute the game loop.
play: function [ ] [
    clear
    until [
        turn human
        turn computer
    ] [ gameOver? ]
    printWinner
]

; Init the players' data before a new game.
init: function [ ] [
    human\pronoun: "you"
    human\possessive: "Your"
    human\bug\feelerType: 'A'
    computer\pronoun: "I"
    computer\possessive: "My"
    computer\bug\feelerType: 'F'
]

init
printCredits
printInstructions
play
print "I hope you enjoyed the game, play it again soon!!"

Bunny

; Bunny

; Original version in BASIC:
;   Anonymous, 1978.
;   Creative Computing's BASIC Games.
;   - http://vintage-basic.net/games.html
;   - http://vintage-basic.net/bcg/bunny.bas
;   - http://www.retroarchive.org/cpm/games/ccgames.zip

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

printCredits: function [] [
    print "Bunny\n"
    print "Original version in BASIC:"
    print "    Creative Computing (Morristown, New Jersey, USA), 1978.\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    input "Press Enter to start the program. "
]

SPACE: ` `

WIDTH: 53

; Line buffer.
line: array.of: WIDTH SPACE

letter: array [`B` `U` `N` `N` `Y`]

letters: size letter

; End of line identifier.
EOL: neg 1

data: array [
    1, 2, EOL, 0, 2, 45, 50, EOL, 0, 5, 43, 52, EOL, 0, 7, 41, 52, EOL,
    1, 9, 37, 50, EOL, 2, 11, 36, 50, EOL, 3, 13, 34, 49, EOL, 4, 14,
    32, 48, EOL, 5, 15, 31, 47, EOL, 6, 16, 30, 45, EOL, 7, 17, 29, 44,
    EOL, 8, 19, 28, 43, EOL, 9, 20, 27, 41, EOL, 10, 21, 26, 40, EOL,
    11, 22, 25, 38, EOL, 12, 22, 24, 36, EOL, 13, 34, EOL, 14, 33, EOL,
    15, 31, EOL, 17, 29, EOL, 18, 27, EOL, 19, 26, EOL, 16, 28, EOL,
    13, 30, EOL, 11, 31, EOL, 10, 32, EOL, 8, 33, EOL, 7, 34, EOL, 6,
    13, 16, 34, EOL, 5, 12, 16, 35, EOL, 4, 12, 16, 35, EOL, 3, 12, 15,
    35, EOL, 2, 35, EOL, 1, 35, EOL, 2, 34, EOL, 3, 34, EOL, 4, 33,
    EOL, 6, 33, EOL, 10, 32, 34, 34, EOL, 14, 17, 19, 25, 28, 31, 35,
    35, EOL, 15, 19, 23, 30, 36, 36, EOL, 14, 18, 21, 21, 24, 30, 37, 37,
    EOL, 13, 18, 23, 29, 33, 38, EOL, 12, 29, 31, 33, EOL, 11, 13, 17,
    17, 19, 19, 22, 22, 24, 31, EOL, 10, 11, 17, 18, 22, 22, 24, 24, 29,
    29, EOL, 22, 23, 26, 29, EOL, 27, 29, EOL, 28, 29, EOL ]

dataSize: size data

; Index of the current datum in the `data` array.
dataIndex: 0

; Retun the current datum.
datum: function [] [
    add 'dataIndex 1
    return data\[sub dataIndex 1]
]

; Draw the graphic out of `data` and `letter`.
draw: function [] [
    while [ less? dataIndex dataSize ] [
        firstColumn: datum
        if? equal? firstColumn EOL [
            loop 0 .. (sub WIDTH 1) 'pos [
                prints line\[pos]
            ]
            print ""
            'line: array.of: WIDTH SPACE
        ] else [
            lastColumn: datum
            loop firstColumn .. lastColumn  'column [
                line\[column]: letter\[mod column letters]
            ]
        ]
    ]
]

clear
printCredits
clear
draw

Diamond

; Diamond

; Original version in BASIC:
;   Example included in Vintage BASIC 1.0.3.
;   http://www.vintage-basic.net

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

lines: 17

; Print a star.
printStar: function[][ print `*` ]

; Print the diamond top part, _i_ lines high.
diamondTop: function[i][
    loop 1 .. (((lines + 1) / 2) - i) + 1 'j [ prints " " ]
    loop 1 .. (i * 2) - 1                 'j [ prints "*" ]
    print ""
]

; Print the diamond bottom part, _i_ lines high.
diamondBottom: function[i][
    loop 1 .. i + 1                             'j [ prints " " ]
    loop 1 .. ((((lines + 1) / 2) - i) * 2) - 1 'j [ prints "*" ]
    print ""
]

loop 1 .. (lines / 2) + 1 'i [ diamondTop    i ]
loop 1 ..  lines / 2      'i [ diamondBottom i ]

Math

; Math

; Original version in BASIC:
;   Example included in Vintage BASIC 1.0.3.
;   http://www.vintage-basic.net

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

until [
    s: input "Enter a number: "
    dup numeric? s else [ print "Number expected. Retry." ]
] []
n: to :floating s

print ~"ABS(|n|) -> abs |n| -> |abs n|"
print ~"ATN(|n|) -> atan |n| -> |atan n|"
print ~"COS(|n|) -> cos |n| -> |cos n|"
print ~"EXP(|n|) -> exp |n| -> |exp n|"
print ~"INT(|n|) -> floor |n| -> |floor n|"
print ~"LOG(|n|) -> ln |n| -> |ln n|"
print ~"SGN(|n|) -> if? less? |n| 0 [neg 1] else [1] -> |if? less? n 0 [neg 1] else [1]|"
print ~"SQR(|n|) -> sqrt |n| -> |sqrt n|"
print ~"TAN(|n|) -> tan |n| -> |tan n|"

Mugwump

; Mugwump

; Original version in BASIC:
;   Written by Bud Valenti's students of Project SOLO (Pittsburg, Pennsylvania, USA), 1978.
;   Slightly modified by Bob Albrecht of People's Computer Company.
;   Creative Computing's BASIC Games.
;   - https://www.atariarchives.org/basicgames/showpage.php?page=114
;   - http://vintage-basic.net/games.html

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

; Constants
let 'gridSize 10
let 'firstCoord 0
let 'lastCoord sub gridSize 1
let 'maxTurns 10
let 'mugwumps 4
let 'firstMugwump 0
let 'lastMugwump sub mugwumps 1

; Arrays
let 'mugwumpX array .of: mugwumps 0
let 'mugwumpY array .of: mugwumps 0
let 'mugwumpHidden array .of: mugwumps false

; Variables
let 'found 0 ; counter

; Print the given prompt, wait until the user enters a valid integer
; and return it.
getNumber: function [prompt] [
    until [
        try? [ let 'number to :integer input prompt ]
    ] []
    number
]

; Return `true` if the given string is "yes" or a synonym.
isYes: function [answer] [
    contains? ["ok", "yeah", "yes", "y"] answer
]

; Return `true` if the given string is "no" or a synonym.
isNo: function [answer] [
    contains? ["no", "nope", "n"] answer
]

; Print the given prompt, wait until the user enters a valid yes/no
; string, and return `true` for "yes" or `false` for "no".
yes: function [prompt] [
    until
        [ let 'answer input prompt ]
        [ or?
            isYes answer
            isNo answer
        ]
    isYes answer
]

; Clear the screen, print the credits and ask the user to press enter.
printCredits: function [] [
    clear
    print "Mugwump\n"
    print "Original version in BASIC:"
    print "    Written by Bud Valenti's students of Project SOLO (Pittsburg, Pennsylvania, USA)."
    print "    Slightly modified by Bob Albrecht of People's Computer Company."
    print "    Published by Creative Computing (Morristown, New Jersey, USA), 1978."
    print "    - https://www.atariarchives.org/basicgames/showpage.php?page=114"
    print "    - http://vintage-basic.net/games.html\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    input "Press Enter to read the instructions. "
]

; Clear the screen, print the instructions and ask the user to press enter.
printInstructions: function [] [
    clear
    print "Mugwump\n"
    print render "The object of this game is to find |mugwumps| mugwumps"
    print render "hidden on a |gridSize| by |gridSize| grid.  Homebase is position |firstCoord|,|firstCoord|."
    print "Any guess you make must be two numbers with each"
    print render "number between |firstCoord| and |lastCoord|, inclusive.  First number"
    print "is distance to right of homebase and second number"
    print "is distance above homebase.\n"
    print render "You get |maxTurns| tries.  After each try, you will see"
    print "how far you are from each mugwump.\n"
    input "Press Enter to start. "
]

; Init the mugwumps' positions, `hidden` flags and count.
hideMugwumps: function [] [
    loop range firstMugwump lastMugwump 'm [
        mugwumpX\[m]: random firstCoord lastCoord
        mugwumpY\[m]: random firstCoord lastCoord
        mugwumpHidden\[m]: true
    ]
    let 'found 0 ; counter
]

; Print the given prompt, wait until the user enters a valid coord
; and return it.
getCoord: function [prompt] [
    while [ true ] [
        let 'coord getNumber prompt
        if contains? range firstCoord lastCoord coord [ return coord ]
        print render "Invalid value |coord|: not in range [|firstCoord|, |lastCoord|]."
    ]
]

; Return `true` if the given mugwump is hidden in the given coords.
isThere?: function [m x y] [
    and?
        mugwumpHidden\[m]
        and?
            equal? mugwumpX\[m] x
            equal? mugwumpY\[m] y
]

; Return the distance between the given mugwump and the given coords.
distance: function [m x y] [
    to
        :integer
        round
            sqrt
                add
                    pow  sub mugwumpX\[m] x  2
                    pow  sub mugwumpY\[m] y  2
]

; Return the given plural or singular ending depending of the given number.
plural: function [n pluralSuffix singularSuffix] [
    if? greater? n 1 [ pluralSuffix ] else [ singularSuffix ]
]

; Run the game.
play: function [] [
    until [ ; game loop
        clear
        hideMugwumps
        loop range 1 maxTurns 'turn [ ; turns loop
            print render "Turn number |turn|\n"
            print render "What is your guess (in range [|firstCoord|, |lastCoord|])?"
            let 'x getCoord "Distance right of homebase (x-axis): "
            let 'y getCoord "Distance above homebase (y-axis): "
            print render "\nYour guess is (|x|, |y|)."
            loop range firstMugwump lastMugwump 'm [
                if isThere? m x y [
                    mugwumpHidden\[m]: false
                    inc 'found
                    print render "You have found mugwump |add m 1|!"
                    if equal? found mugwumps [ break ]
                ]
            ]
            if equal? found mugwumps [ break ] ; exit the turns loop
            loop range firstMugwump lastMugwump 'm [
                if mugwumpHidden\[m] [
                    print render "You are |distance m y y| units from mugwump |add m 1|."
                ]
            ]
            print ""
        ] ; turns loop
        if? equal? found mugwumps [
            print render "\nYou got them all in |turn| turn|plural turn {s} {}|!\n"
            print "That was fun! let's play again…"
            print render "|mugwumps| more mugwumps are now in hiding."
        ] else [
            print render "\nSorry, that's |maxTurns| tr|plural maxTurns {ies} {y}|.\n"
            print "Here is where they're hiding:"
            loop range firstMugwump lastMugwump 'm [
                if mugwumpHidden\[m] [
                    print render "Mugwump |add m 1| is at (|mugwumpX\[m]|, |mugwumpY\[m]|)."
                ]
            ]
        ]
        print ""
    ] [ not? yes "Do you want to play again? " ] ; game loop
]

printCredits
printInstructions
play

Name

; Name

; Original version in BASIC:
;   Example included in Vintage BASIC 1.0.3.
;   http://www.vintage-basic.net

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

name: input "What is your name? "

until [
    numberString: input "Enter a number: "
    dup numeric? numberString else [ print "Number expected. Retry." ]
] []
number: floor to :floating numberString

loop range 1 number [] [ print ~"Hello, |name|" ]

Russian Roulette

; Russian Roulette

; Original version in BASIC:
;   By Tom Adametx, 1978.
;   Creative Computing's BASIC Games.
;   - https://www.atariarchives.org/basicgames/showpage.php?page=141
;   - http://vintage-basic.net/games.html
;   - http://vintage-basic.net/bcg/russianroulette.bas
;   - http://www.retroarchive.org/cpm/games/ccgames.zip

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

pressEnterToStart: function [] [
    input "Press Enter to start. "
]

printCredits: function [] [
    clear
    print "Russian Roulette\n"
    print "Original version in BASIC:"
    print "    Creative Computing (Morristown, New Jersey, USA), ca. 1980.\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    pressEnterToStart
]

printInstructions: function [] [
    clear
    print "Here is a revolver."
    print "Type 'f' to spin chamber and pull trigger."
    print "Type 'g' to give up, and play again."
    print "Type 'q' to quit.\n"
]

play: function [] [
    while [ true ] [ ; game loop
        printInstructions
        times: 0
        while [ true ] [ ; play loop
            action: input "> "
            case [ action ]
                when? [ equal? "f" ] [ ; fire
                    if? greater? random 0 99 83 [
                        print "Bang! You're dead!"
                        print "Condolences will be sent to your relatives."
                        break
                    ] else [
                        inc 'times
                        if? greater? times 10 [
                            print "You win!"
                            print "Let someone else blow his brains out."
                            break
                        ] else [
                            print "Click."
                        ]
                    ]
                ]
                when? [ equal? "g" ] [ ; give up
                    print "Chicken!"
                    break
                ]
                when? [ equal? "q" ] [ ; quit
                    return
                ]
                else [ ]
        ] ; play loop
        pressEnterToStart
    ] ; game loop
]

printCredits
play
print "Bye!"

Sine Wave

; Sine Wave

; Original version in BASIC:
;   Anonymous, 1978.
;   Creative Computing's BASIC Games.
;   - https://www.atariarchives.org/basicgames/showpage.php?page=146
;   - http://vintage-basic.net/games.html
;   - http://vintage-basic.net/bcg/sinewave.bas
;   - http://www.retroarchive.org/cpm/games/ccgames.zip

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

word: array ["" ""]

; Ask the user to enter two words and store them.
getWords: function [] [
    order: array ["first" "second"]
    loop 0 .. 1 'n [
        word\[n]: input ~"Enter the |order\[n]| word: "
    ]
]

printCredits: function [] [
    print "Sine Wave\n"
    print "Original version in BASIC:"
    print "    Creative Computing (Morristown, New Jersey, USA), ca. 1980.\n"
    print "This version in Arturo:"
    print "    Copyright (c) 2023, Marcos Cruz (programandala.net)"
    print "    SPDX-License-Identifier: Fair\n"
    input "Press Enter to start the program. "
]

draw: function [] [
    even: false
    angle: 0
    while [ lessOrEqual? angle 40 ] [
        prints repeat " " floor add 26 mul 25 sin angle
        print word\[to :integer even]
        'even: not? even
        add 'angle 0.25
    ]
]

clear
printCredits
clear
getWords
clear
draw

Slots

; 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

Stars

; Stars

; Original version in BASIC:
;   Example included in Vintage BASIC 1.0.3.
;   http://www.vintage-basic.net

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

name: input "What is your name? "
print render "Hello, |name|."

while [ true ] [
    until [
        numberString: input "How many stars do you want? "
        dup numeric? numberString else [ print "Number expected. Retry." ]
    ] []
    number: floor to :floating numberString

    print repeat "*" number

    answer: input "Do you want more stars? "
    if not? contains? [ "ok", "yeah", "yes", "y"] answer [ break ]
]

Strings

; Strings

; Original version in BASIC:
;   Example included in Vintage BASIC 1.0.3.
;   http://www.vintage-basic.net

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

space: " "

s: input "Enter a string: "

until [
    dup try? [
        n: to :integer input "Enter an integer: "
    ]
    else [print "Integer expected. Retry."]
][]

print ""

prints ~"ASC(\"|s|\") --> "
prints ~"to :integer first \"|s|\" --> "
print to :integer first s

prints ~"CHR$(|n|) --> "
prints ~"to :string to :char |n| --> "
print to :string to :char n

prints ~"LEFT$(\"|s|\", |n|) --> "
prints ~"slice \"|s|\" 0 min range sub |n| 1 sub size \"|s|\" 1 --> "
print ~"\"|slice s 0 min range sub n 1 sub size s 1|\""

prints ~"MID$(\"|s|\", |n|) --> "
prints ~"slice \"|s|\" min range sub |n| 1 sub size \"|s|\" 1 sub size \"|s|\" 1 --> "
print ~"\"|slice s min range sub n 1 sub size s 1 sub size s 1|\""

prints ~"MID$(\"|s|\", |n|, 3) --> "
prints ~"slice \"s\" min range sub |n| 1 sub size \"|s|\" 1 min range add sub |n| 1 sub 3 1 sub size \"|s|\" 1 --> "
print ~"\"|slice s min range sub n 1 sub size s 1 min range add sub n 1 sub 3 1 sub size s 1|\""

prints ~"RIGHT$(\"|s|\", |n|) --> "
prints ~"slice \"|s|\" max range 0 sub size \"|s|\" |n| sub size \"|s|\" 1 --> "
print ~"\"|slice s max range 0 sub size s n sub size s 1|\""

prints ~"LEN(\"|s|\") --> "
prints ~"size \"|s|\" --> "
print size s

prints ~"VAL(\"|s|\") --> "
prints ~"if? numeric? \"|s|\" [to :floating \"|s|\"] else [0] --> "
print [ if? numeric? s [to :floating s] else [0] ]

prints ~"STR$(|n|) --> "
prints ~"to :string |n| --> "
print ~"\"|to :string n|\""

prints ~"SPC(|n|) --> "
prints ~"repeat \" \" |n| --> "
print ~"\"|repeat space n|\""

Rilataj paĝoj

Basics off
Metaprojekto pri la projektoj «Basics of…».
Basics of 8th
Konverto de malnovaj BASIC-programoj al 8th por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Ada
Konverto de malnovaj BASIC-programoj al Ada por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of C#
Konverto de malnovaj BASIC-programoj al C# por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of C3
Konverto de malnovaj BASIC-programoj al C3 por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Chapel
Konverto de malnovaj BASIC-programoj al Chapel por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Clojure
Konverto de malnovaj BASIC-programoj al Clojure por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Crystal
Konverto de malnovaj BASIC-programoj al Crystal por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of D
Konverto de malnovaj BASIC-programoj al D por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Elixir
Konverto de malnovaj BASIC-programoj al Elixir por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of F#
Konverto de malnovaj BASIC-programoj al F# por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Factor
Konverto de malnovaj BASIC-programoj al Factor por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of FreeBASIC
Konverto de malnovaj BASIC-programoj al FreeBASIC por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Gleam
Konverto de malnovaj BASIC-programoj al Gleam por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Go
Konverto de malnovaj BASIC-programoj al Go por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Hare
Konverto de malnovaj BASIC-programoj al Hare por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Haxe
Konverto de malnovaj BASIC-programoj al Haxe por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Icon
Konverto de malnovaj BASIC-programoj al Icon por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Io
Konverto de malnovaj BASIC-programoj al Io por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Janet
Konverto de malnovaj BASIC-programoj al Janet por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Julia
Konverto de malnovaj BASIC-programoj al Julia por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Kotlin
Konverto de malnovaj BASIC-programoj al Kotlin por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Lobster
Konverto de malnovaj BASIC-programoj al Lobster por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Lua
Konverto de malnovaj BASIC-programoj al Lua por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Nature
Konverto de malnovaj BASIC-programoj al Nature por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Neat
Konverto de malnovaj BASIC-programoj al Neat por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Neko
Konverto de malnovaj BASIC-programoj al Neko por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Nelua
Konverto de malnovaj BASIC-programoj al Nelua por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Nim
Konverto de malnovaj BASIC-programoj al Nim por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Nit
Konverto de malnovaj BASIC-programoj al Nit por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Oberon-07
Konverto de malnovaj BASIC-programoj al Oberon-07 por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of OCaml
Konverto de malnovaj BASIC-programoj al OCaml por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Odin
Konverto de malnovaj BASIC-programoj al Odin por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Pike
Konverto de malnovaj BASIC-programoj al Pike por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Pony
Konverto de malnovaj BASIC-programoj al Pony por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Python
Konverto de malnovaj BASIC-programoj al Python por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Racket
Konverto de malnovaj BASIC-programoj al Racket por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Raku
Konverto de malnovaj BASIC-programoj al Raku por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Retro
Konverto de malnovaj BASIC-programoj al Retro por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Rexx
Konverto de malnovaj BASIC-programoj al Rexx por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Ring
Konverto de malnovaj BASIC-programoj al Ring por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Rust
Konverto de malnovaj BASIC-programoj al Rust por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Scala
Konverto de malnovaj BASIC-programoj al Scala por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Scheme
Konverto de malnovaj BASIC-programoj al Scheme por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Styx
Konverto de malnovaj BASIC-programoj al Styx por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Swift
Konverto de malnovaj BASIC-programoj al Swift por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of V
Konverto de malnovaj BASIC-programoj al V por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Vala
Konverto de malnovaj BASIC-programoj al Vala por lerni la fundamentojn de ĉi-tiu lingvo.
Basics of Zig
Konverto de malnovaj BASIC-programoj al Zig por lerni la fundamentojn de ĉi-tiu lingvo.

Eksteraj rilataj ligiloj