Jev × Civilization II

September 18, 2026 · View on GitHub

An original Civilization II browser harness for TypeSafe Jev, with live decision probabilities and a Roman-themed spectator display. Under development; no complete-game victory has been verified yet.

The target is a full win as a male Roman leader, on a small map at Prince difficulty with five civilizations, restless tribes and standard rules.

The runtime uses the original Windows game in DOSBox/Windows 3.1, matching the browser version supplied for this project. Original game and Windows binaries stay in ignored local storage. This repository contains the harness, not those proprietary assets.

See the architecture plan and development record. The controller uses player-observable state, original game pixels and ordinary keyboard/mouse inputs. Named Jev Choice vectors cover empire policy, cities, research, diplomacy, units, exploration and warfare. Displayed values are action probabilities, not a probability of victory.

Local development

python3 -m venv .venv
.venv/bin/pip install -e .
python3 scripts/fetch_runtime.py
python3 -m civ2.server
# Open http://127.0.0.1:3920

For long campaigns, use the dedicated Chrome launcher. It gives each parallel game its own local server and isolated browser profile, with background page throttling disabled. The game remains embedded in the same spectator dashboard; /web/watch.html provides the read-only browser view.

For the faster optional WebAssembly backend, fetch its pinned assets and start a fresh runtime:

python3 scripts/fetch_modern_runtime.py
python3 -m civ2.launcher start --name campaign-modern --port 3930 --backend modern

The modern runtime notes describe the verified asset hashes and host pause fix. This changes the emulator host, while retaining the original game and the same observation, input and recording interfaces.

For the macOS OCR adapter:

mkdir -p .runtime
DEVELOPER_DIR=/Library/Developer/CommandLineTools swiftc scripts/ocr.swift -o .runtime/ocr

TypeSafe authentication is read by the Python client from TYPESAFE_API_KEY or an explicitly selected private env file. Credentials never enter the page or run evidence. Do not commit .env, downloaded games, profiles, or private files.

The current controller is experimental and pauses at unsupported native screens. Current runtime, strategy and recording limitations are tracked in campaign lessons. After building the OCR adapter, a debugging session can use native saves:

python3 -m civ2.boot
python3 -m civ2.run --initial-save .runtime/setup/initial.sav \
  --directory runs/attempt-001 --env-file /path/to/private/env

Install ffmpeg for continuous video capture. The dense spectator panel can show 16 command probabilities and separate independent Jev vectors in the same live/recording layout, plus recent evaluations when there is room. Native city labor includes calibrated worker reassignment and a fresh state check after every change. The optional unit-activation control lets Jev wake an identified fortified unit through the original city window after that review. Enable it with --unit-activation. Jev can also review disbanding a selected unit or transferring its home city through original controls; disbanding requires a separate model decision on the native confirmation. The persistent OCR worker reduces observation overhead. The researched strategy guide is included in actual Jev requests, with its revision and sources retained in the decision evidence.

The recording path uses a read-only Win16 observer, which reads the original game's state without a Save dialog or game-memory writes. Build its ignored runtime overlay, then use a fresh runtime:

python3 -m civ2.boot --port 3930 --profile final-001 \
  --directory .runtime/final-001-setup --no-saves
python3 -m civ2.run --port 3930 --no-saves \
  --setup-directory .runtime/final-001-setup --directory runs/final-001 --planning

Setup verifies that native autosave is off before model play. The original startup autosave, if created before that setting can be changed, is recorded explicitly; later new or modified game saves stop the run. Host observation capsules, screenshots and video are evidence files, not game saves. Native save-based debugging remains available separately.

Optional observed-target planning

The default controller asks Jev for each current unit command. The experimental Python option Session(..., planning=True) first lets Jev choose a persistent task and observed target, then makes a separate call for the next unit command. Every unit order is still independently model-selected from the same canonical actions. Planning executes no input, forces no path and uses no hidden map data.

Task choices and command choices have distinct evidence events, probability displays and counts. Plans are reviewed after observed completion, invalidation or bounded expiry. Add --planning to the CLI to enable it, and --port 3921 to select a separately prepared runtime. See planning setup, comparison and limitations for the Python entry point and parallel-runtime requirements. Neither mode has a verified complete-game victory yet.

Open /web/watch.html on a running server for a responsive, read-only live view without creating another emulator connection.

Acknowledgments

TypeSafe's System One / Jev demonstration inspired the probability display. Runtime provenance, licenses and version findings will be recorded in engine/. Civilization II is the original MicroProse game; this independent experiment is not affiliated with its owners.