Basics of C3
Description of the page content
Conversion of old BASIC programs to C3 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 C3:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-03-07.
//
// Last modified: 20250307T1349+0100.
import std::io;
const SPACE = " ";
const DOT = "*";
const WIDTH = 56;
fn void clearScreen() {
io::printn("\e[0;0H\e[2J");
}
fn String acceptString(String prompt = "") {
io::print(prompt);
String! s = io::readline();
if (catch excuse = s) {
return "";
} else {
return s;
}
}
fn void pressEnter(String prompt = "") {
String discard = acceptString(prompt);
free(discard);
}
fn void printCredits() {
io::printn("3D Plot\n");
io::printn("Original version in BASIC:");
io::printn(" Creative computing (Morristown, New Jersey, USA), ca. 1980.\n");
io::printn("This version in C3:");
io::printn(" Copyright (c) 2025, Marcos Cruz (programandala.net)");
io::printn(" SPDX-License-Identifier: Fair\n");
pressEnter("Press Enter to start. ");
}
fn double a(double z) {
return 30.0 * $$exp(-z * z / 100.0);
}
fn void draw() {
int l = 0;
int z = 0;
int y1 = 0;
String[WIDTH] line = {};
for (double x = -30.0; x <= 30.0; x += 1.5) {
for (int i = 0; i < WIDTH; i += 1) {
line[i] = SPACE;
}
l = 0;
y1 = 5 * (int)($$sqrt(900.0 - x * x) / 5.0);
for (int y = y1; y >= -y1; y += -5) {
z = (int)(25.0 + a($$sqrt(x * x + (double)(y * y))) - 0.7 * (double)y);
if (z > l) {
l = z;
line[z] = DOT;
}
} // y loop
for (int pos = 0; pos < WIDTH; pos += 1) {
io::print(line[pos]);
}
io::printn();
} // x loop
}
fn void main() {
clearScreen();
printCredits();
clearScreen();
draw();
}
Diamond
/*
Diamond
Original version in BASIC:
Example included in Vintage BASIC 1.0.3.
http://www.vintage-basic.net
This version in C3:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-03-05.
Last modified 20250305T0221+0100.
*/
import std::io;
const int LINES = 17;
fn void main() {
for (int i = 1; i < LINES / 2 + 2; i += 1) {
for (int j = 1; j < (LINES + 1) / 2 - i + 2; j += 1) {
io::print(" ");
}
for (int j = 1; j < i * 2; j += 1) {
io::print("*");
}
io::printn();
}
for (int i = 1; i < LINES / 2 + 1; i += 1) {
for (int j; j < i + 1; j += 1) {
io::print(" ");
}
for (int j = 1; j < ((LINES + 1) / 2 - i) * 2; j += 1) {
io::print("*");
}
io::printn();
}
}
Name
// Name
// Original version in BASIC:
// Example included in Vintage BASIC 1.0.3.
// http://www.vintage-basic.net
// This version in C3:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-03-09, 2025-03-12, 2025-03-18.
//
// Last modified: 20250731T1954+0200.
import std::io;
fn String acceptString(String prompt = "") {
io::print(prompt);
String! s = io::readline();
if (catch excuse = s) {
return "";
} else {
return s;
}
}
fn int! acceptInteger(String prompt = "") {
String s = acceptString(prompt);
defer free(s);
return String.to_int(s);
}
fn int acceptValidInteger(String prompt = "", String error = "Integer expected.\n") {
while (true) {
int! n = acceptInteger(prompt);
if (catch excuse = n) {
io::print(error);
} else {
return n;
}
}
}
fn void main() {
String name = acceptString("What is your name? ");
defer free(name);
int number = acceptValidInteger("Enter a number: ");
io::printfn("number=%s", number);
for (int i = 0; i < (number); i += 1) {
io::printfn("Hello, %s!", name);
}
}
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 C3:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-03-08.
//
// Last modified: 20250308T2019+0100.
// Modules {{{1
// =============================================================================
import std::io;
import std::math::random;
import std::thread;
// Terminal {{{1
// =============================================================================
const int BLACK = 0;
const int RED = 1;
const int GREEN = 2;
const int YELLOW = 3;
const int BLUE = 4;
const int MAGENTA = 5;
const int CYAN = 6;
const int WHITE = 7;
const int DEFAULT = 9;
const int STYLE_OFF = 20;
const int FOREGROUND = 30;
const int BACKGROUND = 40;
const int BRIGHT = 60;
const int NORMAL_STYLE = 0;
fn void moveCursorHome() {
io::print("\e[H");
}
fn void setStyle(int style) {
io::printf("\e[%sm", style);
}
fn void resetAttributes() {
setStyle(NORMAL_STYLE);
}
fn void eraseScreen() {
io::print("\e[2J");
}
fn void clearScreen() {
eraseScreen();
resetAttributes();
moveCursorHome();
}
const int DEFAULT_INK = FOREGROUND + WHITE;
const int INPUT_INK = FOREGROUND + BRIGHT + GREEN;
const int TITLE_INK = FOREGROUND + BRIGHT + RED;
// User input {{{1
// =============================================================================
fn String acceptString(String prompt = "") {
io::print(prompt);
String! s = io::readline();
if (catch excuse = s) {
return "";
} else {
return s;
}
}
fn void pressEnter(String prompt = "") {
String discard = acceptString(prompt);
free(discard);
}
// Title and credits {{{1
// =============================================================================
// Print the title at the current cursor position.
//
fn void printTitle() {
setStyle(TITLE_INK);
io::printn("Poetry");
setStyle(DEFAULT_INK);
}
// Print the credits at the current cursor position.
//
fn void printCredits() {
printTitle();
io::printn("\nOriginal version in BASIC:");
io::printn(" Unknown author.");
io::printn(" Published in \"BASIC Computer Games\",");
io::printn(" Creative Computing (Morristown, New Jersey, USA), 1978.\n");
io::printn("This improved remake in C3:");
io::printn(" Copyright (c) 2025, Marcos Cruz (programandala.net)");
io::printn(" SPDX-License-Identifier: Fair");
}
// Main {{{1
// =============================================================================
DefaultRandom rand;
fn void randomize() {
random::seed_entropy(&rand);
}
fn bool isEven(int n) {
return n % 2 == 0;
}
fn void play() {
randomize();
const int MAX_PHRASES_AND_VERSES = 20;
// counters:
int action = 0;
int phrase = 0;
int phrases_and_verses = 0;
int verse_chunks = 0;
while VERSE: (true) {
bool manage_the_verse_continuation = true;
bool maybe_add_comma = true;
switch (action) {
case 0:
case 1:
switch (phrase) {
case 0:
io::print("MIDNIGHT DREARY");
break;
case 1:
io::print("FIERY EYES");
break;
case 2:
io::print("BIRD OR FIEND");
break;
case 3:
io::print("THING OF EVIL");
break;
case 4:
io::print("PROPHET");
}
break;
case 2:
switch (phrase) {
case 0:
io::print("BEGUILING ME");
verse_chunks = 2;
break;
case 1:
io::print("THRILLED ME");
break;
case 2:
io::print("STILL SITTING…");
maybe_add_comma = false;
break;
case 3:
io::print("NEVER FLITTING");
verse_chunks = 2;
break;
case 4:
io::print("BURNED");
}
break;
case 3:
switch (phrase) {
case 0:
io::print("AND MY SOUL");
break;
case 1:
io::print("DARKNESS THERE");
break;
case 2:
io::print("SHALL BE LIFTED");
break;
case 3:
io::print("QUOTH THE RAVEN");
break;
case 4:
if (verse_chunks != 0) {
io::print("SIGN OF PARTING");
}
}
break;
case 4:
switch (phrase) {
case 0:
io::print("NOTHING MORE");
break;
case 1:
io::print("YET AGAIN");
break;
case 2:
io::print("SLOWLY CREEPING");
break;
case 3:
io::print("…EVERMORE");
break;
case 4:
io::print("NEVERMORE");
break;
}
break;
case 5:
action = 0;
io::printn();
if (phrases_and_verses > MAX_PHRASES_AND_VERSES) {
io::printn();
verse_chunks = 0;
phrases_and_verses = 0;
action = 2;
continue VERSE;
} else {
manage_the_verse_continuation = false;
}
}
if (manage_the_verse_continuation) {
thread::sleep_ms(250);
if (maybe_add_comma && !(verse_chunks == 0 || random::next_double(&rand) > 0.19)) {
io::print(",");
verse_chunks = 2;
}
if (random::next_double(&rand) > 0.65) {
io::printn();
verse_chunks = 0;
} else {
io::print(" ");
verse_chunks += 1;
}
}
action += 1;
phrase = random::rand(5);
phrases_and_verses += 1;
if (!(verse_chunks > 0 || isEven(action))) {
io::print(" ");
}
} // verse loop
}
fn void main() {
clearScreen();
printCredits();
pressEnter("\nPress the Enter key to start. ");
clearScreen();
play();
}
Sine Wave
// Sine Wave
//
// Original version in BASIC:
// Creative Computing (Morristown, New Jersey, USA), ca. 1980.
//
// This version in C3:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-03-07.
//
// Last modified: 20250731T1954+0200.
import std::io;
fn void clearScreen() {
io::print("\e[0;0H\e[2J");
}
fn String acceptString(String prompt = "") {
io::print(prompt);
String! s = io::readline();
if (catch excuse = s) {
return "";
} else {
return s;
}
}
fn void pressEnter(String prompt = "") {
String discard = acceptString(prompt);
free(discard);
}
fn String[2] getWords() {
clearScreen();
String[2] word = {"", ""};
String[2] order = {"first", "second"};
for (int n = 0; n <= 1; n += 1) {
while (word[n] == "") {
io::printf("Enter the %s word: ", order[n]);
word[n] = acceptString();
}
}
return word;
}
fn void printCredits() {
clearScreen();
io::printn("Sine Wave\n");
io::printn("Original version in BASIC:");
io::printn(" Creative Computing (Morristown, New Jersey, USA), ca. 1980.\n");
io::printn("This version in C3:");
io::printn(" Copyright (c) 2025, Marcos Cruz (programandala.net)");
io::printn(" SPDX-License-Identifier: Fair\n");
pressEnter("Press Enter to start the program. ");
}
fn void draw() {
clearScreen();
String[2] word = getWords();
bool even = false;
for (double angle = 0.0; angle <= 40.0; angle += 0.25) {
int spaces = (int)(26.0 + $$floor(25.0 * $$sin(angle)));
for (int i = 0; i < spaces; i += 1) {
io::print(" ");
}
io::printn(word[(int)even]);
even = !even;
}
free(word[0]);
free(word[1]);
}
fn void main() {
printCredits();
draw();
}
Stars
// Stars
//
// Original version in BASIC:
// Example included in Vintage BASIC 1.0.3.
// http://www.vintage-basic.net
//
// This version in C3:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-03-18.
//
// Last modified: 20250731T1954+0200.
import std::io;
fn String acceptString(String prompt = "") {
io::print(prompt);
String! s = io::readline();
if (catch excuse = s) {
return "";
} else {
return s;
}
}
fn int! acceptInteger(String prompt = "") {
String s = acceptString(prompt);
defer free(s);
return String.to_int(s);
}
fn int acceptValidInteger(String prompt = "", String error = "Integer expected.\n") {
while (true) {
int! n = acceptInteger(prompt);
if (catch excuse = n) {
io::print(error);
} else {
return n;
}
}
}
fn bool isYes(String s) {
String lowercase_s = String.new_ascii_to_upper(s);
defer free(lowercase_s);
switch(lowercase_s) {
case "OK":
case "Y":
case "YEAH":
case "YES":
return true;
default:
return false;
}
}
fn void main() {
String name = acceptString("What is your name? ");
defer free(name);
io::printfn("Hello, %s.", name);
int stars = 0;
while (true) {
stars = acceptValidInteger("How many stars do you want? ");
for (int n = 0; n < stars; n += 1) {
io::print("*");
}
io::print("\nDo you want more stars? ");
String answer = acceptString();
defer free(answer);
if (!isYes(answer)) {
break;
}
}
}
