Skip to main content
A scenario defines the world that agents live in: the physical layout, agent starting conditions, passive dynamics (e.g. resource regeneration), and reward functions. It is the outermost container that stitches together world state, components, and agents into an environment that follows the Gym-style reset / step interface. Create a custom scenario when the existing scenarios do not match your research question—for example, a new geography, a different reward structure, or passive dynamics that no existing scenario implements.

How scenarios relate to components

Scenarios and components have complementary roles: A scenario lists the components it expects in component_set and passes them as the components argument when instantiating the environment.

Required abstract methods

Every BaseEnvironment subclass must implement five abstract methods. The signatures below come directly from base_env.py:
Called first in every reset cycle. Responsible for placing resources and landmarks on the world map. Use self.world.maps to write to the spatial state.
Called immediately after reset_starting_layout(). Clear inventories, escrow, and endogenous quantities, then place agents at their starting locations.
Called at every timestep after all component steps have run. Implement passive world dynamics here. May be a no-op if all dynamics are handled by components.
Return a dict of {agent_idx: obs_dict}. Observations from the scenario are prefixed with "world-" when merged into the full observation bundle. The structure must remain the same for every call within an episode.
Called once per timestep to compute scalar rewards for every agent, including the planner. Return 0.0 for agents whose objectives are not modelled.

Step-by-step: implementing a custom scenario

1

Set class attributes and declare entities

required_entities lists the world entities the scenario depends on. Coin and Labor are always present by default. Additional resources, landmarks, and endogenous variables are registered from this list and from each included component’s required_entities.
2

Define __init__ with env_config kwargs

Accept scenario-specific parameters before forwarding to super().__init__():
After super().__init__() you can access:
  • self.world — World object wrapping the map, agents, and planner
  • self.world.agents — list of mobile agent objects
  • self.world.planner — the planner agent object
  • self.n_agents — number of mobile agents
  • self.world_size — [height, width] of the map
  • self.episode_length — timesteps per episode
3

Implement reset_starting_layout

Populate the world map with resources and landmarks.
For a scenario with no spatial resources (like OneStepEconomy), leave this as a no-op:
4

Implement reset_agent_states

Clear agent state and set initial conditions.
5

Implement scenario_step

Define passive world dynamics that run every timestep regardless of agent actions.
Leave as a no-op if all dynamics come from components:
6

Implement generate_observations

Produce scenario-level observations. These are prefixed with "world-" when merged.
self.inv_scale is 0.01 when allow_observation_scaling=True and 1 otherwise. Apply it to inventory quantities to keep observation values in a RL-friendly range.
7

Implement compute_reward

Return a scalar reward for every agent (including the planner) at every timestep.
To implement episodic (terminal) rewards, accumulate a running metric during scenario_step() and emit a non-zero reward only on the final timestep (self.world.timestep == self.episode_length).
8

Add optional customization hooks

Two optional methods let you extend reset and metric reporting:

Registering the scenario

The registry key is scenario.name (case-insensitive). The scenario is exposed as:
Add an import of your scenario module to ai_economist/foundation/scenarios/__init__.py (or import it manually) so that the class is registered before foundation.scenarios.get() is called.

Instantiating the environment

Pass component specs as a list of ("ComponentName", {kwargs}) tuples:

OneStepEconomy as a reference

The built-in OneStepEconomy scenario (ai_economist/foundation/scenarios/one_step_economy/one_step_economy.py) is an ideal minimal reference. It has a no-op reset_starting_layout, a clean reset_agent_states, a no-op scenario_step, and well-documented generate_observations and compute_reward implementations.