# `rcex` — a per-player nibble array, and the rule is one line - **Type:** subsystem (field semantics) - **Address / RVA:** `ServerSystem` field, streamed as `int64` (`struct-recovery.md` row `0xf8`); ticked inside `ServerSystem::ProcessTurn` (the "`rcex` tick", already in `addresses.json`'s body-order note for `0x0074…`) - **Status:** **mapped** — rule holds 7/7 across the corpus, from the saves alone, no VM time - **Confidence:** high on the rule, medium on the *name* of the event that sets it - **Owner / date:** lane W2 · 2026-09-08 - **Closes:** `system-visibility-prediction.md` §"What the model deliberately does not write" — "`rcex` (6 leaves per pair). **Unexplained.**"; `system-visibility-record.md` §8 row "`rcex` | unassigned" --- ## The rule `rcex` is a **64-bit array of sixteen 4-bit counters, one per player index**. Player *p*'s counter is nibble *p*, i.e. bits `4p … 4p+3`. On the turn where a system enters player *p*'s `AFlags` — the per-player acquisition/observation bit — nibble *p* is set to **1**. On the next turn the tick in `ServerSystem::ProcessTurn` decrements it to **0**. That is the whole of the observed `0 → 1<<16 → 0` behaviour, and it is exactly the shape `strategic-turn-internals.md` guessed at ("`Bats2` / `rcex` 64-bit nibble arrays: per-player 4-bit countdowns (battle / recon cooldown)") without being able to pin the index. ## The evidence Every system in the 11-save corpus with a non-zero `rcex`, with its `AFlags` beside it: | save | frame | system | `rcex` | set bit | ⇒ nibble | `AFlags` | ⇒ set bit | nibble value | |---|---:|---|---:|---:|---:|---:|---:|---:| | `turn2-state` | 2 | Hyperion | 65536 | 16 | **4** | 16 | **4** | 1 | | `turn2-state` | 2 | Koa'Vo | 268435456 | 28 | **7** | 128 | **7** | 1 | | `turn2-state` | 2 | Kaa'Vaalu | 65536 | 16 | **4** | 16 | **4** | 1 | | `turn2-state` | 2 | Markab | 65536 | 16 | **4** | 16 | **4** | 1 | | `turn2-state` | 2 | Kea'Pono | 65536 | 16 | **4** | 16 | **4** | 1 | | `turn2-state` | 2 | Ko'Rorkor | 65536 | 16 | **4** | 16 | **4** | 1 | | `human-turn2-orders` | 2 | Terra | 4096 | 12 | **3** | 8 | **3** | 1 | **7 for 7.** `nibble index == the index of the single set `AFlags` bit`, and the nibble's value is always 1. The seventh row is the strong one: `human-turn2-orders.sav` is a **different game** with a different map, a different system and a different player index, and it obeys the same rule. Every other save in the corpus — `turn1-state`, `turn3-state`, `human-turn3-noderoute`, and all six Zuul saves from frame 5 to frame 23 — has `rcex == 0` on all 28 systems, which is what a counter that decays to zero in one turn looks like when nothing was acquired that turn. That also explains the `system-visibility-record.md` §7 observation directly: `rcex` moves `0 → 65536` on `turn1 → turn2` and back `65536 → 0` on `turn2 → turn3` **on the same six systems**, and Koa'Vo takes `1 << 28` rather than `1 << 16` — because Koa'Vo was acquired by player 7 and the other five by player 4. ## Why this had to be six leaves per pair and not more The visibility model's residual was "6 leaves per pair" for `rcex`. It is six because six systems changed hands in the turn-1→turn-2 pair and each contributes one `int64` leaf. The count was never about `rcex` being complicated; it was about nobody having connected the nibble index to the player index. ## How this could be wrong, and the symptom of each way (rule 2) - **The index is not the player index but something correlated with it on this corpus.** Every save here has **single-bit** `AFlags` on every system — the corpus limitation `system-visibility-prediction.md` already flags — so "nibble index == player index" and "nibble index == index of the lowest set `AFlags` bit" are indistinguishable. *Falsifying workload:* a save where **two** players acquire the same system on the same turn. The rule predicts **two** nibbles set to 1; a lowest-bit rule predicts one. - **The initial value is not always 1.** Every observed nibble is 1. A longer cooldown (2, 3) would appear on some other event. *Symptom:* a nibble > 1, and a system whose `rcex` takes two turns to reach zero. Nothing in the corpus shows one. - **It counts something other than acquisition.** `AFlags`, `VFlags` and `EFlags` are all equal on all seven rows, so this corpus cannot separate them. *Falsifying workload:* any save where a system's `VFlags` and `AFlags` disagree. - **The decrement is not in `ServerSystem::ProcessTurn`.** The "rcex tick" is named in that function's body-order note in `addresses.json`, between the `Bats2` tick and the `haltv` clear; the corpus is consistent with it but does not prove the site. *This is the one item that wants a watchpoint* — and it is now cheap: `src/shim/hooks/watchpoints.cpp` arms four 4-byte write watchpoints from a known `this`, and `rcex` is at a fixed offset in `ServerSystem`. See `findings/control-flow/watchpoints-modcount-status.md` §7. ## Cross-refs - `findings/objects/struct-recovery.md` (the `int64` typing, and the warning that "R2 int is wrong") - `findings/subsystems/strategic-turn-internals.md` (the nibble-array reading this confirms) - `findings/subsystems/system-visibility-record.md` §7-8 and `findings/subsystems/system-visibility-prediction.md` (the open item this closes) - **`Bats2` is the same shape and is still unassigned.** It is `0` on every system of every corpus save, so it is a rule-6 hypothesis: the nibble-per-player reading is inherited from `rcex` and has never been exercised. The workload is a save taken on the turn after a battle.