public CPos Expand(World world) { var p = Queue.Pop(); while (CellInfo[p.Location].Seen) { if (Queue.Empty) { return(p.Location); } p = Queue.Pop(); } var pCell = CellInfo[p.Location]; pCell.Seen = true; CellInfo[p.Location] = pCell; var thisCost = mobileInfo.MovementCostForCell(world, p.Location); if (thisCost == int.MaxValue) { return(p.Location); } if (customCost != null) { var c = customCost(p.Location); if (c == int.MaxValue) { return(p.Location); } } // This current cell is ok; check all immediate directions: Considered.Add(p.Location); for (var i = 0; i < nextDirections.Length; ++i) { var d = nextDirections[i].First; nextDirections[i].Second = int.MaxValue; var newHere = p.Location + d; // Is this direction flat-out unusable or already seen? if (!world.Map.Contains(newHere)) { continue; } if (CellInfo[newHere].Seen) { continue; } // Now we may seriously consider this direction using heuristics: var costHere = mobileInfo.MovementCostForCell(world, newHere); if (costHere == int.MaxValue) { continue; } if (!mobileInfo.CanEnterCell(world, self, newHere, IgnoreBuilding, CheckForBlocked ? CellConditions.TransientActors : CellConditions.None)) { continue; } if (customBlock != null && customBlock(newHere)) { continue; } var est = Heuristic(newHere); if (est == int.MaxValue) { continue; } var cellCost = costHere; if (d.X * d.Y != 0) { cellCost = (cellCost * 34) / 24; } var userCost = 0; if (customCost != null) { userCost = customCost(newHere); cellCost += userCost; } // directional bonuses for smoother flow! if (laneBias != 0) { var ux = newHere.X + (InReverse ? 1 : 0) & 1; var uy = newHere.Y + (InReverse ? 1 : 0) & 1; if (ux == 0 && d.Y < 0) { cellCost += laneBias; } else if (ux == 1 && d.Y > 0) { cellCost += laneBias; } if (uy == 0 && d.X < 0) { cellCost += laneBias; } else if (uy == 1 && d.X > 0) { cellCost += laneBias; } } var newCost = CellInfo[p.Location].MinCost + cellCost; // Cost is even higher; next direction: if (newCost > CellInfo[newHere].MinCost) { continue; } var hereCell = CellInfo[newHere]; hereCell.Path = p.Location; hereCell.MinCost = newCost; CellInfo[newHere] = hereCell; nextDirections[i].Second = newCost + est; Queue.Add(new PathDistance(newCost + est, newHere)); if (newCost > MaxCost) { MaxCost = newCost; } Considered.Add(newHere); } // Sort to prefer the cheaper direction: // Array.Sort(nextDirections, (a, b) => a.Second.CompareTo(b.Second)); return(p.Location); }
public CPos Expand(World world) { var p = queue.Pop(); while (cellInfo[p.Location.X, p.Location.Y].Seen) { if (queue.Empty) { return(p.Location); } else { p = queue.Pop(); } } cellInfo[p.Location.X, p.Location.Y].Seen = true; var thisCost = mobileInfo.MovementCostForCell(world, p.Location); if (thisCost == int.MaxValue) { return(p.Location); } if (customCost != null) { int c = customCost(p.Location); if (c == int.MaxValue) { return(p.Location); } } // This current cell is ok; check all immediate directions: considered.Add(p.Location); for (int i = 0; i < nextDirections.Length; ++i) { CVec d = nextDirections[i].First; nextDirections[i].Second = int.MaxValue; CPos newHere = p.Location + d; // Is this direction flat-out unusable or already seen? if (!world.Map.IsInMap(newHere.X, newHere.Y)) { continue; } if (cellInfo[newHere.X, newHere.Y].Seen) { continue; } // Now we may seriously consider this direction using heuristics: var costHere = mobileInfo.MovementCostForCell(world, newHere); if (costHere == int.MaxValue) { continue; } if (!mobileInfo.CanEnterCell(world, self, newHere, ignoreBuilding, checkForBlocked, false)) { continue; } if (customBlock != null && customBlock(newHere)) { continue; } var est = heuristic(newHere); if (est == int.MaxValue) { continue; } int cellCost = costHere; if (d.X * d.Y != 0) { cellCost = (cellCost * 34) / 24; } int userCost = 0; if (customCost != null) { userCost = customCost(newHere); cellCost += userCost; } // directional bonuses for smoother flow! if (LaneBias != 0) { var ux = (newHere.X + (inReverse ? 1 : 0) & 1); var uy = (newHere.Y + (inReverse ? 1 : 0) & 1); if (ux == 0 && d.Y < 0) { cellCost += LaneBias; } else if (ux == 1 && d.Y > 0) { cellCost += LaneBias; } if (uy == 0 && d.X < 0) { cellCost += LaneBias; } else if (uy == 1 && d.X > 0) { cellCost += LaneBias; } } int newCost = cellInfo[p.Location.X, p.Location.Y].MinCost + cellCost; // Cost is even higher; next direction: if (newCost > cellInfo[newHere.X, newHere.Y].MinCost) { continue; } cellInfo[newHere.X, newHere.Y].Path = p.Location; cellInfo[newHere.X, newHere.Y].MinCost = newCost; nextDirections[i].Second = newCost + est; queue.Add(new PathDistance(newCost + est, newHere)); if (newCost > maxCost) { maxCost = newCost; } considered.Add(newHere); } // Sort to prefer the cheaper direction: //Array.Sort(nextDirections, (a, b) => a.Second.CompareTo(b.Second)); return(p.Location); }
public bool CanEnterCell(CPos cell, Actor ignoreActor, bool checkTransientActors) { return(Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors, true)); }
public CPos Expand(World world) { var p = queue.Pop(); while (cellInfo[p.Location.X, p.Location.Y].Seen) { if (queue.Empty) { return(p.Location); } else { p = queue.Pop(); } } cellInfo[p.Location.X, p.Location.Y].Seen = true; var thisCost = mobileInfo.MovementCostForCell(world, p.Location); if (thisCost == int.MaxValue) { return(p.Location); } if (customCost != null) { int c = customCost(p.Location); if (c == int.MaxValue) { return(p.Location); } } foreach (CVec d in directions) { CPos newHere = p.Location + d; if (!world.Map.IsInMap(newHere.X, newHere.Y)) { continue; } if (cellInfo[newHere.X, newHere.Y].Seen) { continue; } var costHere = mobileInfo.MovementCostForCell(world, newHere); if (costHere == int.MaxValue) { continue; } if (!mobileInfo.CanEnterCell(world, self, newHere, ignoreBuilding, checkForBlocked, false)) { continue; } if (customBlock != null && customBlock(newHere)) { continue; } var est = heuristic(newHere); if (est == int.MaxValue) { continue; } int cellCost = costHere; if (d.X * d.Y != 0) { cellCost = (cellCost * 34) / 24; } if (customCost != null) { cellCost += customCost(newHere); } // directional bonuses for smoother flow! if (LaneBias != 0) { var ux = (newHere.X + (inReverse ? 1 : 0) & 1); var uy = (newHere.Y + (inReverse ? 1 : 0) & 1); if (ux == 0 && d.Y < 0) { cellCost += LaneBias; } else if (ux == 1 && d.Y > 0) { cellCost += LaneBias; } if (uy == 0 && d.X < 0) { cellCost += LaneBias; } else if (uy == 1 && d.X > 0) { cellCost += LaneBias; } } int newCost = cellInfo[p.Location.X, p.Location.Y].MinCost + cellCost; if (newCost >= cellInfo[newHere.X, newHere.Y].MinCost) { continue; } cellInfo[newHere.X, newHere.Y].Path = p.Location; cellInfo[newHere.X, newHere.Y].MinCost = newCost; queue.Add(new PathDistance(newCost + est, newHere)); } return(p.Location); }
public bool CanEnterCell(int2 cell, Actor ignoreActor, bool checkTransientActors) { return(Info.CanEnterCell(self.World, self.Owner, cell, ignoreActor, checkTransientActors)); }
public bool CanEnterCell(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true) { return(Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors ? CellConditions.All : CellConditions.BlockedByMovers)); }