villsim/docs/design/simple-architecture.md

5.4 KiB

Simple Village Simulation Architecture (MVP)

This document outlines the architecture for the Village Simulation based on Village TZ v2. The system follows a client-server model to ensure strict separation between the simulation logic (Backend) and the visualization (Frontend).

1. System Overview

The system consists of two distinct applications communicating via HTTP (REST API):

  1. Backend (Server): Responsible for the entire simulation state, economic logic, AI decision-making (GOAP-based), and turn management.
  2. Frontend (Client): A web-based frontend (HTML/JavaScript) that queries the current state to render it and sends user commands to the server.

This separation allows replacing the web frontend with other technologies (React/Vue, Unity, etc.) without changing the backend logic.


2. Backend Architecture (Python)

We adhere to a simplified Clean Architecture to keep business logic isolated from the API framework.

2.1. Layered Structure

backend/
├── main.py                 # Entry point, API configuration
├── api/                    # Interface Layer (FastAPI)
│   ├── routes.py           # Endpoints (GET /state, POST /next_turn)
│   └── schemas.py          # Pydantic models for request/response
├── core/                   # Business Logic Layer (The "Brain")
│   ├── engine.py           # Game Loop manager (Day/Night cycle)
│   ├── world.py            # Container for all entities
│   └── market.py           # Order Book matching logic
└── domain/                 # Data Models (Pure Python)
    ├── agent.py            # Agent logic (stats, inventory, survival rules)
    ├── resources.py        # Resource definitions (Meat, Wood, etc.)
    └── action.py           # Action definitions (Hunt, Sleep, Trade)

2.2. Key Components

  1. Domain Models (domain/):

    • Agent: Stores state (Energy, Hunger, Money, Inventory). Contains methods like eat(), work(), but does not know about the game loop.
    • Resource: Enum or classes defining resource properties (decay rate, base value).
  2. Core Engine (core/):

    • GameEngine: Singleton that holds the World state.
    • Turn Processing:
      • The simulation is Turn-Based.
      • The Engine waits for a "Next Turn" signal (or runs on a timer).
      • Processing order: Collect Actions -> Resolve Market -> Update Agent Stats -> Remove Dead Agents.
  3. API (api/):

    • GET /state: Returns the full snapshot of the world (Agents, Market Order Book, Global Stats) in JSON format.
    • POST /control/next_step: Forces the simulation to advance one tick (useful for debugging/manual control).
    • POST /market/order: (Optional) Allows manual intervention to place orders.

3. Frontend Architecture (Web)

The frontend acts as a Visualizer. It does not calculate simulation logic.

3.1. Structure

web_frontend/
├── index.html              # Main HTML page
├── goap_debug.html         # GOAP debugging view
├── styles.css              # Styling
└── src/
    ├── main.js             # Application entry point
    ├── api.js              # Network client (fetch API)
    ├── constants.js        # Configuration constants
    └── scenes/             # Game scenes (Phaser.js)
        ├── BootScene.js    # Loading scene
        └── GameScene.js    # Main game visualization

3.2. Flow

  1. Network Step:
    • Call GET http://localhost:8000/state.
    • Receive JSON: {"turn": 5, "time_of_day": "day", "agents": [...], "market": [...]}.
  2. Update Step:
    • Parse JSON into JavaScript objects.
  3. Draw Step:
    • Update Phaser.js game scene.
    • Render Agents at their coordinates.
    • Render UI overlays (e.g., "Day 1, Step 5", "Total Coins: 500").

4. Data Flow & Synchronization

Since the simulation involves AI agents acting autonomously, the Frontend is primarily an Observer.

  1. Initialization: Server starts, generates N agents.
  2. Loop:
    • Server calculates the turn results (AI decisions -> Outcomes).
    • Frontend polls /state every X milliseconds (or every frame).
    • Frontend updates the screen.

4.1. The "God Mode" Problem

To test the simulation efficiently, the Server exposes a Simulation Controller:

  • Manual Mode: The server waits for a POST /next_step call to advance. The User clicks the advance button in the web frontend -> Frontend sends request -> Server updates -> Frontend fetches new state.
  • Auto Mode: Server runs a background thread updating every N seconds. Frontend just polls.

5. Technology Stack

  • Language: Python 3.11+
  • Backend Framework: FastAPI (for speed and auto-generated docs).
  • Data Validation: Pydantic.
  • AI System: GOAP (Goal-Oriented Action Planning).
  • Frontend: HTML/JavaScript with Phaser.js for rendering.
  • Communication: HTTP (Fetch API/Uvicorn).

6. Future Extensibility (Why this architecture?)

  • Switch to React/Vue: Replace web_frontend/ folder with a React app. The React app simply calls the same GET /state endpoint.
  • Switch to Unity: Unity UnityWebRequest calls GET /state.
  • Database: Currently state is in-memory (core/engine.py). Easy to swap for SQLite/Postgres later by adding a repository layer in Backend.