Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Enviro Ecosystem Sim

A multi-agent ecosystem simulation built with Enviro and C++. The project explores the population-resource balance problem: a species of autonomous gatherer agents competes for finite, regenerating resources. Units that successfully gather can fuel the base to reproduce; units that fail to find food starve and die. The system self-regulates toward a dynamic equilibrium -- or collapses if parameters tip the balance.


Overview

This simulation models a closed ecosystem inspired by ecological dynamics such as the Lotka-Volterra model. Instead of differential equations, the population and resource interactions emerge from individual agent behaviors running in real time.

The core feedback loop:

Resources regenerate  -->  Gatherers collect resources  -->  Base spawns more gatherers
     ^                                                            |
     |                                                            v
Resources deplete  <--  More gatherers consume faster  <--  Population grows
     |
     v
Gatherers starve and die  -->  Population shrinks  -->  Resources recover

This creates a natural oscillation: population booms when resources are abundant, then crashes as overconsumption depletes the map, then slowly recovers as resources regenerate into a less crowded arena.

Agents

  • Base -- a stationary structure that receives resources from gatherers and spends them to produce new units (cost: 5 resources each). If all units die, the base performs an emergency free spawn to prevent extinction.
  • Gatherer (UnitA_collect) -- a small triangular unit with five range sensors. It wanders the arena searching for resources, picks them up, and navigates back to the base. A gatherer that fails to find any resource within 600 frames starves and dies. A gatherer stuck returning for over 900 frames also perishes. This mortality is what prevents unbounded population growth.
  • Resource -- a static diamond-shaped node. Disappears when collected by a gatherer. The map manager periodically spawns new resources, modeling environmental regeneration.
  • MapManager -- an invisible agent that drives resource regeneration: every 200 frames, it spawns up to 5 new resources at random positions (capped at 20 total). It also displays a real-time HUD showing population count and resource stockpile.
  • Walls -- four boundary walls. Gatherers detect them via sensors and steer away.

All agents communicate through Enviro's event system (emit / watch). No agent reads another's internal state -- behaviors emerge purely from local perception and decentralized events.


Key Challenges

1. Balancing population and resource dynamics

The central design challenge is tuning parameters so the system neither explodes (infinite units, instant resource depletion) nor collapses (all units die, resources sit uncollected). The key parameters are: unit spawn cost (5 resources), starvation timeout (600 frames), resource respawn interval (200 frames), and respawn batch size (5). These were tuned through experimentation to produce visible boom-bust oscillations rather than a flat steady state.

2. Event-driven resource claim protocol

When multiple gatherers reach the same resource simultaneously, a naive pickup model causes double-counting. The solution is a two-phase claim/grant protocol: the gatherer emits resource_claim; the resource, if uncollected, marks itself collected and emits resource_granted back to that specific unit only. This ensures each resource is consumed exactly once, which is critical for accurate population dynamics.

3. Safe dynamic agent creation and removal

Both gatherers and resources are created and destroyed at runtime. Enviro's remove_agent() cannot be called from inside a collision or event callback without risking a segmentation fault. The solution is a two-frame delayed deletion: on the first frame the agent sets a dead flag; on the next update() call it performs remove_agent(). All handlers check dead and removed flags before acting.

4. Wall avoidance with range sensors

Gatherers have five sensors (front, front-left, front-right, left, right). The avoid_walls() method compares open space on each side and steers toward the more open direction, slowing down proportionally to front-wall distance. It only reacts to WallH/WallV reflections, ignoring resources and the base, so gathering behavior is not disrupted by the avoidance logic.


Installation and Running

Prerequisites

  • Docker installed on your machine.

Steps

# 1. Clone this repository
git clone https://github.com/doubleBlack2/enviro-ecosystem-sim.git
cd enviro-ecosystem-sim

# 2. Start the Docker container
docker run -p80:80 -p8765:8765 -v $PWD:/source -it klavins/enviro:1.6 bash

# 3. Inside the container, build and run
make
esm start
enviro

Viewing the simulation

Open your browser and go to:

http://localhost

You will see the arena with a red base in the upper-left corner, one initial gatherer unit, seven resource nodes (gold diamonds), and dark boundary walls. The simulation starts immediately.

What to observe

  • Population growth phase: The initial gatherer finds resources and delivers them to the base. Once the base accumulates 5 resources, it spawns a new gatherer. The population grows as long as resources are plentiful.
  • Resource pressure: As the population increases, resources are consumed faster than they regenerate. The map becomes sparse.
  • Starvation and decline: Gatherers that cannot find resources within the timeout period die (disappear from the arena). The population contracts.
  • Recovery: With fewer gatherers competing, resources accumulate again. The base eventually spawns new units, and the cycle repeats.
  • Visual cues: Gatherers turn orange when carrying a resource, red when searching. The HUD in the upper-right corner shows R: (base resource stockpile) and U: (current unit count) -- watch these numbers oscillate over time.

Project Structure

enviro-ecosystem-sim/
├── config.json              # World configuration (agents, arena size, walls)
├── Makefile                 # Compiles src/*.cc into lib/*.so
├── README.md
├── LICENSE
├── defs/
│   ├── base_a.json          # Base definition (static, 20x20 square)
│   ├── unit_a_coll.json     # Gatherer definition (dynamic, triangle, 5 sensors)
│   ├── resource.json        # Resource definition (static, diamond shape)
│   ├── map_manager.json     # Map manager definition (noninteractive)
│   ├── wall_h.json          # Horizontal wall definition (static, 1100x10)
│   └── wall_v.json          # Vertical wall definition (static, 10x700)
└── src/
    ├── base_a.h / base_a.cc         # Base controller (resource tracking, unit spawning)
    ├── unit_a_coll.h / unit_a_coll.cc # Gatherer controller (wander, sense, claim, deliver)
    ├── resource.h / resource.cc     # Resource controller (claim/grant protocol, removal)
    ├── map_manager.h / map_manager.cc # Resource regeneration and HUD display
    ├── wall_h.h / wall_h.cc         # Horizontal wall (empty controller)
    └── wall_v.h / wall_v.cc         # Vertical wall (empty controller)

Agent Communication

All inter-agent communication uses Enviro events. No agent reads another agent's internal state.

Event Sender Receiver Payload
base_a_position Base Gatherers {x, y} -- base coordinates for return navigation
base_a_stats Base MapManager {resources, units} -- for HUD display
resource_nearby Resource Gatherers {resource_id, x, y} -- broadcast every frame
resource_claim Gatherer Resource {resource_id, unit_id} -- request pickup
resource_granted Resource Gatherer, MapManager {resource_id, unit_id} -- confirm pickup
resource_delivered Gatherer Base {faction, amount} -- deposit resources
unit_spawned Base (logged) {faction} -- new unit created
unit_died Gatherer Base {faction} -- unit removed

Sources and Acknowledgements

  • Enviro framework by Prof. Eric Klavins
  • Elma event loop manager
  • Lotka-Volterra population dynamics model (Alfred Lotka, 1925; Vito Volterra, 1926)
  • EEP 520 course materials, University of Washington, Winter 2026

About

A multi-agent ecosystem simulation using Enviro and C++. Three factions compete for resources, fight monsters, and evolve through emergent behaviors.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages