/// <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;
 }
        /// <summary>
        /// Notify of update
        /// </summary>
        public override void notify()
        {
            //these should be passed in or something
            GameWorld gameWorld = new GameWorld(20, 20);
            int x1, x2, y1, y2;    //boundary includes 1 not 2
            x1 = 0; x2 = 0; y1 = 0; y2 = 0;

            // Do some update on View
            //(1) Find the way to get all units within the boundary (all selected units)
            Cell c;
            Unit s;
            List<Unit> selected = new List<Unit>();

            for(int x = x1; x<x2; x++)
            {
                for(int y=y1; y<y2; y++)
                {
                    c = gameWorld.map.cells[x, y];
                    s = c.getUnit();
                    //if (e == null)
                      //  e = c.entity;
                    //if (s!=null && s.getOwner()==)
                        //selected.Add(s);
                }
            }

            //(2) Notify draw in the view object
            // view.DrawSelected(selected);

            // (3) Look at View drawSelected()
        }
        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;
        }
        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 GameWorld.GameWorld loadGameWorld(Stream map)
        {
            BinaryFormatter bin = new BinaryFormatter();

            GameWorld.GameWorld gw = (GameWorld.GameWorld)bin.Deserialize(map);

            return(gw);
        }
        public void saveGameWorld(GameWorld.GameWorld gw, string name)
        {
            string path = "Content/savedMaps/" + name + ".bin";

            using (Stream stream = File.Open(path, FileMode.Create))
            {
                BinaryFormatter bin = new BinaryFormatter();
                bin.Serialize(stream, gw);
            }
        }
        public void saveGameWorld(GameWorld.GameWorld gw, string name)
        {
            string path = "Content/savedMaps/" + name + ".bin";

            using (Stream stream = File.Open(path, FileMode.Create))
            {
                BinaryFormatter bin = new BinaryFormatter();
                bin.Serialize(stream, gw);
            }
        }
 /**** 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);
         }
     }
 }
        /// <summary>
        /// This function will process the events that the observer has seen and will make the observer "react" to those events.
        /// </summary>
        /// <param name="observer">The GameEventObserver that will "react" to GameEvents it has seen.</param>
        /// <param name="gw">The GameWorld the GameEventObserver is in.</param>
        public static void processEvents(GameEventObserver observer, GameWorld gw)
        {
            // Does the observer have GameEvents to process>
            if (observer.getEventList().Count > 0)
            {
                // Check if observer is a Unit.
                if (observer.GetType().Name.Equals("Unit"))
                {
                    Unit unit = (Unit)observer.getEntity();
                    handleEventsForUnit(unit, gw);
                }

                // Clear the event list.
                observer.getEventList().Clear();
            }
        }
        /// <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
                }
            }
        }
        /// <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 VisibilityMapLogic(GameWorld gw, Player humanPlayer)
 {
     this.gw = gw;
     this.map = gw.map;
     this.humanPlayer = humanPlayer;
 }
 public EntityLocController(Scenario scenario)
 {
     this.scenario = scenario;
     this.gw = scenario.getGameWorld();
 }
        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;
        }
        /*** 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;
        }
 public EntityLocController(Scenario scenario, VisibilityMapLogic visMapLogic)
 {
     this.scenario = scenario;
     this.gw = scenario.getGameWorld();
     this.visMapLogic = visMapLogic;
 }
        /// <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 + ")");
                    }
                }
            }
        }
        private void setUpController(Scenario scenario)
        {
            this.scenario = scenario;
            this.gameWorld = this.scenario.getGameWorld();
            this.actionController = new ActionController(scenario);
            this.locController = new EntityLocController(scenario);

            setUpFactories();
            this.creator = new EntityCreator(this.unitFactory, this.buildingFactory);
        }
 private void setUpController(Scenario scenario)
 {
     this.scenario = scenario;
     this.gameWorld = this.scenario.getGameWorld();
     this.visMapLogic = new VisibilityMapLogic(scenario.getGameWorld(), scenario.getPlayer());
     this.locController = new EntityLocController(scenario, this.visMapLogic);
 }