From Wiki of ZZT
Jump to navigation Jump to search
ZZT-OOP namedoor
Internal ID9 (0x09)
Character#char 10 (0x0A)
Other traits
Effect on movementwall
Uses ZZT-OOP color names?yes

The door element is one of the built-in puzzle elements of ZZT. It blocks the player's path unless the player has the corresponding key; together, they allow the designer to create a simple lock-and-key puzzle. When a door is touched without the player carrying its key, the game prints "The X door is locked!" where X is the color, and impedes the player. When the player touches the door while carrying its key, the game prints "The X door is now open." where X is the color, consumes the key, and replaces the door with an identically-colored empty. The engine uses the background color of the door to determine what color of key it requires.

By default, when creating a door, the engine creates a white-foreground element with a background color corresponding to the requested color. For example, any request for a blue door results an element that is white on dark blue (0x1F). This can be exploited with ZZT-OOP to programmatically create elements with a white foreground and a dark background color other than black, which is not normally possible, by using #put to overwrite the door with an applicable element (such as a key or a gem) or using the #change command to turn it into one. An external editor can be used to place any color of door the designer likes, as long as the background color matches the key that must be used to open it. Blinking doors (or bright-background doors if blinking is disabled) function identically to non-blinking (or dark-background) doors. A chart indicating the default door colors follows:

Default door color chart
ZZT-OOP name Element color
Blue white on dark blue (0x1F)
Green white on dark green (0x2F)
Cyan white on dark cyan (0x3F)
Red white on dark red (0x4F)
Purple white on dark purple (0x5F)
Yellow white on dark brown (0x6F)
White white on light gray (0x7F)

Black doors

While doors can be placed in all of the available colors, and black-foreground doors work with no issues, doors with black background colors (or dark-grey when blinking is disabled) will have glitched behavior when interacted with:

  1. Touching a door or opening one will create a garbled mess in place of the color name that includes "Blue", "Green", "Cyan", "Red" and "P";
  2. The player cannot open it unless they have at least 256 gems, whereupon the gems counter will be decremented by at least 256—or more.

Both of these are out-of-bounds errors related to the arrays used for keys, as follows:

Color naming

The color naming for pickup messages is handled by the ColorNames array in GAME.PAS line 92, which has entries for color indexes 1 to 7 of the CGA color palette. This is an array of strings up to eight characters in length. When the engine attempts to access the color name for index 0, the color black, it attempts to access the entry prior to the first entry, Blue, and goes out of bounds into where the preceding ProgressAnimStrings array exists in memory. It then fails to detect when an entry ends, and prints as much of the succeeding portion of memory as it can fit, producing the glitched message. When editing the engine, the bug can be fixed by changing the array range from 1 .. 7 to 0 .. 7 and adding 'Black', to the start of the array before 'Blue',.


The key counter in the world format is defined in GAMEVARS.PAS line 111, under TWorldInfo, as a boolean array named Keys which ranges from 1 to 7, covering CGA color indexes 1 to 7. Collecting the keys of these colors sets their equivalent boolean to "true", which is indicated internally as 01; when used, they are set to false, or 00. When the engine attempts to access the entry of this array for color index 0, the color black, it sets 00 in the byte prior to that of the Blue key, and in doing so goes out of bounds into the second byte of the gems counter, a 16-bit signed integer that thus uses the second byte to indicate units of 256. Because of this, the player's gems counter will be reset to just the amount covered by the first byte, from 0 to 255. The bug can be fixed by changing the Keys array range from 1..7 to 0..7, but doing so will also change the world format, making all standard world files incompatible with the engine.