# Multi-World Game Sketch
# =======================
# This is a SYNTAX EXPLORATION - not runnable code.
# Shows what Common Herb might look like with player isolation.

# -----------------------------------------------------
# GAME WORLD (root - shared visible state)
# -----------------------------------------------------

WORLD game

# Terrain - all players inherit this, can see it
FACT tile_0_0 terrain grass
FACT tile_0_1 terrain grass
FACT tile_1_0 terrain forest
FACT tile_1_1 terrain water

# Buildings
FACT town_hall is_a building
FACT town_hall location tile_5_5
FACT town_hall name "Gulpin Town Hall"

# NPCs (positions visible to all, decisions internal to NPC World)
FACT merchant_bob is_a npc
FACT merchant_bob sprite merchant_male
# Note: NPC decisions are in NPC World, not here

# Items on ground (visible to all)
FACT dropped_001 is_a item
FACT dropped_001 item_type gold
FACT dropped_001 amount 50
FACT dropped_001 location tile_3_2

# World rules for shared physics
RULE item_decays
  WHEN ?item is_a item
  AND ?item dropped_at ?tick
  IF (> (- current_tick ?tick) 1000)
  THEN ?item decayed true

# -----------------------------------------------------
# PLAYER WORLD (one per connected player)
# -----------------------------------------------------

WORLD player_$ID
  PARENT game
  EXPORTS position, display_name, visible_action, is_player
  INTERNAL hp, mana, inventory, gold, quest_log, skill_levels

FUNCTIONAL hp
FUNCTIONAL mana
FUNCTIONAL gold
FUNCTIONAL position

# Initial state
FACT self is_player true
FACT self display_name "$PLAYERNAME"
FACT self position tile_5_5    # Start at town hall
FACT self hp 100
FACT self mana 50
FACT self gold 0

# -- Movement --
# Player inherits terrain from game World, can check walkability

RULE process_move
  WHEN inbox move_request ?dir
  AND self position ?current
  AND (adjacent ?current ?dir) terrain ?terrain   # Inherited from game
  IF (not= ?terrain water)                        # Can't walk on water
  THEN self position (adjacent ?current ?dir)
  AND self visible_action moved ?dir              # Exported - others see this
  RETRACT inbox move_request ?dir

# -- Combat --

RULE process_attack
  WHEN inbox attack_request ?target
  AND self position ?pos
  AND ?target SIBLING_EXPORTS position ?tpos      # Can see sibling exports via server
  IF (adjacent_tile ?pos ?tpos)
  THEN self attacking ?target
  SEND server combat_action self attack ?target
  RETRACT inbox attack_request ?target

# -- Inventory (Internal) --

RULE pickup_item
  WHEN inbox pickup_request ?item
  AND self position ?pos
  AND ?item location ?pos                         # Inherited from game World
  AND ?item item_type ?type
  AND ?item amount ?amt
  SEND server pickup_request self ?item
  RETRACT inbox pickup_request ?item
  # Server will remove item from game World and add to our inventory

# -- Receiving from Server --

RULE receive_damage
  WHEN inbox damage ?amount from ?source
  AND self hp ?current
  THEN self hp (- ?current ?amount)
  RETRACT inbox damage ?amount from ?source

RULE receive_item
  WHEN inbox grant_item ?type ?amount
  THEN inventory has ?type amount ?amount
  RETRACT inbox grant_item ?type ?amount

RULE receive_gold
  WHEN inbox grant_gold ?amount
  AND self gold ?current
  THEN self gold (+ ?current ?amount)
  RETRACT inbox grant_gold ?amount

# -----------------------------------------------------
# SERVER WORLD (authoritative - sees all)
# -----------------------------------------------------

WORLD server
  PARENT game
  # Server has special ALL_EXPORTS privilege

# -- Track All Players --

RULE register_player
  WHEN ?p EXPORTS is_player true
  AND ?p EXPORTS display_name ?name
  AND ?p EXPORTS position ?pos
  THEN player_list contains ?p name ?name at ?pos

# -- Combat Resolution --

RULE resolve_combat
  WHEN ?attacker EXPORTS visible_action attack ?defender
  AND ?attacker EXPORTS position ?apos
  AND ?defender EXPORTS position ?dpos
  IF (adjacent_tile ?apos ?dpos)
  THEN combat_event attacker ?attacker defender ?defender

RULE calculate_damage
  WHEN combat_event attacker ?a defender ?d
  # Server has access to damage formulas, equipment bonuses, etc.
  # (simplified here)
  THEN pending_damage to ?d amount 10 from ?a
  RETRACT combat_event attacker ?a defender ?d

RULE apply_damage
  WHEN pending_damage to ?d amount ?amt from ?src
  SEND ?d damage ?amt from ?src
  RETRACT pending_damage to ?d amount ?amt from ?src

# -- Item Pickup Resolution --

RULE resolve_pickup
  WHEN ?p pending_pickup ?item
  AND ?item location ?loc
  AND ?p EXPORTS position ?ppos
  IF (= ?loc ?ppos)
  AND ?item item_type ?type
  AND ?item amount ?amt
  SEND ?p grant_item ?type ?amt
  RETRACT game FACT ?item location ?loc    # Remove from game World
  RETRACT ?p pending_pickup ?item

# -- Trading --

RULE match_trade
  WHEN ?p1 EXPORTS visible_action trade_offer ?p2 ?item1
  AND ?p2 EXPORTS visible_action trade_offer ?p1 ?item2
  THEN trade_pending between ?p1 ?p2 items ?item1 ?item2

RULE execute_trade
  WHEN trade_pending between ?p1 ?p2 items ?item1 ?item2
  SEND ?p1 trade_complete received ?item2
  SEND ?p2 trade_complete received ?item1
  RETRACT ?p1 inventory has ?item1
  RETRACT ?p2 inventory has ?item2
  RETRACT trade_pending between ?p1 ?p2 items ?item1 ?item2

# -----------------------------------------------------
# NPC CONTROLLER WORLD
# -----------------------------------------------------

WORLD npc_controller
  PARENT game
  EXPORTS npc_position, npc_dialogue_state
  INTERNAL npc_goals, npc_memory, npc_decision_tree

# NPCs make decisions internally, export only positions and dialogue

RULE npc_wander
  WHEN ?npc is_a npc             # Inherited from game
  AND ?npc current_goal wander
  THEN ?npc should_move (random_walkable_adjacent ?npc)

RULE export_npc_position
  WHEN ?npc moved_to ?pos
  THEN npc_position ?npc at ?pos    # Exported - visible to players

# NPC dialogue decisions are INTERNAL
# When player initiates dialogue, NPC state affects responses
# But player doesn't see WHY NPC said what they said

# -----------------------------------------------------
# NOTES ON THIS SKETCH
# -----------------------------------------------------

# 1. INHERITANCE enables shared visible state
#    - All players see the same terrain, buildings, items on ground
#    - Players inherit from game World (read-only)

# 2. EXPORTS enable server authority
#    - Players export position, actions
#    - Server patterns on exports to resolve combat, trades, pickups
#    - Server SEND delivers results back to players

# 3. INTERNAL enables privacy
#    - Player A can't see Player B's HP, inventory, gold
#    - Server CAN see these (special privilege? or explicit access?)
#    - NPC decision logic is internal to NPC controller

# 4. Server as mediator
#    - All "cross-player" actions go through server
#    - Trade requires both players to export trade_offer
#    - Server matches them, executes atomically

# 5. Provenance still works
#    - "Why did I take 10 damage?" -> inbox damage 10 from player_bob
#    - "Why did player_bob attack me?" -> player_bob EXPORTS visible_action attack
#    - But: can't see WHY player_bob decided to attack (that's their internal state)

# 6. Client rendering
#    - Client queries: inherited game facts + own World facts + sibling exports (positions)
#    - Doesn't need to see other players' internals - just positions for rendering
