feat(@projects/@magic-civilization): ✨ add per-tile fauna density updates
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
d0a74e5122
commit
27ade4cd43
4 changed files with 40 additions and 0 deletions
|
|
@ -46,6 +46,17 @@ func tick(grid: RefCounted, seed: int) -> void:
|
||||||
fauna_ecology.call("tick_populations", grid, seed)
|
fauna_ecology.call("tick_populations", grid, seed)
|
||||||
|
|
||||||
|
|
||||||
|
## Per-tile total fauna population for the live-map fauna overlay
|
||||||
|
## (`fauna_overlay_renderer.gd`). One bulk bridge read per refresh: a Dictionary
|
||||||
|
## keyed by `Vector2i(col, row)` → total population (float). Empty when no
|
||||||
|
## engine or no populations yet (emergence has not fired). The overlay reads
|
||||||
|
## this on each `EventBus.worldsim_updated` and normalizes for its heatmap.
|
||||||
|
func tile_densities() -> Dictionary:
|
||||||
|
if fauna_ecology == null:
|
||||||
|
return {}
|
||||||
|
return fauna_ecology.call("populated_tile_densities")
|
||||||
|
|
||||||
|
|
||||||
func _ensure_species_registered() -> void:
|
func _ensure_species_registered() -> void:
|
||||||
## Idempotent: a non-empty registry short-circuits via the engine's
|
## Idempotent: a non-empty registry short-circuits via the engine's
|
||||||
## `population_slot_count` proxy on subsequent ticks (slots only appear
|
## `population_slot_count` proxy on subsequent ticks (slots only appear
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,11 @@ signal creature_died(pos: Vector2i, species_name: String, quality: int)
|
||||||
signal creature_born(pos: Vector2i, species_name: String)
|
signal creature_born(pos: Vector2i, species_name: String)
|
||||||
## Tile crossed Q4 threshold — natural wonder emerged from ecology.
|
## Tile crossed Q4 threshold — natural wonder emerged from ecology.
|
||||||
signal landmark_formed(pos: Vector2i, name: String, quality: int)
|
signal landmark_formed(pos: Vector2i, name: String, quality: int)
|
||||||
|
## Emitted once per full game turn after the continuous worldsim has advanced
|
||||||
|
## (climate physics + fauna `EcologyState.tick` + `WorldsimState.dispatch`).
|
||||||
|
## The fauna overlay subscribes to refresh its per-tile density heatmap so the
|
||||||
|
## evolving living world is visible on the playable map (p2-80 render hook).
|
||||||
|
signal worldsim_updated(turn: int)
|
||||||
|
|
||||||
# -- Natural event signals --
|
# -- Natural event signals --
|
||||||
signal natural_event_spawned(event_type: String, position: Vector2i, intensity: float)
|
signal natural_event_spawned(event_type: String, position: Vector2i, intensity: float)
|
||||||
|
|
|
||||||
|
|
@ -301,6 +301,10 @@ func next_player() -> void:
|
||||||
WorldsimState.dispatch(
|
WorldsimState.dispatch(
|
||||||
fauna_grid, GameState.turn_number, GameState.map_seed
|
fauna_grid, GameState.turn_number, GameState.map_seed
|
||||||
)
|
)
|
||||||
|
# p2-80 render hook: signal the fauna overlay to refresh its
|
||||||
|
# per-tile density heatmap so the evolving living world is
|
||||||
|
# visible on the playable map, not just simulated.
|
||||||
|
EventBus.worldsim_updated.emit(GameState.turn_number)
|
||||||
GameState.current_player_index = 0
|
GameState.current_player_index = 0
|
||||||
GameState.turn_number += 1
|
GameState.turn_number += 1
|
||||||
# Check victory conditions after all players have moved
|
# Check victory conditions after all players have moved
|
||||||
|
|
|
||||||
|
|
@ -851,6 +851,26 @@ impl GdFaunaEcology {
|
||||||
fn populated_tile_count(&self) -> i64 {
|
fn populated_tile_count(&self) -> i64 {
|
||||||
self.inner.tile_populations.len() as i64
|
self.inner.tile_populations.len() as i64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Per-tile total fauna population, as a `Dictionary` keyed by
|
||||||
|
/// `Vector2i(col, row)` → total population (`f64`, summed across all species
|
||||||
|
/// slots on the tile). One bulk read so the live-map fauna overlay
|
||||||
|
/// (`fauna_overlay_renderer.gd`) refreshes per turn with a single bridge
|
||||||
|
/// call instead of `populated_tile_count`×`populations_on_tile`. Tiles with
|
||||||
|
/// zero population are omitted (the map is sparse, mirroring the engine's
|
||||||
|
/// own `tile_populations`). Deterministic order is irrelevant here — the
|
||||||
|
/// renderer keys by position, not iteration order.
|
||||||
|
#[func]
|
||||||
|
fn populated_tile_densities(&self) -> Dictionary {
|
||||||
|
let mut out = Dictionary::new();
|
||||||
|
for (&(col, row), slots) in &self.inner.tile_populations {
|
||||||
|
let total: f32 = slots.iter().map(|s| s.population).sum();
|
||||||
|
if total > 0.0 {
|
||||||
|
out.set(Vector2i::new(col, row), f64::from(total));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── GdAtmosphericChemistry ──────────────────────────────────────────────
|
// ── GdAtmosphericChemistry ──────────────────────────────────────────────
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue