Some years after I read this, I wrote http://canonical.org/~kragen/sw/dev3/lmu.py, which is a simple one-file text MUD. A little too simple, really: you can dig rooms, create objects, change their descriptions, pick them up, drop them, travel around, look at things, and chat with other players. But there's no way to program the objects to have behavior like walking around and picking things up.
It's a bit verbose for me to include a full transcript in an HN comment, but maybe this edited snippet gives a bit of the flavor, at least if you speak Spanish. Riyhor is the player's name.
? ver
Sipapu
Estás en un lugar borroso, sin mucha forma visible, con un pozo.
Sipapu contiene: Riyhor y pitbull.
? cavar este
Otro vacío
Estás en otra habitación sin características particulares.
Otro vacío contiene: Riyhor.
Hay salida hacia el oeste.
? renombrar aca El living
Ahora aca ya no es “Otro vacío” sino “El living”.
? describir aca como Es un lugar bastante chico con tres sillas y una mesa.
Descripción de “El living” cambiado.
? ver
El living
Es un lugar bastante chico con tres sillas y una mesa.
El living contiene: Riyhor.
Hay salida hacia el oeste.
The game world is pretty much just a Zork-style containment hierarchy, though implemented with Python lists and objects rather than linked lists, so, just as in Ultima, the player's possessions are children of the player, the player is a child of the room they're in, and all the rooms are children of the world. Pretty simple.
But it turned out that, despite having already read this story, I'd implemented my own version of the same bug! When you dig ("cavar") it creates a new exit and by default also a new room, but alternatively you can specify an existing room to dig into. But I'd forgotten to check that the destination was a room! Even though you couldn't program player-created game objects to pick things up, players could pick things up, and you could tunnel into a player, walk through the new exit into the player, pick up objects from their inventory, and walk back out. In fact, you could even dig into yourself. This did not cause other players to appear and start saying "Malkovich Malkovich Malkovich," for some reason.
It was a pretty entertaining bug for a few days of work.
Also: here's a very simple Logo Adventure I wrote: my first paid commercially published code. Terrapin wanted an example of a Logo program that demonstrated how to use list processing and functional programming, and they included it on the Terrapin Logo disk for the C64. It took advantage of the interactive Logo top level read/eval/print loop, so I didn't need to actually write a parser!
I played that one as well, still remember the hostname by heart. To be honest it wasn't too good compared with some English-speaking MUDs, but it was good to have an option in Spanish.
My favorite object containment related ZORK bug (which I discovered in the origin ZORK on MIT-DM, but which persisted in the InfoCom version), involves the troll holding an axe, blocking the door to the depths of the dungeon, who eats anything you give to him:
>GIVE AXE TO TROLL
The troll, who is not overly proud, graciously accepts the gift
and not having the most discriminating tastes, gleefully eats it.
The troll, disarmed, cowers in terror, pleading for
his life in the guttural tongue of the trolls.
To have killed him in cold blood then would have been cruel, so I tried something else:
>GIVE TROLL TO TROLL
The troll, who is not overly proud, graciously accepts the gift
and not having the most discriminating tastes, gleefully eats it.
*POOF*! No more troll!
(I've actually been able to successfully apply this technique of giving HN trolls their own weapons (quoting their own words back to them), then giving them to themselves (pointing them back to their previous posts), to make them disappear from HN!)
But giving the troll to itself triggered another bug, because apparently it forgot to clear the TROLL flag, so you could still not leave the room, because when you tried to go through the exit the troll previously blocked, it said that "The troll fends you off with a menacing gesture." even though there was no troll in the room.
Decades later I finally found the Zork source code, and it turns out there was actually a troll flag called "TROLL-FLAG!-FLAG" that it forgot to clear, which the exit depended on.
I wrote up the bug in more details, with links to the source code:
Is it OK to link to that source code from Wikipedia? I don't know who officially owns it, though. It was never a commercial product, and was developed at MIT. As the Zork article mentions, the Zork source code was leaked way back in 1977, so the cat's been out of the bag for a long time. A link to the actual source code would be a nice thing to cite in that section.
It is fascinating to read, and really beautiful code, quite understandable even if you don't know MDL, and practically a form of literature.
I played the original Zork on MIT-DM and also the Infocom versions of course. Reading the source code is like seeing the behind-the-scenes underground rooms and passages at Disneyland!
While I was playing Zork, I found a bug. First some context: when you're battling the troll, you can give things to him, and he eats them! Sometimes he drops his axe, and you can pick it up and kill him with it. He blocks the exits until you kill him.
So I tried "give axe to troll," and he ate his own axe, then cowered in terror: "The troll, disarmed, cowers in terror, pleading for his life in the guttural tongue of the trolls."
Not satisfied with that, I tried "give troll to troll", and he devoured himself: "The troll, who is remarkably coordinated, catches the troll and not having the most discriminating tastes, gleefully eats it."
...Except that I still could not get out of the exit, because every time I tried, it said "The troll fends you off with a menacing gesture."
I figured there must be a troll flag that wasn't getting cleared when the troll devoured itself. And sure enough, I found it in the code, and it's called "TROLL-FLAG!-FLAG"!
Here is an excerpt of the MDL troll code, where you can see the bug, where it should clear the troll flag when the troll devours itself, but doesn't (well that's how I would fix it!):
<COND (<VERB? "THROW" "GIVE">
<COND (<VERB? "THROW">
<TELL
"The troll, who is remarkably coordinated, catches the " 1 <ODESC2 <PRSO>>>)
(<TELL
"The troll, who is not overly proud, graciously accepts the gift">)>
<COND (<==? <PRSO> <SFIND-OBJ "KNIFE">>
<TELL
"and being for the moment sated, throws it back. Fortunately, the
troll has poor control, and the knife falls to the floor. He does
not look pleased." ,LONG-TELL1>
<TRO .T ,FIGHTBIT>)
(<TELL
"and not having the most discriminating tastes, gleefully eats it.">
<REMOVE-OBJECT <PRSO>>)>)
(<VERB? "TAKE" "MOVE">
<TELL
"The troll spits in your face, saying \"Better luck next time.\"">)
(<VERB? "MUNG">
<TELL
"The troll laughs at your puny gesture.">)>)
(<AND ,TROLL-FLAG!-FLAG
<VERB? "HELLO">>
<TELL "Unfortunately, the troll can't hear you.">)>>
Xardox (talk) 02:45, 15 January 2013 (UTC)
You can give something that you don't have? I was under the impression that it wouldn't work. Double sharp (talk) 13:17, 13 March 2013 (UTC)
You can give anything that's in the room or your inventory to the troll. So if his axe falls on the floor, "give axe to troll" will work without having to pick it up first, which is supposed to work. But even before he drops the axe you can go "give axe to troll" and he'll eat it while he's holding it, since it's transitively in the room. That's the first thing I did, that made me think of typing "give troll to troll"! Xardox (talk) 03:32, 30 March 2016 (UTC)
It's a bit verbose for me to include a full transcript in an HN comment, but maybe this edited snippet gives a bit of the flavor, at least if you speak Spanish. Riyhor is the player's name.
A slightly longer session is at https://pastebin.com/GSf4Bske.The game world is pretty much just a Zork-style containment hierarchy, though implemented with Python lists and objects rather than linked lists, so, just as in Ultima, the player's possessions are children of the player, the player is a child of the room they're in, and all the rooms are children of the world. Pretty simple.
But it turned out that, despite having already read this story, I'd implemented my own version of the same bug! When you dig ("cavar") it creates a new exit and by default also a new room, but alternatively you can specify an existing room to dig into. But I'd forgotten to check that the destination was a room! Even though you couldn't program player-created game objects to pick things up, players could pick things up, and you could tunnel into a player, walk through the new exit into the player, pick up objects from their inventory, and walk back out. In fact, you could even dig into yourself. This did not cause other players to appear and start saying "Malkovich Malkovich Malkovich," for some reason.
It was a pretty entertaining bug for a few days of work.