babylon.engine
Simulation engine for the Babylon game loop.
This package contains the core game loop logic: - simulation_engine: The step() function for state transformation - simulation: Simulation facade class for multi-tick runs with history - scenarios: Factory functions for creating initial states - factories: Entity factory functions (create_proletariat, create_bourgeoisie) - history_formatter: Narrative generation from simulation history - Dependency injection: ServiceContainer, EventBus, FormulaRegistry
Phase 2.1: Refactored to modular System architecture. Sprint 3: Central Committee (Dependency Injection) Sprint 9: Integration proof with Simulation facade
- class babylon.engine.AsyncSimulationRunner(simulation, tick_interval=1.0)[source]
Bases:
objectAsync runner that decouples UI from simulation engine.
The runner wraps a Simulation instance and provides:
Non-blocking steps: Uses
asyncio.to_thread()to runsimulation.step()without blocking the event loop.State queue: Pushes WorldState snapshots to an async queue for the UI to consume at its own pace.
Continuous play:
start()/stop()manage a background loop that steps the simulation at configurable intervals.Queue overflow handling: Drops oldest states when queue is full (MAX_QUEUE_SIZE=10) to prevent memory issues.
- Parameters:
simulation (Simulation)
tick_interval (float)
- MAX_QUEUE_SIZE
Maximum states to buffer before dropping oldest.
Example
>>> runner = AsyncSimulationRunner(sim, tick_interval=0.5) >>> state = await runner.step_once() # Single step >>> print(f"Now at tick {state.tick}")
- Thread Safety:
The runner uses an asyncio.Lock to serialize step_once() calls, ensuring simulation state consistency even with concurrent access.
- __init__(simulation, tick_interval=1.0)[source]
Initialize the async runner with a simulation.
- Parameters:
simulation (
Simulation) – The Simulation facade to run.tick_interval (
float) – Seconds between steps in continuous mode. Must be positive.
- Raises:
ValueError – If tick_interval is not positive.
- Return type:
None
- property simulation: Simulation
Return the wrapped Simulation instance.
- property queue: Queue[WorldState]
Return the state queue for direct access.
- Returns:
The asyncio.Queue containing WorldState snapshots.
- async start()[source]
Start continuous simulation mode.
Creates a background task that steps the simulation at
tick_intervalintervals. Idempotent - calling start() when already running is a no-op.The task reference is stored to prevent garbage collection.
- Return type:
- async stop()[source]
Stop continuous simulation mode.
Cancels the background task and waits for it to finish. Idempotent - calling stop() when not running is a no-op.
- Return type:
- async step_once()[source]
Execute a single simulation step without blocking.
Uses
asyncio.to_thread()to runsimulation.step()in a thread pool, keeping the event loop responsive.The new state is pushed to the queue. If the queue is full, the oldest state is dropped to make room.
- Return type:
- Returns:
The new WorldState after the step.
Note
Uses an asyncio.Lock to serialize concurrent calls, ensuring simulation state consistency.
- async get_state()[source]
Get a state from the queue without blocking.
- Return type:
- Returns:
The next WorldState if available, None otherwise.
- async get_state_blocking(timeout=None)[source]
Get a state from the queue, waiting if necessary.
- Parameters:
timeout (
float|None) – Maximum seconds to wait. None means wait forever.- Return type:
- Returns:
The next WorldState from the queue.
- Raises:
asyncio.TimeoutError – If timeout expires before a state is available.
- async drain_queue()[source]
Remove and return all states from the queue.
- Return type:
- Returns:
List of all WorldState objects that were in the queue, in order from oldest to newest. Empty list if queue was empty.
- async reset(new_simulation)[source]
Reset the runner with a new simulation.
Stops the runner if running, drains the queue, and assigns the new simulation for future steps.
- Parameters:
new_simulation (
Simulation) – The new Simulation instance to use.- Return type:
- babylon.engine.create_proletariat(id=PERIPHERY_WORKER_ID, name='Proletariat', wealth=0.5, ideology=None, organization=0.1, repression_faced=0.5, subsistence_threshold=0.3, p_acquiescence=0.0, p_revolution=0.0, description='Exploited working class', effective_wealth=0.0, unearned_increment=0.0, ppp_multiplier=1.0, county_fips=None)[source]
Create a proletariat (exploited class) social class.
The proletariat is defined by: - PERIPHERY_PROLETARIAT role (exploited in the world system) - Low default wealth (0.5) - Slightly revolutionary ideology (-0.3) - Low organization (0.1 = 10%) - Moderate repression faced (0.5)
- Parameters:
id (
str) – Unique identifier matching ^C[0-9]{3}$ pattern (default: “C001”)name (
str) – Human-readable name (default: “Proletariat”)wealth (
float) – Economic resources (default: 0.5)ideology (
float|IdeologicalProfile|None) – Ideological position. Acceptsfloat(legacy, scalar -1=revolutionary..+1=reactionary),IdeologicalProfile(spec-066 placeholder + future per-county data), orNoneto use the legacy default-0.3. The spec-066 bridged runner passesIdeologicalProfile(class_consciousness=0.1, national_identity=0.5)to every county entity to materialize the placeholder (r=0.05, l=0.50, f=0.45).organization (
float) – Collective cohesion (default: 0.1)repression_faced (
float) – State violence level (default: 0.5)subsistence_threshold (
float) – Minimum wealth for survival (default: 0.3)p_acquiescence (
float) – P(S|A) - survival through acquiescence (default: 0.0, calculated by engine)p_revolution (
float) – P(S|R) - survival through revolution (default: 0.0, calculated by engine)description (
str) – Optional description (default: “Exploited working class”)effective_wealth (
float) – PPP-adjusted wealth (default: 0.0, calculated by engine)unearned_increment (
float) – PPP bonus (default: 0.0, calculated by engine)ppp_multiplier (
float) – PPP multiplier applied to wages (default: 1.0)county_fips (str | None)
- Return type:
- Returns:
SocialClass configured as proletariat
Example
>>> worker = create_proletariat() >>> worker.role <SocialRole.PERIPHERY_PROLETARIAT: 'periphery_proletariat'> >>> worker.wealth 0.5
- babylon.engine.create_bourgeoisie(id=COMPRADOR_ID, name='Bourgeoisie', wealth=10.0, ideology=None, organization=0.7, repression_faced=0.1, subsistence_threshold=0.1, p_acquiescence=0.0, p_revolution=0.0, description='Capital-owning exploiter class', effective_wealth=0.0, unearned_increment=0.0, ppp_multiplier=1.0, county_fips=None)[source]
Create a bourgeoisie (exploiter class) social class.
The bourgeoisie is defined by: - CORE_BOURGEOISIE role (exploiter in the world system) - High default wealth (10.0) - Reactionary ideology (0.8) - High organization (0.7 = 70%) - Low repression faced (0.1 - protected by state)
- Parameters:
id (
str) – Unique identifier matching ^C[0-9]{3}$ pattern (default: “C002”)name (
str) – Human-readable name (default: “Bourgeoisie”)wealth (
float) – Economic resources (default: 10.0)ideology (
float|IdeologicalProfile|None) – Ideological position. Acceptsfloat(legacy, scalar -1=revolutionary..+1=reactionary),IdeologicalProfile(spec-066 placeholder + future per-county data), orNoneto use the legacy default0.8. The spec-066 bridged runner passesIdeologicalProfile(class_consciousness=0.1, national_identity=0.5)to every county entity to materialize the placeholder (r=0.05, l=0.50, f=0.45).organization (
float) – Collective cohesion (default: 0.7)repression_faced (
float) – State violence level (default: 0.1)subsistence_threshold (
float) – Minimum wealth for survival (default: 0.1)p_acquiescence (
float) – P(S|A) - survival through acquiescence (default: 0.0, calculated by engine)p_revolution (
float) – P(S|R) - survival through revolution (default: 0.0, calculated by engine)description (
str) – Optional description (default: “Capital-owning exploiter class”)effective_wealth (
float) – PPP-adjusted wealth (default: 0.0, calculated by engine)unearned_increment (
float) – PPP bonus (default: 0.0, calculated by engine)ppp_multiplier (
float) – PPP multiplier applied to wages (default: 1.0)county_fips (str | None)
- Return type:
- Returns:
SocialClass configured as bourgeoisie
Example
>>> owner = create_bourgeoisie() >>> owner.role <SocialRole.CORE_BOURGEOISIE: 'core_bourgeoisie'> >>> owner.wealth 10.0
- babylon.engine.format_class_struggle_history(simulation)[source]
Format simulation history as a narrative of class struggle.
Generates a human-readable summary of the simulation history, highlighting wealth transfers, ideological changes, and tension accumulation.
- Parameters:
simulation (
Simulation) – A Simulation instance with history data- Return type:
- Returns:
A formatted string narrative describing the class struggle dynamics.
Example
>>> sim = Simulation(initial_state, config) >>> sim.run(100) >>> print(format_class_struggle_history(sim)) # History of Class Struggle ...
- babylon.engine.create_two_node_scenario(worker_wealth=0.5, owner_wealth=0.5, extraction_efficiency=0.8, repression_level=0.5, worker_organization=0.1, worker_ideology=0.0)[source]
Create the minimal viable dialectic: one worker, one owner, one exploitation edge.
This is the two-node scenario from the Phase 1 blueprint, now ready for Phase 2 simulation. It models the fundamental class relationship: - Worker produces value (source of exploitation edge) - Owner extracts imperial rent (target of exploitation edge) - Tension accumulates on the edge
- Parameters:
worker_wealth (
float) – Initial wealth for periphery worker (default 0.5)owner_wealth (
float) – Initial wealth for core owner (default 0.5)extraction_efficiency (
float) – Alpha in imperial rent formula (default 0.8)repression_level (
float) – State violence capacity (default 0.5)worker_organization (
float) – Worker class cohesion (default 0.1)worker_ideology (
float) – Worker ideology, -1=revolutionary to +1=reactionary (default 0.0)
- Return type:
- Returns:
Tuple of (WorldState, SimulationConfig, GameDefines) ready for step() function.
Example
>>> state, config, defines = create_two_node_scenario() >>> for _ in range(100): ... state = step(state, config) >>> print(f"Worker wealth after 100 ticks: {state.entities['C001'].wealth}")
- babylon.engine.create_imperial_circuit_scenario(periphery_wealth=0.6, core_wealth=0.9, comprador_cut=0.90, imperial_rent_pool=100.0, extraction_efficiency=0.8, repression_level=0.5, solidarity_strength=0.0)[source]
Create the 4-node Imperial Circuit scenario.
This scenario fixes the “Robin Hood” bug in create_two_node_scenario() where super-wages incorrectly flow to periphery workers. In MLM-TW theory, super-wages should only go to the Labor Aristocracy (core workers), NOT periphery workers.
Topology:
graph LR Pw["P_w (Periphery Workers)"] -->|EXPLOITATION| Pc["P_c (Comprador)"] Pc -->|TRIBUTE| Cb["C_b (Core Bourgeoisie)"] Cb -->|WAGES| Cw["C_w (Labor Aristocracy)"] Cb -->|CLIENT_STATE| Pc Pw -.->|"SOLIDARITY (0.0)"| CwValue Flow:
EXPLOITATION: P_w -> P_c (imperial rent extraction from workers)
TRIBUTE: P_c -> C_b (comprador sends tribute, keeps comprador_cut)
WAGES: C_b -> C_w (super-wages to labor aristocracy, NOT periphery!)
CLIENT_STATE: C_b -> P_c (subsidy to stabilize client state)
SOLIDARITY: P_w -> C_w (potential internationalism, starts at 0)
- Parameters:
periphery_wealth (
float) – Initial wealth for periphery worker P001 (default 0.1)core_wealth (
float) – Initial wealth for core bourgeoisie C001 (default 0.9)comprador_cut (
float) – Fraction comprador keeps from extracted value (default 0.90)imperial_rent_pool (
float) – Initial imperial rent pool (default 100.0)extraction_efficiency (
float) – Alpha in imperial rent formula (default 0.8)repression_level (
float) – Base repression level (default 0.5)solidarity_strength (
float) – Initial solidarity between P_w and C_w (default 0.0). When > 0, wage crisis routes to class consciousness (revolutionary). When = 0, wage crisis routes to national identity (fascist).
- Return type:
- Returns:
Tuple of (WorldState, SimulationConfig, GameDefines) ready for step() function.
Example
>>> state, config, defines = create_imperial_circuit_scenario() >>> # Verify wages go to labor aristocracy, not periphery >>> wages_edges = [r for r in state.relationships if r.edge_type == EdgeType.WAGES] >>> assert state.entities[wages_edges[0].target_id].role == SocialRole.LABOR_ARISTOCRACY
- babylon.engine.create_high_tension_scenario()[source]
Create a scenario with high initial tension.
Worker is poor, owner is rich, tension is already elevated. Useful for testing phase transitions and rupture conditions.
- Return type:
- Returns:
Tuple of (WorldState, SimulationConfig, GameDefines) near rupture point.
- babylon.engine.create_labor_aristocracy_scenario()[source]
Create a scenario with a labor aristocracy (Wc > Vc).
Worker receives more than they produce, enabled by imperial rent from elsewhere. Tests consciousness decay mechanics.
- Return type:
- Returns:
Tuple of (WorldState, SimulationConfig, GameDefines) with labor aristocracy.
- class babylon.engine.FormulaRegistry[source]
Bases:
objectRegistry for named mathematical formulas.
Provides a central lookup for all simulation formulas, enabling: - Hot-swapping formulas for testing with mocks - Modding support for custom formula implementations - Centralized formula management
Example
>>> registry = FormulaRegistry.default() >>> la = registry.get("labor_aristocracy_ratio") >>> result = la(core_wages=120.0, value_produced=100.0)
- classmethod default()[source]
Create a registry pre-populated with all standard formulas.
Registers formulas from babylon.formulas: - labor_aristocracy_ratio - is_labor_aristocracy - consciousness_drift - acquiescence_probability - revolution_probability - crossover_threshold - loss_aversion - exchange_ratio - exploitation_rate - value_transfer - prebisch_singer
- Return type:
- Returns:
FormulaRegistry with all standard formulas registered
- class babylon.engine.ServiceContainer(config, database, event_bus, formulas, defines, metrics, field_registry=None, opposition_registry=None, reserve_army_data_source=None, dispossession_data_source=None, productivity_data_source=None, melt_calculator=None, basket_calculator=None, gamma_calculator=None, capital_calculator=None, throughput_calculator=None, transition_engine=None, tensor_registry=None, economics_fallbacks=<factory>, community_hypergraph=None, turnover_profile_source=None, inventory_data_source=None, depreciation_data_source=None, hex_grid=None, persistence=None, tracer=None, boundary_register=None, auditor=None, distribution_calculator=None, interest_calculator=None, credit_cycle_detector=None, fictitious_capital_calculator=None, rent_calculator=None, housing_calculator=None, counter_tendency_calculator=None, value_basis_converter=None, financial_crisis_assessor=None, z1_source=None, housing_data_source=None, periphery_labor_source=None, final_demand_source=None, industry_county_allocator=None, production_chain_calculator=None, bea_industries=None)[source]
Bases:
objectContainer for all simulation services.
Aggregates the six core services needed by the simulation, plus optional economics calculator services for tick dynamics (Feature 017):
- Core:
config: Immutable simulation parameters
database: Database connection for persistence
event_bus: Publish/subscribe communication
formulas: Registry of mathematical formulas
defines: Centralized game coefficients (Paradox Refactor)
metrics: Telemetry collector for observability (Spec 008)
- Field Topology (Feature 002, optional for backward compatibility):
field_registry: Contradiction field computation registry
- Economics (Feature 017, all optional for backward compatibility):
melt_calculator: National MELT computation (Feature 013)
basket_calculator: Basket visibility computation (Feature 013)
gamma_calculator: Reproductive visibility computation (Feature 015)
capital_calculator: Capital stock computation (Feature 012)
throughput_calculator: Throughput position computation (Feature 014)
transition_engine: Class transition engine (Feature 016)
tensor_registry: Cached economic tensor data (Feature 011)
Example
>>> container = ServiceContainer.create() >>> rent = container.formulas.get("imperial_rent") >>> container.event_bus.publish(Event(...)) >>> with container.database.session() as session: ... # do database work >>> container.database.close() >>> default_org = container.defines.DEFAULT_ORGANIZATION >>> container.metrics.increment("ticks_processed")
- Parameters:
config (SimulationConfig)
database (DatabaseProtocol)
event_bus (EventBus)
formulas (FormulaRegistry)
defines (GameDefines)
metrics (MetricsCollectorProtocol)
field_registry (Any)
opposition_registry (Any)
reserve_army_data_source (Any)
dispossession_data_source (Any)
productivity_data_source (Any)
melt_calculator (Any)
basket_calculator (Any)
gamma_calculator (Any)
capital_calculator (Any)
throughput_calculator (Any)
transition_engine (Any)
tensor_registry (Any)
economics_fallbacks (EconomicsFallbackTally)
community_hypergraph (Any)
turnover_profile_source (Any)
inventory_data_source (Any)
depreciation_data_source (Any)
hex_grid (Any)
persistence (Any)
tracer (Any)
boundary_register (Any)
auditor (Any)
distribution_calculator (Any)
interest_calculator (Any)
credit_cycle_detector (Any)
fictitious_capital_calculator (Any)
rent_calculator (Any)
housing_calculator (Any)
counter_tendency_calculator (Any)
value_basis_converter (Any)
financial_crisis_assessor (Any)
z1_source (Any)
housing_data_source (Any)
periphery_labor_source (Any)
final_demand_source (Any)
industry_county_allocator (Any)
production_chain_calculator (Any)
- config: SimulationConfig
- database: DatabaseProtocol
- formulas: FormulaRegistry
- defines: GameDefines
- metrics: MetricsCollectorProtocol
- economics_fallbacks: EconomicsFallbackTally
- bea_industries: list[str] | None = None
The configured BEA Summary industry list — defines the alignment baseline for FR-006 (industry-list mismatch fail-fast). Set at scenario-load time; None until then (the Spec 057 pipeline falls back to graceful-degradation stub behavior when None per data-model.md ServiceContainer notes).
- __init__(config, database, event_bus, formulas, defines, metrics, field_registry=None, opposition_registry=None, reserve_army_data_source=None, dispossession_data_source=None, productivity_data_source=None, melt_calculator=None, basket_calculator=None, gamma_calculator=None, capital_calculator=None, throughput_calculator=None, transition_engine=None, tensor_registry=None, economics_fallbacks=<factory>, community_hypergraph=None, turnover_profile_source=None, inventory_data_source=None, depreciation_data_source=None, hex_grid=None, persistence=None, tracer=None, boundary_register=None, auditor=None, distribution_calculator=None, interest_calculator=None, credit_cycle_detector=None, fictitious_capital_calculator=None, rent_calculator=None, housing_calculator=None, counter_tendency_calculator=None, value_basis_converter=None, financial_crisis_assessor=None, z1_source=None, housing_data_source=None, periphery_labor_source=None, final_demand_source=None, industry_county_allocator=None, production_chain_calculator=None, bea_industries=None)
- Parameters:
config (SimulationConfig)
database (DatabaseProtocol)
event_bus (EventBus)
formulas (FormulaRegistry)
defines (GameDefines)
metrics (MetricsCollectorProtocol)
field_registry (Any)
opposition_registry (Any)
reserve_army_data_source (Any)
dispossession_data_source (Any)
productivity_data_source (Any)
melt_calculator (Any)
basket_calculator (Any)
gamma_calculator (Any)
capital_calculator (Any)
throughput_calculator (Any)
transition_engine (Any)
tensor_registry (Any)
economics_fallbacks (EconomicsFallbackTally)
community_hypergraph (Any)
turnover_profile_source (Any)
inventory_data_source (Any)
depreciation_data_source (Any)
hex_grid (Any)
persistence (Any)
tracer (Any)
boundary_register (Any)
auditor (Any)
distribution_calculator (Any)
interest_calculator (Any)
credit_cycle_detector (Any)
fictitious_capital_calculator (Any)
rent_calculator (Any)
housing_calculator (Any)
counter_tendency_calculator (Any)
value_basis_converter (Any)
financial_crisis_assessor (Any)
z1_source (Any)
housing_data_source (Any)
periphery_labor_source (Any)
final_demand_source (Any)
industry_county_allocator (Any)
production_chain_calculator (Any)
- Return type:
None
- classmethod create(config=None, defines=None, metrics=None, *, hex_grid=None, persistence=None, tracer=None, reserve_army_data_source=None, dispossession_data_source=None, productivity_data_source=None, field_registry=None, opposition_registry=None, melt_calculator=None, basket_calculator=None, gamma_calculator=None, capital_calculator=None, throughput_calculator=None, transition_engine=None, tensor_registry=None, community_hypergraph=None, turnover_profile_source=None, inventory_data_source=None, depreciation_data_source=None, distribution_calculator=None, interest_calculator=None, credit_cycle_detector=None, fictitious_capital_calculator=None, rent_calculator=None, housing_calculator=None, counter_tendency_calculator=None, value_basis_converter=None, financial_crisis_assessor=None, z1_source=None, housing_data_source=None, periphery_labor_source=None, final_demand_source=None, industry_county_allocator=None, production_chain_calculator=None, bea_industries=None)[source]
Factory method to create a fully-initialized container.
Creates all services with sensible defaults. Uses in-memory SQLite for database isolation in tests.
- Parameters:
config (
SimulationConfig|None) – Optional custom config. If None, uses default SimulationConfig.defines (
GameDefines|None) – Optional custom defines. If None, uses default GameDefines.metrics (
MetricsCollectorProtocol|None) – Optional custom metrics collector. If None, creates a new MetricsCollector instance. Pass a mock for testing.field_registry (
Any) – Optional FieldRegistry for contradiction fields (Feature 002).melt_calculator (
Any) – Optional MELTCalculator (Feature 013).basket_calculator (
Any) – Optional BasketVisibilityCalculator (Feature 013).gamma_calculator (
Any) – Optional GammaIIICalculator (Feature 015).capital_calculator (
Any) – Optional CapitalStockCalculator (Feature 012).throughput_calculator (
Any) – Optional ThroughputCalculator (Feature 014).transition_engine (
Any) – Optional ClassTransitionEngine (Feature 016).tensor_registry (
Any) – Optional TensorRegistry for cached tensor data (Feature 011).community_hypergraph (
Any) – Optional XGI Hypergraph for community membership (Feature 022).hex_grid (Any)
persistence (Any)
tracer (Any)
reserve_army_data_source (Any)
dispossession_data_source (Any)
productivity_data_source (Any)
opposition_registry (Any)
turnover_profile_source (Any)
inventory_data_source (Any)
depreciation_data_source (Any)
distribution_calculator (Any)
interest_calculator (Any)
credit_cycle_detector (Any)
fictitious_capital_calculator (Any)
rent_calculator (Any)
housing_calculator (Any)
counter_tendency_calculator (Any)
value_basis_converter (Any)
financial_crisis_assessor (Any)
z1_source (Any)
housing_data_source (Any)
periphery_labor_source (Any)
final_demand_source (Any)
industry_county_allocator (Any)
production_chain_calculator (Any)
- Return type:
- Returns:
ServiceContainer with all services initialized
- class babylon.engine.SimulationObserver(*args, **kwargs)[source]
Bases:
ProtocolProtocol for entities observing simulation state changes.
Observers receive notifications at three lifecycle points: 1. on_simulation_start() - when simulation begins (first step) 2. on_tick() - after each tick completes 3. on_simulation_end() - when simulation ends (explicit end() call)
Note: All state objects (WorldState) are frozen and immutable. Attempting to modify them will raise AttributeError.
Example
>>> class MyObserver: ... @property ... def name(self) -> str: ... return "MyObserver" ... ... def on_simulation_start( ... self, initial_state: WorldState, config: SimulationConfig ... ) -> None: ... print(f"Started at tick {initial_state.tick}") ... ... def on_tick( ... self, previous_state: WorldState, new_state: WorldState ... ) -> None: ... print(f"Tick {previous_state.tick} -> {new_state.tick}") ... ... def on_simulation_end(self, final_state: WorldState) -> None: ... print(f"Ended at tick {final_state.tick}")
- property name: str
Observer identifier for logging and debugging.
- Returns:
A string identifying this observer instance.
- on_simulation_start(initial_state, config)[source]
Called when simulation begins (on first step call).
Use this hook to initialize resources, establish context, or prepare for observing the simulation run.
- Parameters:
initial_state (
WorldState) – The WorldState at tick 0 (before any steps).config (
SimulationConfig) – The SimulationConfig for this run.
- Return type:
- on_tick(previous_state, new_state)[source]
Called after each tick completes with both states for delta analysis.
This is the primary notification hook. Observers receive both the previous and new state to enable delta analysis (what changed).
- Parameters:
previous_state (
WorldState) – WorldState before the tick.new_state (
WorldState) – WorldState after the tick.
- Return type:
- on_simulation_end(final_state)[source]
Called when simulation ends (on explicit end() call).
Use this hook to cleanup resources, generate summaries, or finalize any accumulated data.
- Parameters:
final_state (
WorldState) – The final WorldState when simulation ends.- Return type:
- __init__(*args, **kwargs)
- class babylon.engine.TopologyMonitor(resilience_test_interval=5, resilience_removal_rate=None, logger=None, gaseous_threshold=None, condensation_threshold=None, vanguard_threshold=None)[source]
Bases:
objectObserver tracking solidarity network condensation.
Implements SimulationObserver protocol to receive state change notifications and analyze the topology of SOLIDARITY edges.
- Monitors:
Connected components (atomization vs. condensation)
Percolation ratio (L_max / N)
Liquidity metrics (potential vs. actual solidarity)
Resilience (survives targeted node removal)
- Narrative states logged:
Gaseous: percolation < 0.1 (atomized)
Liquid: percolation crosses 0.5 (condensation detected)
Brittle: potential >> actual (broad but fragile)
Fragile: resilience = False (Sword of Damocles)
- Parameters:
- name
Observer identifier (“TopologyMonitor”)
- history
List of TopologySnapshot for each tick
- __init__(resilience_test_interval=5, resilience_removal_rate=None, logger=None, gaseous_threshold=None, condensation_threshold=None, vanguard_threshold=None)[source]
Initialize TopologyMonitor.
- Parameters:
resilience_test_interval (
int) – Run resilience test every N ticks (0 = disabled). Default 5.resilience_removal_rate (
float|None) – Fraction of nodes to remove in test. Defaults to GameDefines.topology.resilience_removal_rate.logger (
Logger|None) – Logger instance (default: module logger)gaseous_threshold (
float|None) – Percolation ratio below this = atomized. Defaults to GameDefines.topology.gaseous_threshold.condensation_threshold (
float|None) – Percolation ratio for phase transition. Defaults to GameDefines.topology.condensation_threshold.vanguard_threshold (
float|None) – Cadre density threshold for solid phase. Defaults to GameDefines.topology.vanguard_density_threshold.
- Return type:
None
- property history: list[TopologySnapshot]
Return copy of snapshot history.
- get_pending_events()[source]
Return and clear pending events for collection by Simulation facade.
Observer events cannot be emitted directly to WorldState because observers run AFTER WorldState is frozen. Instead, pending events are collected by the Simulation facade and injected into the NEXT tick’s WorldState.
- Return type:
- Returns:
List of pending SimulationEvent objects (cleared after return).
- on_simulation_start(initial_state, _config)[source]
Called when simulation begins.
Initializes history and records initial topology snapshot.
- Parameters:
initial_state (
WorldState) – WorldState at tick 0_config (
SimulationConfig) – SimulationConfig for this run (unused)
- Return type:
- on_tick(_previous_state, new_state)[source]
Called after each tick completes.
Records topology snapshot and detects phase transitions.
- Parameters:
_previous_state (
WorldState) – WorldState before the tick (unused)new_state (
WorldState) – WorldState after the tick
- Return type:
- on_simulation_end(_final_state)[source]
Called when simulation ends.
Logs summary of topology metrics.
- Parameters:
_final_state (
WorldState) – Final WorldState when simulation ends (unused)- Return type:
Modules
Player-verb resolver registry (verb-dispatch engine — Design A). |
|
Bifurcation topology monitor (T032, Phase 10, Feature 033). |
|
Community state store protocol and default implementation (Feature 033). |
|
Context models for simulation tick execution. |
|
Transition error types for the simulation engine. |
|
Event Template evaluation engine. |
|
Factory functions for creating simulation entities. |
|
Field registry for extensible contradiction fields. |
|
Formula registry for hot-swappable mathematical functions. |
|
Typed graph wrappers for Spec 040 Discipline 5. |
|
Headless Postgres-backed simulation runner package. |
|
History Stack module for the Babylon simulation engine. |
|
History formatter for generating narrative summaries. |
|
Hydration package for initializing simulation state from reference data. |
|
Invariant protocol and concrete invariants for the simulation engine. |
|
Observer protocol for simulation state change notifications. |
|
ProtocolObserverAdapter for thread-safe GUI callback delivery. |
|
Observer implementations for simulation state monitoring. |
|
Phase-typed state for engine tick ordering (Spec 040 Discipline 4). |
|
Result type for total functions with explicit error channels. |
|
Async simulation runner for non-blocking UI integration. |
|
Engine scenarios package — Scenario ABC + 6 ported builders. |
|
Backward-compat shim — Spec 059 US4 / ADR-006.1. |
|
Service container for dependency injection. |
|
Simulation package — Spec 059 US1 / ADR-005 Part B. |
|
Simulation engine for the Babylon game loop. |
|
Simulation systems for the Babylon engine. |
|
Topology Monitor for phase transition detection (Sprint 3.1, 3.3). |
|
Trap detection system for the Wayne County Organizer. |