< CG Author Commentary #2: "Corner Pieces"
CG Author Commentary #3: "Rare Drop" >

[Comments] (4) Programmable Minecraft 2: Redstone Boogaloo: I think my first post in this series left me too optimistic about how much you could really do for Minecraft map designers without making programming easier. I did come up with three useful blocks, but I'm gonna save them for a brief follow-up, and in this post I'll go ahead and sketch out a ZZT-OOP-like language for Minecraft.

My reasons are fourfold: 1) This level of abstraction is what I really want, not the circuit stuff. 2) it's simpler to interpret a simple scripting language than to simulate an equally complex circuit. 3) Apparently the next big feature in Minecraft is official mod support, which means someone could actually implement this. 4) I think it's more important that people learn how to program than that they learn how to lay out electrical circuits.

So instead of last time's circuit-level Computer block, imagine a software Object block. An object can take the appearance of any other Minecraft block, or it can have a custom bitmap that's loaded from a map-specific resource directory. An object also has a script, which is probably loaded from a file because I really don't want to use Minecraft as an IDE. The script is where the magic happens.

Here's a ZZT-OOP manual. (I think it's a copy of the original manual, it seems very familiar.) ZZT-OOP is extremely primitive, but because it's so primitive it can be explained in a weblog post, and I'm still familiar with it despite not having used it for fifteen years. So let me adapt it to Minecraft and we'll see what happens.

You program an object in ZZT-OOP by defining its response to stimuli. In Minecraft, stimuli might include:

Maybe more. You get the idea. These are the events in the life of an Object.

You can program an object's response to a stimulus as a series of commands. A lot of these can be taken straight from ZZT-OOP:

Here's an object that tries to move north whenever it's hit with a snowball:

:hit_with snowball
?n

In ZZT-OOP, {direction} means one of: north, south, east, west, randomly, away from player, towards player, in the direction of current movement, etc. In Minecraft you also have up and down, as well as "along the minecart track", "towards the sun", and perhaps others. In a multiplayer scenario, "player" is ambiguous, so I guess it's the nearest visible player.

Some Minecraft-specific responses to stimuli:

Here's a perimeter trap.

:can_see zombie
"Zombie alert!"

Some bits of ZZT-OOP don't make sense in Minecraft because they assume that the world is relatively small and divided into screens. ZZT-OOP has global flags, and the only conditional you can write is "is this flag set"? I propose replacing the global flags with player flags. This lets you track a player's progress and simulate an RPG's "items too important to keep in your normal inventory". It also works in multiplayer.

Conditional statements: I'm undecided. I can think of three ways to go on this, but explaining them all seems boring. (I'm eliding boring stuff throughout, actually.) So for the time being, I'll follow ZZT-OOP, and allow an if statement to check player flags but nothing else.

Now it's time to talk about named stimuli. A named stimulus is one you give a custom name and send out whenever you want. Instead of giving an object code that's triggered by :can_see creeper, you can give it code that runs when some other object emits :i_am_completely_surrounded_by_obsidian.

In ZZT-OOP, the range of a message is the current screen. But Minecraft doesn't have screens. How far should a message travel? For that matter, on a large map with many objects, how many of those objects should be simulated? This wiki talk page indicates that a redstone circuit stops working if you get more than 281 blocks away. It seems fine to say that that's the maximum range of a message, and that objects further away from that won't have their code run.

Time to take a step back. ZZT-OOP is a very primitive language, but the system I laid out above is good enough to script objects that make adventure maps a lot more interesting. It's also useful when you're just playing around on a vanilla Minecraft map. You can program objects to build bridges, lay rail track, scout ahead to light up areas, or create computational sculpture.

To build one of these Object blocks outside creative mode, you'd need something like the Replicator block from last time. Call it the Assembler. You'd load code from a file on disk, and drop in an appropriate object for each line of code: grey wool for the stimulus :adjacent_to grey_wool, raw porkchop + gunpowder for the command spawn creeper. If your object was capable of destroying blocks, placing blocks, or exploding you'd also need to provide the appropriate tools or materials.

Once you put in the necessary items, the Assembler would output your Object, which you could place and it would go to work. The correspondence between resources and code opens up a whole new type of Minecraft puzzle: that of programming an object to do what you want, given limited resources.

So, there you go. I think this is pretty good. I just ripped off ZZT-OOP, but ZZT and Minecraft have a lot in common, so it works. Another option is to rip off Robotic, Megazeux's scripting language. I don't know Robotic, but it certainly has a more active community than ZZT-OOP. The language doesn't matter a whole lot. Really all you really need from the language is stimulus/response. The fun is in tying the language into the game world so that objects can act on it.

[Part 3]

Filed under:

Comments:

Posted by Jack Masters at Fri Dec 09 2011 07:43

It would be interesting to have things set up such that an object would need whatever resources a player would need to perform the activities it's doing. Like, if you want it to mine stone, you have to give it a pickaxe, that pickaxe would degrade as the object worked, and it couldn't harvest obsidian unless the pick you gave it was a diamond one.

This would make it considerably more complicated, and in some cases impossible, to create systems that worked indefinitely, but it would preserve more minecraft's resource management aspect. If an object with the code

?u
#put d diamond_block
#restart

requires only one block of diamond to seed the assembler, then the scarcity of a thing becomes irrelevent as soon as you find a single copy of it.

Posted by Leonard at Fri Dec 09 2011 07:56

Yeah, you can't put something you don't have. I was envisioning that tools for digging, exploding, putting, etc. would need to be placed into the object or harvested by its program. You could even program an object to craft things.

Posted by Jack Masters at Fri Dec 09 2011 08:41

If you wanted to expand the versatility of the language beyond ZZT-OOP, the two big things are an Object's ability to perceive the environment and the lack of variables.

It's not totally true what you said about if statements only checking flags. They can also check whether a certain kind of item is present in the room, and crucially, whether the object is next to a wall.

In ZZT, the only thing an Object can reliably find is the player, because they have the direction Seek and the variables Alligned (sic) and Contact. In all other respects they're like a blind man in a go-cart, who only knows if he's run into something. If you have one object wandering randomly around, there's essentially no way for another object to find it. Even if it happens to crash into it, it can't tell it from a wall without doing something like changing all the walls on the board into fake walls and seeing if the unknown obstacle disappears.

(On that note, changing all of something into something else is the major thing that ZZT objects can do that minecraft objects probably should not do.)

In three dimensions, the difficulty of finding something blind becomes even more problematic, and if Objects need to wander out into an unknown world and return to specific locations, or to find each other in order to resupply, this will become a major issue.

In ZZT, an Object can't even really keep track of its own position relative to a fixed point (at least not without a ridiculous amount of overhead), because there's no internal variables beyond zapping and restoring labels.

If you want to keep track of an integer, you do it by adding and subtracting torches from the player's inventory and hoping there are no dark boards in the game where they could actually use them.

If you want to keep track of a bunch of integers, you do it by writing down data on the board in the form of lines of breakable walls or boulders, and you then have to run around and do a manual headcount of them in order to read the values, because you're blind.

ZZT Objects were very strange things, like blind, deaf wizards with mittens on. They could turn all the air in a room into purple tigers with a snap of their fingers, but they couldn't tell a purple tiger from a green conveyor belt from a flashing rainbow scroll saying THIS IS NOT A TIGER from the entrance to a Pizza Hut without smooshing their face up against the entity in question and methodically (albeit very rapidly) transmuting every different type of item, creature, or terrain in the nearest acre into fake walls and back again, in the process erasing the text off of any scrolls and making the Pizza Hut's entrance into an eldritch portal to the title screen of the game, where the player has no choice but to beat their heads against the S in "SHAREWARE VERSION" until they die.

Posted by Jack Masters at Fri Dec 09 2011 08:51

They could also polymorph themselves into the shape of anything else in the game, but, like gumby, couldn't change color.


[Main] [Edit]

Unless otherwise noted, all content licensed by Leonard Richardson
under a Creative Commons License.