test(scenes): ✅ Add test script and scene for verifying era 7 severance logic
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
f561ec4cc9
commit
6f3cfb5b38
2 changed files with 171 additions and 0 deletions
165
src/game/engine/scenes/tests/courier_era7_severance_proof.gd
Normal file
165
src/game/engine/scenes/tests/courier_era7_severance_proof.gd
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
extends Node
|
||||
## p3-01 bullet 11: era_7 courier severance proof.
|
||||
##
|
||||
## Tests two sub-cases:
|
||||
## 1. Era_7 courier (8 hex/turn) over a 4-hex gap with intact route delivers
|
||||
## in a single step.
|
||||
## 2. A courier already marked intercepted=true produces no further events
|
||||
## (terminal state per spec: intercepted is non-refundable, no re-processing).
|
||||
##
|
||||
## NOTE: The deterministic tile-severance path (pillaging steam_track mid-route)
|
||||
## requires `stamp_tile_improvement` on GdGameState, not yet exposed to GDScript.
|
||||
## That path is covered by the Rust unit test
|
||||
## `steam_track_pillage_intercepts_on_next_step` in mc-turn/src/courier_resolver.rs.
|
||||
|
||||
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:
|
||||
_test_era7_delivers_intact_route()
|
||||
_test_intercepted_route_is_terminal()
|
||||
|
||||
|
||||
func _test_era7_delivers_intact_route() -> void:
|
||||
var state: RefCounted = ClassDB.instantiate("GdGameState") as RefCounted
|
||||
if not _assert("era7_intact: GdGameState instantiates", state != null):
|
||||
return
|
||||
state.call("create_grid", 10, 10)
|
||||
state.call("add_player_militarist", 0, 0)
|
||||
state.call("add_player_militarist", 4, 0)
|
||||
|
||||
var map_view_inst: RefCounted = ClassDB.instantiate("GdCourierMapView") as RefCounted
|
||||
if not _assert("era7_intact: GdCourierMapView instantiates", map_view_inst != null):
|
||||
return
|
||||
var gd_map_view: RefCounted = map_view_inst.call("from_game_state", state) as RefCounted
|
||||
if not _assert("era7_intact: from_game_state returns non-null", gd_map_view != null):
|
||||
return
|
||||
|
||||
var gd_trade: RefCounted = ClassDB.instantiate("GdTrade") as RefCounted
|
||||
if not _assert("era7_intact: GdTrade instantiates", gd_trade != null):
|
||||
return
|
||||
|
||||
# Era_7 moves 8 hexes/turn via straight-line; 4-hex gap → delivers in 1 step.
|
||||
var ledger_inst: RefCounted = ClassDB.instantiate("GdTradeLedger") as RefCounted
|
||||
var agreement_json: String = JSON.stringify({
|
||||
"agreements": [
|
||||
{
|
||||
"SharedMap": {
|
||||
"agreement_id": 0,
|
||||
"partners": [0, 1],
|
||||
"turn_started": 1,
|
||||
"duration": 5,
|
||||
"share_turns_remaining": 0,
|
||||
"payment_gold": 100,
|
||||
"payment_luxury": null,
|
||||
"courier_route": {
|
||||
"sender": 0,
|
||||
"receiver": 1,
|
||||
"courier_era_tier": 7,
|
||||
"dispatched_turn": 1,
|
||||
"position": [0, 0],
|
||||
"eta_turn": null,
|
||||
"delivered": false,
|
||||
"intercepted": false,
|
||||
"planned_path": [],
|
||||
"path_step": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"next_agreement_id": 1
|
||||
})
|
||||
var ledger: RefCounted = ledger_inst.call("from_json", agreement_json) as RefCounted
|
||||
if not _assert("era7_intact: ledger loads", ledger != null):
|
||||
return
|
||||
|
||||
var events: Array = gd_trade.call("step_shared_map_agreements", ledger, gd_map_view, 2) as Array
|
||||
var delivered: bool = false
|
||||
for ev: Dictionary in events:
|
||||
if ev.get("type") == "shared_map_delivered":
|
||||
delivered = true
|
||||
break
|
||||
_assert("era7_intact: era_7 delivers in one step over 4-hex gap", delivered)
|
||||
|
||||
|
||||
func _test_intercepted_route_is_terminal() -> void:
|
||||
var state: RefCounted = ClassDB.instantiate("GdGameState") as RefCounted
|
||||
if not _assert("era7_terminal: GdGameState instantiates", state != null):
|
||||
return
|
||||
state.call("create_grid", 10, 10)
|
||||
state.call("add_player_militarist", 0, 0)
|
||||
state.call("add_player_militarist", 8, 0)
|
||||
|
||||
var map_view_inst: RefCounted = ClassDB.instantiate("GdCourierMapView") as RefCounted
|
||||
var gd_map_view: RefCounted = map_view_inst.call("from_game_state", state) as RefCounted
|
||||
if not _assert("era7_terminal: GdCourierMapView created", gd_map_view != null):
|
||||
return
|
||||
|
||||
var gd_trade: RefCounted = ClassDB.instantiate("GdTrade") as RefCounted
|
||||
if not _assert("era7_terminal: GdTrade instantiates", gd_trade != null):
|
||||
return
|
||||
|
||||
# Courier already in terminal intercepted=true state.
|
||||
var ledger_inst: RefCounted = ClassDB.instantiate("GdTradeLedger") as RefCounted
|
||||
var agreement_json: String = JSON.stringify({
|
||||
"agreements": [
|
||||
{
|
||||
"SharedMap": {
|
||||
"agreement_id": 0,
|
||||
"partners": [0, 1],
|
||||
"turn_started": 1,
|
||||
"duration": 10,
|
||||
"share_turns_remaining": 0,
|
||||
"payment_gold": 100,
|
||||
"payment_luxury": null,
|
||||
"courier_route": {
|
||||
"sender": 0,
|
||||
"receiver": 1,
|
||||
"courier_era_tier": 7,
|
||||
"dispatched_turn": 1,
|
||||
"position": [3, 0],
|
||||
"eta_turn": null,
|
||||
"delivered": false,
|
||||
"intercepted": true,
|
||||
"planned_path": [],
|
||||
"path_step": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"next_agreement_id": 1
|
||||
})
|
||||
var ledger: RefCounted = ledger_inst.call("from_json", agreement_json) as RefCounted
|
||||
if not _assert("era7_terminal: ledger loads", ledger != null):
|
||||
return
|
||||
|
||||
var events: Array = gd_trade.call("step_shared_map_agreements", ledger, gd_map_view, 2) as Array
|
||||
_assert("era7_terminal: no events emitted for already-intercepted courier", events.is_empty())
|
||||
|
||||
var sm_agreements: Array = ledger.call("iter_shared_map") as Array
|
||||
_assert("era7_terminal: intercepted agreement stays in ledger", sm_agreements.size() == 1)
|
||||
|
||||
|
||||
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_era7_severance_proof: %d passed, %d failed" % [_pass_count, _fail_count])
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://courier_era7_severance"]
|
||||
|
||||
[ext_resource type="Script" path="res://engine/scenes/tests/courier_era7_severance_proof.gd" id="1"]
|
||||
|
||||
[node name="CourierEra7SeveranceProof" type="Node"]
|
||||
script = ExtResource("1")
|
||||
Loading…
Add table
Reference in a new issue