Repository navigation
Conversation
… changes Player events now reach a rule two ways: the scenario `events` entries the loader already injects, and modeled causes — `Damage` and `Heal` raise the player events their effect implies, delivered in occurrence order between rule-instance visits on the same tick. - `Damage` on a living target raises `Player Took Damage` then, for a player dealer, `Player Dealt Damage`; a hit that brings health to zero writes the `isDead` cell and raises `Player Died` then `Player Dealt Final Blow`. `Heal` raises `Player Received Healing` then `Player Dealt Healing`. A `Null` dealer raises no dealer-side event; a hit on an already-dead target raises nothing. - Each raised event binds `Event Player`, `Attacker` (the cause's player, `Null` for none), `Victim` and the applied amount as `Event Damage`/`Event Healing`; `attacker`/`victim` join the event-value table and scenario `values` supply them as player ids. - Raised events bound at 1024 per tick: a rule whose own actions re-raise its kind would fan the queue out without bound. Event team and player filters apply to raised and injected events alike; `eventAbility`/`eventDirection` stay not_modeled. Verified: the 291-rule Bastion workload runs to tick 91 and stops at `action wait under a 90% simulation rate` (the athena#120 match-clock gap), past every player-event construct; an injected `playerLeft` fires Bastion's matching rule end to end. Fixes #47
Address the review findings on the player-events change: - `Damage`/`Heal` gated liveness on the health pool, so a `Kill`ed target still took damage events and died a second time while a `Resurrect`ed one could take none. The gate now reads `isDead` — the model's death marker, as `Is Alive` and `Set Health` read it — and falls back to the health pool only where `isDead` cannot answer. - An event value a raised event does not bind stopped `missing_input`, but only injected events take scenario `values`. `EventCtx` now marks raised events, and the read stops `not_modeled` naming the construct, as `eventAbility`/`eventDirection` already do. - `attacker`/`victim` event values accepted any JSON; the loader now requires a player `id` or `null`, per `docs/scenario-format.md`. - Comments that still said "injected event" for context that now also holds raised events were reworded, and `scenario-format.md`, `trace-format.md` and `architecture.md` record the contract clarifications.
|
All four review findings are addressed in
Verification: The PR is ready for follow-up review. |
Address the follow-up review findings on the player-events change: - A `Damage`-killed player leaves the health pool at zero, and the revive actions wrote only the `isDead` cell, so a revived player could never be brought to zero — or raise `Player Died`/`Player Dealt Final Blow` — again. `Respawn`/`Resurrect` now refill the resolved world's `health` pool to `health.max` — `Respawn`'s "with full health", `Resurrect` the same under modeled-not-measured — recording the move as `Damage`/`Heal` do. The regression test now covers the `Damage`-kill→revive path, not only `Kill`→`Resurrect`. - The loader-check bullet in `scenario-format.md` now states `attacker`/`victim` event values are a player `id` or `null`, as the loader accepts. - The `dead()` docstring no longer claims `construct` names the stop a fallback `world_state` touch raises — `world_state` carries the stored resolution error and the read's `missing_input` is swallowed, so `construct` names nothing observable.
|
Follow-up review findings addressed in
Verified: Ready for follow-up review. |
|
Independent review took three rounds. Round 3 found a regression introduced by the round-2 fix: |
Summary
Player events now reach a rule two ways: the scenario
eventsentries the loader already injects, and modeled causes —DamageandHealraise the player events their effect implies, delivered in occurrence order between rule-instance visits on the same tick. Implements #47 (part of #45's Bastion run-to-completion goal).Damageon a living target raisesPlayer Took Damagethen, for a player dealer,Player Dealt Damage; a hit that brings health to zero writes theisDeadcell and raisesPlayer DiedthenPlayer Dealt Final Blow— occurrence order, soPlayer Diedruns beforePlayer Dealt Final Blowregardless of rule file order.HealraisesPlayer Received HealingthenPlayer Dealt Healingfor a player healer. ANulldealer bindsAttackertoNulland raises no dealer-side event; aDamage/Healon an already-dead target raises nothing.Event Player,Attacker,Victim, andEvent Damage/Event Healing(the applied amount).attacker/victimjoin the event-value table; scenariovaluessupply them as declared player ids (a new loader check) ornull.eventAbility/eventDirectionremainnot_modeled.team/playerfilters apply to raised and injected events alike. A busy orWait-suspended instance queues the event like an injected one; raised events bound at 1024 per tick (a rule whose own actions re-raise its kind would otherwise fan out without bound), past which the run stopsnot_modeled.events.rsmodule (size-guard); docs updated (simulator-interface.md,scenario-format.md,architecture.md,findings.md).Cargo.locksyncs the 0.11.1 release version the lock was missing.Verification
cargo fmt --check— clean.cargo clippy --all-targets -- -D warnings— clean.cargo test— all suites pass (newtests/player_events.rs: injectedplayerLeftruns its rule once withEvent Player; killingDamagerunsPlayer DiedthenPlayer Dealt Final Blowin occurrence order with rules declared out of order; bindings forEvent Player/Attacker/Victim/Event Damage; team-filter rejection;Healraises received-then-dealt).cargo check --locked --target wasm32-unknown-unknown -p athena-sim— clean.not_modeled: "action wait under a 90% simulation rate"(the documented athena#120 match-clock gap — the next stop, past every player-event construct). NoDamage/Healexecutes before that stop, so no player-event rules fire in the reference run; with an injectedplayerLeftonp2the run additionally executes Bastion'sUpdate targetPlayer when player leftrule and reaches the same stop.Unverified
architecture.md/findings.md.Attacker/Victim/amount bindings (e.g.Event Damagereads the killing blow insidePlayer Died); a probe would be needed to measure the real per-event sets.Wait-suspended Bastion rule ever queues a derived event end-to-end is unexercised before the tick-91 stop.