โšก DOOM-JEV: Autonomous ViZDoom Agent

September 17, 2026 ยท View on GitHub

Real-time autonomous Doom agent powered by TypeSafe's Jev SystemOne fast-inference model, featuring a decoupled asynchronous control loop, geometric raycasting, and an interactive Rich terminal HUD.


๐Ÿ“– Overview

DOOM-JEV pairs the classic id Software game engine (via ViZDoom) with TypeSafe Jev SystemOne, a low-latency model designed for rapid structured perception and real-time decision-making.

Instead of treating the game as a slow turn-based environment or suffering from network-induced stutter, DOOM-JEV decouples the engine tick rate from the network inference rate:

  • Simulation Loop: Runs at Doom's native 35 ticks/sec with smooth rendering and continuous physics.
  • Inference Loop: Runs asynchronously at ~10 Hz, querying structured decision trees from Jev SystemOne.
  • Carry-Hold Actuation: Between inference batches, the agent smoothly replays and adjusts its action space using real-time geometric tracking, ensuring 0 dropped frames.

๐Ÿ›๏ธ System Architecture

flowchart TD
    subgraph ViZDoom ["๐ŸŽฎ ViZDoom Engine (35 ticks/sec)"]
        State["Game State\n(Depth Buffer, Labels, Game Variables)"]
        Actuator["Actuation Execution\n(8-Channel Action Array)"]
    end

    subgraph Perception ["๐Ÿง  Perception & Serialization"]
        Depth["Depth Median Sampling & Sector Raycasting"]
        LOS["Line-of-Sight Filtering\n(Rendered Label IDs)"]
        YAML["YAML Situation Report"]
    end

    subgraph JevEngine ["โšก TypeSafe Jev SystemOne (Async ~10 Hz)"]
        Client["JevClient POST /v1/systemone"]
        Questions["Structured Questions\n(Macro Goal, Target, Movement, Rotation, Jump, Fire)"]
        Decision["JevResponse (Choices & Calibrated Confidences)"]
    end

    subgraph HybridControl ["๐ŸŽฏ Hybrid Composition DAG"]
        FineAim["Trigonometric Angle Tracking\n(Geometric Crosshair Bearing)"]
        AutoFire["Aggressive Zero-Hesitation Trigger Lock"]
        ActionMap["Action Mapping\n[ATK, FWD, BCK, L, R, TL, TR, JMP]"]
    end

    subgraph UI ["๐Ÿ“Š Terminal HUD & Interactive Control"]
        LiveHUD["Rich Live Terminal HUD"]
        Stdin["Live Command Hook (Dynamic Standing Orders)"]
    end

    State --> Depth & LOS
    Depth & LOS --> YAML
    YAML --> Client
    Stdin -.-> YAML
    Client --> Questions --> Decision
    Decision --> HybridControl
    State --> FineAim
    FineAim & Decision --> AutoFire --> ActionMap
    ActionMap --> Actuator
    YAML & Decision & ActionMap --> LiveHUD
    Actuator --> State

โœจ Key Features

  • Decoupled Asynchronous Loop: The ViZDoom engine ticks continuously while API requests run non-blocking in the background. If a network roundtrip takes 80โ€“120ms, the player never freezes.
  • Geometric Raycasting & Obstacle Detection: Combines ViZDoom's 3D depth buffer median analysis with 2D sector line-segment ray intersection to detect walls ahead, left, and right.
  • Line-of-Sight Target Filtering: Uses the rasterizer's rendered label buffer so the agent only targets hostiles that are actually visible on screen, preventing the model from hallucinating or shooting through solid walls.
  • Hybrid DAG Actuation:
    • Macro Guidance: Jev determines high-level strategy (engage, explore, flee, collect weapon).
    • Micro Geometry: Exact relative bearing trigonometric calculations steer the crosshair directly onto enemies with zero delay.
    • Zero-Hesitation Trigger Lock: Fires immediately when an enemy is within crosshair tolerance (โ‰ค15โˆ˜\le 15^\circ) or when firing confidence exceeds threshold.
  • Interactive Rich Terminal HUD: Displays real-time situational awareness:
    • Situation report (health, armor, weapons, ammo, visible threats, obstacles).
    • Decision DAG with color-coded confidence levels.
    • 8-channel actuation indicators.
    • Live roundtrip API latency (ms).
  • Dynamic Standing Orders: Update the agent's behavior live from the terminal prompt without restarting the simulation.

๐Ÿ“‚ Project Structure

doom-jev/
โ”œโ”€โ”€ agent/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ actuator.py          # Formats action tuples to 8-channel ViZDoom button inputs
โ”‚   โ”œโ”€โ”€ composition_dag.py   # Hybrid DAG merging Jev choices with ground-truth geometry
โ”‚   โ”œโ”€โ”€ jev_client.py        # Async HTTP client for TypeSafe Jev SystemOne API
โ”‚   โ””โ”€โ”€ state_serializer.py  # Raycasting, LOS filtering & YAML situation reporting
โ”œโ”€โ”€ config/
โ”‚   โ””โ”€โ”€ custom_scenario.cfg  # ViZDoom scenario configuration (buttons & game variables)
โ”œโ”€โ”€ logs/                    # Rotating API logs (git-ignored)
โ”œโ”€โ”€ ui/
โ”‚   โ””โ”€โ”€ terminal_hud.py      # Rich Live dashboard layout & confidence rendering
โ”œโ”€โ”€ .env.example             # Example environment file template
โ”œโ”€โ”€ .gitignore               # Ignores .env, logs, venvs, cache, and runtime configs
โ”œโ”€โ”€ main.py                  # Main async event loop & game orchestrator
โ””โ”€โ”€ requirements.txt         # Project dependencies

๐Ÿš€ Quick Start

1. Prerequisites

  • Python 3.10+ (tested on Python 3.14)
  • ViZDoom dependencies (Linux users may need standard SDL2 / Boost libraries if compiling from source)
  • A TypeSafe Jev API Key

2. Clone & Setup Environment

git clone https://github.com/your-username/doom-jev.git
cd doom-jev

# Create and activate virtual environment
python -m venv jevEnv
source jevEnv/bin/activate

# Install dependencies
pip install -r requirements.txt

3. Configure API Credentials

Copy .env.example to .env and add your TypeSafe API key:

cp .env.example .env

Edit .env:

TYPESAFE_API_KEY=your_actual_api_key_here
DOOM_SCENARIO=deathmatch.wad
DOOM_MAP=map01

4. Launch the Agent

python main.py

๐ŸŽฎ Controls & Live Interaction

Dynamic Standing Orders (Command Hook)

While the agent is playing, the terminal remains interactive! Type updated directives and press Enter to instantly shift the agent's behavior:

ORDERS: hunt all visible hostiles aggressively
ORDERS: retreat immediately and find medical supplies
ORDERS: explore corridors and look for a super shotgun

The new standing orders are injected into the next serialized state payload sent to Jev.


โš™๏ธ Configuration & Customization

You can switch scenarios, maps, or bot counts by passing environment variables:

Environment VariableDefaultDescription
TYPESAFE_API_KEY(Required)Your TypeSafe Jev API authentication key
DOOM_SCENARIOdeathmatch.wadScenario WAD file located in ViZDoom's scenarios directory
DOOM_MAPmap01Map identifier to load

Examples:

Run Deathmatch with 3 internal bots:

python main.py

Run Deadly Corridor scenario:

DOOM_SCENARIO=deadly_corridor.wad python main.py

๐Ÿ“Š Action Space (8 Channels)

The agent produces an 8-boolean action vector mapped in config/custom_scenario.cfg:

IndexButtonDescription
0ATTACKPrimary weapon fire (automated trigger lock)
1MOVE_FORWARDAdvance forward
2MOVE_BACKWARDBackpedal / retreat
3MOVE_LEFTStrafe left
4MOVE_RIGHTStrafe right
5TURN_LEFTYaw left (guided by target bearing / Jev)
6TURN_RIGHTYaw right (guided by target bearing / Jev)
7JUMPClear obstacles or projectile dodge

๐Ÿ“œ License

Distributed under the MIT License. See LICENSE for more information.