# Doom

![Doom icon](pwa-512x512.png "Doom icon")

`doom` runs the original shareware episode of Doom in WebAssembly on an RCWeb shared display. Open `/doom/?r=<room>` and scan the on-screen QR code to join the same room with the companion [`doom-c`](../doom-c/appinfo) touch controller.

## About the game

Doom is id Software's landmark 1993 first-person shooter. This app contains the original shareware campaign, Episode 1: Knee-Deep in the Dead. Its nine maps take the player through the demon-infested UAC facilities on Phobos, including one secret level.

The player explores mazes, collects weapons, ammunition, health, armour, and coloured keys, fights monsters, and finds the exit to each level. The campaign, enemy behaviour, map logic, status bar, menus, sound effects, and music are all produced by the original game data and the WebAssembly Doom engine. This RCWeb adaptation adds a shared-screen presentation and remote phone controls without moving the game simulation away from the viewer.

## Player setup

- The viewer shows the game canvas, controller connection status, and the standard RCWeb QR panel.
- When a viewer window is square, portrait, or otherwise no wider than a 4:3 aspect ratio, the inline QR panel is replaced by a `Show QR code` button that opens the same controller link in a modal. Wider layouts keep the QR code visible in the right-hand panel.
- Scanning the QR code opens `/doom-c/` with the current room details, so the phone connects to the correct display.
- Doom is single-player. The first connected phone owns the controls; after it disconnects, another controller can take over immediately when RCWeb reports its departure or after a seven-second presence timeout.
- A refreshed controller keeps its RCWeb identity and reclaims control automatically when its WebSocket reconnects.

## Controls

- Drag the phone stick vertically to move forward or backward and horizontally to turn. Diagonal drags hold both directions so Doom can move and turn simultaneously.
- Drag the separate Strafe slider left or right for sideways movement. It can be held together with movement, turning, firing, using, or running.
- Hold `Fire`, `Use`, or `Run`; tap `Weapon` to cycle weapon slots 1-7.
- The movement stick switches to single-step menu navigation while a Doom menu is open. Use `Menu` to open or close it, then `Select` or `Fire` to confirm the highlighted choice.
- A local keyboard uses this browser-safe mapping: W/S move, A/D strafe, left/right arrows turn, Q fires, E uses, Shift runs, Escape opens the menu, and Enter confirms.

## How RCWeb routes the controls

1. Both pages join the room named by their `?r=` URL through `/assets/core/comms.js`. The Doom viewer creates a QR link to `/doom-c/` with that same room, keeping unrelated rooms isolated.
2. The controller turns touch gestures into named actions such as `up`, `right`, `fire`, or `strafe-left`. It sends an action only when a control is pressed, changed, or released rather than continuously streaming joystick coordinates.
3. `rc.sendFunctionCall("doom", "doomApp.controlDown", ...)` and the matching `controlUp` call target only browsers running the `doom` app in that room. Each call includes the controller's current RCWeb client ID and its persistent controller identity.
4. RCWeb forwards the function call over its WebSocket. The viewer's global `doomApp` API validates that the sender owns the single-player controls, then converts the named action into the keyboard events expected by the WebAssembly engine.
5. Held actions remain pressed in the viewer until their matching release arrives. Independent actions can overlap, which makes diagonal movement and combinations such as running, strafing, and firing possible.
6. The viewer replies directly to the controller's client ID with `doomControl.receiveState`, reporting whether that phone owns the controls and whether Doom is loading, ready, or has failed.

The viewer is authoritative: the WAD, engine, game state, rendering, and audio remain in its browser. RCWeb transports control intent and connection status only; it does not run Doom on the server or copy the game state to the phone.

## Audio

Sound effects and music run through the viewer's browser audio context. If the viewer displays `Enable sound`, press it once on the display to satisfy browser autoplay rules. Episode 1 music is served locally from `/doom/music/`; the game does not depend on an external music host.

## Runtime and attribution

The viewer includes the shareware `doom.wad`, the WebAssembly engine, and locally served Episode 1 music from [farrelke/console-doom](https://github.com/farrelke/console-doom). The fixed WAD and OGG music are stored under `src/main/immutable/app/doom`; the viewer shell and replaceable JavaScript/WebAssembly engine are stored under `src/main/apps/app/doom`. See `UPSTREAM.md` and `COPYING-GPL-2.0.txt` in this app directory for source, license, and attribution details.
