Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/salesforce/ai-economist/llms.txt

Use this file to discover all available pages before exploring further.

Foundation organises world state into three categories of entity: Resources, Landmarks, and Endogenous variables. Each category has its own registry, base class, and role in the simulation.

Resources

Defined in entities/resources.py. A Resource is anything that can sit in an agent’s inventory.
class Resource:
    name = None
    color = None       # RGB array, values in [0, 1]
    collectible = None # True → exists on the world map and can be gathered
When collectible=True, the framework automatically creates a paired {Name}SourceBlock Landmark (see below) and allocates two world-map channels: one for the source block locations and one for the resource amounts currently on the ground.

Built-in resources

# entities/resources.py

@resource_registry.add
class Wood(Resource):
    """Wood resource. collectible."""
    name = "Wood"
    color = np.array([107, 143, 113]) / 255.0
    collectible = True

@resource_registry.add
class Stone(Resource):
    """Stone resource. collectible."""
    name = "Stone"
    color = np.array([241, 233, 219]) / 255.0
    collectible = True

@resource_registry.add
class Coin(Resource):
    """Coin resource. Included in all environments by default. Not collectible."""
    name = "Coin"
    color = np.array([229, 211, 82]) / 255.0
    collectible = False   # Coin is earned/spent, never gathered from the map
Coin is added to every environment automatically—you do not need to declare it in required_entities.

Registering a custom resource

from ai_economist.foundation.entities.resources import Resource, resource_registry
import numpy as np

@resource_registry.add
class Iron(Resource):
    name = "Iron"
    color = np.array([180, 140, 100]) / 255.0
    collectible = True
Include "Iron" in your scenario’s or component’s required_entities list to activate it.

Landmarks

Defined in entities/landmarks.py. A Landmark exists exclusively in the world map—it is never part of an agent’s inventory. Landmarks control whether a tile is passable and who (if anyone) owns it.
class Landmark:
    name   = None
    color  = None
    ownable = None  # Does a specific agent own each instance?
    solid   = True  # Does this landmark block movement?
Three derived properties are set at construction time:
PropertyConditionMeaning
blockingsolid and not ownableNo agent can pass through
privatesolid and ownableOnly the owning agent can pass through
publicnot solid and not ownableAll agents can occupy freely

Built-in landmarks

# entities/landmarks.py

@landmark_registry.add
class House(Landmark):
    """House landmark. Ownable. Solid."""
    name = "House"
    color = np.array([220, 20, 220]) / 255.0
    ownable = True
    solid   = True   # private: only the owner can stand on it

@landmark_registry.add
class Water(Landmark):
    """Water Landmark. Not ownable. Solid."""
    name = "Water"
    color = np.array([50, 50, 250]) / 255.0
    ownable = False
    solid   = True   # blocking: no agent can cross it
For every collectible resource, a source-block landmark is generated automatically:
# Executed at module load for each collectible resource
@landmark_registry.add
class SourceBlock(Landmark):
    """Special Landmark for generating resources. Not ownable. Not solid."""
    name    = "WoodSourceBlock"   # or "StoneSourceBlock", etc.
    ownable = False
    solid   = False               # public: agents move freely over it
So the landmark registry always contains at least WoodSourceBlock, StoneSourceBlock, House, and Water in a typical wood-and-stone scenario.

Endogenous variables

Defined in entities/endogenous.py. Endogenous variables capture the internal state of an agent—quantities that are conceptually private to the agent and not directly observable by others.
class Endogenous:
    name = None

Built-in endogenous variable

# entities/endogenous.py

@endogenous_registry.add
class Labor(Endogenous):
    """Labor accumulated through working. Included in all environments by default."""
    name = "Labor"
Labor is added to every environment automatically and is accessible on each mobile agent:
agent.endogenous["Labor"]   # → float, e.g. 30.25

Registering a custom endogenous variable

from ai_economist.foundation.entities.endogenous import Endogenous, endogenous_registry

@endogenous_registry.add
class Stress(Endogenous):
    name = "Stress"
Then declare "Stress" in your component’s required_entities to have it registered on agents.

How entities compose the World state

During environment construction, BaseEnvironment.__init__ collects all entity names from the scenario’s required_entities and from each component’s required_entities. It classifies each name against the three registries:
# base_env.py (simplified)
self._entities = {
    "resources":  ["Coin"],   # always present
    "landmarks":  [],
    "endogenous": ["Labor"],  # always present
}
self._register_entities(self.required_entities)
for component_cls in component_classes:
    self._register_entities(component_cls.required_entities)
The resulting entity lists are then passed to World, which allocates:
  • One numpy map channel per collectible resource — tracks ground-level resource amounts
  • One numpy map channel per source-block landmark — tracks where resources regenerate
  • One numpy map channel per non-ownable landmark (e.g. Water) — tracks blocking tiles
  • One per-cell (owner, health) pair per ownable landmark (e.g. House)
Each mobile agent’s inventory is populated with a {resource_name: 0} entry for every registered resource, and its endogenous dict with a {endogenous_name: 0} entry for every registered endogenous variable.
# Accessing entity maps at runtime
env.world.maps.get("Wood")            # 2-D numpy array of wood on the ground
env.world.maps.get("WoodSourceBlock") # 2-D array of source block locations
env.world.maps.get("House")           # dict with 'owner' and 'health' arrays

# Entity lists on the environment
env.resources   # → ['Coin', 'Stone', 'Wood']
env.landmarks   # → ['House', 'StoneSourceBlock', 'Water', 'WoodSourceBlock']
env.endogenous  # → ['Labor']