You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A layered decision architecture for intelligent behavior in a real-time 3D world.
10
10
@@ -16,7 +16,7 @@ Compass is a control architecture for agents that must perceive, decide, and act
16
16
17
17
The architecture evolved in a legacy 3D MMORPG sandbox. It progressed from a monolith through reactive rules, state-machine routines, and utility scoring before arriving at goal-oriented planning. Each transition came when the previous approach broke against the world's complexity.
18
18
19
-
> **Scope.** This is a cleaned extraction from a private working repo, published as an architecture reference. Live runtime config, environment assets, and operational glue are intentionally omitted. See [docs/samples/](docs/samples/) for real session output.
19
+
> **Scope.** This is a cleaned extraction from a private working repo, published as an architecture reference. Live runtime config, environment assets, and operational glue are intentionally omitted. See [docs/samples/](docs/samples/) for real session output. For a step-by-step trace from perception to motor output, see [`docs/walkthrough.md`](docs/walkthrough.md).
20
20
21
21
---
22
22
@@ -220,7 +220,7 @@ All samples in [docs/samples/](docs/samples/) are real output from live sessions
220
220
|[Forensics buffer](docs/samples/forensics-ring-buffer.md)| 300-tick ring buffer dump: skeleton aggro interrupts spell memorization, FLEE fires within one tick |
221
221
|[Learned encounter data](docs/samples/learned-encounter-data.md)| Cross-session improvement: grade B → A, fight duration 29.5s → 15.9s, auto-tuned parameters drifting from defaults |
222
222
|[Fight event](docs/samples/structured-fight-event.md)| Structured `fight_end` event with all 20 fields and embedded world snapshot |
223
-
|[Convergence](docs/samples/convergence.md)| 10-session headless run: fight duration drops 53% as encounter history accumulates and cost functions self-correct |
223
+
|[Convergence](docs/samples/convergence.md)| 10-session headless run: fight duration drops 53% as encounter history accumulates and cost functions self-correct |
Copy file name to clipboardExpand all lines: docs/architecture.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -273,7 +273,7 @@ Strategy selection uses learned encounter history when available; after 5+ encou
273
273
274
274
### Terrain
275
275
276
-
Zone geometry is parsed from the game client's asset files own 3D asset files. The parsing pipeline extracts walkable surfaces and produces heightmap caches at 1-unit resolution.
276
+
Zone geometry is parsed from the game client's own 3D asset files. The parsing pipeline extracts walkable surfaces and produces heightmap caches at 1-unit resolution.
Copy file name to clipboardExpand all lines: docs/walkthrough.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ What happens in one tick of the 10 Hz brain loop, traced through the actual sour
6
6
7
7
## 1. Clock gate
8
8
9
-
[`brain/runner/loop.py:552`](../src/brain/runner/loop.py) -- The `TickClock` blocks until the next 100ms boundary. When it releases, the tick counter increments and the loop begins.
9
+
[`brain/runner/loop.py:541`](../src/brain/runner/loop.py) -- The `TickClock` blocks until the next 100ms boundary. When it releases, the tick counter increments and the loop begins.
10
10
11
11
```
12
12
_clock.wait_for_next_tick()
@@ -16,25 +16,25 @@ The clock measures `dt` (actual elapsed time since last tick). At 10 Hz with no
16
16
17
17
## 2. Perception snapshot
18
18
19
-
[`brain/runner/loop.py:557-563`](../src/brain/runner/loop.py) -- `_tick_pre_state` calls `reader.read_state(include_spawns=True)`, which traverses the game client's internal pointer chains via `ReadProcessMemory` and returns a frozen `GameState` dataclass. This snapshot is immutable after creation: the brain thread produces it, every subsequent step consumes it, no locks needed.
19
+
[`brain/runner/loop.py:546`](../src/brain/runner/loop.py) -- `_tick_pre_state` calls `reader.read_state(include_spawns=True)`, which traverses the game client's internal pointer chains via `ReadProcessMemory` and returns a frozen `GameState` dataclass. This snapshot is immutable after creation: the brain thread produces it, every subsequent step consumes it, no locks needed.
20
20
21
21
The `GameState` contains: player position (x, y, z), HP/mana current and max, target info, heading, zone ID, combat flag, sitting flag, and a tuple of `SpawnData` for every visible entity.
22
22
23
23
If the memory read fails (process not responding, pointer chain broken), the tick is skipped entirely -- the brain never evaluates stale state.
24
24
25
25
## 3. World state update
26
26
27
-
[`brain/runner/loop.py:570`](../src/brain/runner/loop.py) -- `WorldStateUpdater.update_world_state()` refreshes the derived world model: NPC tracking (who appeared, who moved, who despawned), pet status, threat detection (approaching hostile entities), and health monitoring. This runs before rule evaluation so that rules see current-tick derived state.
27
+
[`brain/runner/loop.py:559`](../src/brain/runner/loop.py) -- `WorldStateUpdater.update_world_state()` refreshes the derived world model: NPC tracking (who appeared, who moved, who despawned), pet status, threat detection (approaching hostile entities), and health monitoring. This runs before rule evaluation so that rules see current-tick derived state.
28
28
29
29
For tick 1147: the world model registers a level-appropriate NPC at 85 units distance that was not present on the previous tick. The threat scanner classifies it as non-hostile (not approaching). The entity enters the world model's tracking table.
30
30
31
31
## 4. Pre-rule event detection
32
32
33
-
[`brain/runner/loop.py:581-583`](../src/brain/runner/loop.py) -- Three pre-rule handlers run: XP tracking (records any XP change), add detection (checks if a new NPC is attacking the pet), and auto-engage scanning (detects if the current target changed). These update `AgentContext` sub-state objects before the decision engine reads them.
33
+
[`brain/runner/loop.py:570-572`](../src/brain/runner/loop.py) -- Three pre-rule handlers run: XP tracking (records any XP change), add detection (checks if a new NPC is attacking the pet), and auto-engage scanning (detects if the current target changed). These update `AgentContext` sub-state objects before the decision engine reads them.
34
34
35
35
## 5. Rule evaluation (the decision)
36
36
37
-
[`brain/runner/loop.py:608`](../src/brain/runner/loop.py) -- `brain.tick(state)` enters the decision engine. Inside [`brain/decision.py:154-161`](../src/brain/decision.py):
[`brain/decision.py:163-255`](../src/brain/decision.py) -- At Phase 0 (binary conditions, insertion-order priority), rules evaluate top to bottom. The first rule whose condition returns `True` wins. After a winner is found, remaining rules are skipped.
51
+
[`brain/decision.py:182`](../src/brain/decision.py) -- At Phase 0 (binary conditions, insertion-order priority), rules evaluate top to bottom. The first rule whose condition returns `True` wins. After a winner is found, remaining rules are skipped.
52
52
53
53
For tick 1147, the evaluation cascade looks like this (from the decision receipt in the sample data):
54
54
@@ -86,7 +86,7 @@ For this tick: `tab_target()` sends a Tab keypress. The next perception snapshot
86
86
87
87
## 8. Observability
88
88
89
-
[`brain/runner/loop.py:614`](../src/brain/runner/loop.py) -- `_tick_record_diag` runs after the brain tick completes:
89
+
[`brain/runner/loop.py:599`](../src/brain/runner/loop.py) -- `_tick_record_diag` runs after the brain tick completes:
90
90
91
91
-**Decision receipt**: a structured record of which rules fired, their scores, the selected routine, lock state, and tick timing. This is the data in [`docs/samples/decision-trace.md`](samples/decision-trace.md).
92
92
-**Forensics ring buffer**: the last 300 ticks of brain state, continuously overwritten. On death or crash, this buffer flushes to disk -- 30 seconds of pre-incident telemetry.
@@ -95,7 +95,7 @@ For this tick: `tab_target()` sends a Tab keypress. The next perception snapshot
95
95
96
96
## 9. Heartbeat
97
97
98
-
[`brain/runner/loop.py:613`](../src/brain/runner/loop.py) -- The heartbeat timestamp updates. A secondary thread monitors this value; if it goes stale for 10+ seconds, the watchdog triggers recovery (process reconnection or graceful shutdown).
98
+
[`brain/runner/loop.py:598`](../src/brain/runner/loop.py) -- The heartbeat timestamp updates. A secondary thread monitors this value; if it goes stale for 10+ seconds, the watchdog triggers recovery (process reconnection or graceful shutdown).
0 commit comments