zmachine game compatibility plan
=================================

goal: round out the hybrid z-machine interpreter by testing against a variety
of freely available IF games. find what breaks, fix it, build confidence that
the interpreter handles the spec correctly rather than just the two games we
built it against.

background
----------

the interpreter was shaped by tracing two specific games:

- Zork 1 (V3, 69 opcodes) — the Infocom classic
- Lost Pig (V8/V5, 61 opcodes) — modern Inform, 101K instructions

this means the implementation is biased toward what those two games exercise.
other games will hit different opcode combinations, edge cases in string
encoding, parser behaviors, object tree structures, and screen model usage.

version coverage
~~~~~~~~~~~~~~~~

V3, V5, and V8 cover essentially everything worth playing:

- V3: the Infocom catalog (Zork, Hitchhiker's, Planetfall, etc)
- V5: most modern Inform-compiled games (Photopia, Curses, Spider and Web)
- V8: V5 with x8 packed addresses (Lost Pig, some larger Inform games)

versions we are NOT targeting:

- V1/V2: original mainframe Zork only. almost nothing uses these.
- V4: tiny transitional version. Trinity is the notable game. maybe 5 games
  total ever published. if a V4 game trips a bug we'll fix it (the version
  gates already include V4 in the 4-5 range) but we're not seeking them out.
- V6: graphical z-machine. mouse, pictures, complex screen model. only a
  handful of late Infocom titles (Zork Zero, Shogun, Arthur, Journey). out
  of scope — the MUD is text.
- V7: almost nonexistent. maybe 1-2 games ever. not worth thinking about.

known stub opcodes
~~~~~~~~~~~~~~~~~~

the dispatch table is complete for V3/V5/V8, but ~12 opcodes have "TODO"
docstrings — they're registered but may not work correctly::

    op_set_colour       — color setting (can likely remain a no-op for MUD)
    op_throw            — throw to catch frame (needs real implementation)
    op_print_ret        — print embedded string + newline + return true
    op_save_v4          — V4 save (store result, not branch)
    op_restore_v4       — V4 restore (store result, not branch)
    op_piracy           — always branch true (standard behavior, stub is fine)
    op_sread_v4         — V4 input (like V3 sread but with timing)
    op_erase_line       — erase current line (display op, can be no-op)
    op_get_cursor       — get cursor position (display op, needs stub)
    op_not_v5           — bitwise NOT, VAR form (should be trivial)
    op_encode_text      — encode ZSCII to dictionary format
    op_print_table      — formatted table output

some of these are fine as no-ops (color, erase_line). others need real
implementations if games use them (throw, print_ret, encode_text).

phase 1 — acquire games
------------------------

download freely available z-machine games from the IF Archive
(https://ifarchive.org). all games below are free to distribute.

priority targets (well-known, diverse, good coverage):

V3 games::

    Hitchhiker's Guide to the Galaxy  — Infocom, nasty parser edge cases
                                         NOTE: check if freely available.
                                         Infocom titles are abandonware
                                         but not legally free. skip if
                                         we can't get a legit copy.

V5 games::

    Curses                — Graham Nelson, 1993. first Inform game. large,
                            exercises many opcodes. freely available.
    Photopia              — Adam Cadre, 1998. minimal puzzles, narrative
                            heavy, lots of text output. free.
    Spider and Web        — Andrew Plotkin, 1998. notoriously clever parser
                            tricks, unreliable narrator mechanic. free.
    Shade                 — Andrew Plotkin, 2000. small, atmospheric,
                            good smoke test. free.
    Anchorhead            — Michael Gentry, 1998. horror, larger game,
                            heavy object manipulation. original z-machine
                            version is free (later Inform 7 version is
                            commercial — use the original).
    Bronze                — Emily Short, 2006. tutorial-style, good for
                            testing standard patterns. free.
    Counterfeit Monkey    — Emily Short, 2012. complex, large, exercises
                            advanced Inform features. free.

V8 games::

    (Lost Pig already working — look for other V8 titles on IF Archive
    to broaden coverage if any exist)

also worth checking: games compiled with different Inform versions (Inform 5,
6, 7-to-Z) to catch compiler-specific patterns.

the agent doing this work should:

1. find each game on ifarchive.org or the author's site
2. download the story file (.z3, .z5, .z8)
3. verify the z-machine version byte (byte 0 of story file)
4. place in content/stories/ with a note about source/license

phase 2 — smoke test each game
-------------------------------

for each acquired game, run it through the interpreter and record results.

use the existing trace infrastructure::

    scripts/trace_zmachine.py   — V3 opcode tracing
    scripts/trace_lostpig.py    — V5/V8 opcode tracing

for each game:

1. run the trace script (or adapt it for the game)
2. record: how many instructions execute, which opcodes are used,
   where it crashes (if it crashes)
3. try interactive play for at least 10-15 commands
4. categorize the result:

   - WORKS: plays correctly, no crashes
   - CRASHES: hits an unimplemented or buggy opcode (record which one)
   - MISBEHAVES: runs but output is wrong (garbled text, wrong responses,
     display issues)
   - BLOCKS ON INPUT: hangs or mishandles input in some way

build a results table like::

    game              | version | result     | notes
    ------------------|---------|------------|---------------------------
    Curses            | V5      | CRASHES    | op_encode_text at 0x1234
    Photopia          | V5      | WORKS      | 45K instructions to prompt
    Spider and Web    | V5      | MISBEHAVES | status line garbled
    ...

phase 3 — fix failures
-----------------------

group failures by type and fix them:

missing/stub opcodes
~~~~~~~~~~~~~~~~~~~~

for each "TODO" opcode that a real game exercises:

1. read the z-machine spec (``zmach06e.pdf`` or inform-fiction.org/zmachine)
2. implement per spec
3. add a unit test
4. verify the game that triggered it now works

spec compliance bugs
~~~~~~~~~~~~~~~~~~~~

for opcodes that are implemented but behave wrong:

1. compare our implementation against the spec
2. check edge cases (signed vs unsigned, overflow, zero-length strings)
3. fix and add regression test

display/screen model issues
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

V5+ games use the screen model more aggressively than Zork or Lost Pig:

- window splitting, cursor positioning, text styles
- status line formatting
- output stream selection (stream 3 = memory table)

these may need MudScreen improvements. the MUD doesn't need pixel-perfect
screen emulation but it needs to not crash and should produce readable output.

string encoding edge cases
~~~~~~~~~~~~~~~~~~~~~~~~~~

different games exercise different parts of ZSCII:

- alphabet table switching (A0/A1/A2)
- abbreviations (V3 has 32, V5+ has 96)
- unicode extensions
- custom alphabet tables (some games define their own)

phase 4 — regression harness
-----------------------------

once games are working, build automated smoke tests:

- for each game, a script that feeds N commands and checks for crashes
- run as part of ``just check`` or a separate ``just smoke`` target
- catches regressions when we change the interpreter

the test doesn't need to verify game output is correct — just that the
interpreter doesn't crash, produces output, and reaches the input prompt.

something like::

    @pytest.mark.parametrize("game,commands", [
        ("zork1.z3", ["look", "open mailbox", "read leaflet"]),
        ("curses.z5", ["look", "inventory", "north"]),
        ("photopia.z5", ["look", "yes"]),
    ])
    def test_game_smoke(game, commands):
        """Run game through interpreter, feed commands, verify no crash."""
        ...

success criteria
----------------

- 5+ freely available games beyond Zork 1 and Lost Pig run without crashes
- all "TODO" stub opcodes that real games exercise have real implementations
- automated smoke tests prevent regressions
- the interpreter handles V3 and V5/V8 games from different compilers

non-goals
---------

- pixel-perfect screen emulation (we're a text MUD)
- V6 graphical games
- V1/V2 support
- multiplayer z-machine (separate effort, see mojozork-audit.rst)
- perfect Infocom compatibility (we care about freely available games first)

related documents
-----------------

- ``docs/how/if-journey.rst`` — integration vision and roadmap
- ``docs/how/mojozork-audit.rst`` — multiplayer z-machine audit
- ``docs/how/zmachine-performance.rst`` — performance profiling and optimization
- ``scripts/trace_zmachine.py`` — V3 opcode tracing
- ``scripts/trace_lostpig.py`` — V5/V8 opcode tracing
