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.
This page will walk you through the process of creating a complete custom weapon for SimArena, including all necessary components, and how to work with weapon configurations in SimArena using the polymorphic JSON serialization system.
The weapon system in SimArena supports two main types of weapons:
Both types share common properties like weapon ID and damage, but have type-specific properties as well.
You may, of course, extend the weapon system to support more types of weapons. For that, you will have to also extend the weapon configuration system. Below we will focus on that use case.
var swordConfig = new MeleeWeaponConfiguration(
weaponId: "sword_01",
damage: 15
);
var bowConfig = new RangedWeaponConfiguration(
weaponId: "bow_01",
damage: 12,
range: 8.0f,
projectileSpeed: 15.0f,
fireRate: 0.8f
);
You can serialize weapon configurations to JSON for storage.
Example JSON output for a melee weapon:
{
"Type": "Melee",
"WeaponId": "sword_01",
"WeaponType": "Melee",
"Damage": 15
}
Example JSON output for a ranged weapon:
{
"Type": "Ranged",
"Range": 8.0,
"ProjectileSpeed": 15.0,
"FireRate": 0.8,
"WeaponId": "bow_01",
"WeaponType": "Ranged",
"Damage": 12
}
Create a new class that inherist from the abstract Weapon
class:
public class CustomWeapon : Weapon
{
// Custom weapon logic here
}
Create a new class that inherits from the abstract WeaponConfiguration
class.
Don’t forget to add the necessary JSON serialization attributes, usually given by the template
[JsonDerivedType(typeof(YourWeaponConfig), "YourWeaponConfig")]
.
[JsonDerivedType(typeof(CustomWeaponConfiguration), "CustomWeapon")]
public class CustomWeaponConfiguration : WeaponConfiguration, IJsonOnDeserialized
{
public float AreaOfEffect { get; set; }
// Parameter-less constructor for JSON deserialization
public CustomWeaponConfiguration() : base("CustomWeapon") { }
// Constructor with parameters
public CustomWeaponConfiguration(string weaponId, int damage, float areaOfEffect)
: base("CustomWeapon", weaponId, damage)
{
AreaOfEffect = areaOfEffect;
}
public void OnDeserialized()
{
// Any validation or post-deserialization logic can go here
}
}
Update the WeaponConfiguration
base class to include your new type:
// in WeaponConfiguration.cs
[JsonPolymorphic(TypeDiscriminatorPropertyName = "Type")]
[JsonDerivedType(typeof(MeleeWeaponConfiguration), "Melee")]
[JsonDerivedType(typeof(RangedWeaponConfiguration), "Ranged")]
[JsonDerivedType(typeof(CustomWeaponConfiguration), "CustomWeapon")] // Add this line
public class WeaponConfiguration
{
// ... existing code ...
}
All weapons share these common properties:
Ranged weapons have these specific properties: