Skip to content

Latest commit

 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Evil Weevil

Code licence: MPL-2.0 Docs licence: CC-BY-SA-4.0 Quantum-Safe Provenance

Rhodium Standard Repository OpenSSF Scorecard SonarQube Quality Gate Archived in Software Heritage

Idris Inside Zig Zero-overhead FFI

A universally injectable enemy-intelligence kernel for computer games: host-agnostic and deterministic, with an Idris2-verified C ABI over a Zig zero-overhead FFI seam, so enemy behaviour is authored once and injected into whatever engine the game already uses.

Important

Status: Phase 1 complete — the ABI seam is frozen; the kernel is a skeleton. This repository was minted from the RSR template on 2026-09-20. What exists today is the seam, end to end and mechanically gated: seven ABI structs proved in Idris2, a generated ee.h at ABI 1.0 that a C host can compile against, a Zig kernel that asserts its own layout at comptime, and two null hosts — one Zig, one C — that agree on three pinned digests (two fixtures, one of them the v0 trace with memory opted out, which is still exactly v0’s). The behaviour itself is deliberately naive: the rule is a utility graph over health, ammo, contacts, range and a remembered bearing — a maximum over scored candidates that reproduces, tick for tick, the five-branch chain it replaced (ADR-0010). No adapter and no support-matrix entry is claimed. STATE.a2ml carries the live number (currently 22%), docs/developer/DEVELOPMENT-PLAN.adoc carries the route, and just seam-check is the one command that reproduces the claim above.

Phase 2 has landed its first half: perception and memory, end to end. An agent that loses sight of a contact investigates where it went, for at most 36 ticks, and then forgets — and forgetting clears the payload rather than only lowering a flag. src/interface/Abi/Memory.idr specifies it and proves the freshness, TTL-boundary and forgetting properties; src/core/kernel.zig implements it; ADR-0009 records what is remembered (a bearing and an age, not a position), where it lives, and how it is checked.

Phase 2 has also landed the control layer above the rule: modes plus a score margin (src/interface/Abi/Modes.idr, ADR-0012). An agent commits to a behaviour — engage, evade, reload, investigate, advance — and a challenger must beat the incumbent by more than 0.125 to take over. On the fixture this exists for, a contact at 40000 with health oscillating across the wound threshold, the graph alone changes its mind 99 times in 100 ticks and the committed agent zero; both readings were measured, not reasoned. The mode lives in three flag bits the freeze left undefined, so nothing in the layout moved and the ABI is still 1.0. Two digests moved, deliberately, and ADR-0006 carries their history — including the retirement of the v0-compat anchor, which was evidence about memory and cannot survive a change to the rule itself.

Phase 2 has also landed the rule itself, rewritten as a utility graph (src/interface/Abi/Utility.idr, ADR-0010) without moving any of the three digests: the weights are the priorities the kernel was already reporting, and the one moment where a score alone would have decided differently — nothing visible, a fresh lead, no ammo — is written as a candidate set of one, because that is what the shipped kernel did. That moment is worth a paragraph in the ADR: the graph, written to match the comment, moved the pinned digest to 57428431722396483, which is how the slice found that Abi.Memory had been asserting a precedence the kernel did not have.

The ABI did not move to make room for it. v0’s ee_agent had carried memory_x, memory_y and memory_age unused since the freeze, and its flags field had no defined bits — so Phase 2 defines bit 0 and uses the fields that were already there. ABI stays 1.0, the layout checksum is unchanged, and a host that never sets the MEMORY_VALID bit gets v0’s behaviour exactly: that is not a promise, it is an assertion against the digest v0 shipped, checked by both hosts on every run.

The whole seam in one command:

just seam-check   # model → artefacts → no drift → C header compiles → 28 tests → both hosts agree

What this is

Most game AI is welded to one engine. Evil Weevil inverts that: the intelligence is a kernel that the game hosts, not a library the game is built around.

The kernel owns perception memory, decision-making (utility scoring over a behaviour graph), steering and a tick budget. It owns no rendering, no physics, no scene graph, and no networking. The host supplies world data once per tick as a validated snapshot; the kernel returns intents. It never calls back into the host mid-tick — which is the single decision that lets one implementation serve very different hosts.

Injection modes

Mode Trade-off

A. In-process library (C ABI: .so/.dll/.dylib)

The default and the fastest. Requires linking or loading a native library.

B. Sidecar process (shared memory + ring buffer)

For hosts that cannot rebuild: mod sandboxes, managed runtimes, anti-cheat-constrained environments. Costs about a frame of latency and no kernel changes.

C. Bytecode blob (WASM / small VM)

For hosts that only accept a data blob, and for browser play. Slowest; same kernel.

A host declares its capabilities at init — navmesh, line-of-sight queries, physics raycasts, waypoint graph, spawn rights — and the kernel degrades gracefully (navmesh absent implies steering plus a waypoint graph) rather than aborting. The word "universally" is only meaningful against that ladder.

Architecture

host adapters        Godot 4 · Unity · Unreal · native Rust/Bevy · null host · WASM
  (thin, per-engine) each must pass the same conformance kit
        |
        v
  === SEAM (frozen, versioned) =============================================
      include/evil_weevil/ee.h      generated from the Idris2 types, never hand-edited
      src/interface/Abi/            Idris2: struct layout proofs, enum exhaustiveness,
                                    tick purity and determinism contract
      src/interface/ffi/            Zig: the C ABI, comptime layout assertions
  === KERNEL (host-agnostic) ===============================================
      perception -> memory -> decision -> action    fixed tick, integer-only math
      behaviour graph + utility scoring, seeded RNG, per-agent budget guard
  === AUTHORING ============================================================
      enemy definition (a2ml) -> compiler -> workbench: headless sim + replay inspector

The seam is frozen in Phase 1 before any behaviour code exists. An adapter written against a moving header is the one mistake that would sink the whole claim.

Determinism

The kernel uses integer and fixed-point maths only — no libm — so a replay is bit-exact across platforms, compilers and injection modes. That buys three things at once: a golden-replay corpus in CI (scenarios in, intent traces out, hashes compared), a server that can re-simulate exactly what a client’s enemies did, and regression detection for "the enemy got dumber at 3am". Each agent carries a hard tick budget and degrades its own behaviour rather than blowing the frame.

AI-Assisted Installation

If you are an AI agent installing this project, read the AI installation guide first — it gives the orientation order, the full prompt sequence, and the privacy notice.

The one trap worth stating up front: do not set RSR_NON_INTERACTIVE=1. It stubs the shell builtin read, which also disables the loops that perform token substitution — the run never terminates and substitutes nothing. Pipe answers to stdin instead. (Measured on this repo’s own mint; see MINT-NOTES.)

Working in this repo

just                    # list every recipe
just validate           # structure + metadata gates
just claude-md          # regenerate the agent arrival pack from the a2ml descriptiles
just repo-map           # regenerate the authoritative repository map (CI fails if stale)
just coapt              # regenerate the coaptation receipt (CI fails if stale)

Agents start at evil-weevil_chora.deed (the repo deed) or CLAUDE.md, not here. The generated region of CLAUDE.md is compiled from .machine_readable/descriptiles/ — edit the a2ml, never the output.

Repository map

The authoritative map is generated, so it cannot drift from the tree: docs/architecture/REPOSITORY-MAP.adoc.

Path What lives there

README.adoc, CLAUDE.md

Start here — humans and AI agents respectively.

src/interface/

The seam: the Idris2 ABI model and proofs (Abi/), the generator (Abi/Gen.idr), the Zig C ABI (ffi/), and generated artefacts.

src/core/

The host-agnostic kernel: fixed-point arithmetic, the deterministic RNG, perception and the v0 decision rule. No behaviour beyond that yet.

include/

evil_weevil/ee.h — the public C ABI, generated and committed. The only header a host needs.

tests/host/

The null host in C: a game with no game in it, which is how the header and the library are tested as a host sees them.

tests/, verification/

Tests; proofs and the golden-replay corpus.

docs/

Human documentation, including the development plan and ADRs.

.machine_readable/

Descriptiles, contractiles and policies that tools and agents read.

build/, Justfile

Every task runs through just; phases live in build/just/.

Where to go next

  • Development plan — what we are building, in what order, and what counts as done.

  • Mint notes — what the RSR mint did and did not do, measured on this repo.

  • ADRs — 0002 variant contract, 0004 injection modes, 0005 ABI versioning, 0006 determinism.

  • Repository map — generated; what every directory is for.

  • AFFIRMATION — the dated honesty snapshot of the repo’s true state.

Licence

Code, configuration and scripts are Mozilla Public License 2.0 (MPL-2.0); prose documentation is CC-BY-SA-4.0. Both texts live in LICENSES/, and per-file SPDX-License-Identifier headers are authoritative. Long-term attribution uses Quantum-Safe Provenance — see the Quantum-Safe Provenance exhibit.

About

A universally injectable enemy-intelligence kernel for computer games.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages