Perslis Defense
Perslis Defense — the mechanical badger, the commanded runtime PERSLIS DEFENSE · DEMO · VDSG · THE COMMANDED RUNTIME

VDSG. Watch the runtime play.

Below is the floor at the wheel of id Software’s DOOM (1993, the shareware IWAD) and Wolfenstein 3D (1992), through the same contract as every other chapter: engine state becomes facts, the rules choose a goal from the admissible set, an evidence memory ranks inside it, and an actuator presses the buttons. There is no model anywhere in the loop. Every decision on the page is explicable from the situation report beside it.

The operator commands it in words — don’t fire, shotgun only, hold position — and an order can only narrow what the pilot may do. It never invents an action, it binds the learner as well as the rules, and when the world cannot satisfy it the order is refused with a reason, every decision, until it can be.

What you see is a recorded run replayed panel for panel from the snapshots the loop published; the live console runs on the operator’s machine (run it yourself). Nothing here is animated by hand.

The console

VDSG · commanded runtime

rules decide · evidence learns · your orders narrow what either may do — no model anywhere in the loop

arm v2.2 REPLAY
orders given during this run →
LIVE · FRAME WITH THE EYE’S CARDS●
Recorded frame from the engine with the eye's labels drawn over it
DECISION STATE-FLOW—
engine state→situation report→rules →orders→evidence→actuator

Every goal the rules could pursue here. An order removes goals from this set; the evidence memory ranks only inside what is left, so learning can never take an action that was forbidden.

SITUATION REPORTthe feed
waiting for the recording…

This is the whole input, built from engine state. The only thing that reads pixels is the eye, and its cards are a second witness, never the map.

TELEMETRY
RULES GENERALISED FROM THE TRACEPEEL tiles
  • nothing widened yet — a rule needs enough harmful encounters to stand clear of the base rate
LEARNING—

WHAT HAPPENED

    ● VDSG PROTOTYPE · ViZDoom on DOOM1.WAD v1.8 · tapped ECWolf on the WL6 data · research lane, nothing qualified

    What you are watching

    engine state  →  situation report  →  RULES (a goal from the admissible set)  →  ORDERS  →  evidence  →  actuator
                                                     ▲                                                           │
                                                     └──────  the goal, the reason, the receipts, the frame  ─────┘

    Seven goals — HEAL · DODGE · RETREAT · ATTACK · SEARCH · RESUPPLY · EXPLORE — in a fixed priority, each admissible only when its object is on the radar: you cannot ATTACK what is not in view, you cannot HEAL without a medikit. The rules are ~300 lines of plain Python with no weights and no state; the same report gives the same goal every time. The evidence memory is the arcade-floor mechanism from chapter 2, ranking inside the admissible set and never outside it.

    The navigator plans on the engine’s own sector geometry: an occupancy grid with doors, lifts, one-way ledges (Doom climbs 24 units and drops any) and keyed doors read from the WAD; the exit switch from the map’s line specials, verified against the engine’s spawn. Each decision on the page is a sentence — to the exit switch, at a yellow door without the yellow key, picked up the red key.

    Commanding it

    An order only narrows

    don’t fire removes the trigger; just dodge removes every goal but DODGE; shotgun only pins the weapon. The parser is a fixed phrase vocabulary with explicit negation — not a model — so text it does not recognise is refused, never guessed. An order can clear buttons; the only thing it ever sets is the weapon it named.

    Refused with a reason

    shotgun only with no shotgun carried is refused — no shotgun carried, every decision, on the receipts panel above, and comes into force the moment one is picked up. The order binds the evidence memory too: learning can rank only inside what the order left, so it cannot take an action you forbade. Enforced at five sites, one regression test each.

    In the DOOM recording the operator gives six orders — don’t fire, as you were, shotgun only, hold position — and the page shows each taken, refused or withdrawn as it happened. Press one in the console to jump to it.

    The eye

    The smallest vision system that can label a frame and range it: the streamed frame shrunk to 64×40, nine-bit colour weighted to the dark end (two bits per channel put 80% of real DOOM in one bin), one colour histogram per class — ceiling, floor, wall, door, enemy, pickup — and a column is whatever class explains its pixels best. Nothing is trained: it is taught by the engine while it plays. On Doom the label buffer names sprites, the grid says where doors are and the depth buffer says how far; on Wolfenstein a ray per column over the tile map does the same. Then it labels frames on its own, and the page shows the histograms filling, the agreement with the teacher and the range error.

    Distance is learned the way a raycaster draws it: height on screen × distance is one constant, so distance = k / height. Measured over 120 s runs: DOOM E1M1 agreement 78–92%; Wolfenstein MAP01 79%, k = 33 against a theoretical 32, range error ±7%. The eye’s own ranging on Doom is ±25–65% — the dark palette makes floor and wall the same colours at range — so where the engine has a depth buffer the pilot uses that as the first witness and the eye’s estimate is shown beside it (eye says 3.8 m). The depth buffer’s scale was measured, not assumed: linear in the perpendicular distance, 7.64 units per step for walls and 7.35 for sprites, over 1,336 + 367 credible samples with sub-unit residuals.

    How far, how fast

    The odometer

    How fast the pilot really moves and turns, read off what each command produced — the 80th percentile of clean full-forward samples, so bumping a wall does not lower it. DOOM: 47 units a decision, 12.8 m/s, calibrated within two seconds; Wolfenstein: 0.7 tiles. Every card then carries a time: door · grey · 12° right · 4.2 m · 0.4 s away.

    The stuck rule, calibrated and sized

    The core rule that binds every goal that moves: not moving forward → pivot; the same movement recurring → stuck, break out, never replan into the loop. Not moving is now judged against the measured pace — under 30% of what the command should have made. The escape pivots toward the deepest open space the eye sees (45–150°, in decisions at the engine’s turn rate) and walks clear for half that depth at the measured pace. Open space ahead yet not moving means something the eye cannot see blocks — a ledge, a body — and the sides alternate as before.

    The calibration found a bug the way calibration should: the Wolfenstein lane was running the stuck rule in DOOM units — five tiles a decision — 150 stuck events in 1,014 decisions, one every eight. In tiles: 9.

    Measured

    WhatMeasuredWhere
    Random / rules / rules + memory3.2 / 17.9 / 20.3 return on 32 seeds — parity, not a win (paired t = 0.78)Freedoom arena, chapter 2
    Kill creditKILLCOUNT is the map’s counter: a pilot ordered never to fire was still credited 55 kills. Damage dealt is the honest number.defect 8, published
    E1M1 (Hurt Me Plenty)cleared: exit switch at 52 s, 4 killsreal DOOM1.WAD
    E1M1 (Nightmare)not cleared in 8 tries, dies at 23–37 sreal DOOM1.WAD
    E1M2 (Hurt Me Plenty)shotgun taken at 10–20 s, red key held; dies at 167–207 s with 17–18 kills. Before weapon seeking it passed within 8.8 m of the chaingun and 16.7 m of the shotgun, never in view, and died with the pistol.real DOOM1.WAD
    The eyeagreement 78–92% (Doom), 79% (Wolf); range ±7% (Wolf), ±25–65% (Doom, own ranging)120 s runs
    Odometer47 units/decision = 12.8 m/s (Doom), 0.7 tiles/decision (Wolf)calibrated in ~2 s
    Stuck rule in the wrong units150 → 9 stuck events per 1,014 decisionsWolfenstein MAP01
    Wolfenstein doors583 of 1,275 decisions spent at doors; USE re-pressed every 0.7 s reverses an opening door in ECWolf — now pressed once, when shutMAP01

    Every figure measured in-house on the machine that recorded the run above; negatives included. Nothing here is qualified.

    Run it live

    The live console serves the same page from a local engine and takes orders as you type them. It needs the game data: DOOM1.WAD is rebuilt from the 1995 shareware installer, the Wolfenstein WL6 files from the 1992 release; both are in the archive, neither ships in the repository.

    python -m doom_floor.console --port 8099 --game doom-e1m1 --skill 5   # DOOM, Nightmare, 78 levels switchable
    python -m wolf_floor.console --port 8098 --level MAP01 --skill 3       # Wolfenstein 3D, 60 floors

    Then http://127.0.0.1:8099: pick a game, a level and a difficulty in the navigator, press play through to advance on every exit and retry on every death, and type an order.

    Limits

    PROTOTYPE. A research lane, nothing qualified. The pilot clears E1M1 on Hurt Me Plenty and not on Nightmare; it does not yet clear E1M2, and its own ranging on Doom is far worse than on Wolfenstein for the reason given above. The replay is a recording: the orders shown were given while it was recorded, and the page does not take new ones. The eye labels by colour alone and is honest about it — the agreement number on the panel is the whole claim.

    The open problem from chapter 6 stands here too: when risk and objective are coupled, failure avoidance alone does not learn the objective. Doom is where that is being measured.

    Next

    Chapter 2 — what we have actually measured, including where it fails →