From 874f7571b907dacdd9fa5017872dd8a83e7a05ee Mon Sep 17 00:00:00 2001 From: autocommit Date: Wed, 15 Apr 2026 20:48:32 -0700 Subject: [PATCH] =?UTF-8?q?feat(scenes):=20=E2=9C=A8=20Update=20auto-play?= =?UTF-8?q?=20logic=20to=20prioritize=20low-tier=20lairs=20for=20safer=20t?= =?UTF-8?q?eleportation=20and=20reduce=20scout=20annihilation=20risk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- src/game/engine/scenes/tests/auto_play.gd | 46 ++++++++++++++++++----- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/game/engine/scenes/tests/auto_play.gd b/src/game/engine/scenes/tests/auto_play.gd index a00e935d..ac0a2b15 100644 --- a/src/game/engine/scenes/tests/auto_play.gd +++ b/src/game/engine/scenes/tests/auto_play.gd @@ -463,6 +463,12 @@ func _teleport_scout_near_lair() -> void: break if scout == null: return + # Build tier lookup from wilds config so we can prefer low-tier lairs + # (a tier-7 Volcanic Fissure annihilates a fresh scout every attempt). + var wilds_cfg: Dictionary = DataLoader.get_wilds_config() + var tier_by_type: Dictionary = {} + for lt_entry: Dictionary in wilds_cfg.get("lair_types", []): + tier_by_type[lt_entry.get("id", "")] = int(lt_entry.get("base_tier", 4)) var lair_positions: Array[Vector2i] = [] for axial: Vector2i in game_map.tiles: var tile: Resource = game_map.tiles[axial] @@ -470,12 +476,20 @@ func _teleport_scout_near_lair() -> void: lair_positions.append(axial) if lair_positions.is_empty(): return + # Pick the lowest-tier lair (break ties by distance). var target_lair: Vector2i = lair_positions[0] - var best_dist: int = HexUtilsScript.hex_distance(scout.position, target_lair) + var target_tile: Resource = game_map.get_tile(target_lair) + var target_tier: int = int(tier_by_type.get( + target_tile.lair_type if target_tile != null else "", 99)) + var target_dist: int = HexUtilsScript.hex_distance(scout.position, target_lair) for lp: Vector2i in lair_positions: + var lt_tile: Resource = game_map.get_tile(lp) + var tier: int = int(tier_by_type.get( + lt_tile.lair_type if lt_tile != null else "", 99)) var d: int = HexUtilsScript.hex_distance(scout.position, lp) - if d < best_dist: - best_dist = d + if tier < target_tier or (tier == target_tier and d < target_dist): + target_tier = tier + target_dist = d target_lair = lp var water_biomes: Array = ["ocean", "coast", "deep_ocean", "lake", "inland_sea", "reef"] for n: Vector2i in HexUtilsScript.get_neighbors(target_lair): @@ -487,8 +501,15 @@ func _teleport_scout_near_lair() -> void: continue var from: Vector2i = scout.position scout.position = norm + # Test scaffold: buff the scout enough to clear a low-tier lair. + # Without this, tier 5-7 wild creatures annihilate a base scout + # and the loot path never fires. + scout.max_hp = 200 + scout.hp = 200 + scout.attack = 40 + scout.defense = 20 _recalc_vision(player, game_map) - print("AutoPlay: teleported scout from %s to %s (lair %s at %s)" % [ + print("AutoPlay: teleported scout from %s to %s (lair %s at %s, buffed)" % [ from, norm, tile.lair_type if tile != null else "?", target_lair ]) return @@ -658,11 +679,14 @@ func _play_turn() -> void: # 0b. Gold rush-buy warriors — spawn at city nearest to attack target. # During active siege, lower the threshold so we can replace losses fast. + # Stack critical (<=1 near target) drops the threshold further. var mil_pre: int = 0 for u_pre: RefCounted in player.units: if u_pre.is_alive() and u_pre.get("can_found_city") != true: mil_pre += 1 - var rush_cost: int = 80 if _in_attack_phase else 120 + var rush_cost: int = 120 + if _in_attack_phase: + rush_cost = 50 if _active_attack_mil_count <= 1 else 80 var mil_cap: int = city_count * 2 if _in_attack_phase and _active_attack_mil_count < 3: mil_cap = maxi(mil_cap, mil_pre + (3 - _active_attack_mil_count)) @@ -1410,10 +1434,10 @@ func _try_attack_adjacent_lair(unit: Variant, game_map: RefCounted) -> void: var atk_dict: Dictionary = { "hp": unit.hp, "max_hp": unit.get_max_hp(), - "attack": unit.get_damage(), - "defense": unit.get_damage_resistance(), - "ranged_attack": unit.get_damage() if unit.is_ranged() else 0, - "range": unit.get_range(), + "attack": unit.get_attack(), + "defense": unit.get_defense(), + "ranged_attack": unit.ranged_attack, + "range": 1 if unit.ranged_attack <= 0 else 2, "movement": unit.get_movement(), "keywords": kws, "flanking": 0, @@ -1463,6 +1487,10 @@ func _try_attack_adjacent_lair(unit: Variant, game_map: RefCounted) -> void: EventBus.lair_cleared.emit(norm, reward) if player != null: var turn_seed: int = GameState.game_rng.seed ^ GameState.turn_number + var fauna_check: Dictionary = DataLoader.get_fauna_species(lair_type_id) + print(" LAIR LOOT: species=%s has_table=%s" % [ + lair_type_id, not fauna_check.is_empty() + ]) ItemSystemScript.roll_fauna_drops( lair_type_id, player,