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:
parent
c0d5a804c5
commit
d3438ef691
1 changed files with 78 additions and 11 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue