# maze32 MVP ## 1. Product goal maze32 is a local browser-based multiplayer maze race hosted by one ESP32-C6. Two players explore the same maze in real time, search for their own keys and exits, and try to leave first. Up to four observers may watch the complete match. The MVP must produce a fair, playable match whose normal target duration is approximately five minutes. There is no match time limit. ## 2. Runtime model - One ESP32-C6 runs the HTTP server, WebSocket server, maze generator, and the authoritative game simulation. - Both players and all observers use ordinary web browsers. - Clients send intentions such as move or drop-key; they never determine the result of an action locally. - The server validates action order, movement cooldowns, collisions, item ownership, visibility, victory, and draws. - The server must never send hidden game state to a player client. Fog of war is enforced when constructing the server response, not merely by hiding elements in the browser. ## 3. Roles and lobby ### Players - Exactly two player slots exist: Player 1 and Player 2. - A player joins with a unique display name and receives a temporary session token. - The UI may suggest humorous available names. - The first player becomes the lobby owner and is the only player who may start the match. - The second player is a participant without start authority. - The match can start only when both player slots are occupied. - Refreshing the browser restores the same player, slot, position, inventory, and match state through the session token. ### Observers - Up to four observers may connect without a password. - Observers do not consume player slots. - Observers are read-only: they cannot start, pause, or control a match. - An observer sees the entire maze without fog of war, both current player positions, keys and their holders, exits, compasses, vision artifacts, match status, connection state, and final result. - An observer disconnect does not pause the match. ### Start sequence - When the lobby owner starts a ready match, both players receive the same `3-2-1` countdown. - Movement is rejected until the countdown completes. - Both players become active at the same authoritative server instant. ## 4. Maze ### Dimensions and representation - The initial configuration is `width = 32`, `height = 32`, or 1,024 cells. - Width and height are runtime configuration values and must not be hard-coded into game logic. - Movement is orthogonal between cells; diagonal movement does not exist. - Every playable cell and required object must be reachable. ### Symmetry and topology - Geometry uses central symmetry under a 180-degree rotation: `(x, y) -> (width - 1 - x, height - 1 - y)`. - Player 2's start, key, exit, and other fairness-relevant placements are the rotated counterparts of Player 1's placements. - The maze contains cycles, alternative routes, dead ends, and many passages between its conceptual halves. - Players can enter either half through multiple routes, but the UI must not identify a cell as belonging to either player. - The maze is not a perfect maze with only one route between points. ### Starts, keys, and exits - Players start at opposite, rotationally symmetric entrance cells. - An entrance is only the starting point; it is not the player's exit. - Each player has one unique key and one unique exit. - A key opens only its matching exit, and only the owner of that key and exit can win through them. - Key and exit pairs are placed rotationally symmetrically and at equal route distances for both players. - Each key begins outside its owner's initial field of view. - Each exit may be at any distant valid symmetric location. - Map generation must make finding the key at least as challenging as the subsequent search for the correct exit. Exact balance thresholds are tunable and must be validated through generation metrics and playtesting. ### Landmarks and generated objects - The maze contains visually distinctive landmarks to support human spatial memory even though explored territory is not retained. - Fairness-relevant landmarks and vision artifacts are generated in rotationally symmetric pairs. - The exact number and density of landmarks and artifact pairs are tunable balance parameters. The MVP must place more than one vision artifact. ## 5. Movement and player interaction - One accepted input moves a player by exactly one traversable cell in one of four directions: up, down, left, or right. - Players act independently; the server does not wait for alternating or simultaneous turns. - A small server-enforced minimum interval exists between accepted moves. Its value is configurable for playtesting. - Rejected movement into a wall does not change position and is not a successful move. - Players do not block each other and may occupy the same cell. - A meeting occurs when both players occupy the same cell. - There are no attacks, health, damage, or other combat mechanics in MVP. Browser controls must support: - keyboard movement on computers; - directional swipes on touchscreens; - an accessible drop-key action for both control modes. ## 6. Keys and inventory - A player may carry at most one key. - A player may pick up either key if the inventory slot is empty. - The carried key disappears from its map cell and becomes server-owned inventory state. - A player always sees which key they carry. - A player may voluntarily drop either their own or the opponent's key. It is placed on the player's current cell. - Entering a cell containing a key while already carrying one does not pick up the second key. - A player may carry the opponent's key elsewhere and drop it as sabotage. - When players meet, every carried key is automatically transferred to its correct owner. If both carry each other's keys, the keys swap owners in the same authoritative event. - Outside the current field of view, a player receives no information that the opponent found, dropped, or carries a key. - When the opponent is visible, their carried key identity is visible too. - A player cannot open or use the opponent's exit, even while carrying the matching opponent key. ## 7. Fog of war - Normal vision radius is three cells around the player. - Walls do not block vision. - For the MVP, radius uses a square/Chebyshev neighborhood: a radius of three exposes at most a `7 x 7` cell area, clipped by map boundaries. - Once a cell leaves the current vision area it becomes completely unknown again; there is no explored-map memory. - Hidden cells reveal neither maze geometry nor stale objects or player positions. - The opponent is visible only while inside the current vision area and disappears immediately after leaving it. - Observers are exempt from fog of war. ## 8. Vision artifacts and compasses ### Vision artifacts - The map contains multiple one-use vision artifacts. - Entering an artifact cell activates it immediately and removes it from the map; it cannot be stored or reused. - The effect increases vision radius from three to six cells. - The effect lasts for the next ten successful moves by that player. - Failed move attempts do not consume an effect move. - Additional artifact types are outside the MVP. ### Compasses - The maze contains two stationary compasses, one associated with each player's exit and placed fairly as a symmetric pair. - A compass cannot be picked up. - A player must enter the appropriate compass cell to activate its hint. - On activation, the UI displays an arrow pointing toward that player's own exit. - A compass does not reveal a route or the exit coordinates. ## 9. Exit, victory, and draw - A player can open only their own exit and only with their own key. - Opening the exit is not itself a victory. - After opening it, the player must perform one additional valid outward move beyond the maze boundary through that exit. - The server records the authoritative exit time. - The first player to complete the outward move wins. - If both authoritative exit times fall within a 200 ms window, the result is a draw. - The normal target match duration is approximately five minutes, but a connected match continues indefinitely until victory or another defined draw condition. ## 10. Connectivity and recovery ### Wi-Fi provisioning - In normal operation the ESP connects to a previously configured Wi-Fi network in station mode. - Network credentials are stored in NVS and reused after reboot. - When the configured network is unavailable or credentials have not been saved, the ESP starts a fallback access point. - The fallback web interface allows the user to configure and save an existing Wi-Fi network. ### Player disconnection - Loss of either player's WebSocket connection pauses the authoritative match. - No player movement or turn-based effect duration advances while paused. - The disconnected player has 60 seconds to reconnect with the existing session token. - A successful reconnect restores the same slot and resumes the same match state. - If the player does not reconnect within 60 seconds, the match ends in a draw. - Reloading a page is treated as a reconnect, not as leaving the match. ## 11. Browser presentation - The browser UI uses one dark, humorous retro arcade visual language across provisioning, lobby, player, and observer modes, as defined in `docs/UI_STYLE.md`. - All player-facing UI copy, game messages, and browser errors are in Russian. - The UI uses a near-black background, purple panels, turquoise interactive accents, yellow for Player 1, blue for Player 2, and plant-like green maze walls. Each player's matching key and exit use the same ownership color. Important state is distinguished by icons, labels, outlines, or shapes in addition to color; amber warnings and blue pause states use distinct treatments so they cannot be confused with player identity. - The player map consumes all space not required by fixed status and control panels. The player view supports a minimum `412 x 916` CSS-pixel viewport without page scrolling. - Computers and tablets support keyboard, swipes, and on-screen arcade controls. Phones show an always-visible four-button directional pad as the primary touch control while retaining avatar drag and directional swipes as optional alternatives. The pad sends only existing orthogonal movement intentions through the authoritative server path. - An always-visible `OK` control with a key icon drops the carried key without confirmation and exposes the Russian accessible label `Сбросить ключ`. - Observer mode requires at least a `1024 x 768` CSS-pixel viewport, initially fits the complete map, and supports zoom and pan. Smaller viewports show a Russian large-screen requirement message. - Sound and vibration are enabled by default after the first user interaction when the browser and device support them. - The application has no runtime internet dependency. It uses local assets, locally authored SVG icons, plain CSS, and a system monospace font styled to resemble a pixel font. ## 12. Technical constraints - Target: ESP32-C6FH4, 4 MB Flash, no required PSRAM. - Build: PlatformIO, `espressif32@7.0.1`, ESP-IDF, compatible `esp32-c6-devkitm-1` profile. - Flash layout: 2 MiB factory application and 1,984 KiB LittleFS; no OTA in MVP. - Static browser assets reside in LittleFS and should be compressed for the production image. - The complete compressed web payload must not exceed 1.5 MiB and must fit the unchanged 1,984 KiB LittleFS partition. - HTTP serves the application and provisioning pages; WebSocket carries live lobby, control, and match messages. - The initial LwIP socket limit is 16. - The implementation must be tested with two player connections and four simultaneous observer connections on the physical device. - Active lobby and match state may live in RAM and need not survive an ESP reboot. Wi-Fi settings must survive reboot. ## 13. MVP acceptance criteria The MVP is accepted when all of the following are demonstrated on the target board: 1. The firmware builds with the locked PlatformIO configuration and fits the application and LittleFS partitions. 2. Wi-Fi station setup persists in NVS, and failed station connection exposes the fallback access-point configuration flow. 3. Two browsers can claim unique player names, restore their slots after page refresh, enter the lobby, and start through the owner-controlled countdown. 4. Four additional browsers can observe the complete match simultaneously without receiving control authority. 5. Repeatedly generated `32 x 32` maps are connected, centrally symmetric, contain cycles and multiple cross-half passages, and preserve equal player-relative placement metrics. 6. Player clients never receive cells or dynamic objects outside their current allowed view; observer clients receive the complete state. 7. Keyboard and touch controls produce server-validated single-cell movement with an enforced configurable cooldown. 8. Key pickup, one-slot inventory, dropping, sabotage, automatic owner return, door restrictions, and visible-carried-key rules behave as specified. 9. Vision artifacts expand the view for exactly ten successful moves, and compass cells display the correct direction to the activating player's own exit. 10. An outward move through an opened own exit determines victory, and exits within 200 ms produce a draw. 11. A player disconnect pauses the match, reconnection restores it, and a 60-second reconnect timeout ends it as a draw. 12. A representative match normally completes in approximately five minutes after balance tuning, without imposing a hard match timer. 13. The Russian retro arcade UI follows `docs/UI_STYLE.md`, works at the required player and observer viewport sizes in the current stable Chrome, Safari, Firefox, and Edge releases, requires no runtime internet access, and stays within the 1.5 MiB compressed web-asset budget. ## 14. Explicitly outside MVP - More than two active players or more than one concurrent match. - More than four observers. - Persistent accounts, passwords, cloud services, matchmaking, or internet play. - Spectator control or moderation tools. - Physical display or gameplay buttons. - ESP-NOW, BLE multiplayer, or multiple-device game simulation. - Additional artifact types, combat, health, traps, or player elimination. - Persistent match recovery after ESP reboot. - OTA firmware partitions and OTA update flow. - Dependence on PSRAM, an unverified LED, or an assumed board pinout.