Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

The Northern World

A pixel-art city simulation built in Godot 4, where autonomous agents are driven by a local LLM. Each agent chooses its destination — and reacts to events like fire. Developed as part of a research internship at the Machine Learning Group, UiT The Arctic University of Norway (Tromsø), intended for display at the Vitensenter (science center).

Agent character preview

Table of Contents

Prerequisites

  • Godot 4.x
  • Docker with the NVIDIA Container Toolkit configured (for the primary vLLM setup)
  • An NVIDIA GPU (developed and tested on a Jetson AGX Orin 64GB)

Quick Start

  1. Start the local LLM server — see LLM Server Setup below.
  2. Open this project folder in Godot (project.godot).
  3. Check that llm_base_url in scripts/agents/agent.gd points to your running LLM server (default: http://localhost:8001).
  4. Open and run the main scene (scenes/DefaultMap.tscn).

Using the Game

  • Camera / view: the game runs in portrait orientation, designed for the Vitensenter's vertical displays.
  • Agents: each agent (villager, lumberjack, firefighter, houseman, traveller, bird, etc.) picks its own destination autonomously via the LLM. You can click and drag any agent to reposition it manually — it will resume its own decision-making once released.
  • Fire tool: use the 🔥 icon in the toolbar to click anywhere on the map and ignite a fire. Fires spread automatically over time and are fought by scripted firefighter agents. Non-firefighter, non-bird agents can be killed by fire and will respawn at their assigned home, having "learned" a lesson from the experience (see Known Limitations).
  • Day/night cycle: runs automatically (2-minute cycle); agents with an assigned home are nudged to return there at night.
  • Survival: agents have hunger/thirst gauges that drain over time and are scripted to refill at a designated well/refill point — this does not involve the LLM.

LLM Server Setup (vLLM + Docker)

⚠️ Jetson-specific. The setup below uses a Docker image built for the Jetson AGX Orin's ARM64 architecture (nvidia-ai-iot/vllm:latest-jetson-orin) and requires the NVIDIA Container Toolkit. On a generic x86 PC without a dedicated NVIDIA GPU, skip ahead to Alternative: Ollama.

This is the primary setup used for development. The game needs a local LLM server running continuously in the background, exposing an OpenAI-compatible API with log-probability scoring support.

chmod +x setup_vllm.sh
./setup_vllm.sh

This script:

  • creates a vllm-qwen container serving Qwen/Qwen2.5-3B-Instruct-AWQ on port 8001
  • sets --restart unless-stopped so it restarts automatically on every boot (as long as Docker itself starts on login — see the script's output for how to check this)
  • is idempotent — safe to re-run if the container already exists

Verify the server is running and responding:

docker logs -f vllm-qwen              # follow model loading
curl http://localhost:8001/v1/models  # should return the model once ready

Alternative: Ollama

For a machine without a dedicated NVIDIA GPU (e.g. a deployment machine without the Jetson):

curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen2.5:3b-instruct
sudo systemctl edit ollama

Add inside the editor:

[Service]
Environment="OLLAMA_HOST=0.0.0.0:8001"
sudo systemctl daemon-reload
sudo systemctl restart ollama
curl http://localhost:8001/v1/models

Then update llm_model / CRITIC_MODEL in agent.gd to "qwen2.5:3b-instruct" (the Ollama model name, different from the HuggingFace name used with vLLM).

Note: Ollama's support for echo/logprobs on /v1/completions (used for the destination-scoring mechanism) has not been as thoroughly validated as vLLM's. After switching, check user://transition_log.jsonl to confirm probabilities vary meaningfully between candidates rather than being uniform or empty.

Configuration

  • scripts/agents/role_config.gd — role definitions (villager, lumberjack, firefighter, houseman, traveller, bird, etc.)
  • scripts/agents/agent.gd — LLM connection settings (llm_base_url, llm_model), movement speed, individual memory, fire-handling logic
  • scripts/agents/agent_memory.gd — persistent per-agent memory (lessons learned after dying to fire)

Project Structure

res://
├── scenes/          # Godot scenes (map, UI)
│   ├── agents/
│   ├── buildings/
│   ├── nature/
│   ├── ui/           
│   └── roads/      
│   ├── DefaultMap.tscn        # Main map
├── scripts/
│   ├── agents/       # agent.gd, role_config.gd, llm_scorer.gd, agent_memory.gd
│   ├── environment/      # world_registry.gd, road_graph.gd, zone_context.gd, fire_manager.gd
│   ├── ui/           # toolbar, menus
│   └── core/      # fire.gd, water_jet.gd
└── assets/

Runtime Logs

The game writes logs during execution outside the project folder, in Godot's user data directory (user://):

File Contents
transition_log.jsonl Every scored destination decision (transition matrix)
token_log.jsonl Per-decision token/logprob breakdown
fire_decision_log.jsonl Fire-avoidance decisions (continue/avoid)
agent_memory/<agent>.json Persistent per-agent memory (Reflexion-style lessons)
agent_memory/reflection_log.jsonl Full history of post-mortem reflections

Location: in Godot, Project → Open User Data Folder.

These files are not version-controlled (see .gitignore) — they are machine- and session-specific.

Known Limitations

  • Agents show a selection bias tied to the first token of a place's name rather than its geographic position or role semantics — see the research logs for details of the experiments run on this.
  • The fire-avoidance mechanism depends on a quantized 3B model; learned lessons are not guaranteed to be followed consistently — check fire_decision_log.jsonl to measure the actual avoidance rate over time.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages