Notes on Random Levels in ZZT

From Kangaroo Effects
Jump to navigation Jump to search

quick note: This is a page to tack notes on procedurally generated (ZZT generally lacking "seeds", this means "random") levels in ZZT. Random dungeons have been used in a lot of games to some degree or another, enjoying a brief fad in 2000-2003 or so, with a smaller piece or two besides.

Because ZZT is not advanced enough to generate things procedurally (as pure data) and then map them, either in board memory terms or in pure variable terms, you have to rely on what you do have: random directions, nine boolean flags, and a host of environmental contexts. There are therefore two lists of building blocks below: One pertaining primarily to objects (that run code), and the other pertaining primarily to environmental objects and enemies (boulders/sliders, slimes, etc.)

What do we want out of ZZT level generation?

For our purposes, we generally want something:

  • Fun
  • Interesting (or at least kind of interesting-looking)
  • Finish-abl

Generally, most games have shot for being actiony (DGN, Run-On, ED Gold) but some segments of Run-On and the more recent-ish backtrax are more puzzle-esque.

ZZT games have traditionally not been able to guarantee passability of generated levels, instead relying on nothing at all (especially egregious when it is more likely to occur, but more forgivable for most of these examples) or on a "cheat" provided by the creator to get players out of supremely bad generation RNG.

Rabbitboots who runs this wiki has provided some excellent starting points for solving this problem in terms of level layout that can be found in his 2018 Doodads world. KKairos has an idea or two as well, mostly for starting from "maze" level things and expanding that to something interesting.

This will be mostly about methods that are useful for quick levels for gameplay, but will acknowledge tangentially when things are really really cool despite being impractical as game level gen.

Important coding blocks

Obviously you'll need to do some coding; there are few if any situations where you can get the level to generate itself.

Objects

because they use ZZT-OOP to get the randomness and act on it. We need them. They come in two flavors:

  • Objects outside of the area of the board doing generation are probably doing gamerunning tasks or dice-rolls for the objects that are acting on level generation
  • Objects inside the area of the board doing generation are probably interacting with the environment before, after and during its generation. In a number of examples, these objects either #become (change type to) part of the environment or become (in their code) enemies for the player to fight. I'll have some more notes on environmental behaviors later on.

Directions

(see: almost every example of procedural ZZT level generation)

some variant of random directionality is used in basically all ZZT games with heavy procedural generation. I think possibly Ekso doesn't, but I'm still working on getting through the list.

really nearly all zzt randomness begins with the random directions in some way, shape, or form. it's the simplest way of getting randomness out of ZZT and the most environmentally predictable. Even in games that don't procedurally generate their levels, you frequently will see this used to round out RPG battle engines with a touch of the ol' RNG.

these are:

rndp <dir> (randomly perpendicular to the given direction) rndne (north or east) rndns (north or south)

rnd (n,s,e, or w, with the horizontal being twice as likely as the vertical, but e/w and n/s pairwise equally likely

and by extension:

rndp rndne (1 of 4 cardinal directions)

so if you need an object to do something at a 1/2 split, it can do rndne with block n and not e

if you need an object to do something with a 1/4 split, it can do rndp rndne with a block in each corner.

If you need to use rndne instead of rndp rndne, you can do it twice with a label that splits first into the "top" and "bottom" of a diceroll, then into the "top" and "bottom" of each split.

I haven't explored rnd yet much, but that's some interesting potential because it allows us to construct situations with likelinesses in 3rds and (at least partially) in 6ths. E.g. an object is 1/6th going to be this, 1/6th that, one 1/3rd thing 1 and 1/3rd thing 2.

Flags

(you have 9 of them, and they can help deliver information from one object to another, e.g. from an object in a dicerolling environment to a set of objects actually making the dungeon happen.

#change commands

You generally need these to change your environmental blocks into something presentable and playable. Sometimes you even need them to help with generation to start with.

Whatever it is Rabbitboots did with that maze walker

Presumably using a combination of all of the above and in an attempt to make KKairos's brain explode in wonder, Rabbitboots built a mazegen that works with only one object to build a small, medium or large maze. It's not really good for a game at this point mainly because it takes a long while to get a maze, but it's a really cool thing. You can find it in his doodads, which is the same place his concept for a walkable house-gen is.

Important environmental blocks

Flag alternatives (if you plan your level generation carefully you can minimize or eliminate use of flags)

If you can ensure that only one object of a type and can be on screen, you can replace some flag use in your dicerolling robot with #put <acceptable dir> <color> <gem>. Heck, if you can get it down further you can even use things like gem, torch, ammo, water, door. But to do that you have to basically keep those objects from being used in generation (or existing on the board) until you're done or almost done with level gen. Sometimes that's not practical, and to be honest, it seems a little extreme to me.

Another thing to note about flag alternatives is how intense they can get on the kb/board limits. "#set c0" even accompanied by "#clear c0", is likely, though not guaranteed, to at LEAST break even with several red/blue/cyan gem checks. Yours truly was working on a generator wherein he was going to replace 4/4 flags a board was capable of using with flag alternatives, but wound up bringing two flags back and using them together to sort of "simulate" having 3 or 4 flags at a cost of uniform distribution.

Boulders and sliders

(see: DGN series 2+, Run-On, LOST, CD/:ZZT)

They can push things and block things and they can be all 7 colors. That's very helpful for procedural generation if you only want to use a few objects, but you want the content to really shine in its scope.

Slimes

(see: Ekso, Endless Dungeon Gold, one room of Kerfuffle!)

Slimes move erratically, and every turn you can #change the breakables they leave into one thing and leave the huge amoeba going, ready for the next #change. That makes them an interesting, if unpredictable, choice for low-cost level generation in terms of KB.

Bombs

(see: Regeneer Caverns)

Bombs create (temporarily) "breakable" objects of various and sundry colors that aren't predictable even though they occur in a predictable oval pattern. This makes them ripe for generation potential, if you can grab them at the right time.

Invisible Walls

Invisible walls provide their own type and can be turned into other types of things, including space. This can make them helpful for helping objects environmentally map a dice-roll to an action.

Known Procedural Level Generation Engines in ZZT

This is just a list for now.

Pits of Pythor

By CoolZX CATFISH.ZZT in the Winter 2000 24 Hours of ZZT competition. Honestly these dungeons are more interesting than the Endless Dungeon GOLD work. And it feels the most truly "roguelike" of any of the generators here.

Does have some unpassable floors.

Dungeon Guru Nostalgia

Used objects in environment and also "rolling dice" to no great effect. Too many doors. Not even a proof-of-concept. many unpassable floors, none of them very interesting.

Dungeon Guru Nostalgia 2

Appears also in Maximum. Has a BenW variant in Ben There, Made This! and WiL's Ultimate variant in Run-On.

Minimal chance of unpassable floors, verified. Somewhat interesting level design.

Dungeon Guru Nostalgia Tower / 2.0

Minimal chance of unpassable floors, according to author.

Endless Dungeon GOLD

Slimes. Used object enemies. Multiple classes. Mildly interesting level design.

Run-On / v2.4

Very interesting, sliders'n'boulders, progression from left to right in most early levels. Very long game with multiple level gen engines.

LOST

Similar generation to Run-On, but allows running in all directions.

EKSO

Uses slime-gen.

Regeneer Caverns

Uses bombs.

Backtrax

Only "pacifist" game in this list that is known. Neat puzzle/arcade feel.

Misery (Demo)

Only appeared as a demo in a mini-magazine by Benco.

NO!

_God_'s NO! has a room with procgen. It's not superbly different or distinct from DGN or early Run-On generation.

Fishtrap

A comedy game by JunkPile (2002) that has some NO! quality segments where hallways are filled in.

Computer Dungeon Slash: ZZT

A variety of engines mostly producing mazes or maze-like things, usually. If you want to know how this works, I recommend playing it with Zeta once, then playing with Zeta and going "-dark" on a couple of generators, while opening it in KevEdit to see what the heck is happening.

Small Spaces (Upcoming)

Zephyr's room in the middle of his upcoming game uses some procgen, perhaps more notable for the appropriately small space. He's done some interesting things with probability.

Note from Zephyr:

My procgen room in small spaces used the procgen in Lancer's boss room as a template, so you should credit him on the page

And actually there are three different rooms with procgen, and the final boss room uses two different kinds

actually FOUR

actually FIVE

["Trace" Project] (Upcoming)

I have a couple varieties of engine in the mix which do things the same way as Backtrax with slightly better setup, but are designed for more action.

Other

Gobble d Gook

Helps build a board that can be used to assist in procedural generation of larger game maps, based on the input of a smaller map. I need to read it and use it more before I remotely understand what's happening.