Skip to content
HN On Hacker News ↗

Canon

▲ 111 points 35 comments by andrewjanke 6d ago HN discussion ↗

Pangram verdict · v3.3

We believe this text is mainly human-written, with some AI content.

5 %

AI likelihood · overall

Human
96% human-written 4% AI-generated
SEGMENTS · HUMAN 1 of 1
SEGMENTS · AI 0 of 1
WORD COUNT 1,775
PEAK AI % 1% · §1
Analyzed
Aug 18
backend: pangram/v3.3
Segments scanned
1 windows
avg 1775 words each
Distribution
96 / 4%
human / AI fraction
Verdict
Human
Pangram v3.3

Article text · 1,775 words · 1 segments analyzed

Human AI-generated
§1 Human · 1%

My eight year old daughter wants to make video games. She’s obsessed with this idea. She likes playing video games too, but it’s just not the same. Experiencing the world, even defeating the world, is too passive. She wants to make the world. So I made her a game where she can make games. A multiplayer world made of text and images and a tiny new scripting language, where she can take anything and everything apart to see how it works. I first learned to code in the days when View Source was a reliable teacher, and I think she deserves the same. The game has a lot of limitations. The language, Cant, is not a very good language, and that’s on purpose. But it also turned out to be a lot of fun. I call it: Canon is a modern, web-based take on the classic MUDs of the Old Internet. For the uninitiated: back before World of Warcraft made the MMORPG a big studio genre, we had text-based MUDs (and MUCKs and MUSHes) where players could adventure and socialize in vast realms made of pure written words. I spent countless hours exploring these imaginary places. I wanted to make something in that spirit that would feel more familiar to a modern audience. Canon has strong opinions about what makes a good MU*, and what makes a good learning environment. Every room, object, and interaction in Canon is player-created, and it can all be inspected, copied, and modified. The kiddo loves it. If you’re the kind of grownup who’s into roleplaying or text adventures, or has some nostalgia for the age of telnet and the early web, you might like it too. But first, recipe blog style, let me tell you how we got here. Training wheels for the bicycle for the mind Do you remember HyperCard? If not, do you remember Myst? (If not, congratulations on being young. Bear with me.) Bill Atkinson dreamed up HyperCard in 1985 after an LSD trip. I first encountered it in 1989, in my 4th grade computer lab, and also had my mind expanded. HyperCard works like this: there are cards. I mean, that’s pretty much it. That’s the genius. There are cards, and you can put computer things on them. Buttons and text and pictures and video. Cards get stacked together. A HyperCard app is called a “stack”. Get it? And then all those buttons and pictures and things: you can make them clickable. And you can tell them to move between cards in the stack. It’s a choose your own adventure book as UX. (If this sounds kind of like a web site, well, yes. HyperCard was one of the first real usable instances of HyperMedia and influenced Tim Berners-Lee’s development of the World Wide Web.) on mouseUp go to card id 123 end mouseUp That there is valid HyperTalk, the programming language underlying HyperCard. But for the most basic interactions like that – click a button, go to a card – you don’t even need to know HyperTalk. You can wire things up using a simple GUI editor. If you can click a button you can use HyperCard. And if you can use HyperCard, you can program HyperCard. I could write a whole series of posts about this. But the two things I want to impart to you now are as follows: HyperCard was magic. HyperCard sucked. It was magic and it sucked In many ways HyperCard stacks were not good apps. They were heavily constrained by the card metaphor. They used input elements from the MacOS visual language, but they did not, and could not, feel like normal native MacOS applications. HyperTalk made the same mistake later repeated by AppleScript: trying to make a programming language look more like natural language, thus failing to be either thing well. To any real programmer it was a frustrating underpowered environment. But those same flaws and constraints made it magically accessible to two hungry groups: non-programmers and curious kids. The first group produced a ton of stuff. The Internet Archive has a playable collection of thousands of stacks. If you remember the Early Web, just browsing the thumbnails should give you a familiar feeling. Games! Zines! Fandoms! Manifestos! Somehow porn! Before the web, people with a Mac and Something To Say traded stacks on floppies. I fell into the second camp. At nine years old I found HyperCard on my elementary school’s Macintosh SE and quickly discovered that unlike most computer programs, everything in HyperCard was editable. I started making the first thing that popped into my mind, which was a Street Fighter style fighting game with two crudely drawn players. Artist’s recreation. Alas, the original stack is lost to The Ages.Which is what I call the box of dead floppies in my parents’ basement. I didn’t know anything about programming, much less advanced gamedev concepts like sprites. But I knew I could link buttons to cards. So I did that. With the determination only a hyperfocused child can muster, I set about drawing individual cards for every possible combination of player moves and positions, with buttons as “controls” to move between them. I’d found me a hammer, and I could see how to make a game out of nothing but nails. You’re on card 154. Player 1 is in quadrant 2, idling. Player 2 is in quadrant 3, defending. If player 1 presses the “attack” button, go to card... It took me weeks staying late after school. But it worked. I made a game. I could play my own creation. I’ve spent my whole career chasing that high. But that was just the beginning. One of the really clever things Bill Atkinson did was to make it so when you edited HyperCard behaviors with the GUI, it just wrote the corresponding code for you. About halfway through my laborious clicking-and-linking project, I noticed the Script… button in the editor, pieced together its implications, and started using a copy & paste HyperTalk snippet and a systematic naming scheme for all my hundreds of cards to speed up development. Near the end the computer teacher (I’m pretty sure we just called the class “computers”) noticed what I was up to and dug the HyperCard Reference Manual out of a drawer for me. This was my first experience reading a tech manual cover to cover. Many years later… I’m not going to make my daughter learn HyperCard. I’m a bit of a Troll Dad, but not that mean. But I did want to reproduce the magical combination of creative freedom and mechanical constraints that made HyperCard so eye-opening for young Nick. Canon needed: Instant gratification. As soon as you put a thing on screen, it’s already part of the game. View Source. Everything in the game should be built with the game’s own tools, and freely editable/copyable/take-apart-able. A GUI for the simplest interactions. A smooth learning gradient from GUI to writing raw code. Just enough power in that code to build a wide range of fun game mechanics, and to teach basic programmer ways of thinking. But limited enough that a beginner could grasp the entire set of primitives. Instant gratification The great thing about a text-based world is that you can add anything you want just by typing “there is a [thing] here”. You’re constrained in how you can build – no fancy 3D visualizations or impressively realistic physics engines – but have unlimited freedom in what you can build. Canon is made of three things: Players Rooms Items Players and Rooms are both just text descriptions and, optionally, images. To make either, you just answer a question: what does this look like? View source Items are everything else. They are also text descriptions and images, so you can flavor an item as anything you want: an inanimate object, a pet, an NPC, a spell effect, a vehicle, a doorway, a quest marker, a message, etc. But in addition to text and images, items are also made of actions and state, via Cant. It looks like this: item "Hooded Lantern" { describe "An iron lantern with a hinged hood." on "light" { narrate "{player}’s {item} swings open and warm light spills out." } } That’s enough to produce a lantern the player can light: Here’s a slightly more complicated item, a magic 8-ball: item "Magic 8-Ball" { describe "A prophetic billiard ball. Give it a shake?" or "Give it a shake to see your future." or "Dare you shake it?" on "shake" { say "It is certain." or "Outlook good." or "Signs point to yes." or "Don’t count on it." or "My sources say no." or "Reply hazy, try again." or "Ask again later." } } The or keyword works anywhere Cant takes a text string. It randomly picks a variant each time the string is used: when a player looks at an item, or triggers an action. I wanted this baked into Canon at the lowest level. There’s something especially delightful, to a new programmer, about an RNG. You tell the computer what to do, and it does it. But you also told it to exercise a tiny bit of its own agency. It’s both surprising and not surprising. You programmed every response, you know all the things it can say, and yet you don’t know exactly what it will say when you press the key or click the button. It’s like suddenly being able to tickle yourself. Notice in addition to shake, this item has a clone button. Every item in Canon can be cloned. Items you own (which include anything you’ve cloned) can be edited. Every game or toy or quest made by another player is also a tutorial. A GUI for the simplest interactions The 8-ball is one of the first toys I made to tempt the kiddo. I left it lying in the starting zone. Even when you know nothing about conditional logic, even if you don’t look at the code, it’s easy to see how it works from a few minutes of playing with the ball. And it’s easy to imagine how you could modify it into a flipping coin, or an NPC that tells random jokes. Or, say, a D20: I am completely serious. If you are a programmer, one thing you might notice about this is that it’s horrible. This is an inefficient way to write something that could obviously be randInt(1,20). But it is extremely approachable. Cant is a language designed to be bad in educational ways. It’s optimized for ease of understanding over speed of writing. It’s the opposite of DRY. A smooth gradient from GUI to code