feat(turn-processor): Reimplement culture processing in turn processor by adding HexUtilsScript dependency and reactivating stubbed-out culture logic

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-04-12 22:50:50 -07:00
parent c0d5a804c5
commit d3438ef691

View file

@ -18,6 +18,7 @@ const PlayerScript: GDScript = preload("res://engine/src/entities/player.gd")
const UnitScript: GDScript = preload("res://engine/src/entities/unit.gd")
const CityScript: GDScript = preload("res://engine/src/entities/city.gd")
const CultureScript: GDScript = preload("res://engine/src/modules/empire/culture.gd")
const HexUtilsScript: GDScript = preload("res://engine/src/map/hex_utils.gd")
const HappinessScript: GDScript = preload("res://engine/src/modules/empire/happiness.gd")
const AscensionRitualScript: GDScript = preload(
"res://engine/src/modules/victory/ascension_ritual.gd"
@ -348,17 +349,83 @@ func _process_economy(player: RefCounted, game_map: RefCounted) -> void: # Play
player.gold = 0
func _process_culture(_player: RefCounted, _game_map: RefCounted) -> void: # Player, GameMap
## DISABLED: CultureScript is an empty stub; both `process_turn` and
## `process_global_culture` raise nonexistent-function errors. See the
## top-of-file out-of-scope list. Revive once the culture module is rebuilt.
## Original body:
## player.culture_per_turn = 0
## for city in player.cities:
## if city is CityScript:
## CultureScript.process_turn(city, game_map, player)
## CultureScript.process_global_culture(player)
pass
func _process_culture(player: RefCounted, game_map: RefCounted) -> void:
## Accumulate culture in each city and expand borders when threshold met.
if game_map == null:
return
for city_ref: Variant in player.cities:
if not city_ref is CityScript:
continue
var c: CityScript = city_ref as CityScript
var tile_json: String = BuildableHelperScript.build_tile_yields_json(c, game_map)
var yields: Dictionary = c.get_yields(tile_json)
var culture: float = float(yields.get("culture", 0))
if culture <= 0.0:
continue
# Accumulate culture
c.set_culture_stored(c.get_culture_stored() + culture)
# Check for border expansion
var threshold: float = _culture_expansion_threshold(c.owned_tiles.size())
if c.get_culture_stored() >= threshold:
c.set_culture_stored(c.get_culture_stored() - threshold)
# Find best adjacent tile to claim
var best_tile: Vector2i = _pick_border_expansion_tile(c, game_map, player)
if best_tile != Vector2i(-1, -1):
c.owned_tiles.append(best_tile)
var tile: Resource = game_map.get_tile(best_tile)
if tile != null:
tile.owner = player.index
EventBus.city_border_expanded.emit(c, best_tile)
func _culture_expansion_threshold(tiles_owned: int) -> float:
## Civ5-style: first ring at 10, then roughly 10 * 1.5^(tiles - 7)
if tiles_owned <= 7:
return 10.0
return 10.0 * pow(1.5, tiles_owned - 7)
func _pick_border_expansion_tile(
city: CityScript, game_map: RefCounted, player: RefCounted
) -> Vector2i:
## Pick the best unclaimed adjacent tile to add to the city's territory.
var candidates: Array[Vector2i] = []
for owned_pos: Vector2i in city.owned_tiles:
var neighbors: Array[Vector2i] = HexUtilsScript.get_neighbors(owned_pos)
for n: Vector2i in neighbors:
var norm: Vector2i = HexUtilsScript.normalize_position(
n, game_map.width, game_map.height, game_map.wrap_mode
)
if norm in city.owned_tiles:
continue
var tile: Resource = game_map.get_tile(norm)
if tile == null:
continue
if tile.owner != -1 and tile.owner != player.index:
continue # Already owned by another player
if norm not in candidates:
candidates.append(norm)
if candidates.is_empty():
return Vector2i(-1, -1)
# Score by yield value — prefer high-production/food tiles
var best: Vector2i = candidates[0]
var best_score: float = 0.0
for pos: Vector2i in candidates:
var tile: Resource = game_map.get_tile(pos)
if tile == null:
continue
var tile_yields: Dictionary = tile.get_yields(player.index)
var score: float = float(tile_yields.get("food", 0)) * 2.0
score += float(tile_yields.get("production", 0)) * 1.5
score += float(tile_yields.get("trade", 0))
score += float(tile_yields.get("culture", 0))
# Bonus for resources
if tile.resource_id != "":
score += 5.0
if score > best_score:
best_score = score
best = pos
return best
func _process_golden_age(player: RefCounted, game_map: RefCounted) -> void: # Player, GameMap