One of the first dopey programs written in BASIC back in the early ’80s, converted to TI graphing calculator BASIC, and then translated to HTML for the fun of having a flashback to the good ol’ days of Viewtron and coding on the TI-99/4A and IBM PCjr circa 1983.




PROGRAM:SKYLINE
:
:© Setup Window for CE Screen
:AxesOff
:BackgroundOff
:ClrDraw
:0->Xmin
:264->Xmax
:0->Ymin
:165->Ymax
:
:Lbl MN
:Menu(“SELECT SKYLINE”,”Random City”,A,”Paris”,B,”Giza”,C,”Quit”,Q)
:
:© — OPTION A: RANDOM CITY —
:Lbl A
:ClrDraw
:© Draw Sky
:For(I,0,100)
:Pt-On(randInt(0,264),randInt(50,165),WHITE)
:End
:
:© Draw Ground
:Line(0,0,264,0,GRAY)
:
:© Draw Buildings Loop
:0->X
:While X<264
:randInt(15,40)->W
:randInt(20,120)->H
:
:© Building Outline
:Line(X,0,X,H,NAVY)
:Line(X,H,X+W,H,NAVY)
:Line(X+W,H,X+W,0,NAVY)
:
:© Windows
:For(A,X+4,X+W-4,5)
:For(B,10,H-10,8)
:If randInt(0,1)
:Pt-On(A,B,YELLOW)
:End
:End
:
:X+W->X
:End
:Goto Z
:
:© — OPTION B: PARIS —
:Lbl B
:ClrDraw
:© Grass
:Line(0,10,264,10,GREEN)
:
:© Eiffel Tower Legs
:Line(100,10,132,130,BLACK)
:Line(164,10,132,130,BLACK)
:
:© Arches and Decks
:Line(110,45,154,45,BLACK)
:Line(122,85,142,85,BLACK)
:Line(100,10,164,10,BLACK)
:
:© Spire
:Line(132,130,132,150,RED)
:
:© Moon
:Circle(30,140,10,LTBLUE)
:Goto Z
:
:© — OPTION C: GIZA —
:Lbl C
:ClrDraw
:© Sand
:Line(0,20,264,20,ORANGE)
:
:© Great Pyramid
:Line(50,20,110,100,ORANGE)
:Line(110,100,170,20,ORANGE)
:
:© Smaller Pyramid
:Line(150,20,190,70,ORANGE)
:Line(190,70,230,20,ORANGE)
:
:© Sun
:Circle(200,140,15,YELLOW)
:Goto Z
:
:© — CLEANUP —
:Lbl Z
:Text(155,5,”PRESS ENTER”)
:Pause
:ClrDraw
:Goto MN
:
:Lbl Q
:ClrDraw
:AxesOn
:Output(1,1,”Done”)
Html simulation
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>TI-Basic Skyline Widget</title>
<style>
:root {
–ti-case: #333333;
–ti-screen-bg: #f0f0f0;
–ti-screen-border: #999;
–btn-blue: #3b82f6;
–btn-gray: #4b5563;
}
body {
font-family: ‘Courier New’, Courier, monospace;
background-color: #1a1a1a;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
color: white;
}
.calculator-case {
background-color: var(–ti-case);
padding: 20px;
border-radius: 20px;
box-shadow: 0 10px 25px rgba(0,0,0,0.5);
width: 100%;
max-width: 400px;
display: flex;
flex-direction: column;
gap: 15px;
}
.screen-container {
background-color: #000;
border: 4px solid #666;
border-radius: 8px;
padding: 2px;
position: relative;
}
canvas {
background-color: #000;
display: block;
width: 100%;
/* 3:2 Aspect Ratio matches standard calculator window broadly */
aspect-ratio: 264 / 165;
border-radius: 4px;
}
.screen-overlay {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 12px;
pointer-events: none;
text-shadow: 1px 1px 0 #000;
}
.controls {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
}
button {
padding: 12px;
border: none;
border-radius: 6px;
font-family: inherit;
font-weight: bold;
cursor: pointer;
transition: transform 0.1s, opacity 0.2s;
color: white;
font-size: 0.9rem;
}
button:active {
transform: translateY(2px);
}
.btn-city { background-color: var(–btn-blue); }
.btn-paris { background-color: #8b5cf6; }
.btn-giza { background-color: #d97706; }
.btn-clear {
grid-column: span 3;
background-color: var(–btn-gray);
margin-top: 5px;
}
.status-led {
width: 10px;
height: 10px;
background-color: #22c55e;
border-radius: 50%;
position: absolute;
top: 10px;
right: 10px;
box-shadow: 0 0 5px #22c55e;
}
</style>
</head>
<body>
<div class=”calculator-case”>
<div style=”display: flex; justify-content: space-between; align-items: center; padding: 0 5px;”>
<span style=”font-weight: bold; color: #ccc; letter-spacing: 1px;”>TI-84 Plus CE</span>
<div style=”display:flex; gap: 5px;”>
<div style=”width: 40px; height: 10px; background: #222; border-radius: 2px;”></div>
<div style=”width: 40px; height: 10px; background: #222; border-radius: 2px;”></div>
</div>
</div>
<div class=”screen-container”>
<div class=”status-led”></div>
<div class=”screen-overlay” id=”statusText”>Select Mode</div>
<canvas id=”skylineCanvas” width=”528″ height=”330″></canvas>
</div>
<div class=”controls”>
<button class=”btn-city” onclick=”drawCity()”>F1: City</button>
<button class=”btn-paris” onclick=”drawParis()”>F2: Paris</button>
<button class=”btn-giza” onclick=”drawGiza()”>F3: Giza</button>
<button class=”btn-clear” onclick=”resetScreen()”>CLEAR / MENU</button>
</div>
</div>
<script>
const canvas = document.getElementById(‘skylineCanvas’);
const ctx = canvas.getContext(‘2d’);
const statusText = document.getElementById(‘statusText’);
// Coordinate scaling to match the TI-Basic 0-264 / 0-165 coordinate system
// The canvas is defined as 528×330 (2x scale for crispness)
const SCALE_X = canvas.width / 264;
const SCALE_Y = canvas.height / 165;
// TI-Basic Colors mapped to CSS
const COLORS = {
WHITE: ‘#FFFFFF’,
GRAY: ‘#808080’,
NAVY: ‘#000080’,
YELLOW: ‘#FFFF00’,
GREEN: ‘#008000’,
BLACK: ‘#000000’,
RED: ‘#FF0000’,
LTBLUE: ‘#ADD8E6’,
ORANGE: ‘#FFA500’,
BG_NIGHT: ‘#111111’,
BG_DAY: ‘#87CEEB’
};
// Utility: Draw Line
function line(x1, y1, x2, y2, color, width = 2) {
ctx.beginPath();
// TI coords originate bottom-left usually, but standard canvas is top-left.
// We need to flip Y.
// Input Y: 0 is bottom, 165 is top.
// Canvas Y: 0 is top, 330 is bottom.
const cx1 = x1 * SCALE_X;
const cy1 = canvas.height – (y1 * SCALE_Y);
const cx2 = x2 * SCALE_X;
const cy2 = canvas.height – (y2 * SCALE_Y);
ctx.moveTo(cx1, cy1);
ctx.lineTo(cx2, cy2);
ctx.strokeStyle = color;
ctx.lineWidth = width * 2; // Thicker for visibility
ctx.stroke();
}
// Utility: Draw Point/Rect (filled)
function ptOn(x, y, color) {
const cx = x * SCALE_X;
const cy = canvas.height – (y * SCALE_Y);
ctx.fillStyle = color;
// Draw a small 4×4 pixel block to represent a “pixel” on the TI screen
ctx.fillRect(cx, cy, 4, 4);
}
// Utility: Draw Circle
function circle(x, y, r, color) {
const cx = x * SCALE_X;
const cy = canvas.height – (y * SCALE_Y);
const cr = r * SCALE_X; // Assume uniform scaling
ctx.beginPath();
ctx.arc(cx, cy, cr, 0, 2 * Math.PI);
ctx.fillStyle = color;
ctx.fill();
}
// Utility: Filled Rect (for buildings)
function fillRect(x, y, w, h, color) {
const cx = x * SCALE_X;
// Y is bottom of rect in TI logic
const cy = canvas.height – ((y + h) * SCALE_Y);
const cw = w * SCALE_X;
const ch = h * SCALE_Y;
ctx.fillStyle = color;
ctx.fillRect(cx, cy, cw, ch);
}
function clearDraw(bgColor = COLORS.BG_NIGHT) {
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function resetScreen() {
clearDraw(‘#000000’);
statusText.innerText = “MENU: SELECT OPTION”;
ctx.fillStyle = “white”;
ctx.font = “20px monospace”;
ctx.textAlign = “center”;
ctx.fillText(“TI-BASIC SKYLINE”, canvas.width/2, canvas.height/2 – 20);
ctx.font = “16px monospace”;
ctx.fillText(“1: Random City”, canvas.width/2, canvas.height/2 + 20);
ctx.fillText(“2: Paris”, canvas.width/2, canvas.height/2 + 50);
ctx.fillText(“3: Giza”, canvas.width/2, canvas.height/2 + 80);
}
// — OPTION A: RANDOM CITY —
function drawCity() {
clearDraw(COLORS.BG_NIGHT);
statusText.innerText = “Prgm: RUNNING…”;
// Draw Sky (Stars)
for(let i=0; i<50; i++) {
const rx = Math.floor(Math.random() * 264);
const ry = Math.floor(Math.random() * (165 – 50) + 50);
ptOn(rx, ry, COLORS.WHITE);
}
// Draw Ground
line(0, 0, 264, 0, COLORS.GRAY, 4);
// Draw Buildings Loop
let x = 0;
// Helper to prevent infinite loops if logic fails
let safety = 0;
const interval = setInterval(() => {
if (x >= 264 || safety > 50) {
clearInterval(interval);
statusText.innerText = “Done”;
return;
}
const w = Math.floor(Math.random() * (40 – 15) + 15);
const h = Math.floor(Math.random() * (120 – 20) + 20);
// Draw Building Body (Filled for HTML5 aesthetic, outlined in basic)
fillRect(x, 0, w, h, COLORS.NAVY);
// Draw Outline
line(x, 0, x, h, COLORS.WHITE, 1);
line(x, h, x+w, h, COLORS.WHITE, 1);
line(x+w, h, x+w, 0, COLORS.WHITE, 1);
// Windows
for (let a = x + 4; a < x + w – 4; a += 5) {
for (let b = 10; b < h – 10; b += 8) {
if (Math.random() > 0.5) {
ptOn(a, b, COLORS.YELLOW);
}
}
}
x += w;
safety++;
}, 100); // Slight delay for animation effect
}
// — OPTION B: PARIS —
function drawParis() {
clearDraw(‘#1a1a2e’); // Dark blue night
statusText.innerText = “Paris”;
// Grass
line(0, 10, 264, 10, COLORS.GREEN, 3);
// Eiffel Tower Legs
// Using fillPolygon for HTML5 solidity, but lines for outlines
// Left leg
line(100, 10, 132, 130, COLORS.GRAY);
// Right leg
line(164, 10, 132, 130, COLORS.GRAY);
// Arches and Decks
line(110, 45, 154, 45, COLORS.WHITE);
line(122, 85, 142, 85, COLORS.WHITE);
line(100, 10, 164, 10, COLORS.WHITE);
// Spire
line(132, 130, 132, 150, COLORS.RED);
// Moon
circle(30, 140, 10, COLORS.LTBLUE);
statusText.innerText = “Done”;
}
// — OPTION C: GIZA —
function drawGiza() {
clearDraw(COLORS.BG_DAY); // Sky blue
statusText.innerText = “Giza”;
// Sand
// Fill bottom
ctx.fillStyle = COLORS.ORANGE;
ctx.fillRect(0, canvas.height – (20 * SCALE_Y), canvas.width, 20 * SCALE_Y);
// Great Pyramid (Filled Triangle)
ctx.beginPath();
ctx.moveTo(50 * SCALE_X, canvas.height – (20 * SCALE_Y));
ctx.lineTo(110 * SCALE_X, canvas.height – (100 * SCALE_Y));
ctx.lineTo(170 * SCALE_X, canvas.height – (20 * SCALE_Y));
ctx.fillStyle = ‘#cd853f’; // Darker orange
ctx.fill();
// Outline
line(50, 20, 110, 100, ‘black’, 1);
line(110, 100, 170, 20, ‘black’, 1);
// Smaller Pyramid
ctx.beginPath();
ctx.moveTo(150 * SCALE_X, canvas.height – (20 * SCALE_Y));
ctx.lineTo(190 * SCALE_X, canvas.height – (70 * SCALE_Y));
ctx.lineTo(230 * SCALE_X, canvas.height – (20 * SCALE_Y));
ctx.fillStyle = ‘#d2691e’; // Chocolate
ctx.fill();
// Outline
line(150, 20, 190, 70, ‘black’, 1);
line(190, 70, 230, 20, ‘black’, 1);
// Sun
circle(200, 140, 15, COLORS.YELLOW);
statusText.innerText = “Done”;
}
// Initial Load
resetScreen();
</script>
</body>
</html>
https://svonberg.org/wp-content/uploads/2026/02/randomworlds.html
