From 176c70de6b0e8521b1eaa62b117e84636808f448 Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Sun, 17 May 2026 12:10:21 -0500 Subject: [PATCH] Add future considerations section to ARCHITECTURE.md Documents the player-as-object goal and calls out the four specific places in the current design (Board.player, player_start, try_move, main.rs overlay) that will need to change when that's implemented. Co-Authored-By: Claude Sonnet 4.6 --- ARCHITECTURE.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index fe32e6e..b78db05 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -150,6 +150,32 @@ A direct mapping from palette character → `(Glyph, Element)` means the map fil --- +## Future considerations + +These are not current requirements but intended future directions. Where a planned change conflicts with current design, the tension is called out explicitly so it can be addressed before it becomes a problem. + +### The player may become an object; boards may have no player + +The long-term goal is for the "player" to be an object on the board that happens to respond to arrow key events — not a hardcoded special entity. Some boards may have no player-like object at all and do something else with input events (a cutscene, a menu, a puzzle that reacts to keys differently). + +ZZT hard-coded the player as a special element and many game authors had to work around this limitation (e.g. hiding the real player behind a wall and scripting a fake one). This is a deliberate improvement over that model. + +**Current design tension:** + +The following assumptions are baked in today and will need to change when this is implemented: + +- `Board.player: Player` is a required non-optional field. A board with no player can't be represented. This should eventually become `Option`, or the player should be removed from `Board` entirely and tracked by the engine layer only when present. + +- `player_start` in the map file is a required header field. It will need to become optional, or player spawning will move into the object/script system (an object with a special role, spawned at its `x`/`y` position). + +- `GameState::try_move` directly mutates `board.player`. Once the player is an object driven by Rhai, movement will go through the scripting dispatch layer instead. `try_move` will likely be replaced by something like `engine.dispatch_event(ArrowKey(dx, dy))`. + +- In `main.rs`, the player is rendered as a hardcoded overlay using `Glyph::player()`. Once the player is an object, it should be rendered as part of the normal object layer, not as a special case. + +None of these are blockers for current work, but avoid making `Board.player` more central than it already is (e.g. don't add methods that assume player presence, don't derive window sizing from player position). + +--- + ## ZZT reference ZZT (1991) was a text-mode game for DOS. Its playfield was 60×25 characters (the right 20 columns were the stats panel). Each board was a self-contained screen with objects (tiles with embedded ZZT-OOP scripts), passageways to adjacent boards, and a fixed element type system (about 50 built-in element types). Players could create worlds with the built-in editor and share `.ZZT` files.