From e0e2e84dc2ee1dfa180cfeea36fa224cb8e4f718 Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Mon, 9 Feb 2026 20:59:07 -0500 Subject: [PATCH] Add smoke test script for running Zork 1 through hybrid interpreter Loads zork1.z3, creates ZMachine with TrivialZUI, and runs interactively with graceful error handling for unimplemented opcodes. --- scripts/run_zork1.py | 103 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100755 scripts/run_zork1.py diff --git a/scripts/run_zork1.py b/scripts/run_zork1.py new file mode 100755 index 0000000..78c3985 --- /dev/null +++ b/scripts/run_zork1.py @@ -0,0 +1,103 @@ +#!/usr/bin/env -S uv run --script +"""Smoke test for hybrid z-machine interpreter with Zork 1.""" + +import sys +import traceback +from pathlib import Path + + +def main(): + # Add src to path so we can import mudlib + project_root = Path(__file__).parent.parent + sys.path.insert(0, str(project_root / "src")) + + from mudlib.zmachine import ZMachine + from mudlib.zmachine.trivialzui import create_zui + from mudlib.zmachine.zcpu import ( + ZCpuError, + ZCpuNotImplemented, + ZCpuQuit, + ZCpuRestart, + ) + + print("=" * 60) + print("Z-Machine Interpreter Test: Zork 1") + print("=" * 60) + print() + print("Loading story file: content/stories/zork1.z3") + + story_path = project_root / "content" / "stories" / "zork1.z3" + + if not story_path.exists(): + print(f"ERROR: Story file not found at {story_path}") + sys.exit(1) + + with open(story_path, "rb") as f: + story_bytes = f.read() + + print(f"Loaded {len(story_bytes)} bytes") + print() + print("Creating ZUI and ZMachine instance...") + + ui = create_zui() + zmachine = ZMachine(story_bytes, ui, debugmode=False) + + print("Starting interpreter...") + print("(Press Ctrl+C to exit)") + print() + print("-" * 60) + print() + + try: + zmachine.run() + print() + print("-" * 60) + print("Interpreter exited normally.") + + except ZCpuQuit: + print() + print("-" * 60) + print("Game quit via QUIT opcode.") + + except ZCpuRestart: + print() + print("-" * 60) + print("Game requested restart via RESTART opcode.") + print("(Restart not implemented in this test script)") + + except ZCpuNotImplemented as e: + print() + print("-" * 60) + print("FAILED: Unimplemented opcode encountered") + print(f"Error: {e}") + print() + traceback.print_exc() + sys.exit(1) + + except ZCpuError as e: + print() + print("-" * 60) + print("FAILED: Z-Machine CPU error") + print(f"Error: {e}") + print() + traceback.print_exc() + sys.exit(1) + + except KeyboardInterrupt: + print() + print() + print("-" * 60) + print("Interrupted by user (Ctrl+C)") + + except Exception as e: + print() + print("-" * 60) + print("FAILED: Unexpected error") + print(f"Error: {e}") + print() + traceback.print_exc() + sys.exit(1) + + +if __name__ == "__main__": + main()