示例#1
0
        /// <summary>
        /// Returns a UnitRange containing up to 3 lists of points: which squares the unit can move to,
        /// which squares the unit can attack, and which squares the unit can utility-ize.
        /// </summary>
        /// <param name="unit">The unit we are querying for</param>
        /// <param name="blockedSpaces">spaces the unit is not allowed to occupy (e.g. due to ally unit already being there)</param>
        /// <returns></returns>
        /// //TODO: Add this to a different class
        public UnitRange GetPathsForUnit(UnitEntity unit, Position unitPosition, List <Position> blockedSpaces)
        {
            UnitRange retRange = new UnitRange();

            List <PathNode> unvisited  = new List <PathNode>();
            List <PathNode> accessible = new List <PathNode>();

            //Step 1
            //make a node for each tile within raw movement range.
            unvisited = GetUnvisitedTiles(unit.Move, unitPosition, unit.MoveCosts, unit.TeamID);

            //Step 2
            //run Dijkstra's algorithm
            accessible = DijkstraPathfinder.CalculatePathDistance(unvisited, unitPosition.xPos, unitPosition.yPos);

            //Accessible now has only the squares which the unit can actually reach.
            //break them back into Tuples for the UnitRange
            HashSet <Position> validPositions = new HashSet <Position>();

            foreach (PathNode node in accessible.Where(node => node.distance <= unit.Move))
            {
                validPositions.Add(new Position(node.pos.xPos, node.pos.yPos));
            }
            //blocked positions can be pathed through, but not ended in.
            //you can end in your own space though
            validPositions.RemoveWhere(s => blockedSpaces.Contains(s) && !(s.Equals(unitPosition)));

            //Item ranges
            HashSet <Position> attackRanges        = unit.AllAttackRanges();
            HashSet <Position> utilityRanges       = unit.AllUtilityRanges();
            HashSet <Position> attackablePositions = new HashSet <Position>();
            HashSet <Position> utilityPositions    = new HashSet <Position>();

            foreach (Position pos in validPositions)
            {
                foreach (Position offset in attackRanges)
                {
                    Position targetTile = new Position(pos.xPos + offset.xPos, pos.yPos + offset.yPos);
                    if (targetTile.xPos >= 0 && targetTile.xPos < Width && targetTile.yPos >= 0 && targetTile.yPos < Height)
                    {
                        attackablePositions.Add(targetTile);
                    }
                }

                foreach (Position offset in utilityRanges)
                {
                    Position targetTile = new Position(pos.xPos + offset.xPos, pos.yPos + offset.yPos);
                    if (targetTile.xPos >= 0 && targetTile.xPos < Width && targetTile.yPos >= 0 && targetTile.yPos < Height)
                    {
                        utilityPositions.Add(targetTile);
                    }
                }
            }

            retRange.moveRange    = validPositions;
            retRange.attackRange  = attackablePositions;
            retRange.utilityRange = utilityPositions;

            return(retRange);
        }
示例#2
0
        /// <summary>
        /// Adds a UnitEntity to the map at the given position,
        /// and returns a reference to its corresponding MapUnit
        /// </summary>
        /// <param name="unitEntity"></param>
        /// <param name="position"></param>
        /// <returns></returns>
        public MapUnit AddUnit(UnitEntity unitEntity, Position position)
        {
            MapUnit mu;

            try
            {
                mu = unitMap[position.xPos, position.yPos];
            }
            catch (System.IndexOutOfRangeException)
            {
                //unit not added
                throw new MapSizeException("Selection outside of bounds");
            }
            if (mu != null)
            {
                throw new MapUnitOverlapException("Added unit on top of another unit");
            }
            else
            {
                mu          = new MapUnit(unitEntity);
                mu.Position = new Position(position.xPos, position.yPos);
                unitMap[position.xPos, position.yPos] = mu;
                return(mu);
            }
        }
示例#3
0
        //public MapUnit GetUnitByPosition(int x, int y)
        //{
        //	if (x >= terrainMap.GetLength(0) || x < 0)
        //	{
        //		throw new MapSizeException("Selection outside of X bounds");
        //	}
        //	if (y >= terrainMap.GetLength(1) || y < 0)
        //	{
        //		throw new MapSizeException("Selection outside of Y bounds");
        //	}
        //	MapUnit mu = unitMap[x, y];
        //	if (mu == null)
        //	{
        //		throw new UnitNotFoundException("No unit present at x,y");
        //	}

        //	return mu;
        //}

        /// <summary>
        /// Gets the movable squares for the unit, based on their speed, etc.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        internal UnitRange GenerateMovesquares(UnitEntity value)
        {
            MapUnit         mu            = GetUnityByEntity(value);
            List <Position> blockedSpaces = GetUnitAllies(value.TeamID);

            return(GetPathsForUnit(mu.Stats, mu.Position, blockedSpaces));
        }
        private int CalculateEngagementRange(Position engageSquare, UnitEntity target)
        {
            Position targPos = SessionMap.GetUnityByEntity(target).Position;

            Position diff = engageSquare - targPos;

            return(Math.Abs(diff.xPos) + Math.Abs(diff.yPos));
        }
        /// <summary>
        /// Returns a UnitRange containing up to 3 lists of points: which squares the unit can move to,
        /// which squares the unit can attack, and which squares the unit can utility-ize.
        /// </summary>
        /// <param name="unit">The unit we are querying for</param>
        /// <param name="blockedSpaces">spaces the unit is not allowed to occupy (e.g. due to enemy unit already being there)</param>
        /// <returns></returns>
        /// //TODO: Add this to a different class
        public UnitRange GetPathsForUnit(UnitEntity unit, List <Position> blockedSpaces)
        {
            UnitRange retRange = new UnitRange();

            //List<PathNode> unvisited = new List<PathNode>();
            //List<PathNode> accessible = new List<PathNode>();

            ////Step 1
            ////make a node for each tile within raw movement range.
            //unvisited = GetUnvisitedTiles(unit.speed, unit.xPos, unit.yPos, unit.moveCosts);

            ////Step 2
            ////run Dijkstra's algorithm
            //accessible = DijkstraPathfinder.CalculatePathDistance(unvisited, unit.xPos, unit.yPos);

            ////Accessible now has only the squares which the unit can actually reach.
            ////break them back into Tuples for the UnitRange
            //HashSet<Position> validPositions = new HashSet<Position>();
            //foreach (PathNode node in accessible.Where(node => node.distance <= unit.speed))
            //{
            //	validPositions.Add(new Position(node.pos.xPos, node.pos.yPos));
            //}
            ////blocked positions can be pathed through, but not ended in
            //validPositions.RemoveWhere(s => blockedSpaces.Contains(s));

            ////Item ranges
            //HashSet<Position> attackRanges = unit.AllAttackRanges();
            //HashSet<Position> utilityRanges = unit.AllUtilityRanges();
            //HashSet<Position> attackablePositions = new HashSet<Position>();
            //HashSet<Position> utilityPositions = new HashSet<Position>();

            //foreach (Position pos in validPositions)
            //{
            //	foreach (Position offset in attackRanges)
            //	{
            //		Position targetTile = new Position(pos.xPos + offset.xPos, pos.yPos + offset.yPos);
            //		if (targetTile.xPos >= 0 && targetTile.xPos < Width && targetTile.yPos >= 0 && targetTile.yPos < Height)
            //		{
            //			attackablePositions.Add(targetTile);
            //		}
            //	}

            //	foreach (Position offset in utilityRanges)
            //	{
            //		Position targetTile = new Position(pos.xPos + offset.xPos, pos.yPos + offset.yPos);
            //		if (targetTile.xPos >= 0 && targetTile.xPos < Width && targetTile.yPos >= 0 && targetTile.yPos < Height)
            //		{
            //			utilityPositions.Add(targetTile);
            //		}
            //	}
            //}

            //retRange.moveRange = validPositions;
            //retRange.attackRange = attackablePositions;
            //retRange.utilityRange = utilityPositions;

            return(retRange);
        }
示例#6
0
 /// <summary>
 ///  dds the given unit to this Roster
 /// </summary>
 /// <param name="unit"></param>
 /// <returns>True if unit was added, false otherwise</returns>
 public bool AddUnit(UnitEntity unit)
 {
     if (unit.TeamID != TeamID)
     {
         unit.TeamID = this.TeamID;
         return(this.units.Add(unit));
     }
     return(false);
 }
        /// <summary>
        /// Depending on the state, returns objects to render:
        ///  - if no unit selected -> GetActions(x,y), OpenMenu();
        ///  - if new unit selected -> SelectUnit(x,y);
        ///  - if unit already selected -> GetActions(x,y [selectedUnit]), OpenMenu();
        ///  - if In Menu -> SelectFromMenu();
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public List <GameAction> OnConfirmationInputReceived(int x, int y)
        {
            List <GameAction> retList = new List <GameAction>();

            switch (state)
            {
            case SelectionState.NoSelection:
                //attempt to select a unit
                if (SessionMap.QueryTileContents(x, y) == MapSelectionResponse.unitTile)
                {
                    UnitEntity target = SessionMap.GetUnitInfoByPosition(x, y);
                    //only select units who haven't already acted are valid
                    if (target.HasActed == false)
                    {
                        SelectUnit(x, y);
                        retList.Add(new UnitSelectedAction(selectedUnit));
                        return(retList);
                    }
                }
                //open the map menu (e.g. end turn, etc.)
                openMenus.Push(GetActions());
                retList.Add(new MenuOpenedAction(openMenus.Peek()));
                return(retList);

            case SelectionState.UnitSelected:
                //if the current position is in the valid move-space of the unit,
                //generate the actions from there
                if (moveSquares.moveRange.Contains(new Position(x, y)))
                {
                    //open the unit menu (attack, wait, etc.)
                    openMenus.Push(GetActions(x, y));
                    retList.Add(new MenuOpenedAction(openMenus.Peek()));
                    return(retList);
                }
                //the current position is past the valid move-space of the unit,
                //generate the actions from the last valid position
                else if (lastPath != null)
                {
                    openMenus.Push(GetActions(lastPath.Last().xPos, lastPath.Last().yPos));
                    retList.Add(new MenuOpenedAction(openMenus.Peek()));
                    return(retList);
                }
                else
                {
                    throw new SessionStateInvalidException("Could not determine where to calculate actions from");
                }

            case SelectionState.MenuOpen:
                throw new NotImplementedException();

            default:
                throw new SessionStateInvalidException("Could not determine a course of action");
            }
        }
        /// <summary>
        /// Moves the unit along the path
        /// </summary>
        /// <param name="path"></param>
        /// <param name="position"></param>
        private List <GameAction> MoveUnit(UnitEntity unit, List <Position> path)
        {
            List <GameAction> retList = new List <GameAction>();
            MapUnit           mu      = SessionMap.GetUnityByEntity(unit);

            foreach (Position pnode in path)
            {
                bool isFinal = path.Last().Equals(pnode);
                if (!mu.Position.Equals(pnode))
                {
                    SessionMap.MoveUnit(mu, pnode, isFinal);
                    retList.Add(new UnitMoveAction(mu, pnode, isFinal));
                    //Unit Moved event
                }
            }

            return(retList);
        }
示例#9
0
        /// <summary>
        /// Finds a unit on the map, based on their UnitEntity
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public MapUnit GetUnityByEntity(UnitEntity value)
        {
            int w = unitMap.GetLength(0);             // width
            int h = unitMap.GetLength(1);             // height


            for (int x = 0; x < w; ++x)
            {
                for (int y = 0; y < h; ++y)
                {
                    if (unitMap[x, y] != null && unitMap[x, y].Stats.Equals(value))
                    {
                        return(unitMap[x, y]);
                    }
                }
            }
            return(null);
        }
        /// <summary>
        /// Gets actions for the currently selected unit at the given position
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private MenuData GetActions(int x, int y)
        {
            //UnitActionCommand enum
            List <string> unitActions = new List <string>
            {
                //always add wait
                UnitActionCommand.Wait.ToString()
            };

            //attack
            foreach (Position pos in selectedUnit.AllAttackRanges())
            {
                UnitEntity unitEntity = SessionMap.QueryUnitPosition(x + pos.xPos, y + pos.yPos);
                if (unitEntity == null)
                {
                    continue;
                }
                if (unitEntity.TeamID != selectedUnit.TeamID)
                {
                    unitActions.Add(UnitActionCommand.Attack.ToString());
                    break;
                }
            }

            //Staff
            foreach (Position pos in selectedUnit.AllUtilityRanges())
            {
                UnitEntity unitEntity = SessionMap.QueryUnitPosition(x + pos.xPos, y + pos.yPos);
                if (unitEntity == null)
                {
                    continue;
                }
                if (unitEntity.TeamID == selectedUnit.TeamID)
                {
                    unitActions.Add(UnitActionCommand.Staff.ToString());
                    break;
                }
            }

            return(new MenuData(unitActions)
            {
                MenuType = MenuTypes.Unit
            });
        }
        /// <summary>
        /// Navigate backwards through a given menu, returning the previous menu, or unselecting the unit if
        /// selected and no open menu
        /// </summary>
        /// <returns></returns>
        public List <GameAction> OnNegationInputReceived()
        {
            List <GameAction> retList = new List <GameAction>();

            if (MenuOpen)
            {
                retList.Add(new MenuClosedAction(openMenus.Pop()));
                return(retList);
            }
            if (selectedUnit != null)
            {
                UnitEntity ue = selectedUnit;
                selectedUnit = null;

                retList.Add(new UnitDeselectedAction(ue));
                return(retList);
            }

            //nothing to back out of.
            return(retList);
        }
        private List <UnitEntity> GetAttackTargets()
        {
            Position          attackPosition = lastPath.Last();
            List <UnitEntity> retList        = new List <UnitEntity>();


            foreach (Position pos in selectedUnit.AllAttackRanges())
            {
                UnitEntity unitEntity = SessionMap.QueryUnitPosition(attackPosition.xPos + pos.xPos, attackPosition.yPos + pos.yPos);
                if (unitEntity == null)
                {
                    continue;
                }
                if (unitEntity.TeamID != selectedUnit.TeamID)
                {
                    retList.Add(unitEntity);
                }
            }

            return(retList);
        }
示例#13
0
 public MapUnit(UnitEntity ue)
 {
     this.Stats = ue;
 }
 public CombatDrawAction(UnitEntity attacker, UnitEntity defender) : base(GameActionType.CombatDraw)
 {
     this.Attacker = attacker;
     this.Defender = defender;
 }
 public CombatHitAction(UnitEntity attacker, int attackerDamage, List <int> randNumbersUsed) : base(GameActionType.CombatHit)
 {
     this.AttackingUnit   = attacker;
     this.AttackerDamage  = attackerDamage;
     this.RandNumbersUsed = randNumbersUsed;
 }
示例#16
0
 public UnitDeselectedAction(UnitEntity ue) : base(GameActionType.UnitDeselected)
 {
     this.DeselectedUnit = ue;
 }
 public UnitSelectedAction(UnitEntity selectedUnit) : base(GameActionType.UnitSelected)
 {
     this.SelectedUnit = selectedUnit;
 }
示例#18
0
        /// <summary>
        /// Finds a path to the given space, using current path as a starting point
        /// </summary>
        /// <param name="selectedUnit"></param>
        /// <param name="targ"></param>
        /// <param name="currentPath"></param>
        /// <returns></returns>
        internal List <Position> FindPath(UnitEntity unit, Position targ, List <Position> currentPath)
        {
            List <PathNode> unvisited  = new List <PathNode>();
            List <PathNode> accessible = new List <PathNode>();

            //Part 1 - make sure the target is not already in the path
            if (currentPath.Contains(targ))
            {
                int i = currentPath.IndexOf(targ);
                return(currentPath.GetRange(0, i + 1));
            }

            //Part 2 - find path from existing position
            if (unit.Move - currentPath.Count > 0)             //fail fast for finding path from scratch
            {
                Position previousPosition = currentPath.Last();

                //Step 1
                //make a node for each tile within modified movement range.
                unvisited = GetUnvisitedTiles(unit.Move - currentPath.Count, previousPosition, unit.MoveCosts, unit.TeamID);

                //Step 2
                //run Dijkstra's algorithm
                accessible = DijkstraPathfinder.CalculatePathDistance(unvisited, previousPosition.xPos, previousPosition.yPos);

                if (accessible.Find(s => s.pos.Equals(targ)) != null)
                {
                    //we can reach the new square from our existing path. return the new path as an append to the existing path
                    List <Position> appendList = new List <Position>();

                    PathNode markerNode = accessible.Find(s => s.pos.Equals(targ));

                    while (markerNode != null && !markerNode.pos.Equals(previousPosition))
                    {
                        appendList.Add(markerNode.pos);
                        markerNode = markerNode.previousNode;
                    }

                    appendList.Reverse();
                    currentPath.AddRange(appendList);
                    return(currentPath);
                }
                //else - we need to find the path from scratch
            }

            //Part 3 - calculate path from scratch

            //Step 1
            //make a node for each tile within modified movement range.
            unvisited = GetUnvisitedTiles(unit.Move, currentPath[0], unit.MoveCosts, unit.TeamID);

            //Step 2
            //run Dijkstra's algorithm
            accessible = DijkstraPathfinder.CalculatePathDistance(unvisited, currentPath[0].xPos, currentPath[0].yPos);
            if (accessible.Find(s => s.pos.Equals(targ)) != null)
            {
                //we can reach the new square from our existing path. return the new path as an append to the existing path
                List <Position> retList = new List <Position>();

                PathNode markerNode = accessible.Find(s => s.pos.Equals(targ));

                while (markerNode != null)
                {
                    retList.Add(markerNode.pos);
                    markerNode = markerNode.previousNode;
                }

                retList.Reverse();

                return(retList);
            }
            else
            {
                throw new PathFindingException("Could not find path to a navigable tile");
            }
        }
示例#19
0
 public CombatMissAction(UnitEntity attackingUnit, List <int> randNumbersUsed) : base(GameActionType.CombatMiss)
 {
     this.RandNumbersUsed = randNumbersUsed;
     this.AttackingUnit   = attackingUnit;
 }
 public List <GameAction> InitiateCombat(UnitEntity attacker, UnitEntity defender, int range)
 {
     return(InitiateCombat((FE7UnitEntity)attacker, (FE7UnitEntity)defender, range));
 }
示例#21
0
 public UnitWaitAction(UnitEntity selectedUnit) : base(GameActionType.UnitWait)
 {
     this.WaitingUnit = selectedUnit;
 }