glav avatar glav committed 51832b1

Fixing up movement engine and also adjusted player logic to make a half smart test player

Comments (0)

Files changed (14)

EcoDev.Core/Common/BaseEntity.cs

 		public string Name { get; set; }
 		public Guid LifeKey { get; set; }
 		public abstract EntityBaseType EntityType { get; }
-		public IWorld World { get; set; }
+		public IInhabitantWorld World { get; set; }
 
 		public EntitySize Size { get; set; }
 		public EntityMaterial CompositionMaterial { get; set; }

EcoDev.Core/Common/BuildingBlocks/PlayerOccupiedBlock.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EcoDev.Core.Common.Maps;
+
+namespace EcoDev.Core.Common.BuildingBlocks
+{
+	public class PlayerOccupiedBlock : MapBlock
+	{
+		public override MapBlockAccessibility Accessibility
+		{
+			get { return MapBlockAccessibility.CannotGainEntryOrExit; }
+		}
+	}
+}

EcoDev.Core/Common/IWorld.cs

 
 namespace EcoDev.Core.Common
 {
-	// This is the interface available to a player so ensure we dont allow anything too visible in the 
-	// world to be available
-	public interface IWorld
+	// This is the interface available to a player/inhabitant so ensure we dont allow anything too visible in the 
+	// world to be available. It is their "window" on the world and is a subset of the
+	// full world.
+	public interface IInhabitantWorld
 	{
 		void WriteDebugInformation(string source, string message);
 	}

EcoDev.Core/EcoDev.Core.csproj

     <Compile Include="Common\BuildingBlocks\MapBlockAccessibility.cs" />
     <Compile Include="Common\BuildingBlocks\MapEntranceBlock.cs" />
     <Compile Include="Common\BuildingBlocks\MapExitBlock.cs" />
+    <Compile Include="Common\BuildingBlocks\PlayerOccupiedBlock.cs" />
     <Compile Include="Common\BuildingBlocks\SolidBlock.cs" />
     <Compile Include="Common\IWorld.cs" />
     <Compile Include="Common\Maps\MapPosition.cs" />

EcoDev.UnitTests/PositionEngineTests.cs

 		[TestMethod]
 		public void NextRelativePositionShouldBeValid()
 		{
-			var engine = new InhabitantPositionEngine();
-			
+			var engine = new InhabitantPositionEngine(new DummyWorld());
+
 			var entity = new LivingEntityWithQualities();
 			entity.PositionInMap = new MapPosition(5,5,0);
 
 
 		}
 	}
+
+	public class DummyWorld : IEcoWorld
+	{
+		public void AddPlayer(LivingEntityWithQualities player)
+		{
+			throw new NotImplementedException();
+		}
+
+		public event EventHandler<DebugInfoEventArgs> DebugInformation;
+
+		public void DestroyWorld()
+		{
+			throw new NotImplementedException();
+		}
+
+		public event EventHandler<EntityExitEventArgs> EntityExited;
+
+		public event EventHandler<InhabitantActionEventArgs> InhabitantPerformedAction;
+
+		public IEnumerable<LivingEntityWithQualities> Inhabitants
+		{
+			get { throw new NotImplementedException(); }
+		}
+
+		public void StartWorld()
+		{
+			throw new NotImplementedException();
+		}
+
+		public Engine.MapEngine.Map WorldMap
+		{
+			get { throw new NotImplementedException(); }
+		}
+
+		public void WriteDebugInformation(string source, string message)
+		{
+			throw new NotImplementedException();
+		}
+
+		public void WriteDebugInformation(string source, string message, params object[] args)
+		{
+			throw new NotImplementedException();
+		}
+	}
+
 }

EcoDev.UnitTests/WorldTests.cs

 		public void WorldCanConstructValidPositionContext()
 		{
 			var world = GetTestWorld();
-			var positionEngine = new InhabitantPositionEngine();
+			var positionEngine = new InhabitantPositionEngine(world);
 
 			Assert.IsNotNull(world);
 
 			world.AddInhabitantsToMap();
 
 			var playerInWorld = world.Inhabitants.First();
-			var posContext = positionEngine.ConstructPositionContextForEntity(playerInWorld, world.WorldMap);
+			var posContext = positionEngine.ConstructPositionContextForEntity(playerInWorld);
 
 			Assert.IsNotNull(posContext);
 

EcoDev/EcoDev.Engine.csproj

     <Compile Include="WorldEngine\DebugInfoEventArgs.cs" />
     <Compile Include="WorldEngine\EcoWorld.cs" />
     <Compile Include="WorldEngine\EntityExitEventArgs.cs" />
+    <Compile Include="WorldEngine\IEcoWorld.cs" />
     <Compile Include="WorldEngine\InhabitantActionEventArgs.cs" />
     <Compile Include="WorldEngine\InhabitantPositionEngine.cs" />
     <Compile Include="WorldEngine\MovementActionResponse.cs" />

EcoDev/WorldEngine/ActionResponse.cs

 {
 	internal abstract class ActionResponse
 	{
+		private IEcoWorld _world;
+		public ActionResponse(IEcoWorld world)
+		{
+			_world = world;
+		}
 		public LivingEntityWithQualities Inhabitant { get; set; }
-		public EcoWorld World { get; set; }
+		public IEcoWorld World { get { return _world; } }
 		public ActionResult DecidedAction { get; set; }
 
 		protected abstract void HandleActionToPerform();

EcoDev/WorldEngine/ActionResponseFactory.cs

 		static ActionResponseFactory()
 		{
 			// Build up a list of ActionResponses
-			_responseList.Add( ActionToPerform.Move, (entity,world, actionResult) => { return new MovementActionResponse() { Inhabitant = entity, World = world, DecidedAction = actionResult }; });
+			_responseList.Add( ActionToPerform.Move, (entity,world, actionResult) => { return new MovementActionResponse(world) { Inhabitant = entity, DecidedAction = actionResult }; });
 		}
 
 		public static ActionResponse CreateActionResponseHandler(ActionResult actionResult, LivingEntityWithQualities entity,EcoWorld world)

EcoDev/WorldEngine/EcoWorld.cs

 
 namespace EcoDev.Engine.WorldEngine
 {
-	public class EcoWorld : IWorld, IDisposable
+	public class EcoWorld : IEcoWorld, IInhabitantWorld, IDisposable
 	{
 		Map _worldMap;
 		CancellationTokenSource _tokenSource;
 		string _worldName;
 		Task _worldTask = null;
 		const int MIN_MILLISECONDS_TO_CYCLE_THROUGH_PLAYER_ACTIONS = 1000;
-		public InhabitantPositionEngine _positionEngine = new InhabitantPositionEngine();
+		public InhabitantPositionEngine _positionEngine;
 		static object _debugLock = new object();
 		bool _enableDebug = false;
 
 			}
 
 			_tokenSource = CancellationTokenSource.CreateLinkedTokenSource(new CancellationToken(false));
+			_positionEngine = new InhabitantPositionEngine(this);
 		}
 
 		public Map WorldMap { get { return _worldMap; } }
 			for (int cnt = 0; cnt < _inhabitants.Count; cnt++)
 			{
 				var inhabitant = _inhabitants[cnt];
-				var posCtxt = _positionEngine.ConstructPositionContextForEntity(inhabitant, _worldMap);
+				var posCtxt = _positionEngine.ConstructPositionContextForEntity(inhabitant);
 				if (posCtxt.CurrentPosition is MapExitBlock)
 				{
 					playersCompleted.Add(inhabitant);
 			// for a relative speed of 3
 			for (var speedCnt = 0; speedCnt < entity.Qualities.RelativeSpeed; speedCnt++)
 			{
-				var positionContext = _positionEngine.ConstructPositionContextForEntity(entity, _worldMap);
+				var positionContext = _positionEngine.ConstructPositionContextForEntity(entity);
 				ActionContext context = new ActionContext(positionContext);
 
 				var asyncEngine = new AsyncActionExecutionEngine(entity, context);
 			try
 			{
 				responseActionHandler.ExecuteActionToPerform();
-				var positionCOntext = _positionEngine.ConstructPositionContextForEntity(entity, _worldMap);
+				var positionCOntext = _positionEngine.ConstructPositionContextForEntity(entity);
 				if (positionCOntext.CurrentPosition is MapExitBlock)
 				{
 					// Player has found an exit.

EcoDev/WorldEngine/IEcoWorld.cs

+using System;
+namespace EcoDev.Engine.WorldEngine
+{
+	public interface IEcoWorld
+	{
+		void AddPlayer(EcoDev.Engine.Entities.LivingEntityWithQualities player);
+		event EventHandler<DebugInfoEventArgs> DebugInformation;
+		void DestroyWorld();
+		event EventHandler<EntityExitEventArgs> EntityExited;
+		event EventHandler<InhabitantActionEventArgs> InhabitantPerformedAction;
+		System.Collections.Generic.IEnumerable<EcoDev.Engine.Entities.LivingEntityWithQualities> Inhabitants { get; }
+		void StartWorld();
+		EcoDev.Engine.MapEngine.Map WorldMap { get; }
+		void WriteDebugInformation(string source, string message);
+		void WriteDebugInformation(string source, string message, params object[] args);
+	}
+}

EcoDev/WorldEngine/InhabitantPositionEngine.cs

 using EcoDev.Core.Common.Maps;
 using EcoDev.Core.Common.Actions;
 using EcoDev.Core.Common;
+using EcoDev.Core.Common.BuildingBlocks;
 
 namespace EcoDev.Engine.WorldEngine
 {
 	public class InhabitantPositionEngine
 	{
-		internal PositionContext ConstructPositionContextForEntity(LivingEntityWithQualities entity, Map worldMap)
+		private IEcoWorld _world;
+
+		public InhabitantPositionEngine(IEcoWorld world)
+		{
+			if (world == null)
+			{
+				throw new ArgumentNullException("World cannot be NULL");
+			}
+			_world = world;
+		}
+		internal PositionContext ConstructPositionContextForEntity(LivingEntityWithQualities entity)
 		{
 			int relativeSight = entity.Qualities.RelativeSight;
+			var worldMap = _world.WorldMap;
 
 			MapBlock currentPosition = worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition);
 			var fwdFacingBlocks = new List<MapBlock>();
 					for (int blockCnt = 0; blockCnt <= relativeSight; blockCnt++)
 					{
 						int relativePos = 1 + blockCnt;
-						fwdFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
-						rearFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
-						leftFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
-						rightFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
+						fwdFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
+						rearFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
+						leftFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
+						rightFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
 					}
 					break;
 				case WorldAxis.PositiveY:
 					for (int blockCnt = 0; blockCnt <= relativeSight; blockCnt++)
 					{
 						int relativePos = 1 + blockCnt;
-						fwdFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
-						rearFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
-						leftFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
-						rightFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
+						fwdFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
+						rearFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
+						leftFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
+						rightFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
 					}
 					break;
 				case WorldAxis.PositiveZ:
 					for (int blockCnt = 0; blockCnt <= relativeSight; blockCnt++)
 					{
 						int relativePos = 1 + blockCnt;
-						fwdFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
-						rearFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
-						leftFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
-						rightFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
+						fwdFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
+						rearFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
+						leftFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
+						rightFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
 					}
 					break;
 				case WorldAxis.NegativeY:
 					for (int blockCnt = 0; blockCnt <= relativeSight; blockCnt++)
 					{
 						int relativePos = 1 + blockCnt;
-						fwdFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
-						rearFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
-						leftFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
-						rightFacingBlocks.Add(worldMap.Get(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
+						fwdFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition - relativePos, entity.PositionInMap.zPosition));
+						rearFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
+						leftFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition + relativePos, entity.PositionInMap.yPosition + relativePos, entity.PositionInMap.zPosition));
+						rightFacingBlocks.Add(GetBlockTypeAtMapPosition(entity.PositionInMap.xPosition - relativePos, entity.PositionInMap.yPosition, entity.PositionInMap.zPosition));
 					}
 					break;
 				case WorldAxis.NegativeZ:
 			return posContext;
 		}
 
+		private MapBlock GetBlockTypeAtMapPosition(int xPos, int yPos, int zPos)
+		{
+			var blockInMap = _world.WorldMap.Get(xPos, yPos, zPos);
+			var entities= _world.Inhabitants.ToArray();
+			for (int cnt=0; cnt < entities.Length; cnt++)
+			{
+				var entity = entities[cnt];
+				if (entity.PositionInMap.xPosition == xPos && entity.PositionInMap.yPosition == yPos && entity.PositionInMap.zPosition == zPos)
+				{
+					blockInMap = new PlayerOccupiedBlock();
+				}
+			}
+			return blockInMap;
+		}
+
 		internal MapPosition GetNextRelativePositionInMap(LivingEntityWithQualities entity, MovementDirection direction)
 		{
 			var nextPosition = new MapPosition(entity.PositionInMap);

EcoDev/WorldEngine/MovementActionResponse.cs

 {
 	internal class MovementActionResponse : ActionResponse
 	{
-		InhabitantPositionEngine _positionEngine = new InhabitantPositionEngine();
+		InhabitantPositionEngine _positionEngine;
+		public MovementActionResponse(IEcoWorld world) : base( world)
+		{
+			_positionEngine = new InhabitantPositionEngine(World);
+		}
 		protected override void HandleActionToPerform()
 		{
-			var positionCtxt = _positionEngine.ConstructPositionContextForEntity(Inhabitant,World.WorldMap);
+			var positionCtxt = _positionEngine.ConstructPositionContextForEntity(Inhabitant);
 			MapBlock blockToMoveTo = GetPotentialBlockToMoveToInMap(positionCtxt);
 
 			int relativeSpeed = Inhabitant.Qualities.RelativeSpeed;

TestEcoWorldHost/TestPlayer.cs

 
 namespace TestEcoWorldHost
 {
-	public class TestPlayer:LivingEntity
+	public class TestPlayer : LivingEntity
 	{
+		MovementDirection rememberedDirection;
+
 		public TestPlayer()
 		{
 			Name = "Beta Boy";
 			LifeKey = Guid.NewGuid();
-			Size = new EntitySize() { Height = 1, Thickness=1, Width = 1};
+			Size = new EntitySize() { Height = 1, Thickness = 1, Width = 1 };
 			Weight = 10;
 
 		}
-		public override ActionResult DecideActionToPerform(EcoDev.Core.Common.Actions.ActionContext actionContext)
+		public override ActionResult DecideActionToPerform(ActionContext actionContext)
 		{
 			try
 			{
 							break;
 					}
 					World.WriteDebugInformation(Name, string.Format("Attempting to move {0} based on previous action to block {1}", PreviousAction.DirectionToMove, nextBlockBAsedOnPreviousMovement != null ? nextBlockBAsedOnPreviousMovement.GetType().ToString() : "Empty"));
-					
-					
+
+
+					// If we can keep moving in the same direction, then do it.
+					// Elselet it flow through to normal directional logic
+					if (CheckAccessibilityOfMapBlock(nextBlockBAsedOnPreviousMovement))
+					{
+						action.DirectionToMove = PreviousAction.DirectionToMove;
+						World.WriteDebugInformation(Name, string.Format("Moving {0} based on previous action", action.DirectionToMove));
+						return action;
+					}
+
 					// If we were moving back, then try going left or right first
 					if (PreviousAction.DirectionToMove == MovementDirection.Back)
 					{
+						Random rnd = new Random(DateTime.Now.Millisecond);
+						if (rnd.Next(0, 20) > 17)
+						{
+							var spontaneousDirections = new MovementDirection[] { MovementDirection.Back, MovementDirection.Forward, MovementDirection.Right, MovementDirection.Left };
+							var randomDir = spontaneousDirections[rnd.Next(0, 3)];
+							action.DirectionToMove = randomDir;
+							return action;
+						}
+
 						if (CheckAccessibilityOfMapBlock(actionContext.Position.LeftFacingPositions[0]))
 						{
 							nextBlockBAsedOnPreviousMovement = actionContext.Position.LeftFacingPositions[0];
 							action.DirectionToMove = MovementDirection.Left;
+							rememberedDirection = action.DirectionToMove;
 							return action;
 						}
 						if (CheckAccessibilityOfMapBlock(actionContext.Position.RightFacingPositions[0]))
 						{
 							nextBlockBAsedOnPreviousMovement = actionContext.Position.RightFacingPositions[0];
 							action.DirectionToMove = MovementDirection.Right;
+							rememberedDirection = action.DirectionToMove;
 							return action;
 						}
 					}
-					// If we can keep moving in the same direction, then do it.
-					// Elselet it flow through to normal directional logic
-					if (CheckAccessibilityOfMapBlock(nextBlockBAsedOnPreviousMovement))
-					{
-						action.DirectionToMove = PreviousAction.DirectionToMove;
-
-						World.WriteDebugInformation(Name,string.Format("Moving {0} based on previous action", action.DirectionToMove));
-						return action;
-					}
 				}
 
 				// move forward if we can
 			}
 			catch (Exception ex)
 			{
-				World.WriteDebugInformation("Player: "+ Name, string.Format("Player Generated exception: {0}",ex.Message));
+				World.WriteDebugInformation("Player: " + Name, string.Format("Player Generated exception: {0}", ex.Message));
 				throw ex;
 			}
 		}
 
 		private bool CheckAccessibilityOfMapBlock(MapBlock block)
 		{
-			if (block == null || block.Accessibility == MapBlockAccessibility.AllowEntry || block.Accessibility == MapBlockAccessibility.AllowExit || block.Accessibility == MapBlockAccessibility.AllowPotentialEntry)
+			if ((block == null || block.Accessibility == MapBlockAccessibility.AllowEntry 
+					|| block.Accessibility == MapBlockAccessibility.AllowExit 
+					|| block.Accessibility == MapBlockAccessibility.AllowPotentialEntry)
+					&& !(block is MapEntranceBlock))
 			{
 				return true;
 			}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.