// TODO: refactor this to be handled by region // assumes the tiles are adjacent to each other public virtual float costBetween(PathTile t1, PathTile t2) { float cost = ((t1.tile.index - t2.tile.index).magnitude > 1f) ? Mathf.Sqrt(2f) : 1f; // base cost between tiles // cost due to elevation float elevationDelta = (t2.tile.pos.y - t1.tile.pos.y); if (elevationDelta < 0) { cost -= elevationDelta / downElevatonPerPoint; } else { cost += elevationDelta / upElevatonPerPoint; } //Debug.Log("PathFinder cost between " + t1.tile.index + " and " + t2.tile.index + ": " + cost + " elevation influence " + (elevationDelta / downElevatonPerPoint)); // cost due to tile attributes //cost += t2.tile.moveCostPenalty; if (cost > this.maxIncrementalCost) { return(float.PositiveInfinity); } return(cost); }
// assumes the tiles are adjacent to each other public virtual float costBetween(PathTile t1, PathTile t2) { float cost = 1f; // base cost between tiles // cost due to elevation float elevationDelta = (t2.tile.getY() - t1.tile.getY()); if (elevationDelta < 0) { cost -= elevationDelta / downElevatonPerPoint; } else { cost += elevationDelta / upElevatonPerPoint; } // cost due to tile attributes cost += t2.tile.moveCostPenalty; if (cost > this.maxIncrementalCost) { return(float.PositiveInfinity); } return(cost); }
public bool CompareTo(PathTile pt) { if (this.tile.index == pt.tile.index) { return(true); } else { return(false); } }
public float heuristic(Region region, PathTile start, PathTile goal) { float cost = region.distanceBetweenTiles(start.tile, goal.tile); float elevationDelta = start.tile.pos.y - goal.tile.pos.y; if (elevationDelta < 0) { cost += -elevationDelta / downElevatonPerPoint; } else { cost += elevationDelta / upElevatonPerPoint; } return(cost); }
public float heuristic(PathTile start, PathTile goal) { float cost = HexTile.distanceBetweenHexCoords(start.tile.index, goal.tile.index); float elevationDelta = (start.tile.getY() - goal.tile.getY()); if (elevationDelta < 0) { cost += -elevationDelta / downElevatonPerPoint; } else { cost += elevationDelta / upElevatonPerPoint; } return(cost); }
public bool equals(PathTile pt) { return(this.tile.Equals(pt.tile)); }
public void addExploredPathtile(PathTile pt) { this.exploredPathTiles.Add(pt); }
public void addPathtile(PathTile pt) { this.pathTiles.Add(pt); }
public float costBetween(PathTile t1, PathTile t2) { return(uniformCost); }
public float heuristic(Region region, PathTile start, PathTile goal) { // Dijkstra can be considered as a special case of A* where heuristic is always equal zero return(0); }
// *** HEURISTIC COMPUTATIONS *** /// public abstract float heuristic(Region region, PathTile start, PathTile goal);
public PathResult pathFromTo(Region region, Tile start, Tile goal, bool playersCanBlockPath = false) { PathResult pathResult = new PathResult(); PathTile goalPt = new PathTile(goal); // set up lists PriorityQueue <PathTile> frontier = new PriorityQueue <PathTile>(); Dictionary <Vector2Int, PathTile> explored = new Dictionary <Vector2Int, PathTile>(); Dictionary <Vector2Int, PathTile> previous = new Dictionary <Vector2Int, PathTile>(); Dictionary <Vector2Int, float> costs = new Dictionary <Vector2Int, float>(); PathTile crt; crt = new PathTile(start); crt.depth = 0; frontier.Enqueue(crt, 0); previous[crt.tile.index] = null; costs[crt.tile.index] = 0; // start pathfinding while (!frontier.IsEmpty()) { // get current crt = frontier.Dequeue(); // record that the tile was explored explored[crt.tile.index] = crt; if (crt.equals(goalPt)) { // reached goal; search complete pathResult.reachedGoal = true; pathResult.pathCost = costs[crt.tile.index]; break; } // get neighbor tiles List <PathTile> neighbors = new List <PathTile>(); foreach (Tile neighborTile in region.getTileNeighbors(crt.tile.index)) { PathTile neighbor = new PathTile(neighborTile); //neighborPt.cost = crt.cost + costBetween(crt, neighborPt); neighbor.depth = crt.depth + 1; neighbors.Add(neighbor); } // add neighbor tiles to search float cost, priority; foreach (PathTile neighbor in neighbors) { // check if exceeding max depth if (neighbor.depth > maxDepth) { break; } // compute cost float _cost = costBetween(crt, neighbor); //// check if path is blocked by another player //if (playersCanBlockPath && GameControl.gameSession.checkForPlayersAt(neighbor.tile) != null) //{ // if (!neighbor.CompareTo(goalPt)) // ensures that you can move to a tile with an enemy // _cost = float.PositiveInfinity; // set highest cost to signify that the tile is unreachable //} cost = costs[crt.tile.index] + _cost; if (cost <= maxCost) { if (!costs.ContainsKey(neighbor.tile.index) || cost < costs[neighbor.tile.index]) { costs[neighbor.tile.index] = cost; // compute heuristic priority priority = cost + heuristic(region, neighbor, goalPt); priority -= neighbor.depth * heuristicDepthInfluence; // makes so that tiles closest to goal are more eagerly explored frontier.Enqueue(neighbor, priority); previous[neighbor.tile.index] = crt; } } } } // build list of tiles on path if goal was reached if (pathResult.reachedGoal) { pathResult.addPathtile(goalPt); crt = previous[goal.index]; while (crt != null) { pathResult.addPathtile(crt); crt = previous[crt.tile.index]; } } foreach (PathTile pt in explored.Values) { pathResult.addExploredPathtile(pt); } return(pathResult); }
public float heuristic(PathTile start, PathTile goal) { return(0); }
// *** HEURISTIC COMPUTATIONS *** /// public abstract float heuristic(PathTile start, PathTile goal);