public static List<Position> FindPath( Engine engine, Unit unit, Tile start, Tile end )
        {
            List<Position> path = null;

            if (!unit.CanMove(end.position))
            {
                foreach (Position pos in BreadthFirst(engine, end.position, -1, 500))
                {
                    if (unit.CanMove(pos))
                    {
                        end = engine.map.tiles[pos.x, pos.y];
                        break;
                    }
                }
            }
            if (!unit.CanMove(end.position))
            {
                return null;
            }

            bool success = false;
            start.pathParent = null;
            start.pathDistance = 0;
            start.pathHeuristic = start.pathDistance + FValue(start, end);
            PriorityQueue<Tile> openSet = new PriorityQueue<Tile>();
            openSet.Enqueue(start);
            int count = 0;

            //generate path
            while ( openSet.Count() > 0 )
            {
                count += 1;
                Tile currentBest = openSet.Dequeue();
                currentBest.pathIndex = pathCounter;
                // if we are at the goal end
                if (currentBest.position.Equals(end.position))
                {
                    success = true;
                    break;
                }
                // Give up if we backtrack too far
                if ((currentBest.pathHeuristic >= start.pathHeuristic*14 &&
                    count > 2000) || count > 4000)
                {
                    break;
                }
                // Take current best, generate all possible nodes, push them onto queue
                foreach (var neighbor in currentBest.neighbors)
                {
                    if (!unit.CanMove(neighbor.position))
                    {
                        continue;
                    }
                    double tentativeCost = currentBest.pathDistance + neighbor.tileType.movementCost;
                    if (neighbor.pathIndex < pathCounter)
                    {
                        neighbor.pathIndex = pathCounter;
                        neighbor.pathParent = currentBest;
                        neighbor.pathDistance = tentativeCost;
                        neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end);
                        openSet.Enqueue(neighbor);
                    }
                    else if (tentativeCost < neighbor.pathDistance)
                    {
                        // Update costs if the current path is better than the existing one
                        neighbor.pathParent = currentBest;
                        neighbor.pathDistance = tentativeCost;
                        neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end);
                        openSet.HeapifyUp(neighbor);
                    }
                }
            }
            if ( success )
            {
                // Generate path by following parent from end to start
                path = new List<Position>();
                Tile runner = end;
                while (runner != null)
                {
                    path.Insert(0, runner.position);
                    runner = runner.pathParent;
                }
            }

            pathCounter += 1;

            return path;
        }
        public static List <Position> FindPath(Engine engine, Unit unit, Tile start, Tile end)
        {
            List <Position> path = null;

            if (!unit.CanMove(end.position))
            {
                foreach (Position pos in BreadthFirst(engine, end.position, -1, 500))
                {
                    if (unit.CanMove(pos))
                    {
                        end = engine.map.tiles[pos.x, pos.y];
                        break;
                    }
                }
            }
            if (!unit.CanMove(end.position))
            {
                return(null);
            }

            bool success = false;

            start.pathParent    = null;
            start.pathDistance  = 0;
            start.pathHeuristic = start.pathDistance + FValue(start, end);
            PriorityQueue <Tile> openSet = new PriorityQueue <Tile>();

            openSet.Enqueue(start);
            int count = 0;

            //generate path
            while (openSet.Count() > 0)
            {
                count += 1;
                Tile currentBest = openSet.Dequeue();
                currentBest.pathIndex = pathCounter;
                // if we are at the goal end
                if (currentBest.position.Equals(end.position))
                {
                    success = true;
                    break;
                }
                // Give up if we backtrack too far
                if ((currentBest.pathHeuristic >= start.pathHeuristic * 14 &&
                     count > 2000) || count > 4000)
                {
                    break;
                }
                // Take current best, generate all possible nodes, push them onto queue
                foreach (var neighbor in currentBest.neighbors)
                {
                    if (!unit.CanMove(neighbor.position))
                    {
                        continue;
                    }
                    double tentativeCost = currentBest.pathDistance + neighbor.tileType.movementCost;
                    if (neighbor.pathIndex < pathCounter)
                    {
                        neighbor.pathIndex     = pathCounter;
                        neighbor.pathParent    = currentBest;
                        neighbor.pathDistance  = tentativeCost;
                        neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end);
                        openSet.Enqueue(neighbor);
                    }
                    else if (tentativeCost < neighbor.pathDistance)
                    {
                        // Update costs if the current path is better than the existing one
                        neighbor.pathParent    = currentBest;
                        neighbor.pathDistance  = tentativeCost;
                        neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end);
                        openSet.HeapifyUp(neighbor);
                    }
                }
            }
            if (success)
            {
                // Generate path by following parent from end to start
                path = new List <Position>();
                Tile runner = end;
                while (runner != null)
                {
                    path.Insert(0, runner.position);
                    runner = runner.pathParent;
                }
            }

            pathCounter += 1;

            return(path);
        }
Beispiel #3
0
        private void ProduceOrder(Order order)
        {
            // If the unit is told to build a structure far away, and he is not in range yet
            if (CanMove() && order.targetPosition != null && order.targetPosition.Distance(position) > 1)
            {
                MoveTowards(order.targetPosition);
                return;
            }

            status = Status.Producing;
            // If the player does not has enough moneyz
            if (owner.gold < order.unitTypeBuild.goldCost ||
                owner.iron < order.unitTypeBuild.ironCost ||
                owner.manaCystals < order.unitTypeBuild.manaCrystalsCost)
            {
                // Try again later
                engine.ScheduleUpdate(buildRetryCooldown, this);
                return;
            }

            // Find place to put unit
            Position targetLocation  = position;
            Position producePosition = null;

            if (order.targetPosition == null)
            {
                foreach (var testPosition in Pathfinder.BreadthFirst(engine, targetLocation, distance: 1))
                {
                    if (engine.GetUnitAt(testPosition) == null)
                    {
                        producePosition = testPosition;
                        break;
                    }
                }
            }
            else
            {
                producePosition = order.targetPosition;
            }
            if (producePosition == null)
            {
                // Try again in the future
                engine.ScheduleUpdate(buildRetryCooldown, this);
                return;
            }

            // Subtract resources
            owner.gold        -= order.unitTypeBuild.goldCost;
            owner.iron        -= order.unitTypeBuild.ironCost;
            owner.manaCystals -= order.unitTypeBuild.manaCrystalsCost;

            // Create the unit
            Unit u = engine.AddUnit(order.unitTypeBuild, producePosition, owner);

            if (order.targetPosition != null && u.CanMove())
            {
                // Tell the produced unit to go to the rally point
                engine.OrderMove(u, order.targetPosition);
            }
            else if (u.type.name.Equals("GoldMine"))
            {
                engine.OrderGather(u, u.position);
            }

            NextOrder();
            engine.ScheduleUpdate(buildCooldown, this);
        }