The Curator System
Overview
The curator is the AI layer that manages your settlement's cultural direction. It sits between you (the patron) and your elves, translating high-level artistic vision into concrete settlement decisions: who does what, what gets built, when to hold a revel.
Elf Revel uses a three-tier intentionality model:
- Patron (you) -- provides taste, values, and broad artistic direction via
ArtisticDirectionsettings and direct messages. - Curator (AI advisor) -- reads the settlement state and issues
CulturalCommands. Two implementations: a rule-basedDummyCurator(always available) and an LLM-backedLlmCurator(native only, usesclaudeCLI). - Elves (autonomous agents) -- execute tick-level behaviors: gathering, building, composing, attending revels. They have their own needs, aesthetics, and relationships.
The human has taste, the AI has hands, the elves have lives.
How It Works
The CulturalAdvisor Trait
Every curator implements the CulturalAdvisor trait, which defines three core methods:
| Method | Purpose |
|---|---|
consult(world) | Produce a list of CulturalCommands based on current game state |
consult_with_message(world, message) | Same, but with a player-typed message for context |
should_consult(world, events) | Decide whether the curator wants to run this tick |
Two additional methods handle forest-clearing tracking (on_forest_cleared) and UI display (last_reasoning).
When the Curator Is Consulted
The default cadence is once per game day (every 100 ticks). The should_consult method fires at day boundaries -- when tick / DAY_LENGTH changes.
The LlmCurator extends this with event-driven triggers. It will also consult when:
| Event | Condition |
|---|---|
RevelEnded | Always |
ArtCompleted | Always |
InspirationCrisis | Always |
ResourceLow | When amount < 5 |
SpiritStateChanged | When spirit enters "Anger" |
It also returns true immediately if a pending LLM result has arrived from the background thread.
The CulturalCommand Enum
When consulted, the curator returns a Vec<CulturalCommand>. Each variant maps to a concrete game action:
| Command | Fields | Effect |
|---|---|---|
AssignRole | name: String, role: ElfRole | Sets an elf's workshop assignment. Roles: Gatherer, Builder, Composer, Unassigned |
SetResourcePriority | Vec<ResourceType> | Reorders the settlement's gathering priority. Types: Food, Wood, Stone, FineWood |
QueueBuild | kind: BuildingType | Adds a building to the construction queue. Types: Dwelling, Garden, Workshop, FeastHall |
ClearForest | position: Position | Assigns an idle builder (or any idle elf) to clear a forest tile at the given coordinates |
ScheduleRevel | (none) | Transitions RevelState from None to Gathering with 5 ticks remaining |
Message | text: String | Adds curator commentary to the UI event log -- no gameplay effect |
Command Dispatch
Commands are applied via apply_commands(world, commands, curator). Each command:
- Mutates the
GameWorlddirectly (e.g., inserting intopolicies.workshop_assignments, pushing topolicies.build_queue). - Returns a
CulturalEventfor the UI log (e.g.,RoleAssigned,PriorityShifted,BuildQueued,ReadyForRevel,CuratorMessage).
For QueueBuild, the system first calls find_build_site to locate a suitable position:
- First choice: nearest meadow tile to the map center that is not occupied or already queued.
- Fallback: nearest
YoungForesttile, which gets cleared first (assigns an idle builder toClearForesttask). TheDummyCuratorlimits this to one clearing per consultation via itscleared_todayflag.
The search radius is (min(map_width, map_height) * 0.15).max(5.0) + 6 tiles from center.
The Curator Enum (Runtime Dispatch)
At runtime, the game holds a Curator enum that wraps either variant:
pub enum Curator {
Dummy(DummyCurator),
Llm(LlmCurator),
}
On WASM targets (browser build), LlmCurator is a thin stub that delegates to an inner DummyCurator, since the claude CLI is not available in the browser. The UI label shows "rules" for the dummy curator and the model name (e.g., "haiku") for the LLM curator.
State Snapshot Format
The curator never reads GameWorld directly for LLM consumption. Instead, SettlementState::from_world(world) produces a plain-data snapshot that the prompt layer serializes as readable text.
The snapshot includes:
| Section | Data |
|---|---|
| Header | Day, tick, season, day-in-season, year, weather, temperature |
| Resources | Name, current amount, daily rate -- for Food, Wood, Stone, FineWood |
| Elves | Name, role, task, skills (music/building/gathering), morale, satisfaction, aesthetic label, aesthetic distance from center, friend/rival names, portfolio count, aspirations, fandom, discontented/blocked flags |
| Aesthetic center | Settlement-wide average on four axes: structure, tradition, emotion, social |
| Compositions | Name, composer, genre, quality tier, mastery/originality/emotional scores, aesthetic position, properties, patron-favorite flag. Capped at 15 most recent |
| Revel state | Current phase (None / Gathering / Performing / Aftermath) plus history of last 5 revels with highlight composition and average score |
| Buildings | Count by type (Dwelling, Garden, Workshop, FeastHall) plus build queue size |
| Spirit | State label and meter value (0-100) |
| Current policies | Role assignments and resource priority order |
The prompt layer (prompt.rs) adds climate-aware alerts -- winter food warnings below 20, storm shelter alerts, discontented elf warnings, and spirit anger alerts -- before the main state sections.
Interactions
- Dummy Curator -- the rule-based fallback that handles bootstrap and steady-state decisions.
- LLM Curator -- the Claude-backed advisor with background threading and structured output.
- Needs & Mood -- morale values that appear in the state snapshot and inform curator decisions.
Tips
- The curator only runs at day boundaries by default. If your settlement is in crisis, the LLM curator reacts faster because it also triggers on critical events.
Messagecommands are free -- they have no gameplay cost. The LLM curator uses them to explain its reasoning in the event log.- The
QueueBuildcommand does not specify a location. The system automatically finds the best build site near the map center, clearing young forest if no meadow is available. - When the LLM curator's background thread dies or
claudeis not found, it permanently falls back to theDummyCuratorfor the rest of the session. - On WASM (browser), only the dummy curator is available. The LLM curator requires the native TUI build.