re: the bark firing sites and the Probability roll

36 of the 64 event names are executable strings, so the string-xref join names
the eight sites that raise them; all eight share one entry, sub_8220FA98.
Probability is a per-cent roll -- the scaling constant at 0x820856F8 is exactly
100.0.  sub_82210670 suppresses an already-queued (speaker, rule) pair, treats
a message as eligible only if its bit is clear in the runtime mask at +36, and
picks uniformly, then hands Pattern/Priority/EffectiveTime to sub_822109B0.

Measured negative: the pick path never reads +20, +24 or +32.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Claude (auto)
2026-08-27 17:04:18 +00:00
parent 6ee041c1bf
commit 8dc270091b
3 changed files with 136 additions and 9 deletions

View File

@@ -4245,3 +4245,56 @@ spending a query on it. The remaining handle is the map's consumer reached via
**Still open:** the firing policy proper (who rolls `Probability`, compares
`Priority`, ticks `Interval`, what `IntervalFluctuation` randomises); which of
the 49 speakers are wingmen.
---
## ✅ 2026-08-27 — who fires a bark, and the first half of the firing policy
Continues the chatter thread; reached through the **call graph**, after the
offset-intersection handle was refuted last iteration.
**Docs checked:** `preset-message-rules.md` (mine), `squadron-orders.md` — it
owns `sub_82320B48` as the selector for the twelve-string `0x820AEEB0` enum and
warns it is a comms axis. **What it does not say** is that the function is one of
**eight bark firing sites sharing a single entry point**, and that it also raises
`COUNTER`, `COUNTER_TO_PLAYER` and `FOUND_PLAYER`.
**36 of the 64 event names are executable strings** (`0x820AEEC8``0x820B2160`),
so the string-xref join names the firing sites directly: `sub_823800A8` (17
events — damage/destruction), `sub_82320B48` (15 — squadron orders + 3),
`sub_8237B020` (9 — player state), `sub_823B1438` (ammo), `sub_82381B10`
(evasion), and three singles.
**`sub_8220FA98` is the shared entry** — the only callee common to all eight.
Lock around `this+4`; enable byte `[this+8843]`; speaker lookup in the map at
`[this+8820]`; index `[this+8816] 1` into a vector inside that entry (phase is
a *reading*, not measured); event-name lookup → the rule object; then the roll.
**`Probability` is a per-occurrence percentage — now measured, not inferred.**
`f0 = rand01 · 100.0` and `f0 > [rule+16]` returns without firing. The constant
at `0x820856F8` is exactly **100.0**, read from the image. `sub_8220D970` folds
two `rand()` calls into a 16-bit uniform.
**`sub_82210670` picks the line.** (1) Walks the pending list at
`[this+8736]` for a node matching this (speaker, rule) pair and **bails if the
same bark is already queued**. (2) Recomputes `MessageCount` from the vector and
takes a message as eligible only if its bit is **clear** in `[rule+36]` — the
word the loader zeroes — so **`+36` is a runtime exclusion mask** ("already
spoken" is the obvious reading; the write site was not found). (3) Uniform pick:
`eligible · rand01`, subtract `1.0` (`0x8208583C`) per eligible bit until the
counter empties or the accumulator reaches `0.0` (`0x8209FD28`). (4) Reads
`[rule+18]` `Pattern`, `[rule+17]` `Priority`, `[rule+28]` `EffectiveTime` and
hands them with the chosen message to `sub_822109B0`.
**Measured negative:** the pick path does **not** read `+20` `Interval`,
`+24` `IntervalFluctuation` or `+32` (the disc `Yes` mask). They are consumed
after the hand-off. Within the chatter CU (`0x8220C000``0x82216000`), `+17` and
`+18` are read by exactly **two** functions — the comparator and this one — which
is what makes the attribution safe where the binary-wide search was not. **The
bounded offset search is sound once the call graph says which functions matter;
the unbounded one is what was refuted.**
**Still open:** everything after `sub_822109B0` — how `Priority` orders the
queue, whether `Interval` is a per-event or per-speaker cooldown, what
`IntervalFluctuation` randomises, where `+36`'s bits get set, and what reads
`+32`. Also still open: which of the 49 speakers are wingmen.