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); }
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); }