diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index 4c7b5b8eb9..58ff4eaf1a 100644 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -22,30 +22,13 @@ using OpenRA.Traits; namespace OpenRA { - public interface IActor - { - ActorInfo Info { get; } - IWorld World { get; } - uint ActorID { get; } - Player Owner { get; set; } - - T TraitOrDefault(); - T Trait(); - IEnumerable TraitsImplementing(); - - IEnumerable Render(WorldRenderer wr); - } - - public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable, IActor + public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable { public readonly ActorInfo Info; - ActorInfo IActor.Info { get { return this.Info; } } public readonly World World; - IWorld IActor.World { get { return World; } } public readonly uint ActorID; - uint IActor.ActorID { get { return this.ActorID; } } [Sync] public Player Owner { get; set; } diff --git a/OpenRA.Game/Map/CellLayer.cs b/OpenRA.Game/Map/CellLayer.cs index fdab4ab374..72c607fd2d 100644 --- a/OpenRA.Game/Map/CellLayer.cs +++ b/OpenRA.Game/Map/CellLayer.cs @@ -24,7 +24,7 @@ namespace OpenRA readonly T[] entries; - public CellLayer(IMap map) + public CellLayer(Map map) : this(map.TileShape, new Size(map.MapSize.X, map.MapSize.Y)) { } public CellLayer(TileShape shape, Size size) diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 94360760b6..eae3e9e1b5 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -111,19 +111,7 @@ namespace OpenRA MissionSelector = 4 } - public interface IMap - { - TileShape TileShape { get; } - - int2 MapSize { get; set; } - bool Contains(CPos cell); - CPos CellContaining(WPos pos); - WVec OffsetOfSubCell(SubCell subCell); - IEnumerable FindTilesInCircle(CPos center, int maxRange); - WPos CenterOfCell(CPos cell); - } - - public class Map : IMap + public class Map { static readonly int[][] CellCornerHalfHeights = new int[][] { @@ -163,10 +151,6 @@ namespace OpenRA public const int MaxTilesInCircleRange = 50; public readonly TileShape TileShape; - TileShape IMap.TileShape - { - get { return TileShape; } - } [FieldLoader.Ignore] public readonly WVec[] SubCellOffsets; public readonly SubCell DefaultSubCell; @@ -243,12 +227,6 @@ namespace OpenRA public int2 MapSize; - int2 IMap.MapSize - { - get { return MapSize; } - set { MapSize = value; } - } - [FieldLoader.Ignore] public Lazy> MapTiles; [FieldLoader.Ignore] public Lazy> MapResources; [FieldLoader.Ignore] public Lazy> MapHeight; diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 43bf359b3f..aab063b763 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -24,15 +24,7 @@ namespace OpenRA { public enum WorldType { Regular, Shellmap } - public interface IWorld - { - IActor WorldActor { get; } - int WorldTick { get; } - IMap Map { get; } - TileSet TileSet { get; } - } - - public class World : IWorld + public class World { class ActorIDComparer : IComparer { @@ -122,13 +114,10 @@ namespace OpenRA } public readonly Actor WorldActor; - IActor IWorld.WorldActor { get { return WorldActor; } } public readonly Map Map; - IMap IWorld.Map { get { return Map; } } public readonly TileSet TileSet; - TileSet IWorld.TileSet { get { return TileSet; } } public readonly ActorMap ActorMap; public readonly ScreenMap ScreenMap; diff --git a/OpenRA.Mods.Common/Pathfinder/CellInfoLayerManager.cs b/OpenRA.Mods.Common/Pathfinder/CellInfoLayerManager.cs index 7745c10b33..5badfe959e 100644 --- a/OpenRA.Mods.Common/Pathfinder/CellInfoLayerManager.cs +++ b/OpenRA.Mods.Common/Pathfinder/CellInfoLayerManager.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.Common.Pathfinder /// /// Creates (or obtains from the pool) a CellLayer given a map /// - CellLayer NewLayer(IMap map); + CellLayer NewLayer(Map map); } public sealed class CellInfoLayerManager : ICellInfoLayerManager @@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Pathfinder cellInfoPool.Enqueue(ci); } - public CellLayer NewLayer(IMap map) + public CellLayer NewLayer(Map map) { CellLayer result = null; var mapSize = new Size(map.MapSize.X, map.MapSize.Y); diff --git a/OpenRA.Mods.Common/Pathfinder/PathCacheStorage.cs b/OpenRA.Mods.Common/Pathfinder/PathCacheStorage.cs index fca898eb36..e39ecd5fae 100644 --- a/OpenRA.Mods.Common/Pathfinder/PathCacheStorage.cs +++ b/OpenRA.Mods.Common/Pathfinder/PathCacheStorage.cs @@ -22,10 +22,10 @@ namespace OpenRA.Mods.Common.Pathfinder } const int MaxPathAge = 50; - readonly IWorld world; + readonly World world; Dictionary cachedPaths = new Dictionary(100); - public PathCacheStorage(IWorld world) + public PathCacheStorage(World world) { this.world = world; } diff --git a/OpenRA.Mods.Common/Pathfinder/PathFinderCacheDecorator.cs b/OpenRA.Mods.Common/Pathfinder/PathFinderCacheDecorator.cs index 2f6bc396ba..96b7bde3f6 100644 --- a/OpenRA.Mods.Common/Pathfinder/PathFinderCacheDecorator.cs +++ b/OpenRA.Mods.Common/Pathfinder/PathFinderCacheDecorator.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.Common.Pathfinder this.cacheStorage = cacheStorage; } - public List FindUnitPath(CPos source, CPos target, IActor self) + public List FindUnitPath(CPos source, CPos target, Actor self) { using (new PerfSample("Pathfinder")) { @@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.Pathfinder } } - public List FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WRange range, IActor self) + public List FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WRange range, Actor self) { using (new PerfSample("Pathfinder")) { diff --git a/OpenRA.Mods.Common/Pathfinder/PathGraph.cs b/OpenRA.Mods.Common/Pathfinder/PathGraph.cs index ad139a22af..bdd1177b9c 100644 --- a/OpenRA.Mods.Common/Pathfinder/PathGraph.cs +++ b/OpenRA.Mods.Common/Pathfinder/PathGraph.cs @@ -38,11 +38,11 @@ namespace OpenRA.Mods.Common.Pathfinder bool InReverse { get; set; } - IActor IgnoredActor { get; set; } + Actor IgnoredActor { get; set; } - IWorld World { get; } + World World { get; } - IActor Actor { get; } + Actor Actor { get; } } public struct GraphConnection @@ -61,21 +61,21 @@ namespace OpenRA.Mods.Common.Pathfinder public class PathGraph : IGraph { - public IActor Actor { get; private set; } - public IWorld World { get; private set; } + public Actor Actor { get; private set; } + public World World { get; private set; } public Func CustomBlock { get; set; } public Func CustomCost { get; set; } public int LaneBias { get; set; } public bool InReverse { get; set; } - public IActor IgnoredActor { get; set; } + public Actor IgnoredActor { get; set; } readonly CellConditions checkConditions; - readonly IMobileInfo mobileInfo; + readonly MobileInfo mobileInfo; CellLayer cellInfo; public const int InvalidNode = int.MaxValue; - public PathGraph(CellLayer cellInfo, IMobileInfo mobileInfo, IActor actor, IWorld world, bool checkForBlocked) + public PathGraph(CellLayer cellInfo, MobileInfo mobileInfo, Actor actor, World world, bool checkForBlocked) { this.cellInfo = cellInfo; World = world; diff --git a/OpenRA.Mods.Common/Pathfinder/PathSearch.cs b/OpenRA.Mods.Common/Pathfinder/PathSearch.cs index 37cc477ca9..e1ecf22b06 100644 --- a/OpenRA.Mods.Common/Pathfinder/PathSearch.cs +++ b/OpenRA.Mods.Common/Pathfinder/PathSearch.cs @@ -32,13 +32,13 @@ namespace OpenRA.Mods.Common.Pathfinder considered = new LinkedList>(); } - public static IPathSearch Search(IWorld world, IMobileInfo mi, IActor self, bool checkForBlocked) + public static IPathSearch Search(World world, MobileInfo mi, Actor self, bool checkForBlocked) { var graph = new PathGraph(CellInfoLayerManager.Instance.NewLayer(world.Map), mi, self, world, checkForBlocked); return new PathSearch(graph); } - public static IPathSearch FromPoint(IWorld world, IMobileInfo mi, IActor self, CPos from, CPos target, bool checkForBlocked) + public static IPathSearch FromPoint(World world, MobileInfo mi, Actor self, CPos from, CPos target, bool checkForBlocked) { var graph = new PathGraph(CellInfoLayerManager.Instance.NewLayer(world.Map), mi, self, world, checkForBlocked); var search = new PathSearch(graph) @@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.Pathfinder return search; } - public static IPathSearch FromPoints(IWorld world, IMobileInfo mi, IActor self, IEnumerable froms, CPos target, bool checkForBlocked) + public static IPathSearch FromPoints(World world, MobileInfo mi, Actor self, IEnumerable froms, CPos target, bool checkForBlocked) { var graph = new PathGraph(CellInfoLayerManager.Instance.NewLayer(world.Map), mi, self, world, checkForBlocked); var search = new PathSearch(graph) diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 78dc552ee2..28c69392ac 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -29,16 +29,8 @@ namespace OpenRA.Mods.Common.Traits All = TransientActors | BlockedByMovers } - public interface IMobileInfo : IMoveInfo - { - int MovementCostForCell(World world, CPos cell); - bool CanEnterCell(World world, Actor self, CPos cell, out int movementCost, Actor ignoreActor = null, CellConditions check = CellConditions.All); - bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, CellConditions check = CellConditions.All); - int GetMovementClass(TileSet tileset); - } - [Desc("Unit is able to move.")] - public class MobileInfo : IMobileInfo, IOccupySpaceInfo, IFacingInfo, UsesInit, UsesInit, UsesInit + public class MobileInfo : IMoveInfo, IOccupySpaceInfo, IFacingInfo, UsesInit, UsesInit, UsesInit { [FieldLoader.LoadUsing("LoadSpeeds")] [Desc("Set Water: 0 for ground units and lower the value on rough terrain.")] diff --git a/OpenRA.Mods.Common/Traits/World/PathFinder.cs b/OpenRA.Mods.Common/Traits/World/PathFinder.cs index 1dc1e7c29b..332aaa6b12 100644 --- a/OpenRA.Mods.Common/Traits/World/PathFinder.cs +++ b/OpenRA.Mods.Common/Traits/World/PathFinder.cs @@ -32,9 +32,9 @@ namespace OpenRA.Mods.Common.Traits /// Calculates a path for the actor from source to destination /// /// A path from start to target - List FindUnitPath(CPos source, CPos target, IActor self); + List FindUnitPath(CPos source, CPos target, Actor self); - List FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WRange range, IActor self); + List FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WRange range, Actor self); /// /// Calculates a path given a search specification @@ -52,16 +52,16 @@ namespace OpenRA.Mods.Common.Traits public class PathFinder : IPathFinder { static readonly List EmptyPath = new List(0); - readonly IWorld world; + readonly World world; - public PathFinder(IWorld world) + public PathFinder(World world) { this.world = world; } - public List FindUnitPath(CPos source, CPos target, IActor self) + public List FindUnitPath(CPos source, CPos target, Actor self) { - var mi = self.Info.Traits.Get(); + var mi = self.Info.Traits.Get(); // If a water-land transition is required, bail early var domainIndex = world.WorldActor.TraitOrDefault(); @@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Traits return pb; } - public List FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WRange range, IActor self) + public List FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WRange range, Actor self) { var mi = self.Info.Traits.Get(); var targetCell = world.Map.CellContaining(target); diff --git a/OpenRA.Test/Fakes.cs b/OpenRA.Test/Fakes.cs deleted file mode 100644 index c86e2058d4..0000000000 --- a/OpenRA.Test/Fakes.cs +++ /dev/null @@ -1,206 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using OpenRA.Mods.Common.Traits; - -namespace OpenRA.Test -{ - public class FakeActor : IActor - { - IWorld world; - - public ActorInfo Info - { - get { throw new NotImplementedException("No need to implement this yet"); } - } - - public IWorld World - { - get { return world; } - } - - public uint ActorID - { - get { return 1; } - } - - public Player Owner - { - get { return null; } - set { } - } - - public T TraitOrDefault() - { - return default(T); - } - - public T Trait() - { - return default(T); - } - - public IEnumerable TraitsImplementing() - { - throw new NotImplementedException("No need to implement this yet"); - } - - public T TraitInfo() - { - return default(T); - } - - public IEnumerable Render(Graphics.WorldRenderer wr) - { - throw new NotImplementedException("No need to implement this yet"); - } - - public FakeActor(IWorld world) - { - // TODO: Complete member initialization - this.world = world; - } - - public FakeActor() - { - // TODO: Complete member initialization - } - } - - public class FakeWorld : IWorld - { - FakeActor worldactor; - IMap map; - - public IActor WorldActor - { - get { return worldactor; } - } - - public int WorldTick - { - get { return 50; } - } - - public IMap Map - { - get { return map; } - } - - public TileSet TileSet - { - get { throw new NotImplementedException("No need to implement this yet"); } - } - - public FakeWorld(IMap map) - { - // TODO: Complete member initialization - this.map = map; - } - - public FakeWorld(IMap map, FakeActor worldactor) - { - // TODO: Complete member initialization - this.map = map; - this.worldactor = worldactor; - } - } - - public class FakeMobileInfo : IMobileInfo - { - Func conditions; - - public int MovementCostForCell(World world, CPos cell) - { - if (conditions(cell)) - return 125; - return int.MaxValue; - } - - public bool CanEnterCell(World world, Actor self, CPos cell, out int movementCost, Actor ignoreActor = null, CellConditions check = CellConditions.All) - { - movementCost = MovementCostForCell(world, cell); - return conditions(cell); - } - - public int GetMovementClass(TileSet tileset) - { - throw new NotImplementedException("No need to implement this yet"); - } - - public FakeMobileInfo(Func conditions) - { - this.conditions = conditions; - } - - public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, CellConditions check = CellConditions.All) - { - return conditions(cell); - } - - public object Create(ActorInitializer init) - { - throw new NotImplementedException(); - } - } - - public class FakeMap : IMap - { - int width; - int height; - - public FakeMap(int width, int height) - { - // TODO: Complete member initialization - this.width = width; - this.height = height; - } - - public TileShape TileShape - { - get { return TileShape.Rectangle; } - } - - public int2 MapSize - { - get { return new int2(width, height); } - set { throw new NotImplementedException("No need to implement this yet"); } - } - - public bool Contains(CPos cell) - { - return cell.X >= 0 && cell.X < width && cell.Y >= 0 && cell.Y < height; - } - - public CPos CellContaining(WPos pos) - { - throw new NotImplementedException("No need to implement this yet"); - } - - public WVec OffsetOfSubCell(Traits.SubCell subCell) - { - throw new NotImplementedException("No need to implement this yet"); - } - - public IEnumerable FindTilesInCircle(CPos center, int maxRange) - { - throw new NotImplementedException("No need to implement this yet"); - } - - public WPos CenterOfCell(CPos cell) - { - throw new NotImplementedException("No need to implement this yet"); - } - } -} diff --git a/OpenRA.Test/OpenRA.Test.csproj b/OpenRA.Test/OpenRA.Test.csproj index 1fb738326f..1de6db7b34 100644 --- a/OpenRA.Test/OpenRA.Test.csproj +++ b/OpenRA.Test/OpenRA.Test.csproj @@ -45,12 +45,10 @@ - - diff --git a/OpenRA.Test/PathfinderTests.cs b/OpenRA.Test/PathfinderTests.cs deleted file mode 100644 index 11eac1175c..0000000000 --- a/OpenRA.Test/PathfinderTests.cs +++ /dev/null @@ -1,269 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Linq; -using Moq; -using NUnit.Framework; -using OpenRA; -using OpenRA.Mods.Common.Pathfinder; -using OpenRA.Mods.Common.Traits; -using OpenRA.Test; - -namespace PathfinderTests -{ - [TestFixture] - public class PathfinderTests - { - const int Width = 128; - const int Height = 128; - IWorld world; - IMap map; - IActor actor; - - [SetUp] - public void Setup() - { - map = new FakeMap(Width, Height); - var worldactor = new FakeActor(); - world = new FakeWorld(map, worldactor); - actor = new FakeActor(world); - } - - IMap BuildFakeMap(int mapWidth, int mapHeight) - { - var map = new Mock(); - map.SetupGet(m => m.TileShape).Returns(TileShape.Rectangle); - map.Setup(m => m.MapSize).Returns(new int2(mapWidth, mapHeight)); - map.Setup(m => m.Contains(It.Is(pos => pos.X >= 0 && pos.X < mapWidth && pos.Y >= 0 && pos.Y < mapHeight))).Returns(true); - - return map.Object; - } - - IWorld BuildFakeWorld(IMap map) - { - var world = new Mock(); - world.SetupGet(m => m.Map).Returns(map); - world.SetupGet(m => m.WorldActor).Returns(new Mock().Object); - return world.Object; - } - - static bool IsValidPos(CPos pos, int mapWidth, int mapHeight) - { - return pos.X >= 0 && pos.X < mapWidth && pos.Y >= 0 && pos.Y < mapHeight; - } - - [Test] - [Ignore] - public void FindPathOnRoughTerrainTest() - { - // Arrange - - // Create the MobileInfo Mock. Playing with this can help to - // check the different paths and points a unit can walk into - var mi = new FakeMobileInfo(pos => !(!IsValidPos(pos, Width, Height) || - (pos.X == 50 && pos.Y < 100) || - (pos.X == 100 && pos.Y > 50))); - - var from = new CPos(1, 1); - var target = new CPos(125, 75); - - IPathSearch search; - Stopwatch stopwatch; - List path5 = null; - List path6 = null; - List path7 = null; - List path8 = null; - var pathfinder = new PathFinder(world); - - // Act - stopwatch = new Stopwatch(); - foreach (var a in Enumerable.Range(1, 50)) - { - search = PathSearch.FromPoint(world, mi, actor, from, target, true); - stopwatch.Start(); - path5 = pathfinder.FindPath(search); - - stopwatch.Stop(); - search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(51, 100), true); - stopwatch.Start(); - path6 = pathfinder.FindPath(search); - - stopwatch.Stop(); - search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(49, 50), true); - stopwatch.Start(); - path7 = pathfinder.FindPath(search); - - stopwatch.Stop(); - search = PathSearch.FromPoint(world, mi, actor, new CPos(127, 0), new CPos(50, 101), true); - stopwatch.Start(); - path8 = pathfinder.FindPath(search); - } - - Console.WriteLine("I took " + stopwatch.ElapsedMilliseconds + " ms with new pathfinder"); - - IPathSearch search2; - stopwatch = new Stopwatch(); - foreach (var a in Enumerable.Range(1, 50)) - { - search = PathSearch.FromPoint(world, mi, actor, from, target, true); - search2 = PathSearch.FromPoint(world, mi, actor, target, from, true).Reverse(); - stopwatch.Start(); - path5 = pathfinder.FindBidiPath(search, search2); - - stopwatch.Stop(); - search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(51, 100), true); - search2 = PathSearch.FromPoint(world, mi, actor, new CPos(51, 100), new CPos(0, 0), true).Reverse(); - stopwatch.Start(); - path6 = pathfinder.FindBidiPath(search, search2); - - stopwatch.Stop(); - search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(49, 50), true); - search2 = PathSearch.FromPoint(world, mi, actor, new CPos(49, 50), new CPos(0, 0), true).Reverse(); - stopwatch.Start(); - path7 = pathfinder.FindBidiPath(search, search2); - - stopwatch.Stop(); - search = PathSearch.FromPoint(world, mi, actor, new CPos(127, 0), new CPos(50, 101), true); - search2 = PathSearch.FromPoint(world, mi, actor, new CPos(50, 101), new CPos(127, 0), true).Reverse(); - stopwatch.Start(); - path8 = pathfinder.FindBidiPath(search, search2); - } - - Console.WriteLine("I took " + stopwatch.ElapsedMilliseconds + " ms with new FindBidipathfinder"); - } - - /// - /// We can't rely on floating point math to be deterministic across all runtimes. - /// The cases that use this will need to be changed to use integer math - /// - public const double Sqrt2 = 1.414; - - static int Est1(CPos here, CPos destination) - { - var diag = Math.Min(Math.Abs(here.X - destination.X), Math.Abs(here.Y - destination.Y)); - var straight = Math.Abs(here.X - destination.X) + Math.Abs(here.Y - destination.Y); - - // Min cost to arrive from once cell to an adjacent one - // (125 according to tests) - const int D = 100; - - // According to the information link, this is the shape of the function. - // We just extract factors to simplify. - var h = D * straight + (D * Sqrt2 - 2 * D) * diag; - - return (int)(h * 1.001); - } - - static int Est2(CPos here, CPos destination) - { - var diag = Math.Min(Math.Abs(here.X - destination.X), Math.Abs(here.Y - destination.Y)); - var straight = Math.Abs(here.X - destination.X) + Math.Abs(here.Y - destination.Y); - - // HACK: this relies on fp and cell-size assumptions. - var h = (100 * diag * Sqrt2) + 100 * (straight - (2 * diag)); - return (int)(h * 1.001); - } - - /// - /// Tests the refactor of the default heuristic for pathFinder - /// - [Test] - public void EstimatorsTest() - { - Assert.AreEqual(Est1(new CPos(0, 0), new CPos(20, 30)), Est2(new CPos(0, 0), new CPos(20, 30))); - } - - [Test] - public void Remove1000StoredPaths() - { - var world = new Mock(); - world.SetupGet(m => m.WorldTick).Returns(50); - var pathCacheStorage = new PathCacheStorage(world.Object); - var stopwatch = new Stopwatch(); - for (var i = 0; i < 1100; i++) - { - if (i == 100) - { - // Let's make the world tick further so we can trigger the removals - // when storing more stuff - world.SetupGet(m => m.WorldTick).Returns(110); - stopwatch.Start(); - } - - pathCacheStorage.Store(i.ToString(), new List()); - if (i == 100) - { - stopwatch.Stop(); - Console.WriteLine("I took " + stopwatch.ElapsedMilliseconds + " ms to remove 1000 stored paths"); - } - } - } - - /// - /// Test for the future feature of path smoothing for Pathfinder - /// - [Test] - public void RayCastingTest() - { - // Arrange - var sut = new RayCaster(); - CPos source = new CPos(1, 3); - CPos target = new CPos(3, 0); - - // Act - var valid = sut.RayCast(source, target); - - // Assert - } - } - - public class RayCaster - { - // Algorithm obtained in http://playtechs.blogspot.co.uk/2007/03/raytracing-on-grid.html - public IEnumerable RayCast(CPos source, CPos target) - { - int dx = Math.Abs(target.X - source.X); - int dy = Math.Abs(target.Y - source.Y); - int x = source.X; - int y = source.Y; - - int x_inc = (target.X > source.X) ? 1 : -1; - int y_inc = (target.Y > source.Y) ? 1 : -1; - int error = dx - dy; - dx *= 2; - dy *= 2; - - for (int n = 1 + dx + dy; n > 0; --n) - { - yield return new CPos(x, y); - - if (error > 0) - { - x += x_inc; - error -= dy; - } - else - { - y += y_inc; - error += dx; - } - } - } - - public bool RayClear() - { - return true; - } - } -}