test(scenes): Add and update test logic in courier_era2_round_trip_proof.gd and courier_era2_round_trip_proof.tscn to verify round-trip behavior for courier era 2.

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-04-29 09:59:55 -07:00
parent a538d38832
commit f561ec4cc9
2 changed files with 135 additions and 0 deletions

View file

@ -0,0 +1,129 @@
extends Node
## p3-01 bullet 11: era_2 courier round-trip proof.
## Signs a SharedMapAgreement between two players whose capitals are 4 hexes
## apart, dispatches an era_2 (foot_runner, 1 hex/turn) courier via straight-
## line movement, and steps turn-by-turn until SharedMapDelivered fires.
## Asserts delivery occurs within 6 steps and the share-window opens.
var _pass_count: int = 0
var _fail_count: int = 0
func _ready() -> void:
if not ClassDB.class_exists("GdTradeLedger"):
print("[SKIP] GdTradeLedger not registered — GDExtension not loaded")
get_tree().quit(0)
return
_run_proof()
_print_results()
get_tree().quit(0 if _fail_count == 0 else 1)
func _run_proof() -> void:
# Build a GameState with two players whose capitals are 4 hexes apart.
var state: RefCounted = ClassDB.instantiate("GdGameState") as RefCounted
if not _assert("GdGameState instantiates", state != null):
return
state.call("create_grid", 10, 10)
state.call("add_player_militarist", 0, 0) # player 0 capital at (0,0)
state.call("add_player_militarist", 4, 0) # player 1 capital at (4,0)
# Build the courier map view from that state.
var map_view_inst: RefCounted = ClassDB.instantiate("GdCourierMapView") as RefCounted
if not _assert("GdCourierMapView instantiates", map_view_inst != null):
return
# from_game_state is a static constructor; call it via instance in GDScript.
var gd_map_view: RefCounted = map_view_inst.call("from_game_state", state) as RefCounted
if not _assert("GdCourierMapView.from_game_state returns non-null", gd_map_view != null):
return
var gd_trade: RefCounted = ClassDB.instantiate("GdTrade") as RefCounted
if not _assert("GdTrade instantiates", gd_trade != null):
return
# Build a SharedMapAgreement and an era_2 courier route, add to ledger.
var sm: RefCounted = gd_trade.call("shared_map_agreement_new", 0, 1, 50, 6) as RefCounted
if not _assert("SharedMapAgreement created", sm != null):
return
var route: RefCounted = gd_trade.call("courier_route_new", 0, 1) as RefCounted
if not _assert("CourierRoute created", route != null):
return
# Build ledger JSON with the era_2 courier at position (0,0), no path
# (straight-line fallback moves 1 hex/turn toward (4,0)).
var ledger_inst: RefCounted = ClassDB.instantiate("GdTradeLedger") as RefCounted
if not _assert("GdTradeLedger instantiates", ledger_inst != null):
return
var agreement_json: String = JSON.stringify({
"agreements": [
{
"SharedMap": {
"agreement_id": 0,
"partners": [0, 1],
"turn_started": 1,
"duration": 6,
"share_turns_remaining": 0,
"payment_gold": 50,
"payment_luxury": null,
"courier_route": {
"sender": 0,
"receiver": 1,
"courier_era_tier": 2,
"dispatched_turn": 1,
"position": [0, 0],
"eta_turn": null,
"delivered": false,
"intercepted": false,
"planned_path": [],
"path_step": 0
}
}
}
],
"next_agreement_id": 1
})
# from_json is a static factory; in GDScript call via instance.
var ledger: RefCounted = ledger_inst.call("from_json", agreement_json) as RefCounted
if not _assert("Ledger loads from JSON", ledger != null):
return
# Step up to 20 turns; era_2 moves 1 hex/turn, 4 hexes → deliver by turn 4.
var delivered_event_found: bool = false
var delivered_turn: int = -1
for turn: int in range(1, 21):
var events: Array = gd_trade.call("step_shared_map_agreements", ledger, gd_map_view, turn) as Array
for ev: Dictionary in events:
if ev.get("type") == "shared_map_delivered":
delivered_event_found = true
delivered_turn = turn
break
if delivered_event_found:
break
_assert("SharedMapDelivered event emitted within 20 steps", delivered_event_found)
_assert("Delivery happens by turn 6 (4 hexes at 1/turn + slack)", delivered_turn <= 6)
# After delivery the agreement should be in the share-window phase.
var sm_agreements: Array = ledger.call("iter_shared_map") as Array
_assert("Ledger contains SharedMap agreement after delivery", sm_agreements.size() == 1)
if sm_agreements.size() > 0:
var sm_out: RefCounted = sm_agreements[0] as RefCounted
_assert("Agreement is_delivered", sm_out.call("is_delivered") as bool)
var share_remaining: int = sm_out.call("get_share_turns_remaining") as int
_assert("Share window is open (turns_remaining > 0)", share_remaining > 0)
func _assert(label: String, condition: bool) -> bool:
if condition:
_pass_count += 1
print("[PASS] %s" % label)
else:
_fail_count += 1
push_error("[FAIL] %s" % label)
return condition
func _print_results() -> void:
print("courier_era2_round_trip_proof: %d passed, %d failed" % [_pass_count, _fail_count])

View file

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://courier_era2_round_trip"]
[ext_resource type="Script" path="res://engine/scenes/tests/courier_era2_round_trip_proof.gd" id="1"]
[node name="CourierEra2RoundTripProof" type="Node"]
script = ExtResource("1")