Home Economic Map Zones

Economic Map Zones

Tax, property, and growth are segment overlays — axis-aligned zones on the same map layout as terrain and resources. They are not biomes and not terrain surface tiles. Biomes, adjacency, and cultivation live in 38 — Biomes, adjacency & terrain transitions.

Related: 10 — Economy & markets, 23 — Harvest, 08 — Inventory & storage (banks after property), 21 — World content schemas, player ledger (LedgerCategory::Taxes).


1. Summary

Designers draw three overlay kinds in content-admin World → Map layout (primary large-scale editor):

Overlay Purpose
Tax zones Copper sink on successful harvest inside the zone
Property zones Crown-owned parcels players can buy/sell; upkeep; reclaim
Growth zones Fertility + crop tags shorten matching plant node respawn

Layers stay independent: a cell can sit in temperate biome + taxed crown land + fertile growth at once. Sampling uses the same highest z_order wins rule as terrain zones (tie-break: later in the YAML list).


2. Design principles

Principle Meaning
Overlays, not tiles Econ rules do not replace terrain_zones; they query (x,y) at harvest / buy / respawn
Web Map first Place, select, drag, delete, and property panels ship in content-admin Map layout; native editor is fine-detail only
Soft tax Broke players still complete harvest; tax deducts what they can pay (no hard block)
Growth ≠ biome Fertility and crop tags are economic/farming rules; climate is a biome layer (38)
Reserved farm gates Growth zones declare allowed_kinds / allowed_biomes for later procgen and cultivate — even before those systems run
Weather as multiplier Respawn uses weather_mult (default 1.0) so weather can land without schema rewire

3. Shared zone shape

Same rect model as terrain (21):

tax_zones:
  - id: mill-road-tax
    z_order: 0
    rects:
      - { x0: 120, y0: 130, x1: 160, y1: 150 }
    # fields below vary by kind

Legacy single-rect x0/y0/x1/y1 on the zone may load; prefer rects:.

Overlap: highest z_order among zones of the same overlay family (tax vs tax, growth vs growth). Different families stack independently.


4. Tax zones

4.1 Fields

Field Type Meaning
id string Stable id
rects list Coverage
z_order int Stack within tax overlays
rate_bps int Tax in basis points of harvest copper value (e.g. 500 = 5%)
flat_copper int Optional flat copper added to the tax bill (default 0)
label string? Designer / UI label

Harvest copper value: sum of minted/granted items’ nominal copper (template or instance valuation used elsewhere for ledgers). If valuation is unset, use flat_copper only or skip percentage.

4.2 Runtime

On harvest complete (finish_harvest):

  1. Resolve tax_zone_at(x, y).
  2. Compute bill = flat_copper + floor(harvest_value_copper * rate_bps / 10000).
  3. If the harvester owns an overlapping property parcel (see §5), apply owner_tax_discount_bps from that property (or a global settings default).
  4. Deduct min(bill, player_copper)soft deduct. Ledger entry: LedgerCategory::Taxes.
  5. Never cancel the harvest for insufficient funds.

Workers harvesting for an employer: tax the employer copper when policy says so (same soft rule); otherwise tax the acting character. Default: tax the character that receives the items.


5. Property zones

5.1 Fields

Field Type Meaning
id string Parcel id
rects list Parcel footprint
z_order int Stack within property overlays
crown_price_copper int Buy price from the crown
max_area_m2 float? Optional cap; reject buy if rect area exceeds
upkeep_copper_per_day int Upkeep sink (game-day via WorldClock)
upkeep_grace_days int Days unpaid before reclaim (default e.g. 3)
owner_tax_discount_bps int Discount on tax bills while owned (e.g. 2500 = 25% off)
label string? UI label

Runtime ownership is not stored only in YAML: segment defines the parcel geometry and crown terms; ownership + upkeep arrears live in control-plane / worker persistence keyed by (segment_id, property_zone_id).

5.2 Buy / sell / upkeep

Action Behavior
Buy from crown Player in/near parcel, pays crown_price_copper, becomes owner if unowned
Sell to crown Owner sells back at configured fraction of crown price (settings), clears ownership
Upkeep Each game-day tick: charge owner upkeep_copper_per_day (soft or hard per settings; default soft then grace)
Reclaim After upkeep_grace_days with arrears: ownership clears; parcel returns to crown

Banks / housing static storage (08) may key off owned property later; property zones are the land-claim precursor.


6. Growth zones

6.1 Fields

Field Type Meaning
id string Zone id
rects list Coverage
z_order int Stack within growth overlays
fertility float >= 1.0 shortens respawn (e.g. 1.5 → respawn / 1.5). Clamp to settings min/max
crop_tags string[] Node or item tags that receive the bonus; empty = all plant nodes in zone
allowed_kinds string[] Reserved: sim terrain kinds allowed for farm tiles / cultivate (38)
allowed_biomes string[] Reserved: biome ids that may host this growth overlay’s farming rules
label string? UI label

6.2 Respawn formula

At harvest-complete when entering cooldown:

base = node.respawn_ticks
zone = growth_zone_at(node.x, node.y)
if zone matches node (crop_tags empty OR intersection with node/item tags):
  effective = base / fertility * weather_mult
else:
  effective = base * weather_mult_outside   # usually 1.0
until_tick = tick + max(1, ceil(effective))

weather_mult defaults to 1.0 until regional weather exists (38 § weather). Same stub on the growth path avoids a later schema break.

6.3 Crop tags

Resource nodes and/or yield item templates carry crop_tags: [carrot, vegetable, …]. Catalog and Map layout expose tag pickers via /api/catalog.


7. Sampling helpers

Sim provides:

  • tax_zone_at(segment, x, y) -> Option<&TaxZoneDef>
  • property_zone_at(...) / property_zones_covering(...) for ownership checks
  • growth_zone_at(...)

Mirror terrain_zone_at overlap rules within each family.


8. Content-admin Map layout

Required for done criteria (content-admin rule):

Capability Detail
Draw Brush or rect tool for tax / property / growth
Select / drag / delete Same interaction patterns as terrain and nodes
Property panel Kind-specific fields above
Labels Two-letter tags + hover titles
Validate Overlap warnings; property area vs max_area_m2; unknown crop tags
Save PUT map-layout → segment YAML

Native flatland-editor may visualize overlays later; web Map layout is primary for large-scale placement and catalog cross-links.


9. Settings knobs

Under assets/config/server-settings.yaml (names illustrative):

economy_zones:
  tax_soft_deduct: true
  default_owner_tax_discount_bps: 0
  property_sellback_bps: 5000          # 50% of crown price
  growth_fertility_min: 1.0
  growth_fertility_max: 3.0
  weather_mult_default: 1.0

10. Example (starter-plains sketch)

tax_zones:
  - id: plains-crossroads-tax
    z_order: 0
    rate_bps: 400
    flat_copper: 0
    rects:
      - { x0: 118, y0: 128, x1: 155, y1: 148 }

property_zones:
  - id: crown-plot-a
    z_order: 0
    crown_price_copper: 5000
    upkeep_copper_per_day: 25
    upkeep_grace_days: 3
    owner_tax_discount_bps: 2500
    rects:
      - { x0: 130, y0: 135, x1: 145, y1: 145 }

growth_zones:
  - id: mill-fields
    z_order: 0
    fertility: 1.4
    crop_tags: [carrot, potato, vegetable]
    allowed_kinds: [grass, tilled]
    allowed_biomes: [temperate_plains]
    rects:
      - { x0: 125, y0: 120, x1: 150, y1: 135 }

11. Exit criteria

  • Zones load from segment YAML and appear in Map layout CRUD
  • Harvest inside tax zone writes a tax ledger line and soft-deducts copper
  • Owned property applies tax discount
  • Matching growth zone shortens plant respawn_ticks by fertility
  • Crown buy/sell + upkeep grace reclaim work for a sample parcel
  • weather_mult and allowed_kinds / allowed_biomes are present (mult may stay 1.0)

12. Non-goals

  • Biome climate, adjacency, procedural fill, cultivate intents → 38
  • Full broker markets / sales tax E2 → 10
  • Bank chests keyed to parcels → after property ships (08)
  • Fractional plot purchase, tax share, and player farming40 (supersedes whole-zone-only buy UX)