Refactored project to have separate AIAgents for each tank
authorJustin Worthe <justin.worthe@entelect.co.za>
Sun, 20 Oct 2013 15:14:49 +0000 (17:14 +0200)
committerJustin Worthe <justin.worthe@entelect.co.za>
Sun, 20 Oct 2013 15:14:49 +0000 (17:14 +0200)
.gitignore [new file with mode: 0644]
Entelect.BattleCity.Challenge/AiAgent.cs
Entelect.BattleCity.Challenge/Entelect.BattleCity.Challenge.csproj
Entelect.BattleCity.Challenge/GameInProgress.cs
Entelect.BattleCity.Challenge/Move.cs
Entelect.BattleCity.Challenge/Program.cs

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..ef293be
--- /dev/null
@@ -0,0 +1,4 @@
+Entelect.BattleCity.Challenge/obj
+Entelect.BattleCity.Challenge/bin
+*.suo
+*.csproj.user
index e577bcb..df9afb4 100644 (file)
@@ -7,46 +7,35 @@ namespace Entelect.BattleCity.Challenge
     {
         private int _tankId;
 
-        public AiAgent()
-        {
-
-        }
-
         public AiAgent(int tankId)
         {
             _tankId = tankId;
         }
 
-        public Move GetBestMove(ChallengeService.state?[][] state, ChallengeService.game game, int tankIndex)
+        public Move GetBestMove(ChallengeService.game game, ChallengeService.state?[][] board, ChallengeService.player me, ChallengeService.player enemy)
         {
-            ChallengeService.player me = null;
-            ChallengeService.player enemy = null;
             ChallengeService.unit tank = null;
             bool bulletInAir = false;
 
-            string playerName = game.playerName;
-            foreach (ChallengeService.player player in game.players)
+            foreach (var unit in me.units)
             {
-                if (player.name.Equals(playerName))
+                if (unit.id == _tankId)
                 {
-                    me = player;
-                }
-                else
-                {
-                    enemy = player;
+                    tank = unit;
                 }
             }
-            if (me.units.Length <= tankIndex)
+
+            if (tank == null)
             {
+                Console.WriteLine("Tank {0} does not exist", _tankId);
                 return null;
             }
-            tank = me.units[tankIndex];
 
             if (me.bullets != null)
             {
                 foreach (var bullet in me.bullets)
                 {
-                    if (Math.Abs(bullet.x - tank.x) < state.Length / 4)
+                    if (Math.Abs(bullet.x - tank.x) < board.Length / 4)
                     {
                         bulletInAir = true;
                     }
@@ -56,18 +45,20 @@ namespace Entelect.BattleCity.Challenge
             var enemyBase = enemy.@base;
 
             ChallengeService.direction chosenDirection = 
-                tank.y != enemyBase.y ?
+                tank.y+2 != enemyBase.y ?
                 (
-                    tank.y > enemyBase.y ?
+                    tank.y+2 > enemyBase.y ?
                     ChallengeService.direction.UP :
                     ChallengeService.direction.DOWN
                 ) :
                 (
-                    tank.x > enemyBase.x ?
+                    tank.x+2 > enemyBase.x ?
                     ChallengeService.direction.LEFT :
                     ChallengeService.direction.RIGHT
                 );
 
+            Console.WriteLine("Chosen direction for tank {0} is {1} and bulletInAir is {2}", _tankId, chosenDirection, bulletInAir);
+
             if (chosenDirection != tank.direction || bulletInAir)
             {
                 return MoveInDirection(tank.id, chosenDirection);
index 83bc159..74f95c6 100644 (file)
@@ -56,7 +56,6 @@
   </ItemGroup>
   <ItemGroup>
     <None Include="App.config" />
-    <None Include="ChallengeService.wsdl" />
     <None Include="Service References\ChallengeService\ChallengeService.wsdl" />
     <None Include="Service References\ChallengeService\Entelect.BattleCity.Challenge.ChallengeService.delta.datasource">
       <DependentUpon>Reference.svcmap</DependentUpon>
index 61fa436..6581eb7 100644 (file)
@@ -5,59 +5,132 @@ using System.Threading;
 
 namespace Entelect.BattleCity.Challenge
 {
-    class GameInProgress
+    public class GameInProgress
     {
-        public static void run(ChallengeService.ChallengeClient service, ChallengeService.state?[][] state)
+        private ChallengeService.ChallengeClient _service;
+        private ChallengeService.game _currentState;
+        private ChallengeService.player _me;
+        private ChallengeService.player _enemy;
+
+        private ChallengeService.state?[][] _board;
+
+        private AiAgent _tank1Ai;
+        private AiAgent _tank2Ai;
+
+        public GameInProgress(ChallengeService.ChallengeClient service, ChallengeService.state?[][] board)
         {
-            AiAgent agent = new AiAgent();
+            _service = service;
+            _board = board;
+
+            updateGameStatus();
+
+            _tank1Ai = new AiAgent(_me.units[0].id);
+            _tank2Ai = new AiAgent(_me.units[1].id);
+        }
 
+
+
+        public void run()
+        {
             while (true)
             {
-                var game = service.getStatus();
                 long currentTick = DateTime.Now.Ticks;
-                long nextTick = game.nextTickTime.Ticks;
+                long nextTick = _currentState.nextTickTime.Ticks;
                 if (currentTick > nextTick)
                 {
+                    Console.Error.WriteLine("Current game state is out of date");
+                    updateGameStatus();
                     continue;
                 }
+                makeNextMove();
+                waitForNextTick();
+
+                updateGameStatus();
+            }
+        }
 
-                // AI logic here
-                Move tank1Move = agent.GetBestMove(state, game, 0);
-                Move tank2Move = agent.GetBestMove(state, game, 1);
+        private void makeNextMove()
+        {
+            Move tank1Move = _tank1Ai.GetBestMove(_currentState, _board, _me, _enemy);
+            Move tank2Move = _tank2Ai.GetBestMove(_currentState, _board, _me, _enemy);
+
+            sendMovesToService(tank1Move, tank2Move);
+        }
+
+        private void sendMovesToService(Move tank1Move, Move tank2Move)
+        {
+            if (tank1Move != null && tank2Move != null)
+            {
+                Console.WriteLine("Actions chosen for two tanks");
+                Console.WriteLine(tank1Move.ToString());
+                Console.WriteLine(tank2Move.ToString());
+                _service.setActions(tank1Move.Action, tank2Move.Action);
+            }
+            else if (tank1Move != null)
+            {
+                Console.WriteLine("Actions chosen for first tank only");
+                Console.WriteLine(tank1Move.ToString());
+                _service.setAction(tank1Move.Tank, tank1Move.Action);
+            }
+            else if (tank2Move != null)
+            {
+                Console.WriteLine("Actions chosen for second tank only");
+                Console.WriteLine(tank2Move.ToString());
+                _service.setAction(tank2Move.Tank, tank2Move.Action);
+            }
+        }
 
-                if (tank1Move != null)
+        private void waitForNextTick()
+        {
+            var nextTick = _currentState.nextTickTime.Ticks;
+            var currentTick = DateTime.Now.Ticks;
+
+            long sleepTime = nextTick - currentTick;
+            if (sleepTime < 0L)
+            {
+                Console.Error.WriteLine("ERROR: Gone passed the next tick time");
+            }
+            else
+            {
+                Console.WriteLine("Sleeping until {1} for {0}ms", sleepTime, _currentState.nextTickTime.ToString());
+                try
                 {
-                    service.setActionAsync(tank1Move.Tank, tank1Move.Action);
+                    Thread.Sleep(TimeSpan.FromTicks(sleepTime));
                 }
-                if (tank2Move != null)
+                catch (Exception ex)
                 {
-                    service.setActionAsync(tank2Move.Tank, tank2Move.Action);
+                    Console.Error.WriteLine("Exception thrown while waiting for next tick");
+                    Console.Error.WriteLine("Exception message: "+ ex.Message);
                 }
+            }
+        }
 
-                currentTick = DateTime.Now.Ticks;
+        private void updateGameStatus()
+        {
+            _currentState = _service.getStatus();
+
+            bool meFound = false;
+            bool enemyFound = false;
 
-                long sleepTime = nextTick - currentTick;
-                if (sleepTime < 0L)
+            foreach (ChallengeService.player player in _currentState.players)
+            {
+                if (player.name.Equals(_currentState.playerName))
                 {
-                    Console.Error.WriteLine("ERROR: Gone passed the next tick time");
+                    _me = player;
                 }
                 else
                 {
-                    Console.WriteLine("Sleeping until {1} for {0}ms", sleepTime, game.nextTickTime.ToString());
+                    _enemy = player;
                 }
+            }
 
-                try
-                {
-                    Thread.Sleep(TimeSpan.FromTicks(sleepTime));
-                }
-                catch (Exception)
-                {
-                    continue;
-                }
-                //while (startTick < nextTick)
-                //{
-                //    startTick += (DateTime.Now.Ticks - startTick);
-                //}
+            if (!meFound)
+            {
+                Console.Error.WriteLine("Logged in player was not found");
+            }
+            if (!enemyFound)
+            {
+                Console.Error.WriteLine("Logged in opponent was not found");
             }
         }
     }
index 1813c59..7fba664 100644 (file)
@@ -15,5 +15,10 @@ namespace Entelect.BattleCity.Challenge
             Tank = tank;
             Action = action;
         }
+
+        public override string ToString()
+        {
+            return string.Format("Tank {0}: {1}", Tank, Action.ToString());
+        }
     }
 }
index 5764426..29d8e8e 100644 (file)
@@ -9,8 +9,10 @@ namespace Entelect.BattleCity.Challenge
             var endpointConfigurationName = "ChallengePort";
             var address = new EndpointAddress(args[0]);
             var service = new ChallengeService.ChallengeClient(endpointConfigurationName, address);
-            var state = service.login();
-            GameInProgress.run(service, state);
+            var board = service.login();
+
+            var game = new GameInProgress(service, board);
+            game.run();
         }
     }
 }