diff --git a/.project/objectives/README.md b/.project/objectives/README.md index 1808608d..9b4ffa1a 100644 --- a/.project/objectives/README.md +++ b/.project/objectives/README.md @@ -17,8 +17,8 @@ | **P0** | 44 | 0 | 0 | 0 | 0 | 0 | 44 | | **P1** | 88 | 0 | 0 | 0 | 0 | 1 | 89 | | **P2** | 130 | 0 | 0 | 0 | 0 | 1 | 131 | -| **P3 (oos)** | 33 | 0 | 2 | 0 | 0 | 29 | 64 | -| **total** | **295** | **0** | **2** | **0** | **0** | **31** | **328** | +| **P3 (oos)** | 34 | 0 | 1 | 0 | 0 | 29 | 64 | +| **total** | **296** | **0** | **1** | **0** | **0** | **31** | **328** | @@ -26,7 +26,7 @@ | Team Lead | Remaining | |---|---| -| [warcouncil](../team-leads/warcouncil.md) | 2 | +| [warcouncil](../team-leads/warcouncil.md) | 1 | diff --git a/.project/objectives/p3-23-trade-richness-gold-strategic.md b/.project/objectives/p3-23-trade-richness-gold-strategic.md index 9a1f33a5..9858c8ff 100644 --- a/.project/objectives/p3-23-trade-richness-gold-strategic.md +++ b/.project/objectives/p3-23-trade-richness-gold-strategic.md @@ -2,10 +2,10 @@ id: p3-23 title: Trade richness — gold & strategic-resource trades with opponents priority: p3 -status: partial +status: done scope: game1 owner: warcouncil -updated_at: 2026-06-25 +updated_at: 2026-06-26 --- ## Summary @@ -46,19 +46,19 @@ is all **inert in-game until the diplomacy turn-integration is revived**. The (`evaluate_trades` is the shared evaluation surface). *(In-game: the FFI caller must source each player's `tile_strategics` — forward-compatible via `#[serde(default)]`. Wiring follow-up.)* -- [~] Logic in Rust (`mc-trade`): gold-for-luxury sale + strategic-for-strategic +- [x] Logic in Rust (`mc-trade`): gold-for-luxury sale + strategic-for-strategic swap + strategic sale all evaluate + activate (8 cargo tests; mc-trade 66/0). - **In-game application — part A (gold flow) wired but INERT:** `GdTradeLedger.gold_flow_for` - + `GdEconomy` `trade_gold` param + `economy.gd` sourcing are correct and GUT-tested - (`test_trade_gold_flows_into_net_gold`, seller +/buyer −) — but they read - `GameState.trade_ledger_json`, which is **never populated in-game** (the only writer is - the disabled `Diplomacy.process_turn`). So gold flow works the instant the trade - integration is revived, but produces 0 until then. - **[ ] REAL remaining work — revive the diplomacy trade turn-integration** (see the - DISCOVERY note): reconcile the 3 `diplomacy.gd ↔ process_trades` contract drifts, - re-enable `Diplomacy.process_turn` in `turn_manager.gd` (carefully — disabled modules - there can abort the arena turn loop), add `PlayerState.traded_strategics` + unit-gating, - verify the full pipeline headless + GUT. Then the deal UI. → status stays `partial`. + **In-game application — REVIVED + verified end-to-end (2026-06-25/26, steps 1–5).** + The diplomacy trade turn-integration is live: (1) `diplomacy.gd ↔ process_trades` + contract reconciled (`_serialize_players` emits PlayerTradeInput, `process_turn` + consumes `{ledger}`); (2) `Diplomacy.process_turn` re-enabled in `turn_manager.gd`, + loop-survival proven (25-turn arena, exit 0); (3) `PlayerState.traded_strategics` + + unit-gating (`_player_owns_resource` honors traded strategics); (4) tile-sourcing + + full chain GUT-proven; (5) **deal UI** — active swaps/sales render in the diplomacy + panel (`diplomacy_deal_proof.tscn`, screenshot reviewed: luxury/strategic/sale rows + with correct direction + gold). Gold flow is no longer inert — `process_turn` now + populates `GameState.trade_ledger_json` each round, which `economy.gd` reads. Full + GUT suite 750/0. ## Progress (2026-06-25) @@ -163,6 +163,8 @@ reads `incoming_strategics`, happiness reads sale luxuries; (c) GDScript deal UI ## Notes -Verified 2026-06-25. Status `partial`: luxury swaps work; gold + strategic trades -are the missing half. (Strategic-resource trade may be a deliberate Game-1 scope -limit — confirm before building if it conflicts with the strategic-scarcity design.) +Verified 2026-06-26. Status `done`: gold sales + strategic swaps + luxury swaps all +form in `mc-trade`, the diplomacy turn-integration is revived and runs each round, and +deals apply in-game (gold flow, happiness luxuries, strategic unit-gating) and render in +the diplomacy panel. Closed across revival steps 1–5 (see Progress); GUT 750/0 + panel +screenshot reviewed in-conversation. The `tribute.rs` path remains Game-2 deferred. diff --git a/public/games/age-of-dwarves/data/objectives.json b/public/games/age-of-dwarves/data/objectives.json index 49d2d159..43bdf58c 100644 --- a/public/games/age-of-dwarves/data/objectives.json +++ b/public/games/age-of-dwarves/data/objectives.json @@ -1,12 +1,12 @@ { - "generated_at": "2026-06-26T03:38:21Z", + "generated_at": "2026-06-26T04:07:21Z", "totals": { "oos": 31, - "missing": 0, - "done": 295, - "partial": 2, - "in_progress": 0, + "done": 296, + "partial": 1, "stub": 0, + "missing": 0, + "in_progress": 0, "total": 328 }, "objectives": [ @@ -3274,10 +3274,10 @@ "id": "p3-23", "title": "Trade richness — gold & strategic-resource trades with opponents", "priority": "p3", - "status": "partial", + "status": "done", "scope": "game1", "owner": "warcouncil", - "updated_at": "2026-06-25", + "updated_at": "2026-06-26", "summary": "> **DISCOVERY (2026-06-25, verify-first):** the original premise was wrong. The\n> inter-player trade turn-integration is **DISABLED in the played game**, not\n> \"luxury-only\". `turn_manager.gd:287` has `Diplomacy.process_turn()` commented out\n> with a stale \"empty stub module\" note (diplomacy.gd was rebuilt but never\n> re-enabled). The *only* writer of `GameState.trade_ledger_json` is diplomacy.gd:32\n> inside that disabled call, so **no inter-player trades run at all** (luxury, strategic,\n> or gold). Worse, the `diplomacy.gd ↔ GdTrade.process_trades` contract has drifted\n> in 3 places: (1) `_serialize_players` emits `{index, traded_luxuries, personality}`\n> but `process_trades` deserializes `Vec` (`player_index`,\n> `tile_luxuries`, `tile_strategics`, `trade_willingness`); (2) `process_trades`\n> returns `{ledger}` but diplomacy.gd reads `result[\"trade_ledger_json\"]`,\n> `[\"relation_changes\"]`, `[\"new_trades\"]`, `[\"broken_trades\"]`; (3) relations\n> advancement isn't returned. So enabling is NOT a one-line uncomment.\n\nThe **simulation logic is complete + cargo-tested** (luxury/strategic swaps + gold\nsales in `mc-trade`, 66/0) and the gold-flow application is wired (part A) — but it\nis all **inert in-game until the diplomacy turn-integration is revived**. The\n`tribute.rs` path stays Game-2 deferred." }, { diff --git a/src/game/engine/scenes/tests/diplomacy_deal_proof.gd b/src/game/engine/scenes/tests/diplomacy_deal_proof.gd new file mode 100644 index 00000000..dcc3e011 --- /dev/null +++ b/src/game/engine/scenes/tests/diplomacy_deal_proof.gd @@ -0,0 +1,80 @@ +extends Control +## p3-23 proof: the REAL diplomacy panel rendering ACTIVE INTER-PLAYER TRADE +## DEALS (luxury swap, strategic swap, gold sale) in its per-rival agreement +## section. Crafts a GameState with a human + two AI rivals and a trade ledger +## holding one of each deal type, instantiates the real diplomacy_panel.tscn +## (exercising get_active_agreements + _make_agreement_section), self-captures. + +const OUTPUT_DIR: String = "user://screenshots" +const VIEWPORT_SIZE: Vector2i = Vector2i(1280, 720) +const CAPTURE_DELAY: float = 0.8 +const PANEL_SCENE: PackedScene = preload("res://engine/scenes/hud/diplomacy_panel.tscn") +const PlayerScript: GDScript = preload("res://engine/src/entities/player.gd") + +const LEDGER_JSON: String = ( + '{"agreements":[' + + '{"LuxurySwap":{"partners":[0,1],' + + '"gives_a":"furs","gives_b":"silk","turn_started":1}},' + + '{"ResourceSale":{"partners":[0,1],"seller":1,"buyer":0,' + + '"resource":"horses","strategic":true,"gold_per_turn":2,"turn_started":1}},' + + '{"StrategicSwap":{"partners":[0,2],' + + '"gives_a":"iron_ore","gives_b":"coal_seam","turn_started":1}}' + + '],"next_agreement_id":0}' +) + +var _captured: bool = false + + +func _ready() -> void: + set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + get_viewport().size = VIEWPORT_SIZE + DisplayServer.window_set_size(VIEWPORT_SIZE) + RenderingServer.set_default_clear_color(Color(0.06, 0.07, 0.10)) + DataLoader.load_theme("age-of-dwarves") + ThemeAssets.set_theme("age-of-dwarves") + ThemeVocabulary.load_vocabulary("age-of-dwarves") + _setup_state() + var panel: Control = PANEL_SCENE.instantiate() as Control + add_child(panel) + panel.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + # The first frame(s) come back blank on this renderer — let the panel lay out + # and render several frames before grabbing the viewport texture. + for _i: int in range(8): + await get_tree().process_frame + await get_tree().create_timer(CAPTURE_DELAY).timeout + _capture_and_quit() + + +func _setup_state() -> void: + var human: RefCounted = PlayerScript.new(0, "You", "dwarf") + human.is_human = true + var r1: RefCounted = PlayerScript.new(1, "Ironhold", "dwarf") + r1.is_human = false + r1.clan_id = "ironhold" + var r2: RefCounted = PlayerScript.new(2, "Goldvein", "dwarf") + r2.is_human = false + r2.clan_id = "goldvein" + GameState.players = [human, r1, r2] + GameState.diplomacy = {} + GameState.trade_ledger_json = LEDGER_JSON + + +func _capture_and_quit() -> void: + if _captured: + return + _captured = true + DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(OUTPUT_DIR)) + var image: Image = get_viewport().get_texture().get_image() + if image == null: + push_error("diplomacy_deal_proof: viewport image null") + get_tree().quit(1) + return + var rel_path: String = "%s/diplomacy_deal_proof.png" % OUTPUT_DIR + var abs_path: String = ProjectSettings.globalize_path(rel_path) + var err: Error = image.save_png(abs_path) + if err == OK: + print("SCREENSHOT_PATH:%s" % abs_path) + print("diplomacy_deal_proof: %dx%d saved" % [image.get_width(), image.get_height()]) + else: + push_error("diplomacy_deal_proof: save failed: %s" % error_string(err)) + get_tree().quit() diff --git a/src/game/engine/scenes/tests/diplomacy_deal_proof.tscn b/src/game/engine/scenes/tests/diplomacy_deal_proof.tscn new file mode 100644 index 00000000..244f1a02 --- /dev/null +++ b/src/game/engine/scenes/tests/diplomacy_deal_proof.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://engine/scenes/tests/diplomacy_deal_proof.gd" id="1"] + +[node name="DiplomacyDealProof" type="Control"] +layout_mode = 3 +anchors_preset = 15 +script = ExtResource("1")