SimArena is a powerful toolkit for creating, configuring, and running simulations with multiple agents in various scenarios. It provides a robust foundation for AI research and development, with support for custom objectives, brains, weapons, and maps.
The Map Analysis System is a flexible framework designed to track and analyze various events that occur during simulation. This system can be useful for creating strategic AI behaviors, generating heatmaps, and understanding battlefield dynamics.
The system uses multiple analyzers that implement the IMapAnalysis
interface to track different types of events
such as deaths, damage, and healing (those are examples; the system is meant to be extended). Each analyzer provides
querying capabilities and can be accessed by AI brains for strategic decision making.
This system is designed to be easily extended to track other events on the map and provide analysis tools for those events as well.
The Map Analysis System automatically tracks various events during simulation and provides methods to query this data for:
TacticalBrain
for an example)The system currently includes:
// Access analyzers through the simulation
var deathAnalysis = simulation.GetMapAnalyzer<DeathAnalysis>();
// Check if it's initialized, for safety
if (deathAnalysis != null && deathAnalysis.IsInitialized)
{
// Use the analyzer
var totalDeaths = deathAnalysis.GetTotalDataCount();
}
// Or access by analysis type name
var analyzer = simulation.GetMapAnalyzer("Death");
public class MyExampleTacticalBrain : Brain
{
protected override void ExecuteThink()
{
var mapQuerier = Simulation.GetMapAnalyzer<DeathAnalysis>();
if (!mapQuerier.IsInitialized)
{
// Fallback behavior
MoveRandomly();
return;
}
// For example, assess current position risk
var deathsNearby = mapQuerier.GetDataInRadius(Agent.X, Agent.Y, 3);
var riskLevel = CalculateRisk(deathsNearby.Count);
if (riskLevel > 0.8)
{
// Move to safer area
MoveToSaferPosition(mapQuerier);
}
else if (riskLevel < 0.3)
{
// Seek opportunities in moderate-risk areas
MoveToOpportunityArea(mapQuerier);
}
}
}
Gets all data points within a specified radius of a coordinate.
var nearbyEvents = mapQuerier.GetDataInRadius(agent.X, agent.Y, 3);
Gets all data points at a specific coordinate.
var eventsHere = mapQuerier.GetDataAtCoordinate(x, y);
Gets the total number of data points recorded.
var totalCount = mapQuerier.GetTotalDataCount();
Gets all data points grouped by coordinate for density analysis.
var dataByCoord = mapQuerier.GetDataByCoordinate();
Gets death statistics for a specific team.
var teamDeaths = deathAnalysis.GetDeathsByTeam(1);
Console.WriteLine($"Team 1 has lost {teamDeaths.Count} agents");
Gets the most densely populated (by death count) areas on the map.
var dangerousAreas = deathAnalysis.GetMostDenseAreas(radius: 3, topCount: 5);
foreach (var area in dangerousAreas)
{
Console.WriteLine($"Danger zone at ({area.X}, {area.Y}): {area.DeathCount} deaths");
}
Represents a death event:
public struct DeathData : IPositionalData
{
public int X { get; }
public int Y { get; }
public DateTime Timestamp { get; }
public int Step { get; }
public string AgentName { get; }
public int Team { get; }
}
Represents a damage event:
public struct DamageData : IPositionalData
{
public int X { get; }
public int Y { get; }
public DateTime Timestamp { get; }
public int Step { get; }
public int DamageAmount { get; }
public int DealerTeam { get; }
public int ReceiverTeam { get; }
public string DealerName { get; }
public string ReceiverName { get; }
}
Represents a healing event:
public struct HealingData : IPositionalData
{
public int X { get; }
public int Y { get; }
public DateTime Timestamp { get; }
public int Step { get; }
public int HealingAmount { get; }
public int HealerTeam { get; }
public int PatientTeam { get; }
public string HealerName { get; }
public string PatientName { get; }
}
Represents an area with calculated data density:
public class DensityArea<TData> where TData : IPositionalData
{
public int X { get; }
public int Y { get; }
public int DataCount { get; }
public double DensityScore { get; }
public IReadOnlyList<TData> DataPoints { get; }
}
The Map Analysis System is automatically initialized when a Simulation is created and automatically tracks deaths through the event system. No manual setup is required.
// Create simulation - Map Analysis System is automatically initialized
var simulation = new Simulation(width: 50, height: 50);
// Access an analyzer
var deathAnalysis = simulation.GetMapAnalyzer<DeathAnalysis>();
If you want to implement your own simulation, you will need to make sure to call InitializeMapAnalyzers
and subscribe to the necessary events to track the data you want to analyze.
The included TacticalBrain
class demonstrates how to use the Map Analysis System for strategic decision making:
analyzer.IsInitialized
before using any querying methodsPotential future features that we can implement could include: