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
The two open springing actions now carry opposite found-trap semantics:
Cache:TakeTreasure on a cache with a found trap still rolls the 2-in-6, and emits exploration.trap.safe when a known trap's die misses (src/osrlib/crawl/exploration.py, the take path). Finding a treasure trap is not defeating it — removal is the thief's separate roll.
Door: opening a door past a foundopen-trigger room trap skips the roll silently (PR The blade drops when the door swings: room traps spring on open #44), extending the room-trap rule that found traps never spring — the party walks around the known pit, stands aside from the known blade.
So the same physical action — performing a known trap's springing action — is lethal 2-in-6 at a cache and perfectly safe at a door, and the exploration.trap.safe contract ("a known trap's trigger resolved without springing") is unreachable for door traps. A front end that renders the known-trap-fails-to-fire beat off trap.safe works for braved caches and never fires at doors.
The decision to make
Each rule is defensible alone — the split is the B/X room-vs-treasure trap distinction (anyone finds and avoids room traps; treasure traps need thief removal), and the kind-based reading says the current behavior is right. But it was never decided, only inherited, and neither docs/adaptations.md nor the event docstrings acknowledge it. Either:
Pin the split. Document in the adaptations register that found room traps (enter and open alike) never spring while found treasure traps roll until removed, and note that trap.safe is a cache-only event.
Unify. Make a found door trap roll and emit trap.safe on a miss, the cache way — at the cost of the walked-around-pit doctrine's consistency on the room side.
(1) is almost certainly right; the work is making it explicit.
The divergence
The two
openspringing actions now carry opposite found-trap semantics:TakeTreasureon a cache with a found trap still rolls the 2-in-6, and emitsexploration.trap.safewhen a known trap's die misses (src/osrlib/crawl/exploration.py, the take path). Finding a treasure trap is not defeating it — removal is the thief's separate roll.open-trigger room trap skips the roll silently (PR The blade drops when the door swings: room traps spring on open #44), extending the room-trap rule that found traps never spring — the party walks around the known pit, stands aside from the known blade.So the same physical action — performing a known trap's springing action — is lethal 2-in-6 at a cache and perfectly safe at a door, and the
exploration.trap.safecontract ("a known trap's trigger resolved without springing") is unreachable for door traps. A front end that renders the known-trap-fails-to-fire beat offtrap.safeworks for braved caches and never fires at doors.The decision to make
Each rule is defensible alone — the split is the B/X room-vs-treasure trap distinction (anyone finds and avoids room traps; treasure traps need thief removal), and the kind-based reading says the current behavior is right. But it was never decided, only inherited, and neither
docs/adaptations.mdnor the event docstrings acknowledge it. Either:trap.safeis a cache-only event.trap.safeon a miss, the cache way — at the cost of the walked-around-pit doctrine's consistency on the room side.(1) is almost certainly right; the work is making it explicit.
Found by the review pass on PR #44.