public void testGiveCommand()
        {
            Scenario scenario = new Scenario(20, 20);
            Controller controller = new Controller(scenario);

            Unit unit = new Unit(scenario.getPlayer(), 200);
            controller.addUnit(unit, 10f, 10f);

            // Create a MoveAction
            MoveAction action = new MoveAction(8f, 8f, scenario.getGameWorld(), unit);

            // Test if the ActionController returns true when it gives the command.
            Assert.IsTrue(controller.giveActionCommand(unit, action));

            // Test if the MoveAction is actually on the unit's action queue.
            Assert.IsTrue(unit.getActionQueue()[0] == action);

            // Create a second MoveAction
            MoveAction action2 = new MoveAction(7f, 7f, scenario.getGameWorld(), unit);

            // Test if the ActionController interrupts the current MoveAction and replaces it with the new one.
            Assert.IsTrue(controller.giveActionCommand(unit, action2));
            Assert.IsTrue(unit.getActionQueue()[0] == action2);
            Assert.IsFalse(unit.getActionQueue().Contains(action));
        }
        byte WAIT_TICKS = 30; // How many ticks to wait for another unit to move.

        #endregion Fields

        #region Constructors

        /// <summary>
        /// This constructor will create a MoveAction to the given targetX, and targetY.
        /// </summary>
        /// <param name="targetX">X coordinate destination of the move action in game space.</param>
        /// <param name="targetY">Y coordinate destination of the move action in game space.</param>
        /// <param name="gw">The GameWorld that the move action is occurring in.</param>
        /// <param name="entity">The Entity being given the MoveAction. (Should only be given to Units)</param>
        public MoveAction(float targetX, float targetY, GameWorld gw, Entity entity)
        {
            this.actionType = ActionType.Move;
            this.targetY = targetY;
            this.targetX = targetX;
            this.entity = entity;
            this.gw = gw;
            unit = (Unit)entity;
            float startX = unit.x;
            float startY = unit.y;

            if ((int)targetX >= gw.map.width || (int)targetX < 0 || (int)targetY >= gw.map.height || (int)targetY < 0)
            {
                // Invalid target position.
                path = new List<Cell>();
            }
            else
            {
                path = findPath.between(gw.map, gw.map.getCell((int)startX, (int)startY), gw.map.getCell((int)targetX, (int)targetY));

                // Don't bother with path if it is just to same cell.
                if (path.Count > 1)
                {
                    targetCell = path[1];
                    cellIndex = 1;
                }
                else
                {
                    path = new List<Cell>();
                }
            }
        }
        public void testInsertCommand()
        {
            Scenario scenario = new Scenario(20, 20);
            Controller controller = new Controller(scenario);

            Unit unit = new Unit(scenario.getPlayer(), 200);
            controller.addUnit(unit, 10f, 10f);

            // Create a MoveAction
            MoveAction action = new MoveAction(8f, 8f, scenario.getGameWorld(), unit);

            // Test if the ActionController returns true when it gives the command.
            Assert.IsTrue(controller.giveActionCommand(unit, action));

            // Test if the MoveAction is actually on the unit's action queue.
            Assert.IsTrue(unit.getActionQueue()[0] == action);

            // Create a second MoveAction
            MoveAction action2 = new MoveAction(7f, 7f, scenario.getGameWorld(), unit);

            // Insert the second MoveAction to the beginning of the units action queue.
            ActionController.insertIntoActionQueue(unit, action2);
            Assert.IsTrue(unit.getActionQueue()[0] == action2);
            Assert.IsTrue(unit.getActionQueue()[1] == action);
        }
        Unit unit; // Unit performing the AttackAction

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Given a Unit, an Entity and a GameWorld, this constructor will create a GuardAttack object where the Unit is
        /// attacking the Entity in the GameWorld.
        /// </summary>
        /// <param name="unit">The Unit being given the GuardAttack command.</param>
        /// <param name="target">The Entity being targeted by the command.</param>
        /// <param name="gw">The GameWorld this is occurring in.</param>
        public GuardAttack(Unit unit, Entity target, GameWorld gw)
        {
            this.unit = unit;
            this.target = target;
            this.gw = gw;
            this.actionType = ActionType.GuardAttack;
        }
        public void testMapWithUnitMove()
        {
            Scenario scenario = new Scenario(20, 20);
            Controller controller = new Controller(scenario);
            Unit unit = new Unit(scenario.getPlayer(), new UnitStats());
            controller.addUnit(unit, 6, 6);

            MoveAction move = new MoveAction(10, 10, scenario.getGameWorld(), unit);

            controller.giveActionCommand(unit, move);

            // Update the world so that the unit moves.
            for (int i = 0; i < 1000; i++)
            {
                controller.updateWorld();
            }

            // Test that all of the cells within the units visibility range have been explored.
            for (int i = (int)unit.x - (int)unit.stats.visibilityRange; i < (int)unit.x + (int)unit.stats.visibilityRange; i++)
            {
                for (int j = (int)unit.y - (int)unit.stats.visibilityRange; j < (int)unit.y + (int)unit.stats.visibilityRange; j++)
                {
                    Assert.IsTrue(scenario.getGameWorld().map.getCell(i, j).explored);
                }
            }
        }
 /// <summary>
 /// </summary>
 /// <param name="building"></param>
 /// <param name="unit"></param>
 public BuildAction(Building building, Unit unit, GameWorld gw)
 {
     this.building = building;
     this.unit = unit;
     this.actionType = ActionType.BuildBuilding;
     this.gw = gw;
 }
        public void testUpdateUnit()
        {
            // Create a unit with 50% health
            unit = new Unit(new Player(0), new UnitStats());
            unit.health = 100;
            unit.stats.maxHealth = 200;
            UnitStatsLogic.updateUnit(unit, 0);

            // Check if unit's buffs are set to 75%
            Assert.IsTrue(unit.attackBuff == 0.75);
            Assert.AreEqual(0.75, unit.speedBuff);
        }
        public void testDeadUnit()
        {
            // Create a dead unit.
            unit = new Unit(new Player(0), new UnitStats());
            unit.health = 0;
            unit.stats.maxHealth = 200;
            UnitStatsLogic.updateUnit(unit, 0);

            // Check if unit's buffs are set to 50% and that the unit's primary state is set to DEAD.
            Assert.IsTrue(unit.attackBuff == 0.50);
            Assert.AreEqual(0.50, unit.speedBuff);
            Assert.AreEqual(State.PrimaryState.Dead, unit.getState().getPrimaryState());
        }
 /**** FUNCTIONS FOR HANDLING EVENTS WHEN OBSERVER IS A UNIT  ******/
 /// <summary>
 /// Given a Unit and a GameWorld, this function will have the Unit "react" to all GameEvents in it's eventList.
 /// </summary>
 /// <param name="unit">The Unit reacting to it's events.</param>
 /// <param name="gw">The GameWorld the Unit is in.</param>
 private static void handleEventsForUnit(Unit unit, GameWorld gw)
 {
     foreach (GameEvent gameEvent in unit.getEventList())
     {
         // Handle MoveEvent
         if (gameEvent.type == GameEvent.EventType.MoveEvent)
         {
             handleMoveEventUnit(unit, gameEvent, gw);
         }
         // Handle AttackEvent
         else if (gameEvent.type == GameEvent.EventType.AttackEvent)
         {
             handleAttackEventUnit(unit, gameEvent, gw);
         }
     }
 }
        public void testMapWithUnit()
        {
            Scenario scenario = new Scenario(20, 20);
            Controller controller = new Controller(scenario);
            Unit unit = new Unit(scenario.getPlayer(), new UnitStats());
            controller.addUnit(unit, 0, 0);

            // Test that all of the cells within the units visibility range have been explored.
            for (int i = 0; i < unit.stats.visibilityRange; i++)
            {
                for (int j = 0; j < unit.stats.visibilityRange; j++)
                {
                    Assert.IsTrue(scenario.getGameWorld().map.getCell(i, j).explored);
                }
            }
        }
        /// <summary>
        /// This method will update the visibility map to show that all Cells in a Units visibilityRange have been explored.
        /// </summary>
        /// <param name="unit"></param>
        public void updateVisMap(Unit unit)
        {
            // Only update the map if the unit belongs to the Human player.
            if (unit.getOwner() != humanPlayer)
            {
                return;
            }

            byte offset = (byte)unit.stats.visibilityRange;

            int xStart = (short)unit.x - offset;
            int xEnd = (short)unit.x + offset;
            int yStart = (short)unit.y - offset;
            int yEnd = (short)unit.y + offset;

            exploreMap(xStart, xEnd, yStart, yEnd);
        }
        /// <summary>
        /// This method will process an AttackEvent that the unit observed and will determine how the unit should "react" to it.
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="gameEvent"></param>
        /// <param name="gw"></param>
        private static void handleAttackEventUnit(Unit unit, GameEvent gameEvent, GameWorld gw)
        {
            // Check if unit is in the Passive AttackStance.
            if (unit.getAttackStance() == Unit.AttackStance.Passive)
            {
                // Ignore the AttackEvent.
                return;
            }

            // If an ally Entity is being attacked.
            if (gameEvent.targetEntity.getOwner() == unit.getOwner() && unit.getOwner().isEnemy(gameEvent.sourceEntity.getOwner()))
            {
                // If the unit is not performing any action.
                if (unit.getActionQueue().Count == 0)
                {
                    // Attack the sourceEnemy
                }
            }
        }
        public void testMove()
        {
            Scenario scenario = new Scenario(20, 20);
            Controller controller = new Controller(scenario);

            Unit unit = new Unit(scenario.getPlayer(), 200);
            controller.addUnit(unit, 10f, 10f);

            // Create a MoveAction
            MoveAction action = new MoveAction(8f, 8f, scenario.getGameWorld(), unit);

            controller.giveActionCommand(unit, action);

            Assert.AreEqual(scenario.getGameWorld().map.getCell(10, 10), unit.getCell());

            // Run 1000 cycles of the game
            for (int i = 0; i < 1000; i++)
            {
                controller.updateWorld();
            }

            // Test if the unit has ended up in the target cell.
            Assert.AreEqual(scenario.getGameWorld().map.getCell(8, 8), unit.getCell());
        }
        /// <summary>
        /// This method will find the cell closest to 'unit' that 'entity' is currently occupying.
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static Cell findClosestCell(Unit unit, StaticEntity se, GameWorld gw)
        {
            Cell cell = null;
            float dis = 10000;

            short xC = se.orginCell.Xcoord;
            short yC = se.orginCell.Ycoord;
            short width = se.width;
            short height = se.height;

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    if (EntityLocController.findDistance(unit.x, unit.y, xC + i, yC + j) <= dis)
                    {
                        cell = gw.map.getCell(xC + i, xC + j);
                        dis = EntityLocController.findDistance(unit.x, unit.y, xC + i, yC + j);
                    }
                }
            }

            return cell;
        }
        public bool setUnit(Unit unit)
        {
            if (this.isValid && this.unit == null)
            {
                this.unit = unit;
                this.isValid = false;
                return true;
            }

            return false;
        }
        private void updateCellsUnitIsObserving(Unit unit)
        {
            // Have unit stop observing all the cells it is currently observing.
            unit.unregisterAll();

            byte offset = (byte)unit.stats.visibilityRange;

            int xStart = (short)unit.x - offset;
            int xEnd = (short)unit.x + offset;
            int yStart = (short)unit.y - offset;
            int yEnd = (short)unit.y + offset;

            // Make sure that our bounds are valid. (Assumes that no Unit has a visibility range longer than the map.)
            if (xStart < 0)
            {
                xStart = 0;
            }
            else if (xEnd >= gw.map.width)
            {
                xEnd = gw.map.width;
            }

            if (yStart < 0)
            {
                yStart = 0;
            }
            else if (yEnd >= gw.map.height)
            {
                yEnd = gw.map.height;
            }

            // Set all cell explored flags to true.
            for (int i = xStart; i < xEnd; i++)
            {
                for (int j = yStart; j < yEnd; j++)
                {
                    unit.register(gw.map.getCell(i, j));
                }
            }
        }
        /// <summary>
        /// This method will update the pointers to the Cell in the GameWorld that is occuppied by the Unit.
        /// </summary>
        /// <param name="unit">The unit who's location is being updated.</param>
        public void updateUnitLocation(Unit unit)
        {
            if (!unit.getCell().contains(unit.x, unit.y))
            {
                Cell newCell = gw.map.getCell((int)Math.Floor(unit.x), (int)Math.Floor(unit.y));
                Cell oldCell = unit.getCell();

                oldCell.removeUnit();

                // NOTE: doesn't check if newCell is already occupied.
                unit.setCell(newCell);
                newCell.setUnit(unit);
            }
        }
 private static void updateAttackBuff(Unit unit)
 {
     /* The attackBuff is affected by a unit's health. The attack buff may be reduced to 50% if the unit loses all of it's health. */
     double baseAttack = 0.5 + 0.5 * unit.health / unit.stats.maxHealth;
     unit.attackBuff = baseAttack;
 }
 private static void updateSpeedBuff(Unit unit)
 {
     double baseSpeed = 0.5 + 0.5 * unit.health / unit.stats.maxHealth;
     unit.speedBuff = baseSpeed;
 }
        /*** HELPER FUNCTIONS ****/
        /// <summary>
        /// This function will search the cells that the unit can see for the closest enemy Unit.
        /// </summary>
        /// <param name="unit">The unit doing the searching</param>
        /// <param name="gw">The GameWorld to search</param>
        /// <returns>The closest enemy Unit or null if none exists</returns>
        private static Unit searchCellsForEnemy(Unit unit, GameWorld gw)
        {
            byte offset = (byte)unit.stats.visibilityRange;

            int xStart = (short)unit.x - offset;
            int xEnd = (short)unit.x + offset;
            int yStart = (short)unit.y - offset;
            int yEnd = (short)unit.y + offset;

            // Make sure that our bounds are valid. (Assumes that no Unit has a visibility range longer than the map.)
            if (xStart < 0)
            {
                xStart = 0;
            }
            else if (xEnd >= gw.map.width)
            {
                xEnd = gw.map.width;
            }

            if (yStart < 0)
            {
                yStart = 0;
            }
            else if (yEnd >= gw.map.height)
            {
                yEnd = gw.map.height;
            }

            Unit target = null;
            float distance = 10000f;
            // Set all cell explored flags to true.
            for (int i = xStart; i < xEnd; i++)
            {
                for (int j = yStart; j < yEnd; j++)
                {
                    Unit temp = gw.map.getCell(i,j).getUnit();

                    if (temp != null && unit.getOwner().isEnemy(temp.getOwner()))
                    {
                        float tDis = EntityLocController.findDistance(unit.x, unit.y, temp.x, temp.y);

                        if (tDis < distance)
                        {
                            target = temp;
                            distance = tDis;
                        }
                    }
                }
            }

            return target;
        }
        /// <summary>
        /// This method will update the pointers to the Cell in the GameWorld that is occuppied by the Unit.
        /// </summary>
        /// <param name="unit">The unit who's location is being updated.</param>
        public void updateUnitLocation(Unit unit)
        {
            if (!unit.getCell().contains(unit.x, unit.y))
            {
                Cell newCell = gw.map.getCell((int)Math.Floor(unit.x), (int)Math.Floor(unit.y));
                Cell oldCell = unit.getCell();

                oldCell.removeUnit();

                // NOTE: doesn't check if newCell is already occupied.
                unit.setCell(newCell);
                newCell.setUnit(unit);

                // Update the visibility map.
                this.visMapLogic.updateVisMap(unit);

                // Update the Cells that the unit is observing.
                updateCellsUnitIsObserving(unit);

                // Notify all observers of the cell that a unit has moved onto the cell.
                newCell.notify(new ZRTSModel.GameEvent.GameEvent(newCell, unit, unit, ZRTSModel.GameEvent.GameEvent.EventType.MoveEvent));
            }
        }
 /// <summary>
 /// This function will create a new Unit that belongs to 'owner' and has the UnitStats belonging to 'type'
 /// </summary>
 /// <param name="owner"></param>
 /// <param name="type"></param>
 /// <returns>A new Unit.</returns>
 public Unit createUnit(Player.Player owner, string type)
 {
     Unit u = new Unit(owner, stats[type]);
     u.health = u.stats.maxHealth;
     return u;
 }
 public SimpleAttackAction(Unit unit, Entity target)
 {
     this.unit = unit;
     this.target = target;
     this.actionType = ActionType.SimpleAttack;
 }
 public void removeUnit()
 {
     this.isValid = true;
     this.unit = null;
 }
 /// <summary>
 /// Checking if unit is being selected
 /// </summary>
 /// <param name="u">Unit object</param>
 /// <returns>True if it is being selected</returns>
 private bool isUnitBeingSelected(ZRTSModel.Entities.Unit u)
 {
     return(this.scenario.getPlayer().SelectedEntities.Count > 0 && this.scenario.getPlayer().SelectedEntities.Contains(u));
 }
        /// <summary>
        /// This function will process a MoveEvent and will make the unit "react" to that move event.
        /// </summary>
        /// <param name="unit">The Unit that observed the event.</param>
        /// <param name="gameEvent">The MoveEvent</param>
        /// <param name="gw">The GameWorld this is occurring in.</param>
        private static void handleMoveEventUnit(Unit unit, GameEvent gameEvent, GameWorld gw)
        {
            Console.Write("Unit at (" + unit.x + ", " + unit.y + "): ");
            // Check if unit caused this MoveEvent
            if (gameEvent.sourceEntity == (Entity)unit)
            {
                Unit target = searchCellsForEnemy(unit, gw);

                if (target != null)
                {
                    Console.WriteLine("See Enemy at " + target.getCell().Xcoord + ", ("+ target.getCell().Ycoord + ")");
                }
            }

            // unit did not cause move event
            else
            {
                // Check if sourceEntity is an enemy
                if (unit.getOwner().isEnemy(gameEvent.sourceEntity.getOwner()))
                {
                    // Check if unit is in the Aggressive AttackStance
                    if (unit.getAttackStance() == Unit.AttackStance.Agressive)
                    {
                        if(isInterruptable(unit))
                        {
                            AttackAction attackAction = new AttackAction(unit, gameEvent.sourceEntity, gw);
                            ActionController.Instance.giveCommand(unit, attackAction);
                            Console.WriteLine("Aggressive attack the entity in cell: " + gameEvent.orginCell.Xcoord + ", " + gameEvent.orginCell.Ycoord + ")");
                        }
                    }

                    // Check if unit is in the Guard AttackStance
                    else if (unit.getAttackStance() == Unit.AttackStance.Guard)
                    {
                        GuardAttack guardAttack = new GuardAttack(unit, gameEvent.sourceEntity, gw);
                        ActionController.Instance.giveCommand(unit, guardAttack);
                        Console.WriteLine("Guard attack the entity in cell: " + gameEvent.orginCell.Xcoord + ", " + gameEvent.orginCell.Ycoord + ")");
                    }
                }
            }
        }
 public Unit createUnit(Unit unit, string type)
 {
     return unit;
 }
 /// <summary>
 /// Given a Unit an a string type, this function will give the unit the UnitStats of that type of Unit.
 /// </summary>
 /// <param name="unit">The Unit being given the UnitStats</param>
 /// <param name="type">denotes what type of UnitStats to use.</param>
 /// <returns></returns>
 public Unit createUnit(Unit unit, string type)
 {
     unit.stats = stats[type];
     unit.health = unit.stats.maxHealth;
     return unit;
 }
        Unit unit; // Unit performing the AttackAction

        #endregion Fields

        #region Constructors

        public AttackAction(Unit unit, Entity target, GameWorld gw)
        {
            this.unit = unit;
            this.target = target;
            this.gw = gw;
        }
 /// <summary>
 /// Adds a Unit to the game.
 /// </summary>
 /// <param name="unit">The unit being added.</param>
 /// <param name="x">Desired X-coord of the Unit.</param>
 /// <param name="y">Desired Y-coord of the Unit.</param>
 /// <returns>true if the unit is added successfully, false otherwise.</returns>
 public bool addUnit(Unit unit, float x, float y)
 {
     return locController.addEntity(unit, x, y);
 }
 public Unit createUnit(ZRTSModel.Player.Player owner, string unitType)
 {
     Unit unit = new Unit(owner, uFact.getStats(unitType));
     return unit;
 }