# One-switch Doom experiment

This artifact asks whether an auto-scanning controller with one binary selection channel can complete real Doom-engine tasks. It runs against ViZDoom 1.3.0's bundled `basic` and `my_way_home` scenarios, records every switch selection, and publishes the raw trial data.

The automated experiment is a controller-sufficiency test, not a usability study. A policy observes engine state and decides which highlighted action it wants, but the only path from that policy to the engine is the same binary `select now` event exposed by the manual player. No disabled switch users were recruited, and the results must not be presented as evidence that the interface is comfortable, fast, or usable by a particular person.

## Reproduce the recorded matrix

Prerequisites: Python 3.10 or newer on a platform supported by ViZDoom.

```powershell
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe run_experiment.py
.\.venv\Scripts\python.exe verify_results.py
```

The full matrix runs six deterministic seeds at scan dwell times of 4, 9, and 18 Doom tics. ViZDoom's default rate is 35 tics per second, so those conditions correspond to approximately 114, 257, and 514 milliseconds per highlighted menu item.

For a fast installation check:

```powershell
.\.venv\Scripts\python.exe run_experiment.py --quick
```

The quick run writes `results-quick.json` and related quick-check files, so it does not overwrite the recorded 36-trial matrix.

## Play through the same one-switch interface

```powershell
.\.venv\Scripts\python.exe play_one_switch.py --scenario my_way_home --dwell-ms 500
```

The only gameplay selection input is `SPACE` or one mouse-button click. The highlight advances automatically, and activating the switch selects the yellow action. `ESC` closes the test harness; it is not sent to the game.

An adaptive switch that emits a Space key can use the same path. This code does not claim compatibility with every switch interface, mounting position, activation profile, or operating-system accessibility stack.

## Outputs

- `outputs/results.json`: environment, claim boundary, aggregate summaries, and all 36 trials.
- `outputs/results.sha256`: checksum for the recorded JSON.
- `outputs/trials.csv`: flat per-trial measurements.
- `outputs/evidence/`: first-party engine frames and switch event logs for selected successful and timed-out runs.
- `outputs/manual-session-*.json`: created only when someone runs the interactive player.

## Controller contract

The scanner presents three actions in a fixed cycle. At each highlight, the observer can either do nothing or activate one switch. A press executes the highlighted macro for a fixed number of Doom tics, then scanning restarts from the first menu item.

Combat menu:

1. Attack for 4 tics.
2. Strafe left for 3 tics.
3. Strafe right for 3 tics.

Maze menu:

1. Move forward for 8 tics.
2. Turn left for 2 tics.
3. Turn right for 2 tics.

The policy cannot directly call an engine action. It returns an action name; the scanner waits until that name is highlighted and emits the corresponding engine button only after one binary selection event.

## Boundaries

- The trials use ViZDoom's bundled research scenarios, not a complete commercial Doom campaign.
- The combat and navigation verbs are split across two scenarios.
- The automated policy reads labels, actor positions, and map sectors. A human player sees the rendered game and scanner instead.
- The reported elapsed engine time is controller-scheduled tics capped by each scenario's timeout; it is not wall-clock benchmark time.
- Six seeds per condition are enough to expose deterministic controller failures, not estimate population-level usability.
- Windows was the recorded platform. ViZDoom's own documentation recommends Linux or WSL for serious time- and resource-intensive experiments.
