From a51f7a53aa2c487ebf94ba0363038574ae8bb590 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Tue, 7 Jul 2026 00:22:32 -0400 Subject: feat: hidden exits (and related flags) work with commands that change room ids. exit code simplified and unified between impassable and blocked exits. --- internal/game/exit_display.go | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 internal/game/exit_display.go (limited to 'internal/game/exit_display.go') diff --git a/internal/game/exit_display.go b/internal/game/exit_display.go new file mode 100644 index 0000000..4540669 --- /dev/null +++ b/internal/game/exit_display.go @@ -0,0 +1,56 @@ +package game + +import ( + "thehouseoficarus/internal/net" + "thehouseoficarus/internal/world" +) + +// exitDisplay summarizes how an exit appears to a player: whether it is listed +// at all (and traversable by the map BFS / walk pathfinder), whether movement +// is refused (and the look listing should tag it "(blocked)"), and whether the +// listing should tag it "(HIDDEN)". +// +// It is the single source of truth shared by the look listing, the standalone +// `exits` command, `look `, movement, the map connector state, the +// `verbs` command, and the walk pathfinder — replacing the per-callsite inline +// checks that previously disagreed (e.g. gods saw a "(blocked)" tag in look +// even though they can traverse and the map renders the link open). +// +// Semantics: +// - Hidden exit: visible only once discovered (gods always discover). When +// visible it is tagged "(HIDDEN)". A nil player (background render) never +// discovers, so hidden exits are absent. +// - God mode: exits are visible and never blocked (matches map rendering). +// - always_blocked: absolute — blocks movement/listing/map regardless of any +// condition. The condition is NOT evaluated when always_blocked is set. +// - condition: blocks when present and failing for this player. +type exitDisplay struct { + Visible bool + Blocked bool + TagHidden bool +} + +func (g *Game) exitDisplayState(sess *net.Session, roomID int, dir world.ExitDir, exit world.ExitDef) exitDisplay { + var ed exitDisplay + p := sessPlayer(sess) + if exit.Hidden { + // exitDiscovered already returns true for gods; nil player never discovers. + if p != nil && g.exitDiscovered(p, roomID, dir) { + ed.Visible = true + ed.TagHidden = true + } + return ed + } + ed.Visible = true + if p == nil || p.GodMode { + return ed + } + if exit.AlwaysBlocked { + ed.Blocked = true + return ed + } + if exit.Condition != nil && !g.checkCondition(sess, exit.Condition) { + ed.Blocked = true + } + return ed +} -- cgit v1.2.3