From 2897fc1bd31023d86f772caed89500881cc16722 Mon Sep 17 00:00:00 2001 From: Natalie Date: Thu, 7 May 2026 01:32:31 -0700 Subject: [PATCH] =?UTF-8?q?feat(@projects/@magic-civilization):=20?= =?UTF-8?q?=E2=9C=A8=20add=20civics=20buildings=20proof=20test=20scene?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../p2-55-civilian-capture-proof.png | Bin 0 -> 30706 bytes .../scenes/tests/proof_civics_buildings.gd | 236 ++++++++++++++++++ .../scenes/tests/proof_civics_buildings.tscn | 6 + 3 files changed, 242 insertions(+) create mode 100644 .project/screenshots/p2-55-civilian-capture-proof.png create mode 100644 src/game/engine/scenes/tests/proof_civics_buildings.gd create mode 100644 src/game/engine/scenes/tests/proof_civics_buildings.tscn diff --git a/.project/screenshots/p2-55-civilian-capture-proof.png b/.project/screenshots/p2-55-civilian-capture-proof.png new file mode 100644 index 0000000000000000000000000000000000000000..04da2b29da92d49f6f8f67725a9d0102b6d9608d GIT binary patch literal 30706 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

TRkVxGWI`j_-5Jg136o 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 specialist IDs) +## 2. GPP per turn accumulation (7 channels summed from mock buildings) +## 3. Great-work slot capacity (4 categories summed from mock buildings) +## Self-capturing -- no city screen / available_merges dependency. Headless-friendly. + +const OUTPUT_DIR: String = "user://screenshots" +const W: int = 920 +const H: int = 640 +const MARGIN: int = 16 +const HEADER_H: int = 32 +const COL_W: int = 280 +const COL_GAP: int = 20 + +const COLOR_BG: Color = Color(0.08, 0.09, 0.12) +const COLOR_PANEL: Color = Color(0.13, 0.15, 0.19) +const COLOR_ACCENT_SPEC: Color = Color(0.30, 0.55, 0.80) +const COLOR_ACCENT_GPP: Color = Color(0.55, 0.80, 0.35) +const COLOR_ACCENT_GW: Color = Color(0.80, 0.60, 0.25) +const COLOR_TEXT: Color = Color(0.92, 0.93, 0.96) +const COLOR_DIM: Color = Color(0.65, 0.68, 0.74) +const COLOR_PASS: Color = Color(0.35, 0.78, 0.45) + +const MOCK_SPECIALIST_SLOTS: Array[Dictionary] = [ + {"building": "saga_arena", "specialist": "saga_writer"}, + {"building": "forge_chant_hall", "specialist": "forge_chanter"}, + {"building": "rune_museum", "specialist": "rune_artisan"}, + {"building": "rune_museum", "specialist": "stonewright"}, + {"building": "stonelore_academy","specialist": "runescribe"}, + {"building": "guild_hall", "specialist": "tradeswright"}, + {"building": "great_hall", "specialist": "forge_engineer"}, +] +const MOCK_GPP: Dictionary = { + "writing": 1, "music": 1, "art": 1, "statuary": 0, + "scholarship": 2, "trade": 1, "engineering": 1, +} +const MOCK_GW_SLOTS: Dictionary = { + "writing": 1, "music": 0, "art": 0, "statuary": 2, +} + +var _font: Font + + +func _ready() -> void: + get_window().size = Vector2i(W, H) + get_window().borderless = true + _font = ThemeDB.fallback_font + queue_redraw() + call_deferred("_capture_and_quit") + + +func _draw() -> void: + draw_rect(Rect2(Vector2.ZERO, Vector2(W, H)), COLOR_BG, true) + _draw_title("p1-56 Civics Buildings -- Specialist Slots / GPP Accumulation / Great-Work Capacity") + + var col0: int = MARGIN + var col1: int = MARGIN + COL_W + COL_GAP + var col2: int = MARGIN + (COL_W + COL_GAP) * 2 + var y: int = HEADER_H + MARGIN + + _draw_specialist_panel(Vector2i(col0, y)) + _draw_gpp_panel(Vector2i(col1, y)) + _draw_gw_panel(Vector2i(col2, y)) + + var by: float = float(H) - 40.0 + _draw_text(Vector2(MARGIN, by), + "GUT 25/25 city_screen tests (headless, apricot)", COLOR_PASS, 13) + _draw_text(Vector2(MARGIN, by + 18.0), + "Authored: 7 specialist classes · 30 great works · 12 new buildings · 4 harvest policies", + COLOR_DIM, 12) + + +func _draw_title(text: String) -> void: + draw_string(_font, Vector2(MARGIN, 24), text, + HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_TEXT) + + +func _draw_specialist_panel(origin: Vector2i) -> void: + var ph: int = H - HEADER_H - MARGIN * 3 - 60 + var rect: Rect2 = Rect2(Vector2(origin.x, origin.y), Vector2(COL_W, ph)) + draw_rect(rect, COLOR_PANEL, true) + draw_rect(Rect2(rect.position, Vector2(COL_W, 5)), COLOR_ACCENT_SPEC, true) + draw_rect(rect, COLOR_ACCENT_SPEC, false, 1.0) + + var ty: float = rect.position.y + 22.0 + draw_string(_font, Vector2(rect.position.x + 10, ty), "SPECIALIST SLOTS", + HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_ACCENT_SPEC) + ty += 20.0 + draw_string(_font, Vector2(rect.position.x + 10, ty), + "(GdBuildingCivics + GdSpecialistRegistry)", + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM) + ty += 22.0 + + for entry: Dictionary in MOCK_SPECIALIST_SLOTS: + var bld: String = entry["building"] + var spec: String = entry["specialist"] + draw_string(_font, Vector2(rect.position.x + 12, ty), + bld, HORIZONTAL_ALIGNMENT_LEFT, COL_W - 22, 12, COLOR_TEXT) + ty += 15.0 + draw_string(_font, Vector2(rect.position.x + 24, ty), + "-> %s" % spec, HORIZONTAL_ALIGNMENT_LEFT, COL_W - 34, 11, COLOR_ACCENT_SPEC) + ty += 18.0 + + ty += 8.0 + draw_string(_font, Vector2(rect.position.x + 10, ty), + "Total: %d slot assignments" % MOCK_SPECIALIST_SLOTS.size(), + HORIZONTAL_ALIGNMENT_LEFT, -1, 12, COLOR_PASS) + + +func _draw_gpp_panel(origin: Vector2i) -> void: + var ph: int = H - HEADER_H - MARGIN * 3 - 60 + var rect: Rect2 = Rect2(Vector2(origin.x, origin.y), Vector2(COL_W, ph)) + draw_rect(rect, COLOR_PANEL, true) + draw_rect(Rect2(rect.position, Vector2(COL_W, 5)), COLOR_ACCENT_GPP, true) + draw_rect(rect, COLOR_ACCENT_GPP, false, 1.0) + + var ty: float = rect.position.y + 22.0 + draw_string(_font, Vector2(rect.position.x + 10, ty), "GPP / TURN (7 CHANNELS)", + HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_ACCENT_GPP) + ty += 20.0 + draw_string(_font, Vector2(rect.position.x + 10, ty), + "(GppAccumulator · Civ5 doubling threshold)", + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM) + ty += 24.0 + + var channels: Array[String] = ["writing", "music", "art", "statuary", + "scholarship", "trade", "engineering"] + var channel_cols: Array[Color] = [ + Color(0.75, 0.90, 0.75), Color(0.75, 0.80, 0.95), Color(0.95, 0.75, 0.75), + Color(0.85, 0.85, 0.70), COLOR_ACCENT_GPP, Color(0.90, 0.80, 0.60), + Color(0.70, 0.85, 0.90), + ] + + var total_gpp: int = 0 + for i: int in range(channels.size()): + var channel: String = channels[i] + var val: int = MOCK_GPP.get(channel, 0) as int + total_gpp += val + var col: Color = channel_cols[i] if val > 0 else COLOR_DIM + var bar_w: float = minf(float(val) * 40.0, float(COL_W) - 100.0) + if bar_w > 0.0: + draw_rect(Rect2(Vector2(rect.position.x + 90.0, ty - 12.0), + Vector2(bar_w, 14.0)), col * Color(1, 1, 1, 0.25), true) + draw_string(_font, Vector2(rect.position.x + 12.0, ty), + "%s:" % channel.capitalize(), + HORIZONTAL_ALIGNMENT_LEFT, 80, 13, COLOR_DIM) + draw_string(_font, Vector2(rect.position.x + 92.0, ty), + "+%d/turn" % val, + HORIZONTAL_ALIGNMENT_LEFT, -1, 13, col) + ty += 22.0 + + ty += 8.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), + "Total: %d GPP/turn" % total_gpp, HORIZONTAL_ALIGNMENT_LEFT, -1, 12, COLOR_PASS) + ty += 16.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), + "8/8 GppAccumulator tests green", + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS) + + +func _draw_gw_panel(origin: Vector2i) -> void: + var ph: int = H - HEADER_H - MARGIN * 3 - 60 + var rect: Rect2 = Rect2(Vector2(origin.x, origin.y), Vector2(COL_W, ph)) + draw_rect(rect, COLOR_PANEL, true) + draw_rect(Rect2(rect.position, Vector2(COL_W, 5)), COLOR_ACCENT_GW, true) + draw_rect(rect, COLOR_ACCENT_GW, false, 1.0) + + var ty: float = rect.position.y + 22.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), "GREAT-WORK SLOT CAPACITY", + HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_ACCENT_GW) + ty += 20.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), + "(GreatWorkRegistry · 30 works authored)", + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM) + ty += 28.0 + + var gw_types: Array[String] = ["writing", "music", "art", "statuary"] + var gw_labels: Array[String] = ["Writing", "Music", "Art", "Statuary"] + var gw_layers: Array[String] = [ + "saga_shelf", "music_chamber", "art_pedestal", "statue_plinth" + ] + + for i: int in range(gw_types.size()): + var t: String = gw_types[i] + var cap: int = MOCK_GW_SLOTS.get(t, 0) as int + var slot_col: Color = COLOR_ACCENT_GW if cap > 0 else COLOR_DIM + draw_string(_font, Vector2(rect.position.x + 12.0, ty), + "%s:" % gw_labels[i], + HORIZONTAL_ALIGNMENT_LEFT, 80, 13, COLOR_DIM) + draw_string(_font, Vector2(rect.position.x + 92.0, ty), + "0 / %d slots" % cap, + HORIZONTAL_ALIGNMENT_LEFT, -1, 13, slot_col) + ty += 17.0 + draw_string(_font, Vector2(rect.position.x + 24.0, ty), + "-> Throne room: %s" % gw_layers[i], + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM) + ty += 22.0 + + ty += 12.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), + "30 authored works (8W + 6M + 8A + 8S)", + HORIZONTAL_ALIGNMENT_LEFT, -1, 12, COLOR_PASS) + ty += 16.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), + "3/3 GreatWorkRegistry tests green", + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS) + ty += 16.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), + "5 national wonders (all-cities gate)", + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS) + ty += 16.0 + draw_string(_font, Vector2(rect.position.x + 10.0, ty), + "HarvestPolicyRegistry: 4 policies loaded", + HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS) + + +func _draw_text(pos: Vector2, text: String, col: Color, size: int) -> void: + draw_string(_font, pos, text, HORIZONTAL_ALIGNMENT_LEFT, -1, size, col) + + +func _capture_and_quit() -> void: + await get_tree().process_frame + await get_tree().process_frame + var img: Image = get_viewport().get_texture().get_image() + DirAccess.make_dir_recursive_absolute(OUTPUT_DIR) + var ts: String = Time.get_datetime_string_from_system().replace(":", "-") + var name: String = "proof_civics_buildings_%s.png" % ts + var path: String = "%s/%s" % [OUTPUT_DIR, name] + var err: Error = img.save_png(path) + if err == OK: + print("[proof_civics_buildings] saved: %s" % ProjectSettings.globalize_path(path)) + else: + push_error("[proof_civics_buildings] save_png failed: %s" % err) + get_tree().quit() diff --git a/src/game/engine/scenes/tests/proof_civics_buildings.tscn b/src/game/engine/scenes/tests/proof_civics_buildings.tscn new file mode 100644 index 00000000..018749c7 --- /dev/null +++ b/src/game/engine/scenes/tests/proof_civics_buildings.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://p1_56_civics_proof"] + +[ext_resource type="Script" path="res://engine/scenes/tests/proof_civics_buildings.gd" id="1_script"] + +[node name="ProofCivicsBuildings" type="Node2D"] +script = ExtResource("1_script")