Пример #1
0
        public static Dictionary <short, MoveNode> GetReachableZone(FightGame fight, Map map, short currentCellId)
        {
            Dictionary <short, MoveNode> zone = new Dictionary <short, MoveNode>();

            if (fight.PlayedFighter.MovementPoints <= 0)
            {
                return(zone);
            }

            var maxDistance = fight.PlayedFighter.MovementPoints;

            List <PathNode> opened = new List <PathNode>();
            Dictionary <short, PathNode> closed = new Dictionary <short, PathNode>();

            var node = new PathNode(currentCellId, fight.PlayedFighter.MovementPoints, fight.PlayedFighter.ActionPoints, 0, 0, 1);

            opened.Add(node);
            closed[currentCellId] = node;

            while (opened.Count > 0)
            {
                var current = opened.Last();
                opened.Remove(current);
                var cellId     = current.CellId;
                var neighbours = MapPoint.GetNeighbourCells(cellId, false);

                var tacklers = new List <FighterEntry>();
                int i        = 0;
                while (i < neighbours.Count)
                {
                    var tackler = fight.Fighters.FirstOrDefault(f => f.CellId == neighbours[i]?.CellId);

                    if (neighbours[i] != null && tackler == null)
                    {
                        i++;
                        continue;
                    }

                    neighbours.RemoveAt(i);
                    if (tackler != null)
                    {
                        tacklers.Add(tackler);
                    }
                }

                GetTackleCost(fight, tacklers, current.AvailableMp, current.AvailableAp, out int mpCost, out int apCost);
                var availableMp = current.AvailableMp - mpCost - 1;
                var availableAp = current.AvailableAp - apCost;
                var tackleMp    = current.TackleMp + mpCost;
                var tackleAp    = current.TackleAp + apCost;
                var distance    = current.Distance + 1;
                var reachable   = availableMp >= 0;

                // TODO: Handle marked cells

                for (i = 0; i < neighbours.Count; i++)
                {
                    if (closed.ContainsKey(neighbours[i].CellId))
                    {
                        var previous = closed[neighbours[i].CellId];
                        if (previous.AvailableMp > availableMp)
                        {
                            continue;
                        }

                        if (previous.AvailableMp == availableMp && previous.AvailableAp >= availableAp)
                        {
                            continue;
                        }
                    }

                    if (!map.Cells[neighbours[i].CellId].IsWalkable(true))
                    {
                        continue;
                    }

                    zone[neighbours[i].CellId] = new MoveNode(apCost, mpCost, cellId, reachable);
                    node = new PathNode(neighbours[i].CellId, availableMp, availableAp, tackleMp, tackleAp, distance);
                    closed[neighbours[i].CellId] = node;

                    if (current.Distance < maxDistance)
                    {
                        opened.Add(node);
                    }
                }
            }

            foreach (short cellKey in zone.Keys)
            {
                zone[cellKey].Path = GetPath(currentCellId, cellKey, zone);
            }

            return(zone);
        }