Skip to content

Area and feature ids share the trap-ref namespace but are only checked for uniqueness apart #47

Description

@mmacy

The gap

_area_ref and _feature_ref both mint "dungeon:level:id", and the sprung/found/removed gating in DungeonState treats those strings as one namespace — but validate_adventure checks area ids and feature ids for uniqueness only within their own lists. A level with area "vault" (an open-trigger blade, say) and treasure feature "vault" (a needle trap) validates clean.

The collision cross-contaminates trap state:

  • Springing the room blade appends d:1:vault to sprung_traps, and _handle_take_treasure's guard (ref not in state.sprung_traps) then treats the untouched cache trap as already sprung — silently disarmed.
  • A thief's successful RemoveTreasureTrap on the cache appends the same ref to removed_traps; nothing on the room side reads removed_traps today (the dead term was dropped in PR The blade drops when the door swings: room traps spring on open #44), but any future room-trap disarm path would inherit the confusion.
  • A room_traps search that finds the area trap marks found_traps with a ref the cache-side gating also reads.

PR #44 widened how much traffic runs through this shared namespace (the door path and the door-edge search both write it), which is how the review pass surfaced it.

The fix

validate_adventure should reject an id collision between areas and features within the same dungeon level — one namespace, one uniqueness check. Cheap, content-side, and no play-time cost.

Found by the review pass on PR #44.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions