GDT and Testing

In order to test the port of Dungeon (mainframe Zork) to Sharpee, I obviously needed a testing infrastructure. I had already implemented a transcript system that allows the author to create .transcript files and run the test harness. This is the transcript file for the mailbox:

title: Mailbox and Leaflet
story: dungeo
description: Test opening mailbox and reading the leaflet

---

# Examine the mailbox
> examine mailbox
[OK: contains "small mailbox"]
[EVENT: true, type="if.event.examined"]

# Open the mailbox
> open mailbox
[OK: contains "open"]
[EVENT: true, type="if.event.opened"]
[EVENT: true, type="action.success"]
[EVENT: false, type="action.blocked"]

# Search inside the mailbox
> search mailbox
[OK: contains "leaflet"]
[EVENT: true, type="if.event.searched"]

# Take the leaflet
> take leaflet
[OK: contains "take"]
[OK: contains "leaflet"]
[EVENT: true, type="if.event.taken"]

# Read it
> read leaflet
[OK: contains "DUNGEO"]
[EVENT: true, type="action.success"]

# Check inventory
> inventory
[OK: contains "carrying"]
[OK: contains "leaflet"]

# Put it back
> put leaflet in mailbox
[OK: contains "put"]
[EVENT: true, type="if.event.put_in"]
[EVENT: true, type="action.success"]

# Close the mailbox
> close mailbox
[OK: contains "close"]
[EVENT: true, type="if.event.closed"]
[EVENT: true, type="action.success"]

Sharpee is an event-based system, so being able to test text emissions and the existence of events or a lack of their existence is used to validate story development.

Of course we still have the issue of testing deep into the game and it would be tedious to setup the world model in a particular state before testing or running one super long transcript. The later versions of mainframe Zork had a debugging tool the player could use called GDT. It had the ability to be blocked with a code, but the last VAX implementation had gdtFLAG:1, so it was always available.

I dug up the entire command list and adapted it to the port. We had to make one change to the game engine, allowing a hook before CommandValidator, but that's an easy change to tolerate. It doesn't break continuity or architecture. We also have AuthorModel to allow GDT to make mutations in the world model without validation. This means the player can get things from anywhere at any time using the correct GDT command.

Original GDT Commands (38 total)

Display Commands (15)

CmdNameOriginal PurposeSharpee Equivalent
DRDisplay RoomsShow room propertiesList room entities with traits
DODisplay ObjectsShow object propertiesList object entities with traits
DADisplay ADVSShow adventurer stateShow player inventory, location, score
DCDisplay CEVENTShow clock eventsList active daemons/fuses (ADR-071)
DXDisplay ExitsShow room exitsList room connections
DHDisplay HacksShow debug varsShow thief activity, sword glow, etc.
DLDisplay LengthsShow array sizesShow entity counts by type
DVDisplay VillainsShow villain stateShow NPC state (ADR-070)
DFDisplay FlagsShow game flagsShow world state flags
DSDisplay StateShow overall stateShow turn count, score, game phase
DNDisplay SwitchesShow switch valuesShow boolean world state
DMDisplay MessagesShow message indicesList message IDs
DTDisplay TextPrint text by indexPrint message by ID
DPDisplay ParserShow parser stateShow last parse result
D2Display ROOM2Secondary room dataShow room metadata
DZDisplay PuzzlePuzzle room gridShow Royal Puzzle state

Alter Commands (9)

CmdNameOriginal PurposeSharpee Equivalent
AHAlter HERETeleport playerMove player to room by ID
AOAlter ObjectsMove objectsSet entity location
ARAlter RoomsModify room propsSet room traits
AFAlter FlagsModify game flagsSet world state
ACAlter CEVENTModify timersAdjust daemon/fuse timing
AAAlter ADVSModify playerSet score, inventory, etc.
AXAlter ExitsModify connectionsAdd/remove room exits
AVAlter VillainsModify NPC stateSet NPC properties
ANAlter SwitchesModify switchesSet world booleans
AZAlter PuzzleModify puzzleSet Royal Puzzle state

Villain Toggle Commands (8)

CmdNameOriginal Purpose
NCNo CyclopsDisable cyclops
NDNo DeathsEnable immortality
NRNo RobberDisable thief
NTNo TrollDisable troll
RCRestore CyclopsRe-enable cyclops
RDRestore DeathsDisable immortality
RRRestore RobberRe-enable thief
RTRestore TrollRe-enable troll

Utility Commands (4)

CmdNameOriginal Purpose
TKTakeAcquire any object
PDProgram DetailToggle verbose debug
HEHelpList GDT commands
EXExitReturn to game

We did not implement AF and DF since those are unique to the MDL/Fortran implementations.

Here's a transcript test for GDT that shows its capabilities:

title: GDT Unrestricted Access
story: dungeo
description: Tests that GDT can access and manipulate entities regardless of visibility

---

# Uses the parsed command transformer to bypass entity validation

# Enter GDT mode
> gdt
[OK: contains "GAME DEBUGGING TOOL"]

# Test TK with multi-word entity name (not visible from starting location)
# The brass lantern is in the living room, not visible from West of House
> tk brass lantern
[OK: contains "Taken: brass lantern"]

# Verify we got it in inventory
> da
[OK: contains "brass lantern (i06)"]

# Test AO to move something to a location we're not in
# Move the lantern to the kitchen (single-word location)
> ao brass lantern kitchen
[OK: contains "Moved: brass lantern -> Kitchen"]

# Test DR to verify it moved
> dr kitchen
[OK: contains "brass lantern (i06)"]

# Take it back
> tk brass lantern
[OK: contains "Taken: brass lantern"]

# Test AO with special location 'player'
> ao brass lantern player
[OK: contains "Moved: brass lantern -> player inventory"]

# Verify in inventory
> da
[OK: contains "brass lantern (i06)"]

# Exit GDT
> ex
[OK: contains "Returning to game"]

# Verify we still have the lantern after exiting GDT
> inventory
[OK: contains "brass lantern"]

Subscribe to My So Called Interactive Fiction Life

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe