test(client): corner-reveal proof updated to D-252 semantics + deterministic cone wait

The proof encoded move-writes-facing ('Move West -> now facing West'); under
D-252 the view changes only via SetFacing, so the test now looks West
explicitly (helper gains an action_data passthrough). The +2-tick wait could
catch the facing flip before the visibility recompute — the assertion now
polls (bounded) until the westward cone content lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 21:15:32 +02:00
co-authored by Claude Fable 5
parent 0c91ef28ba
commit e46aa404fc
+35 -9
View File
@@ -79,7 +79,10 @@ static func _find_player(snapshot: Dictionary) -> Dictionary:
## - expect_position == null: wait for a snapshot at least 2 ticks past the
## drain point (enough for no-op actions).
func _send_and_receive(
action_name: String, tick: int = 0, expect_position: Variant = null
action_name: String,
tick: int = 0,
expect_position: Variant = null,
action_data: Variant = null,
) -> Variant:
# Drain queued stale snapshots, remembering the newest tick seen.
var last_tick: int = -1
@@ -93,6 +96,8 @@ func _send_and_receive(
pending = _bridge.poll_message()
var inputs: Array = [{"tick": tick, "action_name": action_name}]
if action_data != null:
inputs[0]["action_data"] = action_data
var encoded := Protocol.encode_player_inputs(inputs)
assert_that(encoded.size()).is_greater(0)
var send_err := _bridge.send_message(encoded)
@@ -309,16 +314,37 @@ func test_proof_corner_reveal(
await _send_and_receive("MoveNorth", 4, Vector2(19.5, 14.5))
await _send_and_receive("MoveNorth", 5, Vector2(19.5, 13.5))
# Step 3: Move West onto (18,13) — now facing West, looking straight at
# NPC1 at (16,13) two tiles ahead with no wall between ((17,13) is open).
var snapshot: Dictionary = await _send_and_receive("MoveWest", 6, Vector2(18.5, 13.5))
# Step 3: Move West onto (18,13), then LOOK West explicitly — D-252: moves
# no longer write Facing, the view changes only via SetFacing. NPC1 at
# (16,13) is two tiles dead ahead with no wall between ((17,13) is open).
await _send_and_receive("MoveWest", 6, Vector2(18.5, 13.5))
var snapshot: Dictionary = await _send_and_receive(
"SetFacing", 7, null, {"facing": "West"}
)
# The +2-tick wait can catch the snapshot where the facing field flipped but
# the entity-visibility recompute hasn't landed — keep draining (bounded)
# until the westward cone content arrives.
var settle := 0.0
while settle < RESPONSE_TIMEOUT and not _has_npc_at(snapshot, 16.5, 13.5):
_bridge.poll()
var msg := _bridge.poll_message()
if msg.size() > 0:
var decoded: Variant = Protocol.decode_snapshot(msg)
if decoded != null:
snapshot = decoded
continue
await get_tree().create_timer(0.05).timeout
settle += 0.05
# Player at (18,13) facing West. NPC1 at (16,13) is 2 tiles dead ahead —
# inside the vision cone, no wall between. NPC1 should be visible.
var npc1_found := false
assert_that(_has_npc_at(snapshot, 16.5, 13.5)).is_true()
## True when the snapshot's visible entities include an Npc at (x, y).
func _has_npc_at(snapshot: Dictionary, x: float, y: float) -> bool:
for entity in snapshot.entities:
if entity.kind.variant == "Npc":
if is_equal_approx(entity.x, 16.5) and is_equal_approx(entity.y, 13.5):
npc1_found = true
break
assert_that(npc1_found).is_true()
if is_equal_approx(entity.x, x) and is_equal_approx(entity.y, y):
return true
return false