Attack Works

This commit is contained in:
2020-04-21 20:34:35 -06:00
parent 1acf94c900
commit a7c1f79acb
62 changed files with 927 additions and 55884 deletions

View File

@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\DryIoc.4.1.4\build\DryIoc.props" Condition="Exists('..\packages\DryIoc.4.1.4\build\DryIoc.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F65ECA33-08FF-4797-8E53-B086320214F4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BattleFieldSimulator.Utilities</RootNamespace>
<AssemblyName>BattleFieldSimulator.Utilities</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BootStrapper.cs" />
<Compile Include="Class1.cs" />
<Compile Include="DryIoc\Container.cs" />
<Compile Include="DryIoc\Expression.cs" />
<Compile Include="DryIoc\FastExpressionCompiler.cs" />
<Compile Include="DryIoc\ImTools.cs" />
<Compile Include="IModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\DryIoc.4.1.4\build\DryIoc.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\DryIoc.4.1.4\build\DryIoc.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,37 +0,0 @@
using System;
using DryIoc;
namespace BattleFieldSimulator
{
public class BootStrapper
{
private static readonly string NoBootstrapperMessage = $"Called {nameof(BootStrapper)} before it existed";
private static BootStrapper _bootStrapper;
private static IContainer _container;
public static BootStrapper Instance =>
_bootStrapper ?? throw new InvalidOperationException(NoBootstrapperMessage);
private BootStrapper(params IModule[] modules)
{
_container = new Container();
foreach (var module in modules)
{
module.Register(_container);
}
foreach (var module in modules)
{
module.Resolve(_container);
}
}
public static BootStrapper BootstrapSystem(params IModule[] modules) =>
_bootStrapper = new BootStrapper(modules);
public T Resolve<T>()
{
return _container.Resolve<T>();
}
}
}

View File

@@ -1,6 +0,0 @@
namespace BattleFieldSimulator.Utilities
{
public class Class1
{
}
}

View File

@@ -1,11 +0,0 @@
using DryIoc;
namespace BattleFieldSimulator.Utilities
{
public interface IModule
{
void Register(IContainer container);
void Resolve(IContainer container);
}
}

View File

@@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BattleFieldSimulator.Utilities")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BattleFieldSimulator.Utilities")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("F65ECA33-08FF-4797-8E53-B086320214F4")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DryIoc" version="4.1.4" targetFramework="net472" />
</packages>

View File

@@ -40,10 +40,27 @@
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BattlefieldEnviornment\Map.cs" />
<Compile Include="BattlefieldEnvironment\Environment.cs" />
<Compile Include="BattlefieldEnvironment\EnvironmentFactory.cs" />
<Compile Include="BattlefieldEnvironment\EnvironmentSetup.cs" />
<Compile Include="BattlefieldEnvironment\IEnvironment.cs" />
<Compile Include="BattlefieldEnvironment\IEnvironmentFactory.cs" />
<Compile Include="BattlefieldEnvironment\IEnvironmentSetup.cs" />
<Compile Include="BattlefieldEnvironment\Map\IMap.cs" />
<Compile Include="BattlefieldEnvironment\Map\IMapLoader.cs" />
<Compile Include="BattlefieldEnvironment\Map\Map.cs" />
<Compile Include="BattlefieldEnvironment\Map\MapLoader.cs" />
<Compile Include="BattlefieldEnvironment\Map\Point.cs" />
<Compile Include="BattlefieldEnvironment\Troops\EffectivenessRatios.cs" />
<Compile Include="BattlefieldEnvironment\Troops\ITroop.cs" />
<Compile Include="BattlefieldEnvironment\Troops\ITroopLoader.cs" />
<Compile Include="BattlefieldEnvironment\Troops\Mission.cs" />
<Compile Include="BattlefieldEnvironment\Troops\Troop.cs" />
<Compile Include="BattlefieldEnvironment\Troops\TroopLoader.cs" />
<Compile Include="BootStrapper.cs" />
<Compile Include="ConsoleClient\ConsoleClient.cs" />
<Compile Include="CoreModule.cs" />
@@ -51,7 +68,9 @@
<Compile Include="DryIoc\Expression.cs" />
<Compile Include="DryIoc\FastExpressionCompiler.cs" />
<Compile Include="DryIoc\ImTools.cs" />
<Compile Include="Exceptions\IBattleFieldException.cs" />
<Compile Include="Exceptions\BattleFieldException.cs" />
<Compile Include="Exceptions\InvalidMapException.cs" />
<Compile Include="Exceptions\InvalidTroopException.cs" />
<Compile Include="Exceptions\ItemNotFoundException.cs" />
<Compile Include="FileSystem\FileSystem.cs" />
<Compile Include="FileSystem\FileSystemConstants.cs" />
@@ -64,11 +83,21 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SimRunner\ISimRunner.cs" />
<Compile Include="SimRunner\ISimulation.cs" />
<Compile Include="SimRunner\SimRunner.cs" />
<Compile Include="SimRunner\Simulation.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="maps\SimpleMap.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="troops\SimpleTroopFile.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>

View File

@@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=battlefieldenvironment_005Cmap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=battlefieldenvironment_005Ctroops/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -1,36 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using BattleFieldSimulator.JsonSerialization;
namespace BattleFieldSimulator.BattlefieldEnviornment
{
public class Map
{
public List<List<int>> Grid { get; }
public int X { get; }
public int Y { get; }
public Map(int x, int y, IEnumerable<IJsonObject> grid)
{
X = x;
Y = y;
Grid = ConvertGrid(grid);
}
private List<List<int>> ConvertGrid(IEnumerable<IJsonObject> grid)
{
var r_grid = new List<List<int>>();
var index = 0;
var jsonObjects = grid.ToList();
for (var i = 0; i < X; i++)
{
for (var j = 0; j < Y; j++)
{
r_grid[i][j] = int.Parse(jsonObjects[index].ToString());
index++;
}
}
return r_grid;
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class Environment : IEnvironment
{
public IMap Map { get; }
public List<Troop> Allies { get; }
public List<Troop> Adversaries { get; }
public Environment(IMap map, List<Troop> allies, List<Troop> adversaries)
{
Map = map;
Allies = allies;
Adversaries = adversaries;
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class EnvironmentFactory : IEnvironmentFactory
{
public Environment CreateEnvironment(IMap map, List<Troop> allies, List<Troop> adversaries)
{
return new Environment(map, allies, adversaries);
}
}
}

View File

@@ -0,0 +1,25 @@
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class EnvironmentSetup : IEnvironmentSetup
{
private readonly IMapLoader _mapLoader;
private readonly IEnvironmentFactory _environmentFactory;
private ITroopLoader _troopLoader;
public EnvironmentSetup(IMapLoader mapLoader, IEnvironmentFactory environmentFactory, ITroopLoader troopLoader)
{
_mapLoader = mapLoader;
_environmentFactory = environmentFactory;
_troopLoader = troopLoader;
}
public Environment Setup(string mapName, string troopFile)
{
var map = _mapLoader.LoadMap(mapName);
var allies = _troopLoader.LoadAllies(troopFile);
var adversaries = _troopLoader.LoadAdversaries(troopFile);
var env = _environmentFactory.CreateEnvironment(map, allies, adversaries);
return env;
}
}
}

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public interface IEnvironment
{
IMap Map { get; }
List<Troop> Allies { get; }
List<Troop> Adversaries { get; }
}
}

View File

@@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public interface IEnvironmentFactory
{
Environment CreateEnvironment(IMap map, List<Troop> allies, List<Troop> adversaries);
}
}

View File

@@ -0,0 +1,7 @@
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public interface IEnvironmentSetup
{
Environment Setup(string mapName, string troopFile);
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public interface IMap
{
List<List<int>> Grid { get; }
int X { get; }
int Y { get; }
}
}

View File

@@ -0,0 +1,7 @@
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public interface IMapLoader
{
IMap LoadMap(string mapName);
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BattleFieldSimulator.Exceptions;
using BattleFieldSimulator.JsonSerialization;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class Map : IMap
{
public List<List<int>> Grid { get; }
public int X { get; }
public int Y { get; }
public Map(int x, int y, List<List<int>> grid)
{
X = x;
Y = y;
Grid = grid;
ValidateMap();
}
private void ValidateMap()
{
if(Grid.Count != X)
throw new InvalidMapException($"X Dimension of map is incorrect expecting: {X} but was: {Grid.Count}");
if(Grid[0].Count != Y)
throw new InvalidMapException($"Y Dimension of map is incorrect expecting: {Y} but was: {Grid[0].Count}");
foreach (var row in Grid)
{
foreach (var x in row)
{
if(x > 5 || x < -5)
throw new InvalidMapException($"Map values must be between (-5,5) but value {x} was found.");
}
}
}
}
}

View File

@@ -0,0 +1,22 @@
using System.IO;
using BattleFieldSimulator.FileSystem;
using BattleFieldSimulator.JsonSerialization;
using static BattleFieldSimulator.FileSystem.FileSystemConstants;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class MapLoader : IMapLoader
{
private readonly IJsonSerializer _jsonSerializer;
public MapLoader(IJsonSerializer jsonSerializer)
{
_jsonSerializer = jsonSerializer;
}
public IMap LoadMap(string mapName)
{
return _jsonSerializer.Deserialize(Path.Combine(MapLocation, mapName)).GetMap("Map");
}
}
}

View File

@@ -0,0 +1,17 @@
using System.Reflection;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public struct EffectivenessRatios
{
public const double Aggressiveness = .275;
public const double Size = .4;
public const double MarksmanShip = .3;
public const double Defense = .225;
public const double MovementSpeed = -.2;
}
}

View File

@@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class ITroop
{
int SightDistance { get;}
int EngagementDistance { get;}
int TroopCount { get; }
double MovementSpeed { get; }
double WeaponDamage { get; }
double Marksmanship { get; }
double Aggressiveness { get; }
double Defense { get; }
Queue<Point> AssistanceQueue { get; }
Point Objective { get; }
double CurrentSpeed { get; set; }
List<Troop> IdentifiedEnemy { get; }
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public interface ITroopLoader
{
List<Troop> LoadAllies(string troopFile);
List<Troop> LoadAdversaries(string troopFile);
}
}

View File

@@ -0,0 +1,15 @@
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
[JsonConverter(typeof(StringEnumConverter))]
public enum Mission
{
[EnumMember(Value = "Attack")]
Attack = 1,
[EnumMember(Value = "Defend")]
Defend = 0
}
}

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.Reflection;
using BattleFieldSimulator.Exceptions;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class Troop
{
public int SightDistance { get; }
public int EngagementDistance { get; }
public int TroopCount { get; }
public Mission Mission { get; }
public Point Location { get; }
public double MovementSpeed { get; }
public double WeaponDamage { get; }
public double Marksmanship { get; }
public double Aggressiveness { get; }
public double Defense { get; }
public List<Point> AssistanceQueue { get; }
public Point Objective { get; }
public double CurrentSpeed { get; set; }
public List<Troop> IdentifiedEnemy { get; }
public int Fatalities { get; set; }
public Troop
(
double movementSpeed,
int sightDistance,
int engagementDistance,
double weaponDamage,
double marksmanship,
int troopCount,
double aggressiveness,
double defense,
string mission,
Point point,
Point objective
)
{
SightDistance = sightDistance;
EngagementDistance = engagementDistance;
TroopCount = troopCount;
MovementSpeed = movementSpeed;
WeaponDamage = weaponDamage;
Marksmanship = marksmanship;
Aggressiveness = aggressiveness;
Defense = defense;
var missionM = mission == "Attack" ? Mission.Attack : Mission.Defend;
Mission = missionM;
Location = point;
CurrentSpeed = 0;
AssistanceQueue = new List<Point>();
Objective = objective;
IdentifiedEnemy = new List<Troop>();
Fatalities = 0;
ValidateTroop();
}
private void ValidateTroop()
{
if(SightDistance > 10 || SightDistance < 0)
throw new InvalidTroopException($"SightDistance must be between (1,10) but was: {SightDistance}");
if(EngagementDistance > 10 || EngagementDistance < 0)
throw new InvalidTroopException($"EngagementDistance must be between (1,10) but was: {EngagementDistance}");
if(MovementSpeed > 10 || MovementSpeed < 0)
throw new InvalidTroopException($"MovementSpeed must be between (0,10) but was: {MovementSpeed}");
if(WeaponDamage > 10 || WeaponDamage < 0)
throw new InvalidTroopException($"WeaponDamage must be between (1,10) but was: {WeaponDamage}");
if(Marksmanship > 10 || Marksmanship < 0)
throw new InvalidTroopException($"Marksmanship must be between (1,10) but was: {Marksmanship}");
if(Aggressiveness > 10 || Aggressiveness < 1)
throw new InvalidTroopException($"Aggressiveness must be between (1,10) but was: {Aggressiveness}");
if(Defense > 10 || Defense < 0)
throw new InvalidTroopException($"Defense must be between (1,10) but was: {Defense}");
if(TroopCount<=0)
throw new InvalidTroopException($"TroopCount must be greater than 0 but was: {TroopCount}");
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.IO;
using BattleFieldSimulator.FileSystem;
using BattleFieldSimulator.JsonSerialization;
using static BattleFieldSimulator.FileSystem.FileSystemConstants;
namespace BattleFieldSimulator.BattlefieldEnvironment
{
public class TroopLoader : ITroopLoader
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
public TroopLoader(IJsonSerializer jsonSerializer, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_fileSystem = fileSystem;
}
public List<Troop> LoadAllies(string troopFile)
{
var troops = _jsonSerializer.Deserialize(Path.Combine(TroopFileLocation, troopFile)).GetTroop("Allies");
return troops;
}
public List<Troop> LoadAdversaries(string troopFile)
{
var troops = _jsonSerializer.Deserialize(Path.Combine(TroopFileLocation, troopFile)).GetTroop("Adversaries");
return troops;
}
}
}

View File

@@ -31,7 +31,7 @@ namespace BattleFieldSimulator.ConsoleClient
PrintHelpMenu();
break;
case "-r":
_simRunner.RunSimulation();
_simRunner.RunSimulation("SimpleMap.json", "SimpleTroopFile.json");
break;
default:
return;

View File

@@ -1,3 +1,6 @@
using BattleFieldSimulator.BattlefieldEnvironment;
using BattleFieldSimulator.FileSystem;
using BattleFieldSimulator.JsonSerialization;
using BattleFieldSimulator.SimRunner;
using DryIoc;
@@ -7,7 +10,17 @@ namespace BattleFieldSimulator
{
public void Register(IContainer container)
{
container.Register<ISimRunner, SimRunner.SimRunner>();
container.Register<ISimRunner, SimRunner.SimRunner>(Reuse.Singleton);
container.Register<IMapLoader, MapLoader>(Reuse.Singleton);
container.Register<IFileSystem, FileSystem.FileSystem>(Reuse.Singleton);
container.Register<IEnvironmentFactory, EnvironmentFactory>(Reuse.Singleton);
container.Register<IEnvironmentSetup, EnvironmentSetup>(Reuse.Singleton);
container.Register<IJsonSerializer, JsonSerializer>(Reuse.Singleton);
container.Register<ITroopLoader, TroopLoader>(Reuse.Singleton);
container.Register<ISimulation, Simulation>(Reuse.Singleton);
// container.Register<>(Reuse.Singleton);
}
public void Resolve(IContainer container)

View File

@@ -0,0 +1,11 @@
namespace BattleFieldSimulator.Exceptions
{
public class InvalidMapException : BattleFieldException
{
public InvalidMapException(string message) : base(message)
{
}
public override string Explanation { get; }
}
}

View File

@@ -0,0 +1,11 @@
namespace BattleFieldSimulator.Exceptions
{
public class InvalidTroopException : BattleFieldException
{
public InvalidTroopException(string message) : base(message)
{
}
public override string Explanation { get; }
}
}

View File

@@ -1,11 +1,20 @@
using static System.IO.Path;
using static System.Environment.SpecialFolder;
using static System.Environment;
using static System.Reflection.Assembly;
namespace BattleFieldSimulator.FileSystem
{
public static class FileSystemConstants
{
public static readonly string ExecutionDirectory =
GetDirectoryName(GetExecutingAssembly().Location);
public static readonly string BattleFieldSimulatorDirectory =
Combine(GetFolderPath(LocalApplicationData), "BattleFieldSimulator");
public static readonly string LogDirectory =
Combine(GetFolderPath(CommonDocuments), "BattlefieldSimulator", "Logs");
public static readonly string TroopFileLocation =
Combine(ExecutionDirectory, "troops");
public static readonly string MapLocation =
Combine(ExecutionDirectory, "maps");
}
}

View File

@@ -1,7 +1,13 @@
using System.Collections.Generic;
using BattleFieldSimulator.BattlefieldEnvironment;
namespace BattleFieldSimulator.JsonSerialization
{
public interface IJsonObject
{
IEnumerable<IJsonObject> GetJsonArray(string dataIdentifier);
Map GetMap(string dataIdentifier);
List<Troop> GetTroop(string dataIdentifier);
}
}

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using BattleFieldSimulator.BattlefieldEnviornment;
using BattleFieldSimulator.BattlefieldEnvironment;
using BattleFieldSimulator.Exceptions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BattleFieldSimulator.JsonSerialization
@@ -41,10 +41,40 @@ namespace BattleFieldSimulator.JsonSerialization
return (Map) null;
var x = jArray["X"].Value<int>();
var y = jArray["Y"].Value<int>();
var grid = GetJsonArray("map");
var grid = JsonConvert.DeserializeObject<List<List<int>>>(jArray["Grid"].ToString());
return new Map(x, y, grid);
});
public List<Troop> GetTroop(string dataIdentifier) => GetData<JToken, List<Troop>>(dataIdentifier, jArray =>
{
var r_List = new List<Troop>();
if (!jArray.Any())
return null;
foreach (var token in jArray.Children())
{
var troop = token["Troop"];
var movementSpeed = troop["MovementSpeed"].Value<double>();
var sightDistance = troop["SightDistance"].Value<int>();
var engagementDistance = troop["EngagementDistance"].Value<int>();
var troopCount = troop["TroopCount"].Value<int>();
var marksmanship = troop["Marksmanship"].Value<double>();
var weaponDamage = troop["WeaponDamage"].Value<double>();
var aggressiveness = troop["Aggressiveness"].Value<double>();
var defense = troop["Defense"].Value<double>();
var mission = troop["Mission"].Value<string>();
var entryPointX = troop["EntryPointX"].Value<int>();
var entryPointY = troop["EntryPointY"].Value<int>();
var point = new Point(entryPointX, entryPointY);
var objectiveX = troop["ObjectiveX"].Value<int>();
var objectiveY = troop["ObjectiveY"].Value<int>();
var objective = new Point(objectiveX, objectiveY);
var r_troop = new Troop(movementSpeed, sightDistance, engagementDistance, weaponDamage, marksmanship,
troopCount, aggressiveness, defense, mission, point, objective);
r_List.Add(r_troop);
}
return r_List;
});
private T2 GetData<T1, T2>(string dataIdentifier, Func<T1, T2> convertFunc)
{
if (_jObject.ContainsKey(dataIdentifier))

View File

@@ -1,4 +1,5 @@
using BattleFieldSimulator.SimRunner;
using System;
using BattleFieldSimulator.SimRunner;
namespace BattleFieldSimulator
{
@@ -9,7 +10,14 @@ namespace BattleFieldSimulator
var bootstrapper = BootStrapper.BootstrapSystem(new CoreModule());
var simRunner = bootstrapper.Resolve<ISimRunner>();
var consoleClient = new ConsoleClient.ConsoleClient(simRunner);
consoleClient.Run(args);
try
{
consoleClient.Run(args);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}

View File

@@ -2,6 +2,6 @@ namespace BattleFieldSimulator.SimRunner
{
public interface ISimRunner
{
void RunSimulation();
void RunSimulation(string mapName, string troopFile);
}
}

View File

@@ -0,0 +1,9 @@
using BattleFieldSimulator.BattlefieldEnvironment;
namespace BattleFieldSimulator.SimRunner
{
public interface ISimulation
{
void Run(IEnvironment environment);
}
}

View File

@@ -1,15 +1,30 @@
using System;
using BattleFieldSimulator.BattlefieldEnvironment;
using DryIoc;
using Environment = BattleFieldSimulator.BattlefieldEnvironment.Environment;
namespace BattleFieldSimulator.SimRunner
{
public class SimRunner : ISimRunner
{
public SimRunner()
private readonly IEnvironmentSetup _environmentSetup;
private readonly ISimulation _simulation;
public SimRunner(IEnvironmentSetup environmentSetup, ISimulation simulation)
{
_environmentSetup = environmentSetup;
_simulation = simulation;
}
public void RunSimulation()
public void RunSimulation(string mapName, string troopFile)
{
throw new System.NotImplementedException();
var environment = Setup(mapName, troopFile);
_simulation.Run(environment);
}
private Environment Setup(string mapName, string troopFile)
{
return _environmentSetup.Setup(mapName, troopFile);
}
}
}

View File

@@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Schema;
using BattleFieldSimulator.BattlefieldEnvironment;
using BattleFieldSimulator.FileSystem;
namespace BattleFieldSimulator.SimRunner
{
public class Simulation : ISimulation
{
public Simulation()
{
}
public void Run(IEnvironment environment)
{
var finished = false;
while (!finished)
{
RunRound(environment);
finished = CheckIfFinished(environment.Allies, environment.Adversaries);
}
}
private void RunRound(IEnvironment environment)
{
var map = environment.Map;
var allies = environment.Allies;
var adversaries = environment.Adversaries;
foreach (var troop in allies)
LookAround(troop, map, adversaries);
foreach (var troop in adversaries)
LookAround(troop, map, allies);
CheckCallForHelp(allies, adversaries);
var nextTurn = false;
var current = 0;
while (!nextTurn)
{
if (current >= allies.Count && current >= adversaries.Count)
nextTurn = true;
if (current < allies.Count)
Attack(allies[current], allies[current].IdentifiedEnemy);
if (current < adversaries.Count)
Attack(adversaries[current], adversaries[current].IdentifiedEnemy);
if (current < allies.Count)
if (allies[current].TroopCount == allies[current].Fatalities)
allies.Remove(allies[current]);
if (current < adversaries.Count)
if (adversaries[current].TroopCount == adversaries[current].Fatalities)
adversaries.Remove(adversaries[current]);
current++;
}
}
private void CheckCallForHelp(List<Troop> allies, List<Troop> adversaries)
{
foreach (var eTroop in from ally in allies from eTroop in ally.IdentifiedEnemy where CalculateAttackValues(eTroop, ally)>CalculateAttackValues(ally, eTroop) select eTroop)
{
CallForHelp(eTroop.Location, allies);
}
foreach (var eTroop in from adversary in adversaries from eTroop in adversary.IdentifiedEnemy where CalculateAttackValues(eTroop, adversary)>CalculateAttackValues(adversary, eTroop) select eTroop)
{
CallForHelp(eTroop.Location, adversaries);
}
}
private void CallForHelp(Point eTroopLocation, List<Troop> teams)
{
foreach (var teamMember in teams.Where(teamMember => !teamMember.AssistanceQueue.Contains(eTroopLocation)))
{
teamMember.AssistanceQueue.Add(eTroopLocation);
}
}
private void LookAround(Troop troop, IMap map, List<Troop> enemy)
{
var enterX = 0;
var enterY = 0;
var stopX = 0;
var stopY = 0;
//Calculate first point.
if (troop.Location.X - troop.SightDistance < 0)
enterX = 0;
else
enterX = troop.Location.X - troop.SightDistance;
if (troop.Location.Y - troop.SightDistance < 0)
enterY = 0;
else
enterY = troop.Location.Y - troop.SightDistance;
//Calculate last point
if (troop.Location.X + troop.SightDistance > map.X)
stopX = map.X;
else
stopX = troop.Location.X + troop.SightDistance;
if (troop.Location.Y + troop.SightDistance > map.Y)
stopY = map.Y;
else
stopY = troop.Location.Y + troop.SightDistance;
var nearbyTroops = new List<Troop>();
var adjustedTroopSight = CalculateTrueSightDistance(troop);
for (var x = enterX; x < stopX; x++)
{
for (var y = enterY; y < stopY; y++)
{
var currentCell = new Point(x, y);
if (Distance(troop.Location, currentCell) < adjustedTroopSight)
nearbyTroops.AddRange(enemy.Where(q =>
q.Location.X == currentCell.X && q.Location.Y == currentCell.Y).ToList());
}
}
troop.IdentifiedEnemy.AddRange(VerifyTroopSighting(nearbyTroops, troop, map));
}
private double CalculateTrueSightDistance(Troop troop)
{
if (troop.CurrentSpeed == 0)
return troop.SightDistance;
var sightDeprecation = troop.MovementSpeed / troop.CurrentSpeed;
return troop.SightDistance * sightDeprecation;
}
private List<Troop> VerifyTroopSighting(List<Troop> enemyTroops, Troop troop, IMap map)
{
var returnList = new List<Troop>();
foreach (var enemy in enemyTroops)
{
var x = Math.Min(troop.Location.X, enemy.Location.X);
var y = Math.Min(troop.Location.Y, enemy.Location.Y);
var done = false;
var canSee = true;
while (!done)
{
var startX = x;
var startY = y;
if (map.Grid[x][y] > map.Grid[troop.Location.X][troop.Location.Y] + 2)
canSee = false;
if (x < Math.Max(troop.Location.X, enemy.Location.X))
x++;
if (y < Math.Max(troop.Location.Y, enemy.Location.Y))
y++;
if (startX == x && startY == y)
done = true;
}
if (canSee)
returnList.Add(enemy);
}
return returnList;
}
private void Attack(Troop troop, List<Troop> enemy)
{
if (troop.TroopCount == troop.Fatalities)
return;
var r = new Random();
//Each troop can only engage one enemy
var troopsInEngagement = 0;
for(var i = 0; i < enemy.Count; i++)
{
var e = enemy[i];
var attack = CalculateAttackValues(troop, e);
if (e.TroopCount != e.Fatalities)
{
var startTroopsInEngagement = troopsInEngagement;
var startingEnemyCount = e.TroopCount - e.Fatalities;
var nextEngage = false;
while (!nextEngage)
{
troopsInEngagement++;
if (NextBool(r, attack * 100))
e.Fatalities++;
if (troopsInEngagement - startTroopsInEngagement == startingEnemyCount && i < enemy.Count)
nextEngage = true;
}
}
}
}
private double CalculateAttackValues(Troop troop, Troop enemy)
{
var strengthList = new List<double>();
if(enemy.TroopCount-enemy.Fatalities != 0)
strengthList.Add((troop.TroopCount-troop.Fatalities) / (enemy.TroopCount-enemy.Fatalities)*EffectivenessRatios.Size);
else
strengthList.Add((troop.TroopCount - troop.Fatalities) / double.MinValue*EffectivenessRatios.Size);
strengthList.Add(troop.Aggressiveness / enemy.Aggressiveness*EffectivenessRatios.Aggressiveness);
strengthList.Add(troop.Marksmanship / enemy.Marksmanship*EffectivenessRatios.MarksmanShip);
if (enemy.CurrentSpeed != 0)
strengthList.Add(troop.CurrentSpeed / enemy.CurrentSpeed*EffectivenessRatios.MovementSpeed);
else
strengthList.Add(troop.CurrentSpeed/double.MinValue*EffectivenessRatios.MovementSpeed);
strengthList.Add(troop.Defense/enemy.Defense*EffectivenessRatios.Defense);
return Math.Abs(1-1/strengthList.Sum());
}
private static bool NextBool(Random r, double truePercentage = 50) =>
r.NextDouble() < truePercentage / 100.0;
private double Distance(Point p1, Point p2) =>
Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
private bool CheckIfFinished(List<Troop> environmentAllies, List<Troop> environmentAdversaries) =>
environmentAdversaries.Count == 0 || environmentAllies.Count == 0;
}
}

View File

@@ -0,0 +1,18 @@
{
"Map": {
"X": "10",
"Y" : "10",
"Grid": [
[0, 0, 0, 0, 0, 0, 0, 5, 5, 0],
[0, 1, 1, 1, 0, 0, 0, 5, 5, 0],
[0, 2, 2, 2, 0, 0, 0, 5, 4, 0],
[0, 2, 3, 2, 0, 0, 0, 4, 3, 0],
[0, 2, 2, 1, 0, 0, 0, 3, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
}
}

View File

@@ -0,0 +1,81 @@
{
"Allies": [
{
"Troop":
{
"MovementSpeed": 1.5,
"SightDistance": 4,
"EngagementDistance": 3,
"WeaponDamage": 8.5,
"Marksmanship": 7,
"TroopCount": 30,
"Aggressiveness": 7,
"Defense": 6,
"Mission": "Defend",
"EntryPointX": 0,
"EntryPointY": 0,
"ObjectiveX": 0,
"ObjectiveY": 0
}
},
{
"Troop":
{
"MovementSpeed": 2.5,
"SightDistance": 2,
"EngagementDistance": 1,
"WeaponDamage": 5,
"Marksmanship": 4,
"TroopCount": 10,
"Aggressiveness": 10,
"Defense": 3,
"Mission": "Defend",
"EntryPointX": 0,
"EntryPointY": 2,
"ObjectiveX": 0,
"ObjectiveY": 0
}
}
],
"Adversaries": [
{
"Troop":
{
"MovementSpeed": 2.5,
"SightDistance": 3,
"EngagementDistance": 1,
"WeaponDamage": 7,
"Marksmanship": 4,
"TroopCount": 10,
"Aggressiveness": 10,
"Defense": 3,
"Mission": "Attack",
"EntryPointX": 1,
"EntryPointY": 1,
"ObjectiveX": 0,
"ObjectiveY": 0
}
},
{
"Troop":
{
"MovementSpeed": 2.5,
"SightDistance": 2,
"EngagementDistance": 1,
"WeaponDamage": 1,
"Marksmanship": 4,
"TroopCount": 15,
"Aggressiveness": 10,
"Defense": 3,
"Mission": "Attack",
"EntryPointX": 2,
"EntryPointY": 7,
"ObjectiveX": 0,
"ObjectiveY": 0
}
}
]
}

View File

@@ -0,0 +1,18 @@
{
"Map": {
"X": "10",
"Y" : "10",
"Grid": [
[0, 0, 0, 0, 0, 0, 0, 5, 5, 0],
[0, 1, 1, 1, 0, 0, 0, 5, 5, 0],
[0, 2, 2, 2, 0, 0, 0, 5, 4, 0],
[0, 2, 3, 2, 0, 0, 0, 4, 3, 0],
[0, 2, 2, 1, 0, 0, 0, 3, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
}
}

View File

@@ -6,3 +6,5 @@
/Users/bradybodily/Repositories/CS5110_Multi_Agent/BattleFieldSimulator/BattleFieldSimulator/bin/Debug/Newtonsoft.Json.dll
/Users/bradybodily/Repositories/CS5110_Multi_Agent/BattleFieldSimulator/BattleFieldSimulator/bin/Debug/Newtonsoft.Json.xml
/Users/bradybodily/Repositories/CS5110_Multi_Agent/BattleFieldSimulator/BattleFieldSimulator/obj/Debug/BattleFieldSimulator.csproj.CopyComplete
/Users/bradybodily/Repositories/CS5110_Multi_Agent/BattleFieldSimulator/BattleFieldSimulator/bin/Debug/maps/SimpleMap.json
/Users/bradybodily/Repositories/CS5110_Multi_Agent/BattleFieldSimulator/BattleFieldSimulator/bin/Debug/troops/SimpleTroopFile.json

View File

@@ -0,0 +1,81 @@
{
"Allies": [
{
"Troop":
{
"MovementSpeed": 1.5,
"SightDistance": 4,
"EngagementDistance": 3,
"WeaponDamage": 8.5,
"Marksmanship": 7,
"TroopCount": 30,
"Aggressiveness": 7,
"Defense": 6,
"Mission": "Defend",
"EntryPointX": 0,
"EntryPointY": 0,
"ObjectiveX": 0,
"ObjectiveY": 0
}
},
{
"Troop":
{
"MovementSpeed": 2.5,
"SightDistance": 2,
"EngagementDistance": 1,
"WeaponDamage": 5,
"Marksmanship": 4,
"TroopCount": 10,
"Aggressiveness": 10,
"Defense": 3,
"Mission": "Defend",
"EntryPointX": 0,
"EntryPointY": 2,
"ObjectiveX": 0,
"ObjectiveY": 0
}
}
],
"Adversaries": [
{
"Troop":
{
"MovementSpeed": 2.5,
"SightDistance": 3,
"EngagementDistance": 1,
"WeaponDamage": 7,
"Marksmanship": 4,
"TroopCount": 10,
"Aggressiveness": 10,
"Defense": 3,
"Mission": "Attack",
"EntryPointX": 1,
"EntryPointY": 1,
"ObjectiveX": 0,
"ObjectiveY": 0
}
},
{
"Troop":
{
"MovementSpeed": 2.5,
"SightDistance": 2,
"EngagementDistance": 1,
"WeaponDamage": 1,
"Marksmanship": 4,
"TroopCount": 15,
"Aggressiveness": 10,
"Defense": 3,
"Mission": "Attack",
"EntryPointX": 2,
"EntryPointY": 7,
"ObjectiveX": 0,
"ObjectiveY": 0
}
}
]
}

View File

@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\DryIoc.4.1.4\build\DryIoc.props" Condition="Exists('..\packages\DryIoc.4.1.4\build\DryIoc.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{35646D97-C2E5-4869-8995-2CB075E0631F}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ConsoleClient</RootNamespace>
<AssemblyName>ConsoleClient</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConsoleClientModule.cs" />
<Compile Include="DryIoc\Container.cs" />
<Compile Include="DryIoc\Expression.cs" />
<Compile Include="DryIoc\FastExpressionCompiler.cs" />
<Compile Include="DryIoc\ImTools.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\DryIoc.4.1.4\build\DryIoc.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\DryIoc.4.1.4\build\DryIoc.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,21 +0,0 @@
using System.ComponentModel;
using DryIoc;
namespace ConsoleClient
{
public class ConsoleClientModule
{
public class CoreModule : IModule
{
public void Register(IContainer container)
{
container.Register<ISimRunner, SimRunner.SimRunner>();
}
public void Resolve(IContainer container)
{
throw new System.NotImplementedException();
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
namespace ConsoleClient
{
internal class Program
{
public static void Main(string[] args)
{
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ConsoleClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ConsoleClient")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("35646D97-C2E5-4869-8995-2CB075E0631F")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DryIoc" version="4.1.4" targetFramework="net472" />
</packages>