Forget about the Vision Pro, or whatever Samsung just brought out, we all know that the pinnacle of computing fun has been released in 1982 in the form of the Commodore 64.
One of the coolest things you could show people when writing BASIC on it was the following one-liner:
10 print chr$(205.5 + rnd(1));:goto 10
Executed, this resulted in a diagonal endless maze:
What the one liner does is print a character with the PETSCII code 205
or 206
(or SHIFT + M
and SHIFT + N
) which are fat diagonal lines. It does that using the PRINT
command and the CHR$()
command which turns a number into a character, much like fromCharCode()
does in JavaScript. Luckily enough, the CHR$()
command doesn't care if it gets integers or floats. without the CHR$()
it would be a list of floats:
When you ended a PRINT command with a semicolon, the computer didn't add a new line but kept the cursor where it was.
Michael de Bree also has a version of this that is even shorter using Assembler and the D012
functionality, which stores the current scanline of the screen. He also pointed out that there is a whole book about this one liner and others that use faux random designs on the good old breadbox.
Now, let's try something similar in JavaScript. A classic approach would be nested for loops.
let out = '';
for (let y = 0; y < 10; y++) {
for (let x = 0; x < 40; x++) {
out += (Math.random() > 0.5 ? '\\' : '/');
}
out = out + '\n';
}
console.log(out);
This works, but doesn't look good.
The reason is that slash and backslash have too many pixels around them. UTF-8 has box drawing characters, which allows us to use two diagonals that have less whitespace, ╲
and ╱
respectively, or 2571 and 2572 in unicode.
Using this, and moving from classic nested loops to chained array methods, we can do the following:
console.log(new Array(400).fill().map((_, i) =>
(i % 40 === 0 ? '\n' : '') +
(Math.random() > 0.5 ? '\u2571' : '\u2572')
).join(''));
We create a new array of 400 items, fill it with undefined
and map each item. As the item is irrelevant, we use _
, but what's important is the index, so we send this one as i
. We then add a linebreak on every 40th character or an empty string. We then use Math.random()
and see if it is above 0.5
and add either ╲
or ╱
. We join the array to a string and log it out.
This looks better:
However, it doesn't have the WUT factor the original one liner had. Luckily enough the two unicode characters are also following one another, so we can use fromCharCode()
with Math.random()
to do the same. JS is not as forgiving as BASIC on Commodore64, so we need to round to the next integer and as we use unicode, fromCharCode()
also needs a 0x
to work:
console.log(new Array(400).fill().map((_, i) =>
(i % 40 === 0 ? '\n' : '') +
String.fromCharCode('0x' + '257' +
Math.round(Math.random() + 1))
).join(''));
Coding is fun. Let's do more of it without reason.
Want to do it live with a chance to get to the finals of the CODE100 coding competition? We run another edition of it in Amsterdam on the 29th of February. Apply here as a challenger!