Path: Apply "!id" access to layer-crossing and no-route diagnostics

A stopped guest warp now reports CONNECTOR_UNAVAILABLE instead of
GOAL_UNREACHABLE (P14-02 review r2 follow-up).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Takeshi
2026-10-20 15:12:47 +09:00
co-authored by Claude Opus 5.5
parent 28e3ffe146
commit 0f23d34e9f
2 changed files with 12 additions and 10 deletions
+11 -10
View File
@@ -2097,13 +2097,16 @@ func _edge_meets_vertical_policy(from_cell: Vector3i, edge: Dictionary) -> bool:
or not StringName(edge[&"connector_id"]).is_empty() or edge[&"movement_type"] != MOVEMENT_WALK
func _edge_is_accessible(edge: Dictionary, allowed_access_ids: Array[StringName]) -> bool:
var required_access: StringName = edge[&"access_id"]
# "!id" is open to everyone except actors that carry id (guest-only warp).
## "" is public, "id" needs id, and "!id" is open to everyone except actors
## that carry id (guest-only warp).
static func _access_id_permits(required_access: StringName, allowed_access_ids: Array[StringName]) -> bool:
if String(required_access).begins_with("!"):
if StringName(String(required_access).substr(1)) in allowed_access_ids:
return false
elif not required_access.is_empty() and required_access not in allowed_access_ids:
return StringName(String(required_access).substr(1)) not in allowed_access_ids
return required_access.is_empty() or required_access in allowed_access_ids
func _edge_is_accessible(edge: Dictionary, allowed_access_ids: Array[StringName]) -> bool:
if not _access_id_permits(edge[&"access_id"], allowed_access_ids):
return false
var connector_id: StringName = edge[&"connector_id"]
if connector_id.is_empty():
@@ -2190,8 +2193,7 @@ func _cell_is_temporarily_blocked(cell: Vector3i) -> bool:
## Only the absence of any permitted directed crossing proves unreachable.
func _has_permitted_layer_crossing(from_layer: int, to_layer: int, allowed_access_ids: Array[StringName]) -> bool:
for connector: Dictionary in _connectors.values():
var access_id: StringName = connector[&"access_id"]
if not access_id.is_empty() and access_id not in allowed_access_ids:
if not _access_id_permits(connector[&"access_id"], allowed_access_ids):
continue
var from_cell: Vector3i = connector[&"from"]
var to_cell: Vector3i = connector[&"to"]
@@ -2257,8 +2259,7 @@ func _route_exists_with_overrides(
neighbor_set[neighbor] = true
for connector_id: StringName in connector_ids:
var connector: Dictionary = _connectors[connector_id]
var required_access: StringName = connector[&"access_id"]
if not required_access.is_empty() and required_access not in allowed_access_ids:
if not _access_id_permits(connector[&"access_id"], allowed_access_ids):
continue
if not allow_unavailable_connectors and not _connector_is_operational(connector):
continue
+1
View File
@@ -104,6 +104,7 @@ func _write() -> void:
_clock.advance_minutes(1)
_expect(_runtime.path_service.get_connector(ids[0])[&"operational_state"] == PathService.CONNECTOR_OUTAGE, "reserve outage stops the warp")
_expect(_runtime.path_service.find_path(Vector3i(0, 0, 0), Vector3i(0, 2, 0)).is_empty(), "stopped warp offers no route")
_expect(_runtime.path_service.find_path_report(Vector3i(0, 0, 0), Vector3i(0, 2, 0))[&"reason"] == PathService.ROUTE_CONNECTOR_UNAVAILABLE, "guest sees the stopped warp as an unavailable connector")
ManaOutage.release(_runtime, _state, Warp.MANA_PER_TRIP - 1)
_clock.advance_minutes(1)
_expect(_runtime.path_service.get_connector(ids[0])[&"operational_state"] == PathService.CONNECTOR_OUTAGE, "reserve below one fare keeps the warp closed")