Town Simulation and Supply¶
Design Goals¶
Towns should feel alive because they react to success, neglect, shortages, danger, and investment. Their quest boards, prices, services, and appearance should come from actual local state rather than static scripts.
Dynamic events should be the visible expression of those state changes.
Core Town State¶
Each town should maintain a live state profile with at least:
- population
- security
- morale
- prosperity
- food reserve
- water reserve
- fuel reserve
- medicine reserve
- building materials reserve
- sanitation
- storage capacity
- market liquidity
- militia readiness
Town Health Bands¶
Every major state should resolve into readable bands such as:
- failing
- strained
- stable
- growing
- prosperous
These bands drive UI, NPC behavior, and generated content.
Reserve Units¶
Town simulation should resolve inputs into normalized reserve units rather than only raw item counts. Individual items still matter for trade, crafting, and contracts, but the civic model should aggregate them into shared pools:
food reserve: grain, bread, meat, fish, rations, preserved goodswater reserve: potable water, barrels, ice, treated waterfuel reserve: firewood, charcoal, peat, lamp oilmedicine reserve: herbs, salves, tonics, poulticesbuilding reserve: timber, planks, stone blocks, rope, iron fittings, nails
Every deliverable item template should carry a town_reserve_value by reserve class so the same shipment can update raw stock, contract validation, and shortage relief.
Daily Settlement Formula¶
Use one daily settlement pass per town to convert production, imports, projects, and losses into state changes.
For each reserve class:
net_change = local_production + completed_imports + player_deliveries + npc_baseline_supply - civilian_consumption - militia_consumption - project_draw - spoilage - event_loss
Recommended demand formulas:
food_need = population × climate_food_factor × activity_factor × refugee_factorwater_need = population × climate_water_factor × disease_factorfuel_need = households × climate_fuel_factor + building_fuel_draw + project_fuel_drawmedicine_need = base_medicine_load + injury_load + plague_modifierbuilding_need = active_project_draw + infrastructure_maintenance + event_repair_draw
Then days_of_cover = reserve_units / max(daily_need, 1) should drive both town health bands and market pressure.
Reserve Bands¶
Unless a reserve class has a special rule, use the same cover thresholds:
| Days of Cover | Band | Effects |
|---|---|---|
0-1.9 |
failing | emergency contracts, service shutdown risk, major price spike |
2.0-4.9 |
strained | shortage warnings, higher fees, reduced vendor stock |
5.0-9.9 |
stable | normal board and service behavior |
10.0-19.9 |
growing | project acceleration, mild price relief, broader stock |
20+ |
prosperous | expansion opportunities, festivals, stronger NPC buffer |
A town can be stable overall while one reserve class is failing. The board, market, and event generator should read the worst band first rather than average everything away.
Supply and Demand Engine¶
Town demand should not be a fake number. It should come from actual formulas based on population, climate, active buildings, projects, and disruptions.
Examples:
- more population increases food and water draw
- winter raises fuel demand
- barracks upgrades increase weapon, armor, and ration demand
- plague raises medicine demand and labor loss
- caravan loss lowers imported supply and raises price pressure
Price Index Movement¶
Each market category should use a smoothed local price index instead of raw spot chaos.
pressure_ratio = target_days_of_cover / max(actual_days_of_cover, 1)
instant_index = base_price × scarcity_multiplier × route_multiplier × event_multiplier × tax_multiplier × liquidity_multiplier
next_index = current_index × 0.70 + instant_index × 0.30
Guidelines:
- scarcity should dominate staple food, water, fuel, medicine, and building materials
- route multiplier should rise when caravans fail, roads close, or escort losses mount
- event multiplier should handle spikes such as plague, festival, bridge collapse, or monster surge
- liquidity should keep small towns from matching large-market depth even if both are prosperous
Cap normal daily movement to about 15% outside of crisis states so the market stays readable.
Service State Rules¶
Services should consume the same reserve data instead of using separate script logic.
- low food or water suppresses tavern quality, inn availability, and long-haul contract volume
- low fuel reduces smelting, kiln work, winter comfort, and bathhouse or heat-based services
- low medicine raises healer fees, reduces recovery quality, and increases expedition injury risk
- low building reserve slows repairs, wagon work, and public works throughput
- low liquidity narrows vendor stock and reduces large buy-order depth
The emergency public ration and water floor from the agriculture system should keep a town alive at poor efficiency rather than hard-locking it.
NPC Quest Generation¶
NPC quests should be generated from deficits, opportunities, and risks.
Those same inputs should also drive automatic local event generation.
Deficit-Driven Quests¶
- food shortage creates gather, delivery, hunt, farming, or caravan defense work
- low security creates patrol, bounty, escort, or fortification work
- low medicine creates herb gathering, healer escort, or swamp survey work
Opportunity-Driven Quests¶
- strong surplus can fund expansion projects
- new mine discoveries create labor, guard, and transport jobs
- prosperous towns can host festivals, tournaments, and rare merchant events
Board Priority Calculation¶
Generate town-board work from normalized town_urgency_score rather than fixed category quotas.
Recommended rule:
town_urgency_score = clamp(reserve_deficit × 0.45 + route_pressure × 0.20 + event_pressure × 0.20 + project_priority × 0.15 - recent_completion_relief, 0, 100)
This is same score consumed by expedition-board generation. If analytics need raw contributors, store those as separate snapshot fields instead of inventing a second board-priority formula.
Recommended board mix per refresh:
50%highest-urgency deficit or emergency work30%current opportunity or expansion work20%steady background contracts for routine play
Dynamic Town Events¶
Towns should automatically generate local events when pressure or prosperity crosses thresholds.
Examples:
- food riots or emergency ration drives
- harvest festivals
- plague quarantine
- refugee camps
- public works rushes
- merchant fairs
These events should affect contracts, services, prices, and visible town condition.
Town Upgrades¶
Towns should improve through sustained surplus and project completion.
Potential upgrade paths:
- granary
- well network
- mill
- smokehouse
- infirmary
- barracks
- market hall
- walls
- dockyard
- shrine or mage tower
Upgrades should unlock services, recipes, vendors, and better contract pools.
Project Draw and Maintenance¶
Each town project should have at least foundation, structural, and finishing phases. Phases pull from different reserve pools and should stall visibly if inputs are missing.
- granaries, wells, and mills mostly draw building reserve and labor
- barracks and walls draw building reserve, fuel, and security attention
- market halls and dockyards draw building reserve plus ongoing liquidity support
- infirmaries and shrines consume medicine or upkeep supplies once active
Completed upgrades should also have a maintenance draw. If upkeep is ignored for long enough, the upgrade should degrade before it fully disappears.
Town Degradation¶
If key reserves remain low or danger stays high, towns should degrade.
Possible effects:
- worse vendor stock
- higher prices
- fewer workers available
- building closure
- quest desperation
- refugee events
- disease outbreaks
- lower militia cover on roads
Visual and UX Changes¶
Players should see the town state, not only read about it.
Examples:
- town banners and overlays show condition bands
- market screen shows shortage warnings
- quest board gains urgent tags
- roads show caravan disruption markers
- certain services become disabled or premium-priced
Technical Model¶
Town Coordinator¶
Use one coordinator per town for high-contention state updates such as project contribution, reserve adjustments, tax application, and board refresh.
Persistent Records¶
Store:
towntown_reservetown_buildingtown_projecttown_project_phasetown_condition_snapshottown_generated_contracttown_price_indextown_daily_ledgertown_service_statetown_trade_lane_statetown_reserve_conversion_rule
Tick Model¶
Use two timescales:
- a short tick for active changes such as deliveries, project completion, and board refresh
- a daily settlement tick for consumption, condition recalculation, and long-form project progress
The daily settlement tick should run in this order:
- apply completed local production and inbound shipments
- apply player deliveries, project turn-ins, and event losses
- subtract consumption, spoilage, and maintenance
- resolve reserve bands and service states
- update price indices and contract urgency
- write a
town_condition_snapshotfor UI and event generation
Read Models¶
Expose fast public read models for:
- current shortages and surpluses
- active town projects
- visible service state
- job board urgency
- active local events
These can be cached because they are read-heavy and update on a schedule.
Guild Interaction¶
If a guild controls a town, it should influence policy but not fully replace town needs. A guild can choose tax rates, project priority, and militia spending within guardrails, but hunger and supply pressure still obey the same simulation rules.
Controller policy should change weights, taxes, and project priority, but never bypass shortage math. A wealthy guild can buffer a town with deliveries and spending; it cannot declare famine nonexistent.
Related Systems¶
- farming and food supply
- regional markets and caravans
- player contracts and job boards
- guild governance and taxation