babylon.models.entities

Entity models for the Babylon simulation.

Entities are the objects that make up the simulation: - SocialClass: Phase 1 node - a social class in the world system - Territory: Phase 3.5 node - a strategic sector in the world system - Effect: Atomic state modifications - ContradictionState: Dialectical tension state - ResolutionOutcome: Result of contradiction resolution - Contradiction: Full contradiction with entities and methods - Trigger: Event triggering conditions - TriggerCondition: Individual condition within a trigger

Finance models (Political Economy of Liquidity - Epoch 1): - StateFinance: Financial state of sovereign entities - RevolutionaryFinance: Financial state of revolutionary organizations - PrecarityState: Economic precarity metrics for social classes

All models use Pydantic v2 with Sprint 1 constrained types.

class babylon.models.entities.SocialClass(**data)[source]

Bases: BaseModel

A social class in the world system.

The fundamental unit of the simulation. Classes are defined by their relationship to production and their position in the imperial hierarchy.

This model uses Sprint 1 constrained types for automatic validation: - Currency: [0, inf) for wealth, subsistence_threshold - IdeologicalProfile: Multi-dimensional consciousness model (Sprint 3.4.3) - Probability: [0, 1] for survival probabilities and organization/repression

Parameters:
id

Unique identifier matching pattern ^C[0-9]{3}$

name

Human-readable name for the class

role

Position in the world system (SocialRole enum)

description

Optional detailed description

wealth

Economic resources (Currency, default 10.0)

ideology

Multi-dimensional ideological profile (IdeologicalProfile)

p_acquiescence

P(S|A) - survival probability through acquiescence (Probability)

p_revolution

P(S|R) - survival probability through revolution (Probability)

subsistence_threshold

Minimum wealth for survival (Currency, default 5.0)

organization

Collective cohesion/class consciousness (Probability, default 0.1)

repression_faced

State violence directed at this class (Probability, default 0.5)

Legacy Compatibility:

If a float value is passed for ideology, it will be automatically converted to an IdeologicalProfile using from_legacy_ideology().

property consumption_needs: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])]

Total consumption required per tick (Wealth-independent demand).

property economic: EconomicComponent

Return economic component view (computed, not live).

property ideological: IdeologicalComponent

Return ideological component view (computed, not live).

property material_conditions: MaterialConditionsComponent

Return material conditions component view (computed, not live).

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'str_strip_whitespace': True, 'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property survival: SurvivalComponent

Return survival component view (computed, not live).

classmethod unpack_components_and_convert_legacy(data)[source]

Unpack component objects and convert legacy ideology to IdeologicalProfile.

Return type:

Any

Parameters:

data (Any)

id: str
name: str
role: SocialRole
description: str
wealth: Annotated[float]
ideology: IdeologicalProfile
p_acquiescence: Annotated[float]
p_revolution: Annotated[float]
subsistence_threshold: Annotated[float]
organization: Annotated[float]
repression_faced: Annotated[float]
effective_wealth: Annotated[float]
unearned_increment: Annotated[float]
ppp_multiplier: float
s_bio: Annotated[float]
s_class: Annotated[float]
class babylon.models.entities.Territory(**data)[source]

Bases: BaseModel

A strategic sector in the world system.

Territories are the spatial nodes of the simulation. Unlike SocialClass nodes which represent abstract class positions, Territory nodes represent physical locations that can be occupied, contested, and liberated.

The “Host/Parasite Stack” defines territorial control: - Host (Legal Sovereign): Recognized by State, collects rent/taxes - Occupant (De Facto User): Actually uses the space, may be revolutionary

The “Operational Profile” trades visibility for recruitment: - LOW_PROFILE: Safe from eviction, low recruitment - HIGH_PROFILE: High recruitment, high heat (state attention)

Parameters:
  • id (str)

  • name (str)

  • sector_type (SectorType)

  • territory_type (TerritoryType)

  • host_id (str | None)

  • occupant_id (str | None)

  • profile (OperationalProfile)

  • heat (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Contradiction intensity from dormant (0) to rupture (1)', metadata=[Ge(ge=0.0), Le(le=1.0)])])

  • rent_level (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • population (int)

  • under_eviction (bool)

  • biocapacity (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • max_biocapacity (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • regeneration_rate (float)

  • extraction_intensity (float)

id

Unique identifier matching pattern ^T[0-9]{3}$

name

Human-readable sector name

sector_type

Economic/social character of the territory

territory_type

Classification in settler-colonial hierarchy (Sprint 3.7)

host_id

Optional ID of the Legal Sovereign (collects rent)

occupant_id

Optional ID of the De Facto Occupant (uses space)

profile

Operational profile (visibility stance)

heat

State attention level [0, 1]

rent_level

Economic pressure on occupants [0, inf)

population

Human shield count (sympathizers)

under_eviction

Whether eviction pipeline is active

property clarity_bonus: float

Recruitment bonus from profile visibility.

HIGH_PROFILE attracts cadre through ideological clarity. LOW_PROFILE is safe but boring.

Returns:

0.3 if HIGH_PROFILE, 0.0 if LOW_PROFILE

property is_liberated: bool

Whether territory is a Liberated Zone.

A territory is liberated when there is an occupant but no host (legal sovereign). This represents successful transition from parasitic to sovereign tenure.

Returns:

True if occupant exists and host does not

property is_sink_node: bool

Whether territory is a sink node in the displacement graph.

Sprint 3.7: The Carceral Geography - Necropolitical Triad.

Sink nodes are territories where displaced populations are routed. They have no economic value - only containment/elimination function. Population flows INTO these territories but does not flow OUT easily.

The three sink node types form the Necropolitical Triad: - RESERVATION: Containment (warehousing surplus population) - PENAL_COLONY: Extraction (forced labor, suppresses organization) - CONCENTRATION_CAMP: Elimination (population decay, generates terror)

Returns:

True if territory_type is RESERVATION, PENAL_COLONY, or CONCENTRATION_CAMP

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'str_strip_whitespace': True, 'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
name: str
sector_type: SectorType
territory_type: TerritoryType
host_id: str | None
occupant_id: str | None
profile: OperationalProfile
heat: Annotated[float]
rent_level: Annotated[float]
population: int
under_eviction: bool
biocapacity: Annotated[float]
max_biocapacity: Annotated[float]
regeneration_rate: float
extraction_intensity: float
class babylon.models.entities.GlobalEconomy(**data)[source]

Bases: BaseModel

System-wide economic state for dynamic balance mechanics.

The GlobalEconomy model tracks the “Gas Tank” (imperial rent pool) and the “Driver” parameters (wage rate, repression level) that the bourgeoisie can adjust based on pool levels and tension.

Parameters:
imperial_rent_pool

Accumulated imperial rent available for redistribution. Fed by TRIBUTE inflows, depleted by WAGES and CLIENT_STATE outflows. Default: 100.0 Currency.

current_super_wage_rate

Dynamic wage rate for WAGES edges. Adjusts based on pool level and tension via decision heuristics. Range: [0.05, 0.35]. Default: 0.20 (20%).

current_repression_level

System-wide repression modifier. Blended with per-class repression_faced values. Increases during austerity/crisis periods. Range: [0.0, 1.0]. Default: 0.5.

Pool Flow Logic:

inflow = sum(tribute reaching Core Bourgeoisie after comprador cut) outflow = wages_paid + subsidy_paid delta = inflow - outflow new_pool = old_pool + delta

Decision Thresholds (Aggressive):

pool_ratio >= 0.7: PROSPERITY (can increase wages) pool_ratio < 0.3: AUSTERITY (cut wages or increase repression) pool_ratio < 0.1: CRISIS (emergency measures, emit event)

model_config: ClassVar[ConfigDict] = {'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

imperial_rent_pool: Annotated[float]
current_super_wage_rate: Annotated[float]
current_repression_level: Annotated[float]
class babylon.models.entities.Relationship(**data)[source]

Bases: BaseModel

A directed edge between two entities.

Represents flows of value, solidarity, or repression between classes. In Phase 1, the primary relationship is exploitation: value flows from the periphery worker (source) to the core owner (target).

This model uses Sprint 1 constrained types for automatic validation: - Currency: [0, inf) for value_flow - Intensity: [0, 1] for tension

Parameters:
source_id

Origin entity ID (value/action flows FROM here)

target_id

Destination entity ID (value/action flows TO here)

edge_type

Nature of the relationship (EdgeType enum)

value_flow

Imperial rent or value transfer amount (Currency, default 0.0)

tension

Dialectical tension/contradiction intensity (Intensity, default 0.0)

description

Optional description of the relationship

property edge_data: dict[str, object]

Return edge attributes dict for NetworkX, excluding IDs.

Usage:

G.add_edge(*relationship.edge_tuple, **relationship.edge_data)
property edge_tuple: tuple[str, str]

Return (source_id, target_id) tuple for NetworkX edge creation.

Usage:

G.add_edge(*relationship.edge_tuple, **relationship.edge_data)
property flow: FlowComponent

Return flow component view (computed, not live).

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'str_strip_whitespace': True, 'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod unpack_flow_component(data)[source]

Unpack flow component into flat fields if provided.

Return type:

Any

Parameters:

data (Any)

validate_no_self_loop()[source]

Ensure entities cannot have a relationship with themselves.

Return type:

Relationship

source_id: str
target_id: str
edge_type: EdgeType
value_flow: Annotated[float]
tension: Annotated[float]
description: str
subsidy_cap: Annotated[float]
solidarity_strength: Annotated[float]
class babylon.models.entities.Effect(**data)[source]

Bases: BaseModel

A modification to game state.

Effects are the atoms of change - they modify single attributes on single targets by specific amounts. Every state change in the simulation should be expressible as one or more Effects.

Parameters:
  • target_id (str)

  • attribute (str)

  • operation (Literal['increase', 'decrease', 'set', 'multiply'])

  • magnitude (float)

  • description (str)

target_id

ID of the entity to modify

attribute

Name of the attribute to change

operation

How to modify the value

magnitude

Amount of change (interpretation depends on operation)

description

Human-readable explanation of why this effect occurs

apply_to(current_value)[source]

Calculate the new value after applying this effect.

Parameters:

current_value (float) – The current value of the attribute

Return type:

float

Returns:

The new value after the effect is applied

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

target_id: str
attribute: str
operation: Literal['increase', 'decrease', 'set', 'multiply']
magnitude: float
description: str
class babylon.models.entities.ContradictionState(**data)[source]

Bases: BaseModel

The current state of a dialectical contradiction.

A contradiction is a structural tension between two forces that cannot both be satisfied within the current system. This is the primary model for tracking contradictions.

Parameters:
id

Unique identifier (flexible format for runtime use)

name

Human-readable name

description

Detailed explanation

thesis

The dominant position

antithesis

The opposing position

tension

Current tension level [0, 1]

momentum

Rate of change [-1, 1]

is_principal

Is this the principal contradiction?

resolved

Has this been resolved?

property intensity_level: IntensityLevel

Convert continuous tension to discrete IntensityLevel.

property is_critical: bool

Check if tension is at critical level (rupture imminent).

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
name: str
description: str
thesis: str
antithesis: str
tension: Annotated[float]
momentum: float
is_principal: bool
resolved: bool
class babylon.models.entities.ResolutionOutcome(**data)[source]

Bases: BaseModel

The result of a contradiction reaching resolution.

When a contradiction resolves (tension reaches 0 or 1), this model captures what happened and the consequences.

Parameters:
contradiction_id

ID of the resolved contradiction

resolution_type

How it resolved (synthesis, rupture, suppression)

new_contradictions

IDs of contradictions spawned by resolution

system_changes

Metric deltas caused by resolution

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

contradiction_id: str
resolution_type: ResolutionType
new_contradictions: list[str]
system_changes: dict[str, float]
class babylon.models.entities.Contradiction(**data)[source]

Bases: BaseModel

Full contradiction model with entities and resolution methods.

This is a more detailed model for contradictions that includes references to entities and resolution mechanics. Used for game content definition.

Parameters:
  • id (Annotated[str, _PydanticGeneralMetadata(pattern='^CON[0-9]{3}$')])

  • name (str)

  • description (str)

  • entity_ids (list[str])

  • principal_aspect_id (str | None)

  • secondary_aspect_id (str | None)

  • principal_contradiction_id (str | None)

  • universality (Annotated[str, _PydanticGeneralMetadata(pattern='^(Universal|Particular)$')])

  • particularity (str)

  • antagonism (Annotated[str, _PydanticGeneralMetadata(pattern='^(Primary|Secondary)$')])

  • intensity (IntensityLevel)

  • state (Annotated[str, _PydanticGeneralMetadata(pattern='^(Active|Resolved|Latent)$')])

  • potential_for_transformation (IntensityLevel)

  • conditions_for_transformation (list[str])

  • resolution_methods (dict[str, list[Effect]])

  • intensity_history (list[Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Contradiction intensity from dormant (0) to rupture (1)', metadata=[Ge(ge=0.0), Le(le=1.0)])]])

id

Unique identifier

name

Human-readable name

description

Detailed explanation

entity_ids

IDs of entities involved in this contradiction

universality

Universal or Particular

particularity

Domain (Economic, Political, etc.)

principal_contradiction_id

ID of the principal contradiction (if this is secondary)

principal_aspect_id

ID of the entity representing the principal aspect

secondary_aspect_id

ID of the entity representing the secondary aspect

antagonism

Primary or Secondary antagonism

intensity

Current intensity level

state

Active, Resolved, or Latent

potential_for_transformation

How likely to transform

conditions_for_transformation

What conditions must be met

resolution_methods

Mapping of method names to Effects

property intensity_value: float

Get numerical value for intensity.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

record_intensity()[source]

Record current intensity in history.

Return type:

None

id: str
name: str
description: str
entity_ids: list[str]
principal_aspect_id: str | None
secondary_aspect_id: str | None
principal_contradiction_id: str | None
universality: str
particularity: str
antagonism: str
intensity: IntensityLevel
state: str
potential_for_transformation: IntensityLevel
conditions_for_transformation: list[str]
resolution_methods: dict[str, list[Effect]]
intensity_history: list[Annotated[float]]
class babylon.models.entities.Trigger(**data)[source]

Bases: BaseModel

A condition that can trigger game events.

Triggers define when events should occur based on game state. They can have multiple conditions that must all be met (AND logic) or any one met (OR logic).

Parameters:
id

Unique identifier

description

Human-readable description

trigger_type

Category of trigger (economic, political, social, etc.)

conditions

List of conditions to evaluate

logic

How to combine conditions (all must pass or any must pass)

parameters

Optional parameters for condition evaluation

cooldown_turns

Minimum turns between activations (0 = no cooldown)

last_triggered_turn

Turn when this was last triggered

evaluate(game_state, current_turn=0)[source]

Evaluate if the trigger condition is met.

Parameters:
  • game_state (dict[str, Any]) – The current game state to evaluate against

  • current_turn (int) – The current turn number (for cooldown checking)

Return type:

bool

Returns:

True if the trigger condition is met, False otherwise

mark_triggered(current_turn)[source]

Mark this trigger as having been triggered.

Parameters:

current_turn (int) – The current turn number

Return type:

None

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
description: str
trigger_type: str | None
conditions: list[TriggerCondition]
logic: Literal['all', 'any']
parameters: dict[str, Any]
cooldown_turns: int
last_triggered_turn: int | None
class babylon.models.entities.TriggerCondition(**data)[source]

Bases: BaseModel

A single condition that can be evaluated against game state.

Conditions specify what to check, how to compare, and what threshold to use. Multiple conditions can be combined in a Trigger.

Parameters:
  • path (str)

  • operator (Literal['>=', '<=', '>', '<', '==', '!='])

  • threshold (float)

  • description (str)

path

Dot-notation path to the value in game state (e.g., “economy.gini_coefficient”)

operator

Comparison operator

threshold

Value to compare against

description

Human-readable explanation

evaluate(game_state)[source]

Evaluate this condition against the game state.

Parameters:

game_state (dict[str, Any]) – The current game state dictionary

Return type:

bool

Returns:

True if the condition is met, False otherwise

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

path: str
operator: Literal['>=', '<=', '>', '<', '==', '!=']
threshold: float
description: str
class babylon.models.entities.EventTemplate(**data)[source]

Bases: BaseModel

A declarative template for recurring game events.

EventTemplates are the Paradox Pattern for events - data-driven definitions that the EventTemplateSystem evaluates against WorldState.

When preconditions are satisfied, the first matching resolution’s effects are applied and events are emitted for the narrative layer.

Parameters:
id

Unique identifier (EVT_* pattern).

name

Human-readable name.

description

Detailed explanation.

category

System domain category.

preconditions

Conditions that must be met to trigger.

resolutions

Ordered list of resolution paths.

narrative

Hooks for AI narrative generation.

cooldown_ticks

Minimum ticks between activations.

priority

Higher priority templates evaluate first.

is_on_cooldown(current_tick)[source]

Check if this template is on cooldown.

Parameters:

current_tick (int) – The current simulation tick.

Return type:

bool

Returns:

True if still on cooldown, False otherwise.

mark_triggered(tick)[source]

Mark this template as having been triggered.

Parameters:

tick (int) – The tick at which this was triggered.

Return type:

None

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

validate_resolutions_have_effects_or_events()[source]

Ensure each resolution has at least one effect or event emission.

Return type:

EventTemplate

id: str
name: str
description: str
category: Literal['economic', 'consciousness', 'struggle', 'contradiction', 'territory']
preconditions: PreconditionSet
resolutions: list[Resolution]
narrative: NarrativeHooks | None
cooldown_ticks: int
priority: int
last_triggered_tick: int | None
class babylon.models.entities.Resolution(**data)[source]

Bases: BaseModel

A resolution path with condition and effects.

When an EventTemplate’s preconditions are met, resolutions are evaluated in order. The first resolution whose condition matches (or has no condition) is selected.

Parameters:
id

Resolution identifier (snake_case).

name

Human-readable name.

condition

Optional condition for this resolution path.

effects

Effects to apply when this resolution is selected.

emit_event

Optional event to emit.

narrative

Narrative hooks specific to this resolution.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
name: str | None
condition: PreconditionSet | None
effects: list[TemplateEffect]
emit_event: EventEmission | None
narrative: NarrativeHooks | None
class babylon.models.entities.PreconditionSet(**data)[source]

Bases: BaseModel

A set of conditions that must be satisfied for an event to trigger.

Combines node, edge, and graph-level conditions with specified logic.

Parameters:
node_conditions

Conditions on node attributes.

edge_conditions

Conditions on edge types/counts.

graph_conditions

Conditions on graph-level metrics.

logic

How to combine conditions (all = AND, any = OR).

is_empty()[source]

Check if precondition set has no conditions.

Return type:

bool

Returns:

True if no conditions are defined, False otherwise.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

node_conditions: list[NodeCondition]
edge_conditions: list[EdgeCondition]
graph_conditions: list[GraphCondition]
logic: Literal['all', 'any']
class babylon.models.entities.NodeCondition(**data)[source]

Bases: BaseModel

Condition on node attributes with optional filtering and aggregation.

Evaluates a dot-notation path on nodes, optionally filtered by NodeFilter, then aggregates results and compares to threshold.

Parameters:
  • path (str)

  • operator (Literal['>=', '<=', '>', '<', '==', '!='])

  • threshold (float)

  • node_filter (NodeFilter | None)

  • aggregation (Literal['any', 'all', 'count', 'sum', 'avg', 'max', 'min'])

path

Dot-notation path to node attribute (e.g., ideology.agitation).

operator

Comparison operator.

threshold

Value to compare against.

node_filter

Optional filter to select which nodes to check.

aggregation

How to aggregate across matched nodes.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

path: str
operator: Literal['>=', '<=', '>', '<', '==', '!=']
threshold: float
node_filter: NodeFilter | None
aggregation: Literal['any', 'all', 'count', 'sum', 'avg', 'max', 'min']
class babylon.models.entities.EdgeCondition(**data)[source]

Bases: BaseModel

Condition on edge types/counts with optional node filtering.

Counts or aggregates edges of a specific type, optionally restricted to edges connected to nodes matching the filter.

Parameters:
edge_type

Type of edge to check.

metric

What to measure (count, sum_strength, avg_strength).

operator

Comparison operator.

threshold

Value to compare against.

node_filter

Optional filter to select nodes whose edges to count.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

edge_type: EdgeType
metric: Literal['count', 'sum_strength', 'avg_strength']
operator: Literal['>=', '<=', '>', '<', '==', '!=']
threshold: float
node_filter: NodeFilter | None
class babylon.models.entities.GraphCondition(**data)[source]

Bases: BaseModel

Condition on graph-level aggregate metrics.

Evaluates aggregate properties of the entire graph rather than individual nodes or edges.

Parameters:
  • metric (Literal['solidarity_density', 'exploitation_density', 'average_agitation', 'average_consciousness', 'total_wealth', 'gini_coefficient'])

  • operator (Literal['>=', '<=', '>', '<', '==', '!='])

  • threshold (float)

metric

Graph-level metric to evaluate.

operator

Comparison operator.

threshold

Value to compare against.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

metric: Literal['solidarity_density', 'exploitation_density', 'average_agitation', 'average_consciousness', 'total_wealth', 'gini_coefficient']
operator: Literal['>=', '<=', '>', '<', '==', '!=']
threshold: float
class babylon.models.entities.NodeFilter(**data)[source]

Bases: BaseModel

Filter to select which nodes a condition applies to.

Used to restrict condition evaluation to specific node types, roles, or ID patterns. All specified filters must match (AND logic).

Parameters:
role

Filter by SocialRole values.

node_type

Filter by _node_type attribute (social_class or territory).

id_pattern

Regex pattern for node IDs.

matches(node_id, node_data)[source]

Check if a node matches this filter.

Parameters:
  • node_id (str) – The node’s identifier.

  • node_data (dict[str, Any]) – The node’s data dictionary.

Return type:

bool

Returns:

True if all specified criteria match, False otherwise.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

role: list[SocialRole] | None
node_type: Literal['social_class', 'territory'] | None
id_pattern: str | None
class babylon.models.entities.TemplateEffect(**data)[source]

Bases: BaseModel

Effect specification within an event template.

Similar to the Effect model but supports ${var} substitution for dynamic target resolution at runtime.

Parameters:
  • target_id (str)

  • attribute (str)

  • operation (Literal['increase', 'decrease', 'set', 'multiply'])

  • magnitude (float)

  • description (str)

target_id

Entity ID to modify (supports ${node_id} substitution).

attribute

Attribute name to change.

operation

How to modify the value.

magnitude

Amount of change.

description

Human-readable explanation.

apply_to(current_value)[source]

Calculate the new value after applying this effect.

Parameters:

current_value (float) – The current value of the attribute.

Return type:

float

Returns:

The new value after the effect is applied.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

target_id: str
attribute: str
operation: Literal['increase', 'decrease', 'set', 'multiply']
magnitude: float
description: str
class babylon.models.entities.EventEmission(**data)[source]

Bases: BaseModel

Specification for emitting an EventBus event.

Defines what event to emit when a resolution is selected.

Parameters:
event_type

EventType name to emit.

payload_template

Template for event payload with ${var} substitution.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

event_type: str
payload_template: dict[str, Any]
class babylon.models.entities.NarrativeHooks(**data)[source]

Bases: BaseModel

Hooks for AI observer narrative generation.

Provides context for Persephone to generate narrative around events.

Parameters:
  • motif (str | None)

  • historical_echoes (list[str])

  • flavor_text_key (str | None)

  • entity_refs (list[str])

motif

Narrative motif key (e.g., bifurcation, betrayal).

historical_echoes

References to historical parallels.

flavor_text_key

Key for localized flavor text lookup.

entity_refs

Entity IDs to reference in narrative.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

motif: str | None
historical_echoes: list[str]
flavor_text_key: str | None
entity_refs: list[str]
class babylon.models.entities.EconomicComponent(**data)[source]

Bases: BaseModel

Economic material conditions of a social class.

Parameters:
  • wealth (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • subsistence_threshold (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

wealth: Annotated[float]
subsistence_threshold: Annotated[float]
class babylon.models.entities.IdeologicalComponent(**data)[source]

Bases: BaseModel

Ideological state of a social class (legacy component view).

Parameters:
  • ideology (IdeologicalProfile)

  • organization (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Value in range [0.0, 1.0] representing likelihood', metadata=[Ge(ge=0.0), Le(le=1.0)])])

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ideology: IdeologicalProfile
organization: Annotated[float]
class babylon.models.entities.IdeologicalProfile(**data)[source]

Bases: BaseModel

Multi-dimensional ideological state of a social class.

Sprint 3.4.3 (George Jackson Refactor): This model replaces the scalar ideology field with a multi-dimensional consciousness model.

The key insight: “Fascism is the defensive form of capitalism.” - Agitation + Solidarity -> Class Consciousness (Revolutionary Path) - Agitation + No Solidarity -> National Identity (Fascist Path)

Parameters:
class_consciousness

Relationship to Capital [0.0=False, 1.0=Revolutionary] How clearly the class understands its position relative to capital.

national_identity

Relationship to State/Tribe [0.0=Internationalist, 1.0=Fascist] How strongly the class identifies with nation/race over class.

agitation

Raw political energy from crisis [0.0, inf) Accumulated energy from falling wages, crisis conditions. Routes to either axis based on solidarity_pressure.

classmethod from_legacy_ideology(ideology_value)[source]

Convert legacy scalar ideology [-1, 1] to IdeologicalProfile.

Legacy mapping: - ideology=-1 (revolutionary) -> class_consciousness=1.0, national_identity=0.0 - ideology=0 (neutral) -> class_consciousness=0.5, national_identity=0.5 - ideology=+1 (reactionary) -> class_consciousness=0.0, national_identity=1.0

Parameters:

ideology_value (float) – Legacy ideology scalar in range [-1.0, 1.0]

Return type:

IdeologicalProfile

Returns:

IdeologicalProfile with mapped values

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

to_legacy_ideology()[source]

Convert IdeologicalProfile back to legacy scalar ideology [-1, 1].

This provides backward compatibility for systems still using the scalar ideology representation.

Return type:

float

Returns:

Legacy ideology scalar in range [-1.0, 1.0]

class_consciousness: Annotated[float]
national_identity: Annotated[float]
agitation: Annotated[float]
class babylon.models.entities.SurvivalComponent(**data)[source]

Bases: BaseModel

Survival calculus outputs for a social class.

Parameters:
  • p_acquiescence (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Value in range [0.0, 1.0] representing likelihood', metadata=[Ge(ge=0.0), Le(le=1.0)])])

  • p_revolution (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Value in range [0.0, 1.0] representing likelihood', metadata=[Ge(ge=0.0), Le(le=1.0)])])

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

p_acquiescence: Annotated[float]
p_revolution: Annotated[float]
class babylon.models.entities.MaterialConditionsComponent(**data)[source]

Bases: BaseModel

Material conditions affecting a social class.

Parameters:

repression_faced (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Value in range [0.0, 1.0] representing likelihood', metadata=[Ge(ge=0.0), Le(le=1.0)])])

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

repression_faced: Annotated[float]
class babylon.models.entities.FlowComponent(**data)[source]

Bases: BaseModel

Value flow and tension state of a relationship.

Parameters:
  • value_flow (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • tension (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Contradiction intensity from dormant (0) to rupture (1)', metadata=[Ge(ge=0.0), Le(le=1.0)])])

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

value_flow: Annotated[float]
tension: Annotated[float]
class babylon.models.entities.StateFinance(**data)[source]

Bases: BaseModel

Financial state of a sovereign entity (nation-state, client state).

Tracks treasury, budgets, taxation, and debt for state-level fiscal mechanics. Part of the Political Economy of Liquidity (Epoch 1: The Ledger).

Parameters:
  • treasury (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • police_budget (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • social_reproduction_budget (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • tax_rate (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Formula parameter in range [0, 1]', metadata=[Ge(ge=0.0), Le(le=1.0)])])

  • tribute_income (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • debt_level (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • debt_ceiling (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

treasury

Available liquid funds for deployment. Defaults to 100.0.

police_budget

Repression cost per tick. Defaults to 10.0.

social_reproduction_budget

Welfare cost per tick. Defaults to 15.0.

tax_rate

Extraction rate from bourgeoisie [0, 1]. Defaults to 0.3.

tribute_income

Imperial rent from CLIENT_STATE relationships. Defaults to 0.0.

debt_level

Accumulated liabilities. Defaults to 0.0.

debt_ceiling

Maximum sustainable debt. Defaults to 500.0.

Example

>>> finance = StateFinance(treasury=200.0, police_budget=20.0)
>>> finance.burn_rate
35.0
property burn_rate: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])]

Calculate total spending per tick.

Returns:

Sum of police_budget and social_reproduction_budget.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

treasury: Annotated[float]
police_budget: Annotated[float]
social_reproduction_budget: Annotated[float]
tax_rate: Annotated[float]
tribute_income: Annotated[float]
debt_level: Annotated[float]
debt_ceiling: Annotated[float]
class babylon.models.entities.RevolutionaryFinance(**data)[source]

Bases: BaseModel

Financial state of a revolutionary organization.

Tracks war chest, operational costs, and corruption metrics (heat, drift). Part of the Political Economy of Liquidity (Epoch 1: The Ledger).

Parameters:
  • war_chest (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • operational_burn (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • dues_income (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • expropriation_income (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • donor_income (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • heat (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Contradiction intensity from dormant (0) to rupture (1)', metadata=[Ge(ge=0.0), Le(le=1.0)])])

  • reformist_drift (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Ideological position from revolutionary (-1) to reactionary (+1)', metadata=[Ge(ge=-1.0), Le(le=1.0)])])

war_chest

Available liquid funds for revolutionary activity. Defaults to 5.0.

operational_burn

Minimum cost to maintain organization per tick. Defaults to 2.0.

dues_income

Member contributions per tick. Defaults to 1.0.

expropriation_income

Income from direct action. Defaults to 0.0.

donor_income

Liberal funding income. Defaults to 0.0.

heat

State attention level [0, 1]. Higher = more surveillance. Defaults to 0.0.

reformist_drift

Ideological corruption [-1, 1]. Positive = reformist. Defaults to 0.0.

Example

>>> finance = RevolutionaryFinance(war_chest=50.0, heat=0.7)
>>> finance.heat >= 0.8  # Check if in danger zone
False
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

war_chest: Annotated[float]
operational_burn: Annotated[float]
dues_income: Annotated[float]
expropriation_income: Annotated[float]
donor_income: Annotated[float]
heat: Annotated[float]
reformist_drift: Annotated[float]
class babylon.models.entities.PrecarityState(**data)[source]

Bases: BaseModel

Economic precarity metrics for a social class.

Tracks nominal wages, PPP, inflation and computes real wages and precarity. Part of the Political Economy of Liquidity (Epoch 1: The Ledger).

Parameters:
  • nominal_wage (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • ppp_factor (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Formula parameter in range [0, 1]', metadata=[Ge(ge=0.0), Le(le=1.0)])])

  • inflation_index (float)

  • subsistence_threshold (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])])

  • organization (Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Value in range [0.0, 1.0] representing likelihood', metadata=[Ge(ge=0.0), Le(le=1.0)])])

nominal_wage

Raw wage in currency units. Defaults to 10.0.

ppp_factor

Purchasing power parity adjustment [0, 1]. Defaults to 1.0.

inflation_index

Price level multiplier (>= 1.0). Defaults to 1.0.

subsistence_threshold

Minimum for survival. Defaults to 5.0.

organization

Collective capacity to resist [0, 1]. Defaults to 0.5.

Example

>>> precarity = PrecarityState(nominal_wage=3.0, subsistence_threshold=5.0)
>>> precarity.real_wage
3.0
>>> precarity.precarity_index > 0.5  # Below subsistence = precarious
True
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property precarity_index: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Value in range [0.0, 1.0] representing likelihood', metadata=[Ge(ge=0.0), Le(le=1.0)])]

Calculate precarity based on wage-subsistence gap.

Uses sigmoid function to map gap to probability: - precarity = 1 - sigmoid(real_wage - subsistence_threshold) - At subsistence threshold: precarity = 0.5 - Above subsistence: precarity < 0.5 (secure) - Below subsistence: precarity > 0.5 (precarious)

Returns:

Probability [0, 1] where 1 is maximum precarity.

property proletarianization_risk: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Value in range [0.0, 1.0] representing likelihood', metadata=[Ge(ge=0.0), Le(le=1.0)])]

Calculate risk of class falling into precarious proletariat.

Risk is modulated by organization: organized classes can resist proletarianization even under precarious conditions.

  • proletarianization_risk = precarity_index * (1 - organization)

  • High organization provides protection (multiplier near 0)

  • Low organization means full exposure to precarity

Returns:

Probability [0, 1] where 1 is maximum risk.

property real_wage: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)])]

Calculate real wage adjusted for PPP and inflation.

Returns:

(nominal_wage * ppp_factor) / inflation_index

nominal_wage: Annotated[float]
ppp_factor: Annotated[float]
inflation_index: float
subsistence_threshold: Annotated[float]
organization: Annotated[float]

Modules

contradiction

Contradiction models for dialectical simulation.

economy

GlobalEconomy entity model for Sprint 3.4.4: Dynamic Balance.

effect

Effect model for state modifications.

event_template

Event Template model for declarative game events.

precarity_state

Precarity state model for social class economic conditions.

relationship

Relationship entity model.

revolutionary_finance

Revolutionary finance model for revolutionary organizations.

social_class

SocialClass entity model.

state_finance

State finance model for sovereign entities.

territory

Territory entity model.

trigger

Trigger model for event conditions.