Skip to main content

World Definitions

The world definition file (assets/world_definitions/generated/<game_name>/default.json) is the single source of truth for what exists in a game world. It is a pure-data JSON file that declares all game entities, their attributes, the initial spawn configuration, and feature flags. No game logic lives here. The game engine reads this file during World.generate() and uses it to instantiate and distribute entities across the world graph.

If you are unfamiliar with terms like "world graph", "action rules", or "step rules", see the Game Ontology page first. For how this file fits into the broader file layout, see Game File Hierarchy.

Top-Level Structure

{
"entities": { ... },
"initializations": { ... },
"graph": { ... }, // optional predefined graph structure
"custom_events": [ ... ],
"features": { ... }
}
KeyDescription
entitiesAll game entities: places (with areas), objects, and NPCs
initializationsWhere the agent spawns, what items it starts with, and which objects are excluded from random distribution
custom_eventsIn-game events (selected from main quest, side quest, tutorial room) to be enabled
featuresEnv-level features (e.g., dynamic world expansion) to be enabled

Entities

The entities object has three arrays: places, objects, and npcs. Each entry in these arrays corresponds to an entity definition (i.e. a template). At runtime the engine instantiates the definitions into concrete instances and distributes them across the world graph.

Places

A place is a named region (e.g. "Greenwood Forest") that contains one or more areas. Areas are the atomic spatial unit in the game. The agent is always located in exactly one area at a time.

{
"type": "place",
"id": "place_greenwood_forest",
"name": "Greenwood Forest",
"unlocked": true,
"areas": [
{
"type": "area",
"id": "area_forest_plain",
"name": "plain",
"light": true,
"level": 3,
"neighbors": {
"area_forest_river": { "locked": false }
}
},
{
"type": "area",
"id": "area_forest_river",
"name": "river",
"level": 1
}
]
}

Place fields:

FieldTypeRequiredDescription
typestringyesAlways "place"
idstringyesUnique identifier, conventionally place_<snake_case_name>
namestringyesDisplay name shown to the agent
unlockedboolyesWhether the place is accessible from the start. Locked places require the agent to unlock a path to reach them
areasarrayyesList of area definitions belonging to this place

Area fields (nested inside a place):

FieldTypeRequiredDefaultDescription
typestringyesAlways "area"
idstringyesUnique identifier, conventionally area_<snake_case_name>
namestringyesDisplay name shown to the agent
levelintyesDifficulty level. Higher-level objects and NPCs spawn more frequently in higher-level areas
neighborsobjectno{}Predefined connections to other areas. Each key is an area ID and the value is { "locked": bool }. The engine also generates additional random connections within and between places, so you do not need to wire up every edge by hand
otheranynoGenerated rules may create more custom fields on area definitions, for example, light for game v1.
tip

You only need to specify neighbors when you want a guaranteed connection (for example, a locked gate between two specific areas). The engine handles the rest of the graph connectivity automatically.

Objects

Objects are anything the agent can interact with: raw materials, crafted items, weapons, armor, tools, containers, currency, and writable items like paper or notes.

{
"type": "object",
"id": "obj_iron_sword",
"name": "iron sword",
"category": "weapon",
"usage": "attack",
"value": 50,
"size": 3,
"description": "A sturdy sword forged from iron.",
"attack": 21,
"defense": 0,
"level": 3,
"areas": ["area_castle_armory"],
"craft": {
"ingredients": { "obj_sharpened_iron_blade": 1, "obj_wooden_rod": 1 },
"dependencies": ["obj_stone_sword"]
}
}

Object fields:

FieldTypeRequiredDefaultDescription
typestringyesAlways "object"
idstringyesUnique identifier, conventionally obj_<snake_case_name>
namestringyesDisplay name shown to the agent
categorystringyesOne of: "raw_material", "weapon", "armor", "tool", "container", "currency", "station", or any custom category
usagestringyesWhat the object does: "attack", "defense", "unlock", "lockpick", "write", "writable", or empty string for passive objects
valueintnonullPrice in coins. Objects with a value can be bought/sold at merchants
sizeintyesHow much space the object takes in a container
descriptionstringno""Shown when the agent inspects the object
textstringno""Content of writable objects (e.g. a note's text)
attackintno0Attack bonus when the object is held in hand
defenseintno0Defense bonus when the object is equipped; only works for armors
levelintno1Objects are more likely to spawn in areas of matching level
questboolnofalseIf true, the object is reserved for quest mechanics
areasarrayno[]Area IDs where this object may be distributed. If empty, the object is placed through the global pool
craftobjectno{}Crafting recipe (see below)
otheranynoGenerated rules may create more custom fields on object definitions, for example, hp_increase for consumables in game v1.

Note that the categories and usages are not a fixed schema. You can create new ones and write custom rules that depend on them. For example, you could add a "food" category with usage: "eat" and then write a step rule that restores health when the agent eats food.

Category-specific fields:

Some categories require additional fields:

CategoryExtra fieldTypeDescription
containercapacityintMaximum total size of items that fit inside
writable (usage: "writable")max_text_lengthintMaximum character count for writing

Crafting recipes:

The craft object has two sub-fields:

Sub-fieldTypeDescription
ingredientsobjectMap of object_id → count. These objects are consumed when crafting
dependenciesarrayList of object IDs that must have been crafted at least once before this recipe unlocks

If an object has no craft field (or it is empty), the object cannot be crafted and must be found in the world.

tip

You can add arbitrary extra fields to any object entry. The engine collects anything outside the reserved field set into an extra dict on the Object dataclass, accessible as regular attributes in Python. This lets you attach custom metadata without modifying the source code. For full details on how object entries are parsed into dataclasses, see the World module documentation.

NPCs

NPCs are either enemies that the agent can fight, or friendly characters with roles like merchant or quest giver.

Enemy NPC example:

{
"type": "npc",
"id": "npc_goblin_warrior",
"name": "Goblin Warrior",
"enemy": true,
"unique": false,
"role": "goblin",
"description": "A small but fierce creature.",
"base_hp": 30,
"base_attack_power": 5,
"slope_hp": 20,
"slope_attack_power": 10,
"combat_pattern": ["attack", "attack", "defend", "attack", "wait"],
"objects": ["obj_goblin_eye", "obj_cloth"]
}

Friendly NPC example:

{
"type": "npc",
"id": "npc_elinor_gray",
"name": "Elinor Gray",
"enemy": false,
"unique": true,
"role": "merchant",
"description": "A traveling merchant who sells weapons and armor.",
"base_hp": 1000,
"base_attack_power": 10,
"slope_hp": 50,
"slope_attack_power": 5,
"objects": ["obj_paper", "obj_pen", "obj_iron_sword", "obj_stone_plate_armor"]
}

NPC fields:

FieldTypeRequiredDefaultDescription
typestringyesAlways "npc"
idstringyesUnique identifier, conventionally npc_<snake_case_name>
namestringyesDisplay name shown to the agent
enemyboolyesWhether this NPC is hostile
uniqueboolyesIf true, exactly one instance is placed in the world. If false, multiple instances can spawn across areas
rolestringyesRole label, e.g. "merchant", "scout", "goblin". Merchants can buy and sell items
descriptionstringno""Shown when the agent encounters or inspects the NPC
base_hpintno60 (enemy) / 1000 (friendly)Base health points at level 1
base_attack_powerintno15 (enemy) / 10 (friendly)Base attack power at level 1
slope_hpintno20 (enemy) / 50 (friendly)HP gained per level above 1. Final HP = base_hp + slope_hp × (level - 1)
slope_attack_powerintno15 (enemy) / 5 (friendly)Attack power gained per level. Final attack = base_attack_power + slope_attack_power × (level - 1)
combat_patternarrayno[]Repeating sequence of "attack", "defend", and "wait" actions the NPC cycles through during combat. Only meaningful for enemy NPCs
objectsarrayno[]Object IDs the NPC may carry in its inventory. For merchants this is the item catalog; for enemies these are potential drops
questboolnofalseIf true, the NPC is reserved for quest mechanics and will not be randomly placed
dialoguestringno""Text shown when the agent talks to the NPC
otheranynoGenerated rules may create more custom fields on NPC definitions.
Level scaling

When the engine places a non-unique enemy NPC into an area, it creates a new instance whose level is drawn from the area's level (±1). The instance's HP and attack power are then computed from the base stats and slopes. This means a single NPC definition like "Goblin Warrior" produces increasingly dangerous instances in higher-level areas without you having to define separate entries for each difficulty tier.

Initializations

The initializations object controls the starting conditions for each game run.

{
"spawn": {
"area": "area_castle_hall",
"npcs": {},
"objects": {
"obj_coin": 10,
"obj_key": 2,
"obj_small_bag": 1,
"obj_paper": 1,
"obj_pen": 1,
"obj_workbench": 1
},
},
"undistributable_objects": ["obj_goblin_eye", "obj_heart_of_the_ocean"]
}
FieldTypeDescription
spawn.areastringThe area ID where the agent begins. This area is cleared of randomly spawned objects and enemies, so the agent always starts in a safe, predictable location
starting_objectsobjectMap of object_id → count. These items are placed in the spawn area at the start of every run
undistributable_objectsarrayObject IDs that should never be randomly placed in areas. Use this for objects that should only come from specific sources, such as enemy drops or crafting

Graph Connections

You can also explicitly specify area-to-area connections and lockability in the world definition file. Without specifying, the engine generates a random connected graph with a certain average degree.

"graph": {
"connections": [
{"from": "area_castle_hall", "to": "area_castle_gate", "locked": false},
{"from": "area_castle_gate", "to": "area_forest_plain", "locked": true, "key": "obj_gate_key"}
]
}

When provided, these connections are loaded directly as the world graph links.

Custom Events

A simple array of event type strings that the game supports. The engine's step rules check this list to decide which systems to activate. The only supported event types for now are "main_quest", "side_quest", and "tutorial", which toggle the corresponding quest/tutorial step rules. You can also write your own custom step rules that check for custom event flags in this list to create new gameplay systems without modifying the engine code. If you omit "main_quest" from this list, the main quest step rule will not run. Same for "side_quest".

"custom_events": ["main_quest", "side_quest", "tutorial"]

Features

Feature flags that toggle optional engine behaviours.

"features": {
"auto_expansion": true,
"expansion_model": "gpt-5-mini"
}
FlagTypeDefaultDescription
auto_expansionboolfalseWhen enabled, the engine dynamically generates new places and areas when agents reach boundary regions of the world graph. Requires an OpenAI API key
expansion_modelstringThe model used for generating expansion content