Projects

Selected enterprise projects spanning cloud platforms, data systems, and large-scale transformations.

SIM

Oct 2025

SIM

sim.ericbrandcode.com

I was on vacation in Oslo, Norway for about a week and spent some time in the coffee shops playing around with these algorithms.

This is a real-time agent-based community simulation where autonomous agents inhabit a procedurally generated Voronoi polygon map, gather resources, and build structures. The backend runs a tick-based simulation engine in C#/.NET broadcasting state over SignalR, while the frontend renders the world in 3D using React Three Fiber with dynamic lighting, a day/night cycle, and interactive controls for structure placement, resource gathering, and agent movement. Users configure world generation parameters including resource distribution strength and clumpiness to shape terrain composed of eight resource types across thousands of polygons.

Team: 1
Regions: North America, Europe (Oslo)
C#.NET 9ASP.NET CoreSignalRReactThree.jsReact Three FiberViteTailwind CSSDelaunay TriangulationVoronoi DiagramsA* PathfindingProcedural GenerationWebSocketsRailway

The simulation is built on a client-server architecture with a C#/.NET backend and a React/Three.js frontend communicating in real time over SignalR WebSockets.

World Generation

The world is generated procedurally using Delaunay triangulation (via the DelaunatorSharp library) to produce a Voronoi polygon graph, where each polygon represents a terrain tile with a specific resource type; plains, water, mountain, forest, wetland, clay, stone, or iron ore. The generator applies Lloyd relaxation for more uniform cell distribution, then uses a flood-fill algorithm with configurable strength and clumpiness parameters to distribute resources across the map. Mountains are organized into ranges with elevation gradients, and coastal tiles are identified through a multi-ring elevation system. The result is a graph data structure where each polygon center knows its neighbors, edges, and corners; forming the foundation for both pathfinding and rendering.

The frontend renders the polygon map in 3D using React Three Fiber and Three.js. Each Voronoi polygon is triangulated and rendered as a mesh with per-vertex coloring based on resource type and elevation. Procedurally placed pine and oak trees (controlled by a ratio slider) populate forest tiles using instanced meshes with foliage billboard textures. A directional light simulates the sun with an adjustable arc position and optional automated day/night cycle. The camera supports both orbital mouse controls and WASD keyboard movement with sprint and damping.

The Backend

On the backend, a SimulationEngine runs as a hosted BackgroundService ticking at five updates per second. Each tick advances agent lifecycles, processes movement along pre-computed paths, and handles resource gathering and deposit behaviors. Agents use A* pathfinding over the polygon graph with terrain-aware costs; they strongly prefer plains, tolerate forests, and route around water and mountains. Elevation differences also factor into pathfinding, with hard cutoffs preventing traversal of steep terrain. The engine supports world persistence through JSON serialization, saving and restoring map generation seeds, agent states, and structures.

User Interaction

User interaction happens through several modes: Structure Mode for placing buildings like houses, storage facilities, workshops, farms, mines, and walls; Gather Mode for directing agents to collect resources from specific tiles; Move Mode for commanding agent movement; and Delete Mode for removing structures. Each structure type has defined resource requirements and build times. A right-side settings drawer exposes world generation controls — per-resource strength and clumpiness sliders, polygon count, lighting parameters, and tree distribution — allowing users to regenerate the map with different characteristics.

Challenges

One of the primary challenges was building an efficient Voronoi-based map representation that could serve double duty as both a spatial data structure for simulation logic and a renderable 3D mesh. The polygon graph needed to support fast neighbor lookups for pathfinding while also providing corner vertex data for GPU rendering. Another challenge was keeping the simulation and rendering in sync across the WebSocket connection; the backend locks world state during mutations and sends snapshot-based updates to avoid race conditions. Tuning the A* pathfinding cost weights to produce natural-looking agent movement (agents visibly preferring roads and plains over difficult terrain) required balancing heuristic weights against terrain costs so that geometric distance wouldn't dominate route selection.