Basics of Julia
Description of the page content
Conversion of old BASIC programs to Julia in order to learn the basics of this language.
Tags:
3D Plot
# 3D Plot
# Original version in BASIC:
# Creative Computing (Morristown, New Jersey, USA), ca. 1980.
# This version in Julia:
# Copyright (c) 2023, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
# Written in 2023-07-07/08.
# Last modified: 20241202T2317+0100.
width = 56
function clear()
print("\e[0;0H\e[2J")
end
function print_credits()
clear()
println("3D Plot\n")
println("Original version in BASIC:")
println(" Creative computing (Morristown, New Jersey, USA), ca. 1980.\n")
println("This version in Julia:")
println(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
println("Press Enter to start the program.")
_ = readline()
end
function a(z)
return 30 * exp(-z * z / 100)
end
function draw()
clear()
for x = -30 : 1.5 : 30
line = repeat(" ", width)
l = 0
y1 = 5 * floor(Int, sqrt(900 - x * x) / 5)
for y = y1 : -5 : -y1
z = floor(Int, (25 + a(sqrt(x * x + y * y)) - .7 * y))
if z > l
l = z
line = line[1:z] * "*" * line[z+2:end]
end
end
println(line)
end
end
print_credits()
draw()
Bagels
# Bagels
# Original version in BASIC:
# D. Resek, P. Rowe, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Julia:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written in 2024-07-03/04.
#
# Last modified: 20240704T1235+0200.
# 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
# Prompt the user to enter a command and return it.
function command(prompt = "> ")::String
print(prompt)
return readline()
end
# Print the given prompt and wait until the user enters an empty string.
function press_enter(prompt::String)
while command(prompt) != ""
end
end
# Return `true` if the given string is "yes" or a synonym; otherwise return
# `false`.
function is_yes(answer::String)::Bool
return lowercase(answer) in ["y", "yeah", "yes", "ok"]
end
# Return `true` if the given string is "no" or a synonym; otherwise return
# `false`.
function is_no(answer::String)::Bool
return lowercase(answer) in ["n", "no", "nope"]
end
# Print the given prompt, wait until the user enters a valid yes/no string, and
# return `true` for "yes" or `false` for "no".
function yes(prompt::String)::Bool
answer = ""
while ! (is_yes(answer) || is_no(answer))
answer = command(prompt)
end
return is_yes(answer)
end
# Clear the screen, display the credits and wait for a keypress.
function print_credits()
clear_screen()
println("Bagels")
println("Number guessing game\n")
println("Original source unknown but suspected to be:")
println(" Lawrence Hall of Science, U.C. Berkely.\n")
println("Original version in BASIC:")
println(" D. Resek, P. Rowe, 1978.")
println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
println("This version in Julia:")
println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
press_enter("Press Enter to read the instructions. ")
end
# Clear the screen, print the instructions and wait for a keypress.
function print_instructions()
clear_screen()
println("Bagels")
println("Number guessing game\n")
println("I am thinking of a three-digit number that has no two digits the same.")
println("Try to guess it and I will give you clues as follows:\n")
println(" PICO - one digit correct but in the wrong position")
println(" FERMI - one digit correct and in the right position")
println(" BAGELS - no digits correct")
press_enter("\nPress Enter to start. ")
end
const DIGITS = 3
const MIN_DIGIT = 0
const MAX_DIGIT = 9
const INVALID_DIGIT = MAX_DIGIT + 1
const TRIES = 20
function has_other_than_digits(text::String)::Bool
for char in text
if ! isdigit(char)
return true
end
end
return false
end
# Print the given prompt and get a three-digit number from the user.
function input(prompt::String)::Array{Int64, 1}
user_digit = Int[]
while true
user_input = command(prompt)
if length(user_input) != DIGITS
println("Remember it's a $DIGITS-digit number.")
continue
elseif has_other_than_digits(user_input)
println("What?")
continue
end
empty!(user_digit)
for c in user_input
push!(user_digit, parse(Int, c))
end
user_unique_digit = unique(user_digit)
if length(user_unique_digit) != length(user_digit)
println("Remember my number has no two digits the same.")
continue
end
break
end
return user_digit
end
# Init and run the game loop.
function play()
computer_number = [INVALID_DIGIT, INVALID_DIGIT, INVALID_DIGIT]
user_number = [INVALID_DIGIT, INVALID_DIGIT, INVALID_DIGIT]
score = 0
fermi = 0 # counter
pico = 0 # counter
while true # game loop
clear_screen()
for i in 1 : DIGITS
while true
digit = rand(MIN_DIGIT : MAX_DIGIT)
if digit in computer_number
continue
else
computer_number[i] = digit
break
end
end
end
println("O.K. I have a number in mind.")
for guess in 1 : TRIES
user_number = input("Guess #$(lpad(guess, 2, '0')): ")
fermi = 0
pico = 0
for i in 1 : DIGITS
for j in 1 : DIGITS
if computer_number[i] == user_number[j]
if i == j
fermi += 1
else
pico += 1
end
end
end
end
print(repeat("PICO ", pico))
print(repeat("FERMI ", fermi))
if pico + fermi == 0
print("BAGELS")
end
println()
if fermi == DIGITS
println("You got it!!!")
score += 1
break # tries loop
end
end # tries loop
if fermi != DIGITS
println("Oh well.")
print("That's $TRIES guesses. My number was ")
for i in 1 : DIGITS
print(computer_number[i])
end
println(".")
end
if ! yes("Play again? ")
break # game loop
end
end # game loop
if score != 0
println("A $score-point bagels, buff!!")
end
println("Hope you had fun. Bye.")
end
print_credits()
print_instructions()
play()
Bug
# Bug
# Original version in BASIC:
# Brian Leibowitz, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Julia:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written on 2024-07-04.
# Last modified: 20240705T1630+0200.
mutable struct Bug
body::Bool
neck::Bool
head::Bool
feelers::Int
feeler_type::Char
tail::Bool
legs::Int
end
mutable struct Player
pronoun::String
possessive::String
bug::Bug
end
# Bug body parts.
@enum Part begin
body = 1
neck
head
feeler
tail
leg
end
const FIRST_PART = Int(body)
const LAST_PART = Int(leg)
const PARTS = LAST_PART
const PART_NAME = ["body", "neck", "head", "feeler", "tail", "leg"]
const PART_QUANTITY = [1, 1, 1, 2, 1, 6]
# Bug body attributes.
const BODY_HEIGHT = 2
const FEELER_LENGTH = 4
const LEG_LENGTH = 2
const MAX_FEELERS = 2
const MAX_LEGS = 6
const NECK_LENGTH = 2
# 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
# Move the cursor up by the given number of rows (the default is 1), without
# changing the column position.
function cursor_up(rows = 1)
print("\e[$(rows)A")
end
# Erase the current line, without moving the cursor position.
function erase_line()
print("\e[2K")
end
# Move the cursor to the previous row, without changing the column position,
# and erase its line.
function erase_previous_line()
cursor_up()
erase_line()
end
# Prompt the user to enter a command and return it.
function command(prompt = "> ")::String
print(prompt)
return readline()
end
# Print the given prompt and wait until the user enters an empty string.
function press_enter(prompt::String)
while ! (command(prompt) == "")
end
end
# Clear the screen, display the credits and wait for the Enter key to be
# pressed.
function print_credits()
clear_screen()
println("Bug\n")
println("Original version in BASIC:")
println(" Brian Leibowitz, 1978.")
println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
println("This version in Julia:")
println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
press_enter("Press Enter to read the instructions. ")
end
const COLUMNS = 3
const COLUMN_WIDTH = 8
const COLUMN_SEPARATION = 2
# Print a table with the bug parts' description.
function print_parts_table()
# Headers
header = ["Number", "Part", "Quantity"]
for i in 1 : COLUMNS
print(rpad(header[i], COLUMN_WIDTH + COLUMN_SEPARATION))
end
println()
# Rulers
for i in 1 : COLUMNS
print(repeat("-", COLUMN_WIDTH), i == COLUMNS ? "" : repeat(' ', COLUMN_SEPARATION))
end
println()
# Data
for n in FIRST_PART : LAST_PART
println(
rpad(n, COLUMN_WIDTH + COLUMN_SEPARATION),
rpad(uppercasefirst(PART_NAME[n]), COLUMN_WIDTH + COLUMN_SEPARATION),
PART_QUANTITY[n])
end
end
# Clear the screen, print the instructions and wait for a keypress.
function print_instructions()
clear_screen()
println("Bug")
println("""
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:
"""
)
print_parts_table()
press_enter("\nPress Enter to start. ")
end
# Print a bug head.
function print_head()
println(" HHHHHHH")
println(" H H")
println(" H O O H")
println(" H H")
println(" H V H")
println(" HHHHHHH")
end
# Print the given bug.
function print_bug(bug::Bug)
if bug.feelers > 0
for i in 0 : FEELER_LENGTH - 1
print(" ")
for j in 0 : bug.feelers - 1
print(" ", bug.feeler_type)
end
println()
end
end
if bug.head
print_head()
end
if bug.neck
for i in 0 : NECK_LENGTH - 1
println(" N N")
end
end
if bug.body
println(" BBBBBBBBBBBB")
for i in 0 : BODY_HEIGHT - 1
println(" B B")
end
if bug.tail
println("TTTTTB B")
end
println(" BBBBBBBBBBBB")
end
if bug.legs > 0
for i in 0 : LEG_LENGTH - 1
print(" ")
for j in 0 : bug.legs - 1
print(" L")
end
println()
end
end
end
# Return `true` if the given bug is finished; otherwise return `false`.
function is_finished(bug::Bug)::Bool
return bug.feelers == MAX_FEELERS && bug.tail && bug.legs == MAX_LEGS
end
# Array to convert a number to its equilavent text.
const AS_TEXT = ["a", "two", "three", "four", "five", "six"]
# Return a string containing the given number and noun in their proper form.
function plural(number::Int, noun::String)::String
return AS_TEXT[number] * " " * noun * (number > 1 ? "s" : "")
end
# Add the given part to the given player's bug.
function add_part(part::Int, player::Player)::Bool
changed = false
if part == Int(body)
if player.bug.body
print(", but ", player.pronoun, " already have a body.\n")
else
print("; ", player.pronoun, " now have a body:\n")
player.bug.body = true
changed = true
end
elseif part == Int(neck)
if player.bug.neck
print(", but ", player.pronoun, " already have a neck.\n")
elseif ! player.bug.body
print(", but ", player.pronoun, " need a body first.\n")
else
print("; ", player.pronoun, " now have a neck:\n")
player.bug.neck = true
changed = true
end
elseif part == Int(head)
if player.bug.head
print(", but ", player.pronoun, " already have a head.\n")
elseif ! player.bug.neck
print(", but ", player.pronoun, " need a a neck first.\n")
else
print("; ", player.pronoun, " now have a head:\n")
player.bug.head = true
changed = true
end
elseif part == Int(feeler)
if player.bug.feelers == MAX_FEELERS
print(", but ", player.pronoun, " have two feelers already.\n")
elseif ! player.bug.head
print(", but ", player.pronoun, " need a head first.\n")
else
player.bug.feelers += 1
print("; ", player.pronoun, " now have ", plural(player.bug.feelers, "feeler"))
println(":")
changed = true
end
elseif part == Int(tail)
if player.bug.tail
print(", but ", player.pronoun, " already have a tail.\n")
elseif ! player.bug.body
print(", but ", player.pronoun, " need a body first.\n")
else
print("; ", player.pronoun, " now have a tail:\n")
player.bug.tail = true
changed = true
end
elseif part == Int(leg)
if player.bug.legs == MAX_LEGS
print(", but ", player.pronoun, " have ", AS_TEXT[MAX_LEGS], " feet already.")
elseif ! player.bug.body
print(", but ", player.pronoun, " need a body first.\n")
else
player.bug.legs += 1
print("; ", player.pronoun, " now have ", plural(player.bug.legs, "leg"))
println(":")
changed = true
end
end
return changed
end
# Ask the user to press the Enter key, wait for the input, then erase the
# prompt text.
function prompt()
press_enter("Press Enter to roll the dice. ")
erase_previous_line()
end
# Play one turn for the given player, rolling the dice and updating his bug.
function turn(player::Player)
prompt()
part = rand(FIRST_PART : LAST_PART) # dice
print("$(uppercasefirst(player.pronoun)) rolled a $part ($(PART_NAME[part]))")
if add_part(part, player)
println()
print_bug(player.bug)
end
println()
end
# Print a message about the winner.
function print_winner(p1, p2::Player)
if is_finished(p1.bug) && is_finished(p2.bug)
println("Both of our bugs are finished in the same number of turns!")
elseif is_finished(p1.bug)
print(p1.possessive, " bug is finished.\n")
elseif is_finished(p2.bug)
print(p2.possessive, " bug is finished.\n")
end
end
# Return a new player initialized with the given data.
function new_player(pronoun::String, possessive::String, feeler_type::Char)
bug = Bug(false, false, false, 0, feeler_type, false, 0)
return Player(pronoun, possessive, bug)
end
# Execute the game loop.
function play()
clear_screen()
computer = new_player("you", "your", 'A')
human = new_player("I", "My", 'F')
while ! (is_finished(human.bug) || is_finished(computer.bug))
turn(human)
turn(computer)
end
print_winner(human, computer)
end
print_credits()
print_instructions()
play()
println("I hope you enjoyed the game, play it again soon!!")
Bunny
# Bunny
#
# Original version in BASIC:
# Creative Computing (Morristown, New Jersey, USA), 1978.
#
# This version in Julia:
# Copyright (c) 2023, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
# Written in 2023-09.
#
# Last modified: 20240704T1050+0200.
# Clear the terminal and move the cursor to the top left position.
function clear_screen()
print("\e[0;0H\e[2J")
end
# Clear the screen, print the credits and wait for the Enter key.
function print_credits()
println("Bunny\n")
println("Original version in BASIC:")
println(" Creative Computing (Morristown, New Jersey, USA), 1978.\n")
println("This version in Julia:")
println(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
println("Press Enter to start the program.")
readline()
end
const width = 53
# Print the given line buffer array.
function print_line(line)
for item in line
print(item)
end
println()
end
const EOL = -1 # end of line identifier
# Draw the graphic.
function draw()
letter = ['B', 'U', 'N', 'N', 'Y']
letters = length(letter)
data = [
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 ]
line = Char[] # line buffer
# Init the line buffer with spaces.
for _ in (1 : width)
push!(line, ' ')
end
data_index = 1
while data_index <= length(data)
first_column = data[data_index]
data_index += 1
if first_column == EOL
print_line(line)
fill!(line, ' ')
else
last_column = data[data_index]
data_index += 1
for column in (first_column : last_column)
line[column + 1] = letter[column % letters + 1]
end
end
end
end
clear_screen()
print_credits()
clear_screen()
draw()
Diamond
# Diamond
# Original version in BASIC:
# Example included in Vintage BASIC 1.0.3.
# http://www.vintage-basic.net
# This version in Julia:
# Copyright (c) 2023, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
# Written on 2023-07-08.
# Last modified: 20241029T1615+0100.
lines = 17
for i = 1 : lines / 2 + 1
for j = 1 : (lines + 1) / 2 - i + 1
print(" ")
end
for j = 1 : i * 2 - 1
print("*")
end
println()
end
for i = 1 : lines / 2
for j = 1 : i + 1
print(" ")
end
for j = 1 : ((lines + 1) / 2 - i) * 2 - 1
print("*")
end
println()
end
Math
# Math
# Original version in BASIC:
# Example included in Vintage BASIC 1.0.3.
# http://www.vintage-basic.net
# This version in Julia:
# Copyright (c) 2023, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
# Written in 2023-07, 2023-08, 2023-09, 2024-10.
# Last modified: 20241029T2117+0100.
n = 0.0
while true
print("Enter a number: ")
global n = tryparse(Float64, readline())
if n == nothing
println("Not a valid number.")
else
break
end
end
println("ABS($n) --> abs($n) --> ", abs(n))
println("ATN($n) --> atan($n) --> ", atan(n))
println("COS($n) --> cos($n) --> ", cos(n))
println("EXP($n) --> exp($n) --> ", exp(n))
println("INT($n) --> floor(Int64, $n) --> ", floor(Int64, n))
if n >= 0
println("LOG($n) --> log($n) --> ", log(n))
else
println("LOG($n) --> log($n) --> undefined")
end
println("SGN($n) --> sign($n) --> ", sign(n))
if n >= 0
println("SQR($n) --> sqrt($n) --> ", sqrt(n))
else
println("SQR($n) --> sqrt($n) --> math domain error")
end
println("TAN($n) --> tan($n) --> ", tan(n))
Mugwump
# Mugwump
# Original version in BASIC:
# Written by Bud Valenti's students of Project SOLO (Pittsburg, Pennsylvania, USA).
# Slightly modified by Bob Albrecht of People's Computer Company.
# Published by Creative Computing (Morristown, New Jersey, USA), 1978.
# - https://www.atariarchives.org/basicgames/showpage.php?page=114
# - http://vintage-basic.net/games.html
# This version in Julia:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written on 2024-07-02/03.
#
# Last modified: 20241030T0038+0100.
const GRID_SIZE = 10
const TURNS = 10
const MUGWUMPS = 4
mutable struct Mugwump
hidden::Bool
x::Int
y::Int
end
# Move the cursor to the top left position of the terminal.
function home()
print("\e[H")
end
# Clear the terminal and move the cursor to the top left position.
function clear()
print("\e[2J")
home()
end
# Print the given prompt, wait until the user enters a valid integer and return
# it.
function get_number(prompt::String)::Int
n = 0
while true
print(prompt)
n = tryparse(Int, readline())
if isnothing(n)
println("Invalid number.")
else
break
end
end
return n
end
# Prompt the user to enter a command and return it.
function command(prompt = "> ")::String
print(prompt)
return readline()
end
# Print the given prompt and wait until the user enters an empty string.
function press_enter(prompt::String)
while command(prompt) != ""
end
end
# Return `true` if the given string is "yes" or a synonym; otherwise return
# `false`.
function is_yes(answer::String)::Bool
return lowercase(answer) in ["ok", "yeah", "yes", "y"]
end
# Return `true` if the given string is "no" or a synonym; otherwise return
# `false`.
function is_no(answer::String)::Bool
return lowercase(answer) in ["no", "nope", "n"]
end
# Print the given prompt, wait until the user enters a valid yes/no string, and
# return `true` for "yes" or `false` for "no".
function yes(prompt::String)::Bool
answer = ""
while ! (is_yes(answer) || is_no(answer))
answer = command(prompt)
end
return is_yes(answer)
end
# Clear the screen, print the credits and ask the user to press enter.
function print_credits()
clear()
println("Mugwump\n")
println("Original version in BASIC:")
println(" Written by Bud Valenti's students of Project SOLO (Pittsburg, Pennsylvania, USA).")
println(" Slightly modified by Bob Albrecht of People's Computer Company.")
println(" Published by Creative Computing (Morristown, New Jersey, USA), 1978.")
println(" - https://www.atariarchives.org/basicgames/showpage.php?page=114")
println(" - http://vintage-basic.net/games.html\n")
println("This version in Julia:")
println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
press_enter("Press Enter to read the instructions. ")
end
# Clear the screen, print the instructions and ask the user to press enter.
function print_instructions()
clear()
println("Mugwump\n")
println("The object of this game is to find four mugwumps")
println("hidden on a 10 by 10 grid. Homebase is position 0,0.")
println("Any guess you make must be two numbers with each")
println("number between 0 and 9, inclusive. First number")
println("is distance to right of homebase and second number")
println("is distance above homebase.\n")
println("You get $TURNS tries. After each try, you will see")
println("how far you are from each mugwump.\n")
press_enter("Press Enter to start. ")
end
# Print the given prompt, then waits until the user enters a valid coord and
# returns it.
function get_coord(prompt::String)::Int
coord = 0
while true
coord = get_number(prompt)
if coord < 0 || coord >= GRID_SIZE
println("Invalid value $coord: not in range [0, $(GRID_SIZE - 1)].")
else
break
end
end
return coord
end
# Return `true` if the given mugwump is hidden in the given coords.
function is_here(m::Mugwump, x::Int, y::Int)::Bool
return m.hidden && m.x == x && m.y == y
end
# Return the distance between the given mugwump and the given coords.
function distance(m::Mugwump, x::Int, y::Int)::Int
return round(sqrt((m.x - x) ^ 2 + (m.y - y) ^ 2))
end
# If the given number is greater than 1, return the given plural ending
# (default: "s"); otherwise return the given singular ending (default: an empty
# string).
function plural(n::Int, plural = "s", singular = "")::String
return n > 1 ? plural : singular
end
# Print the mugwumps found in the given coordinates and return the count.
function mugwumps_found(mugwump::Array{Mugwump}, x, y)::Int
found = 0
for m in 1 : MUGWUMPS
if is_here(mugwump[m], x, y)
mugwump[m].hidden = false
found += 1
println("You have found mugwump $(m)!")
end
end
return found
end
# Run the game.
function play()
found = 0 # counter
turn = 0 # counter
mugwump = Array{Mugwump, 1}(undef, MUGWUMPS)
while true # game
clear()
for m in 1 : MUGWUMPS
mugwump[m] = Mugwump(
true,
rand(0 : GRID_SIZE - 1),
rand(0 : GRID_SIZE - 1)
)
end
found = 0
turn = 1
while turn < TURNS
println("Turn number $turn\n")
println("What is your guess (in range [0, $(GRID_SIZE - 1)])?")
x = get_coord("Distance right of homebase (x-axis): ")
y = get_coord("Distance above homebase (y-axis): ")
println("\nYour guess is ($x, $y).")
found += mugwumps_found(mugwump, x, y)
if found == MUGWUMPS
break # turns
else
for m in 1 : MUGWUMPS
if mugwump[m].hidden
println("You are $(distance(mugwump[m], x, y)) units from mugwump $m.")
end
end
println()
end
turn += 1
end # turns
if found == MUGWUMPS
println("\nYou got them all in $turn turn$(plural(turn))!\n")
println("That was fun! let's play again…")
println("Four more mugwumps are now in hiding.")
else
println("\nSorry, that's $TURNS tr$(plural(TURNS, "ies", "y")).\n")
println("Here is where they're hiding:")
for m in 1 : MUGWUMPS
if mugwump[m].hidden
println("Mugwump $m is at ($(mugwump[m].x), $(mugwump[m].y)).")
end
end
end
println()
if ! yes("Do you want to play again? ")
break # game
end
end # game
end
print_credits()
print_instructions()
play()
Name
# Name
# Original version in BASIC:
# Example included in Vintage BASIC 1.0.3.
# http://www.vintage-basic.net
# This version in Julia:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written on 2024-07-01.
#
# Last modified: 20240704T1050+0200.
print("What is your name? ")
name = readline()
n = 0
while true
print("Enter a number: ")
global n = tryparse(Int, readline())
if isnothing(n)
println("Number expected. Retry input line.")
else
break
end
end
for _ = 1:n
println("Hello, $(name)!")
end
Poetry
#=
Poetry
Original version in BASIC:
Unknown author.
Modified and reworked by Jim Bailey, Peggy Ewing, and Dave Ahl at DEC.
Published in "BASIC Computer Games", Creative Computing (Morristown, New Jersey, USA), 1978.
https://archive.org/details/Basic_Computer_Games_Microcomputer_Edition_1978_Creative_Computing
https://github.com/chaosotter/basic-games/tree/master/games/BASIC%20Computer%20Games/Poetry
http://vintage-basic.net/games.html
This improved remake in Julia:
Copyright (c) 2024, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written in 2024-07-08/11, on 2024-12-12.
Last modified: 20241212T2240+0100.
=#
# ==============================================================
const DEFAULT_INK = :white
const INPUT_INK = :light_green
const TITLE_INK = :light_red
const MAX_PHRASES_AND_VERSES = 20
# 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
# Print the given prompt and wait until the user enters a string.
function input_string(prompt::String = "")::String
printstyled(prompt, color = INPUT_INK)
return readline()
end
# Print the given prompt and wait until the user enters an empty string.
function press_enter(prompt::String)
while ! (input_string(prompt) == "")
end
end
# Print the credits at the current cursor position.
function print_credits()
printstyled("Poetry\n\n", color = TITLE_INK)
println("Original version in BASIC:")
println(" Unknown author.")
println(" Published in \"BASIC Computer Games\",")
println(" Creative Computing (Morristown, New Jersey, USA), 1978.\n")
println("This improved remake in Julia:")
println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair")
end
function play()
action = 0
phrase = 0
phrases_and_verses = 0
verse_chunks = 0
while true # verse loop
manage_the_verse_continuation = true
maybe_add_comma = true
if action in [0, 1]
if phrase == 0
print("MIDNIGHT DREARY")
elseif phrase == 1
print("FIERY EYES")
elseif phrase == 2
print("BIRD OR FIEND")
elseif phrase == 3
print("THING OF EVIL")
elseif phrase == 4
print("PROPHET")
end
elseif action == 2
if phrase == 0
print("BEGUILING ME")
verse_chunks = 2
elseif phrase == 1
print("THRILLED ME")
elseif phrase == 2
print("STILL SITTING…")
maybe_add_comma = false
elseif phrase == 3
print("NEVER FLITTING")
verse_chunks = 2
elseif phrase == 4
print("BURNED")
end
elseif action == 3
if phrase == 0
print("AND MY SOUL")
elseif phrase == 1
print("DARKNESS THERE")
elseif phrase == 2
print("SHALL BE LIFTED")
elseif phrase == 3
print("QUOTH THE RAVEN")
elseif phrase == 4 && verse_chunks != 0
print("SIGN OF PARTING")
end
elseif action == 4
if phrase == 0
print("NOTHING MORE")
elseif phrase == 1
print("YET AGAIN")
elseif phrase == 2
print("SLOWLY CREEPING")
elseif phrase == 3
print("…EVERMORE")
elseif phrase == 4
print("NEVERMORE")
end
elseif action == 5
action = 0
println()
if phrases_and_verses > MAX_PHRASES_AND_VERSES
println()
verse_chunks = 0
phrases_and_verses = 0
action = 2
continue
else
manage_the_verse_continuation = false
end
end
if manage_the_verse_continuation
sleep(0.250) # 250 ms
if maybe_add_comma && ! (verse_chunks == 0 || rand() > 0.19)
print(",")
verse_chunks = 2
end
if rand() > 0.65
println()
verse_chunks = 0
else
print(" ")
verse_chunks += 1
end
end
action += 1
phrase = rand(0 : 4)
phrases_and_verses += 1
if ! (verse_chunks > 0 || iseven(action))
print(" ")
end
end # verse loop
end
clear_screen()
print_credits()
press_enter("\nPress the Enter key to start. ")
clear_screen()
play()
Russian Roulette
# Russian Roulette
# Original version in BASIC:
# Creative Computing (Morristown, New Jersey, USA), ca. 1980.
# This version in Julia:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written on 2024-06-28.
#
# Last modified: 20241029T1850+0100.
# Clear the terminal and move the cursor to the top left position.
function clear_screen()
print("\e[2J\e[H")
end
# Prompt the user to enter a command and return it.
function get_command(prompt = "> ")::String
print(prompt)
return readline()
end
function press_enter_to_start()
_ = get_command("Press Enter to start. ")
end
function print_credits()
clear_screen()
println("Russian Roulette\n")
println("Original version in BASIC:")
println(" Creative Computing (Morristown, New Jersey, USA), ca. 1980.\n")
println("This version in Julia:")
println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
press_enter_to_start()
end
function print_instructions()
clear_screen()
println("Here is a revolver.")
println("Type 'f' to spin chamber and pull trigger.")
println("Type 'g' to give up, and play again.")
println("Type 'q' to quit.\n")
end
function play()::Bool
while true # game loop
print_instructions()
times = 0
while true # play loop
command = get_command()
if command == "f" # fire
if Int(floor(100 * rand())) > 83
println("Bang! You're dead!")
println("Condolences will be sent to your relatives.")
break
else
times += 1
if times == 10
println("You win!")
println("Let someone else blow his brains out.")
break
else
println("Click.")
end
end
elseif command == "g" # give up
println("Chicken!")
break
elseif command == "q" # quit
return false
end # case
end # play loop
press_enter_to_start()
end # game loop
return true # play again, do not quit
end
print_credits
while play()
end
println("Bye!")
Seance
#=
Seance
Original version in BASIC:
By Chris Oxlade, 1983.
https://archive.org/details/seance.qb64
https://github.com/chaosotter/basic-games
This version in Julia:
Copyright (c) 2024, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2024-07-05/06.
Last modified: 20240706T0125+0200.
=#
const MAX_SCORE = 50
const MAX_MESSAGE_LENGTH = 6
const MIN_MESSAGE_LENGTH = 3
const BASE_CHARACTER = Int('@')
const PLANCHETTE = '*'
const FIRST_LETTER_NUMBER = 1
const LAST_LETTER_NUMBER = 26
const BOARD_INK = :light_cyan
const DEFAULT_INK = :white
const INPUT_INK = :light_green
const INSTRUCTIONS_INK = :yellow
const MISTAKE_EFFECT_INK = :light_red
const PLANCHETTE_INK = :yellow
const TITLE_INK = :light_red
const MISTAKE_EFFECT_PAUSE = 3 # seconds
const BOARD_WIDTH = 8 # characters displayed on the top and bottom borders
const BOARD_HEIGHT = 5 # characters displayed on the left and right borders
const BOARD_PAD = 1 # blank characters separating the board from its left and right borders
const BOARD_X = 29 # screen column
const BOARD_Y = 5 # screen line
const BOARD_ACTUAL_WIDTH = BOARD_WIDTH + 2 * BOARD_PAD # screen columns
const BOARD_BOTTOM_Y = BOARD_HEIGHT + 1 # relative to the board
const INPUT_X = BOARD_X
const INPUT_Y = BOARD_Y + BOARD_BOTTOM_Y + 4
const MESSAGES_Y = INPUT_Y
# Clear the terminal and move the cursor to the top left position.
function clear_screen()
print("\e[2J\e[H")
end
# Set the cursor position to the given coordinates (the top left position is 1, 1).
function set_cursor_position(line::Int, column::Int)
print("\e[$(line);$(column)H")
end
# Erase from the current cursor position to the end of the current line.
function erase_line_right()
print("\e[K")
end
# Erase the given line to the right of the given column.
function erase_line_right_from(line, column::Int)
set_cursor_position(line, column)
erase_line_right()
end
# Make the cursor invisible.
function hide_cursor()
print("\e[?25l")
end
# Make the cursor visible.
function show_cursor()
print("\e[?25h")
end
# Print the given prompt and wait until the user enters a string.
function input(prompt::String = "")::String
printstyled(prompt, color = INPUT_INK)
return readline()
end
# Print the given prompt and wait until the user presses Enter.
function press_enter(prompt::String)
input(prompt)
end
# Return the x coordinate to print the given text centered on the board.
function board_centered_x(text::String)::Int
return round(BOARD_X + (BOARD_ACTUAL_WIDTH - length(text)) / 2)
end
# Print the given text on the given row, centered on the board, with the given
# or default color.
function print_board_centered(text::String, y::Int, color::Symbol=:default)
set_cursor_position(y, board_centered_x(text))
printstyled(text, color = color)
end
const TITLE = "Seance"
# Print the title at the current cursor position.
function print_title()
printstyled("TITLE\n", color = TITLE_INK)
end
function print_credits()
print_title()
println("\nOriginal version in BASIC:")
println(" Written by Chris Oxlade, 1983.")
println(" https://archive.org/details/seance.qb64")
println(" https://github.com/chaosotter/basic-games")
println("This version in Julia:")
println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
end
function print_instructions()
print_title()
printstyled("""
Messages from the Spirits are coming through, letter by letter. They want you
to remember the letters and type them into the computer in the correct order.
If you make mistakes, they will be angry -- very angry...
Watch for stars on your screen -- they show the letters in the Spirits'
messages.\n""", color = INSTRUCTIONS_INK)
end
# Print the given letter at the given board coordinates in the given or default
# color.
function print_character(y, x::Int, a::Char, color::Symbol=:default)
set_cursor_position(y + BOARD_Y, x + BOARD_X)
printstyled(a, color = color)
end
function print_board()
for i in 1 : BOARD_WIDTH
print_character(0, i + 1, Char(BASE_CHARACTER + i), BOARD_INK) # top border
print_character(BOARD_BOTTOM_Y, i + 1, Char(BASE_CHARACTER + LAST_LETTER_NUMBER - BOARD_HEIGHT - i + 1), BOARD_INK) # bottom border
end
for i in 1 : BOARD_HEIGHT
print_character(i , 0, Char(BASE_CHARACTER + LAST_LETTER_NUMBER - i + 1), BOARD_INK) # left border
print_character(i , 3 + BOARD_WIDTH, Char(BASE_CHARACTER + BOARD_WIDTH + i), BOARD_INK) # right border
end
println()
end
# Print the given mistake effect, wait a configured number of seconds and finally erase it.
function print_mistake_effect(effect::String)
x = board_centered_x(effect)
hide_cursor()
set_cursor_position(MESSAGES_Y, x)
printstyled(effect, color = MISTAKE_EFFECT_INK)
sleep(MISTAKE_EFFECT_PAUSE)
erase_line_right_from(MESSAGES_Y, x)
show_cursor()
end
# Return a new message of the given length, after marking its letters on the board.
function message(length::Int)::String
y = 0
x = 0
message = ""
hide_cursor()
for i in 1 : length
letter_number = rand(FIRST_LETTER_NUMBER : LAST_LETTER_NUMBER)
letter = Char(BASE_CHARACTER + letter_number)
message = message * letter # add letter to message
if letter_number <= BOARD_WIDTH
# top border
y = 1
x = letter_number + 1
elseif letter_number <= BOARD_WIDTH + BOARD_HEIGHT
# right border
y = letter_number - BOARD_WIDTH
x = 2 + BOARD_WIDTH
elseif letter_number <= BOARD_WIDTH + BOARD_HEIGHT + BOARD_WIDTH
# bottom border
y = BOARD_BOTTOM_Y - 1
x = 2 + BOARD_WIDTH + BOARD_HEIGHT + BOARD_WIDTH - letter_number
else
# left border
y = 1 + LAST_LETTER_NUMBER - letter_number
x = 1
end
print_character(y, x, PLANCHETTE, PLANCHETTE_INK)
sleep(1)
print_character(y, x, ' ')
end
show_cursor()
return message
end
# Accept a string from the user, erase it from the screen and return it.
function message_understood()::String
set_cursor_position(INPUT_Y, INPUT_X)
user_input = uppercase(input("? "))
erase_line_right_from(INPUT_Y, INPUT_X)
return user_input
end
function play()
score = 0
mistakes = 0
print_board_centered(TITLE, 1, TITLE_INK)
print_board()
while true
message_length = rand(MIN_MESSAGE_LENGTH : MAX_MESSAGE_LENGTH)
if message(message_length) != message_understood()
mistakes += 1
if mistakes == 1
print_mistake_effect("The table begins to shake!")
elseif mistakes == 2
print_mistake_effect("The light bulb shatters!")
elseif mistakes == 3
print_mistake_effect("Oh, no! A pair of clammy hands grasps your neck!")
return
end
else
score += message_length
if score >= MAX_SCORE
print_board_centered("Whew! The spirits have gone!", MESSAGES_Y)
print_board_centered("You live to face another day!", MESSAGES_Y + 1)
return
end
end
end
end
function main()
clear_screen()
print_credits()
press_enter("\nPress the Enter key to read the instructions. ")
clear_screen()
print_instructions()
press_enter("\nPress the Enter key to start. ")
clear_screen()
play()
println("\n")
end
main()
Sine Wave
# Sine Wave
# Original version in BASIC:
# Creative Computing (Morristown, New Jersey, USA), ca. 1980.
# This version in Julia:
# Copyright (c) 2023, 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
# Last modified: 20250319T1933+0100.
word = ["", ""]
order = ["first", "second"]
function clear()
print("\e[0;0H\e[2J")
end
function print_credits()
clear()
println("Sine Wave\n")
println("Original version in BASIC:")
println(" Creative computing (Morristown, New Jersey, USA), ca. 1980.\n")
println("This version in Julia:")
println(" Copyright (c) 2023, 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
println("Press Enter to start the program.")
_ = readline()
end
function get_words()
global order
global word
clear()
for n = 1 : 2
print(string("\nEnter the ", order[n], " word "))
word[n] = readline()
end
end
function draw()
global word
clear()
even = false
for angle = 0 : 0.25 : 40
print(repeat(" ", Int(floor(26 + 25 * sin(angle)))))
println(word[Int(even) + 1])
even = !even
end
end
print_credits()
get_words()
draw()
Slots
# 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()
Stars
# Stars
# Original version in BASIC:
# Example included in Vintage BASIC 1.0.3.
# http://www.vintage-basic.net
# This version in Julia:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written on 2024-07-01.
#
# Last modified: 20240704T1050+0200.
print("What is your name? ")
name = readline()
println("Hello, $name")
n = 0
while true
while true
print("How many stars do you want? ")
global n = tryparse(Int, readline())
if isnothing(n)
println("Number expected. Retry input line.")
else
break
end
end
println(repeat('*', n))
print("Do you want more stars? ")
answer = lowercase(readline())
if ! (answer in ["yeah", "yes", "y", "ok"])
break
end
end
println("Goodbye, $name")
Strings
# Strings
# Original version in BASIC:
# Example included in Vintage BASIC 1.0.3.
# http://www.vintage-basic.net
# This version in Julia:
# Copyright (c) 2023, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
# Written in 2023-07, 2023-09.
# Last modified: 20240704T1050+0200.
using Unicode
print("Enter a string: ")
s = readline()
n = 0
while true
print("Enter a whole number: ")
f = tryparse(Float64, readline())
if f != nothing
global n = convert(Int64, floor(f))
if n == f
break
end
end
println("Not a valid whole number.")
end
print("ASC(\"$s\") --> ")
print("convert(Int, convert(Char, \"$s\"[1])) --> ")
println(convert(Int, s[1]))
print("CHR\$($n) --> ")
print("convert(Char, $n) --> ")
println("'", convert(Char, n), "'")
print("LEFT\$(\"$s\", $n) --> ")
print("graphemes(\"$s\", 1 : min($n, length(\"$s\"))) --> ")
println("\"", graphemes(s, 1 : min(n, length(s))), "\"")
print("MID\$(\"$s\", $n) --> ")
print("graphemes(\"$s\", $n : length(\"$s\") --> ")
println("\"", graphemes(s, n : length(s)), "\"")
print("MID\$(\"$s\", $n, 3) --> ")
print("graphemes(\"$s\", $n : min($n + 3 - 1, length(\"$s\")) --> ")
println("\"", graphemes(s, n : min(n + 3 - 1, length(s))), "\"")
print("RIGHT\$(\"$s\", $n) --> ")
print("graphemes(\"$s\", max(length(\"$s\") - $n + 1, 1) : length(\"$s\") --> ")
println("\"", graphemes(s, max(length(s) - n + 1, 1) : length(s)), "\"")
print("LEN(\"$s\") --> ")
print("length(\"$s\") --> ")
println(length(s))
print("VAL(\"$s\") --> ")
print("tryparse(Float64, \"$s\") == nothing ? 0 : parse(Float64, \$$s\$) --> ")
println(tryparse(Float64, s) == nothing ? 0 : parse(Float64, s))
print("STR\$($n) --> ")
print("string($n) --> ")
println("\"", string(n), "\"")
print("SPC($n) --> ")
print("repeat(\" \", $n) --> ")
println("\"", repeat(" ", n), "\"")
