public List <CPos> FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WRange range, Actor self) { var mi = self.Info.Traits.Get <MobileInfo>(); var targetCell = world.Map.CellContaining(target); var rangeSquared = range.Range * range.Range; // Correct for SubCell offset target -= world.Map.OffsetOfSubCell(srcSub); // Select only the tiles that are within range from the requested SubCell // This assumes that the SubCell does not change during the path traversal var tilesInRange = world.Map.FindTilesInCircle(targetCell, range.Range / 1024 + 1) .Where(t => (world.Map.CenterOfCell(t) - target).LengthSquared <= rangeSquared && mi.CanEnterCell(self.World as World, self as Actor, t)); // See if there is any cell within range that does not involve a cross-domain request // Really, we only need to check the circle perimeter, but it's not clear that would be a performance win var domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); if (domainIndex != null) { var passable = mi.GetMovementClass(world.TileSet); tilesInRange = new List <CPos>(tilesInRange.Where(t => domainIndex.IsPassable(source, t, (uint)passable))); if (!tilesInRange.Any()) { return(EmptyPath); } } var path = FindBidiPath( PathSearch.FromPoints(world, mi, self, tilesInRange, source, true), PathSearch.FromPoint(world, mi, self, source, targetCell, true).Reverse()); return(path); }
public List<CPos> FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WDist range, Actor self) { var mi = self.Info.TraitInfo<MobileInfo>(); var li = mi.LocomotorInfo; var targetCell = world.Map.CellContaining(target); // Correct for SubCell offset target -= world.Map.Grid.OffsetOfSubCell(srcSub); // Select only the tiles that are within range from the requested SubCell // This assumes that the SubCell does not change during the path traversal var tilesInRange = world.Map.FindTilesInCircle(targetCell, range.Length / 1024 + 1) .Where(t => (world.Map.CenterOfCell(t) - target).LengthSquared <= range.LengthSquared && mi.CanEnterCell(self.World, self, t)); // See if there is any cell within range that does not involve a cross-domain request // Really, we only need to check the circle perimeter, but it's not clear that would be a performance win var domainIndex = world.WorldActor.TraitOrDefault<DomainIndex>(); if (domainIndex != null) { tilesInRange = new List<CPos>(tilesInRange.Where(t => domainIndex.IsPassable(source, t, li))); if (!tilesInRange.Any()) return EmptyPath; } using (var fromSrc = PathSearch.FromPoints(world, li, self, tilesInRange, source, true)) using (var fromDest = PathSearch.FromPoint(world, li, self, source, targetCell, true).Reverse()) return FindBidiPath(fromSrc, fromDest); }
public List <CPos> FindUnitPath(CPos source, CPos target, Actor self, Actor ignoreActor) { var li = self.Info.TraitInfo <MobileInfo>().LocomotorInfo; if (!cached) { domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); cached = true; } // If a water-land transition is required, bail early if (domainIndex != null && !domainIndex.IsPassable(source, target, li)) { return(EmptyPath); } var distance = source - target; if (source.Layer == target.Layer && distance.LengthSquared < 3 && li.CanMoveFreelyInto(world, self, target, null, CellConditions.All)) { return new List <CPos> { target } } ; List <CPos> pb; using (var fromSrc = PathSearch.FromPoint(world, li, self, target, source, true).WithIgnoredActor(ignoreActor)) using (var fromDest = PathSearch.FromPoint(world, li, self, source, target, true).WithIgnoredActor(ignoreActor).Reverse()) pb = FindBidiPath(fromSrc, fromDest); return(pb); }
public List <CPos> FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WDist range, Actor self) { var mi = self.Info.TraitInfo <MobileInfo>(); var targetCell = world.Map.CellContaining(target); //Correct for SubCell offset. //纠正SubCell偏移 target -= world.Map.Grid.OffsetOfSubCell(srcSub); var tilesInRange = world.Map.FindTilesInCircle(targetCell, range.Length / 1024 + 1). Where(t => (world.Map.CenterOfCell(t) - target).LengthSquared <= range.LengthSquared && mi.CanEnterCell(self.World, self, t)); var domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); if (domainIndex != null) { var passable = mi.GetMovementClass(world.Map.Rules.TileSet); tilesInRange = new List <CPos>(tilesInRange.Where(t => domainIndex.IsPassable(source, t, mi, (uint)passable))); if (!tilesInRange.Any()) { return(EmptyPath); } } using (var fromSrc = PathSearch.FromPoints(world, mi, self, tilesInRange, source, true)) using (var fromDest = PathSearch.FromPoint(world, mi, self, source, targetCell, true).Reverse()) return(FindBidiPath(fromSrc, fromDest)); }
List <CPos> CalculatePathToTarget(Actor self, BlockedByActor check) { var loc = self.Location; // PERF: Assume that CandidateMovementCells doesn't change within a tick to avoid repeated queries // when Move enumerates different BlockedByActor values if (searchCellsTick != self.World.WorldTick) { searchCells.Clear(); searchCellsTick = self.World.WorldTick; foreach (var cell in CandidateMovementCells(self)) { if (domainIndex.IsPassable(loc, cell, Mobile.Info.LocomotorInfo) && Mobile.CanEnterCell(cell)) { searchCells.Add(cell); } } } if (!searchCells.Any()) { return(NoPath); } using (var fromSrc = PathSearch.FromPoints(self.World, Mobile.Locomotor, self, searchCells, loc, check)) using (var fromDest = PathSearch.FromPoint(self.World, Mobile.Locomotor, self, loc, lastVisibleTargetLocation, check).Reverse()) return(pathFinder.FindBidiPath(fromSrc, fromDest)); }
public override Activity Tick(Actor self) { if (IsCanceled || !target.IsValid) { return(NextActivity); } var mobile = self.Trait <Mobile>(); var ps1 = new PathSearch(self.World, mobile.Info, self.Owner) { checkForBlocked = true, heuristic = location => 0, inReverse = true }; foreach (var cell in Util.AdjacentCells(target)) { if (cell == self.Location) { return(NextActivity); } else { ps1.AddInitialCell(cell); } } ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self.Owner, mobile.toCell, Util.CellContaining(target.CenterLocation), true); var ret = self.World.WorldActor.Trait <PathFinder>().FindBidiPath(ps1, ps2); return(Util.SequenceActivities(mobile.MoveTo(() => ret), this)); }
public List <CPos> FindUnitPath(CPos source, CPos target, Actor self, Actor ignoreActor) { var mi = self.Info.TraitInfo <MobileInfo>(); // If a water-land transition is required, bail early var domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); if (domainIndex != null) { var passable = mi.GetMovementClass(world.Map.Rules.TileSet); if (!domainIndex.IsPassable(source, target, mi, (uint)passable)) { return(EmptyPath); } } List <CPos> pb; using (var fromSrc = PathSearch.FromPoint(world, mi, self, target, source, true).WithIgnoredActor(ignoreActor)) using (var fromDest = PathSearch.FromPoint(world, mi, self, source, target, true).WithIgnoredActor(ignoreActor).Reverse()) pb = FindBidiPath(fromSrc, fromDest); CheckSanePath2(pb, source, target); return(pb); }
void UpdateInnerPath(Actor self) { var targetCells = Util.AdjacentCells(target); var searchCells = new List <CPos>(); var loc = self.Location; foreach (var cell in targetCells) { if (mobile.CanEnterCell(cell) && (domainIndex == null || domainIndex.IsPassable(loc, cell, movementClass))) { searchCells.Add(cell); } } if (searchCells.Any()) { var ps1 = new PathSearch(self.World, mobile.Info, self) { checkForBlocked = true, heuristic = location => 0, inReverse = true }; foreach (var cell in searchCells) { ps1.AddInitialCell(cell); } ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, targetPosition, true); var ret = pathFinder.FindBidiPath(ps1, ps2); inner = mobile.MoveTo(() => ret); } }
// Scriptable move order // Ignores lane bias and nearby units public Move(Actor self, CPos destination) { mobile = self.Trait <Mobile>(); moveDisablers = self.TraitsImplementing <IDisableMove>().ToArray(); getPath = () => self.World.WorldActor.Trait <IPathFinder>().FindPath( PathSearch.FromPoint(self.World, mobile.Info, self, mobile.ToCell, destination, false) .WithoutLaneBias()); this.destination = destination; this.nearEnough = WDist.Zero; }
public Move(Actor self, CPos destination, Actor ignoredActor) { mobile = self.Trait <Mobile>(); moveDisablers = self.TraitsImplementing <IDisableMove>().ToArray(); getPath = () => self.World.WorldActor.Trait <IPathFinder>().FindPath( PathSearch.FromPoint(self.World, mobile.Info, self, mobile.ToCell, destination, false) .WithIgnoredActor(ignoredActor)); this.destination = destination; this.nearEnough = WRange.Zero; this.ignoredActor = ignoredActor; }
// Scriptable move order // Ignores lane bias and nearby units public Move(Actor self, CPos destination) { mobile = self.Trait <Mobile>(); getPath = () => { List <CPos> path; using (var search = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.ToCell, destination, false) .WithoutLaneBias()) path = self.World.WorldActor.Trait <IPathFinder>().FindPath(search); return(path); }; this.destination = destination; nearEnough = WDist.Zero; }
// Scriptable move order // Ignores lane bias and nearby units public Move(Actor self, CPos destination, Color?targetLineColor = null) { mobile = self.Trait <Mobile>(); getPath = check => { List <CPos> path; using (var search = PathSearch.FromPoint(self.World, mobile.Locomotor, self, mobile.ToCell, destination, check) .WithoutLaneBias()) path = mobile.Pathfinder.FindPath(search); return(path); }; this.destination = destination; this.targetLineColor = targetLineColor; nearEnough = WDist.Zero; }
// Scriptable move order // Ignores lane bias and nearby units public Move(Actor self, CPos destination, Color?targetLineColor = null) { // PERF: Because we can be sure that OccupiesSpace is Mobile here, we can save some performance by avoiding querying for the trait. mobile = (Mobile)self.OccupiesSpace; getPath = check => { List <CPos> path; using (var search = PathSearch.FromPoint(self.World, mobile.Locomotor, self, mobile.ToCell, destination, check) .WithoutLaneBias()) path = mobile.Pathfinder.FindPath(search); return(path); }; this.destination = destination; this.targetLineColor = targetLineColor; nearEnough = WDist.Zero; }
public List <CPos> FindUnitPath(CPos source, CPos target, Actor self, Actor ignoreActor, BlockedByActor check) { // PERF: Because we can be sure that OccupiesSpace is Mobile here, we can save some performance by avoiding querying for the trait. var locomotor = ((Mobile)self.OccupiesSpace).Locomotor; if (!cached) { domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); cached = true; } // If a water-land transition is required, bail early if (domainIndex != null && !domainIndex.IsPassable(source, target, locomotor)) { return(EmptyPath); } var distance = source - target; var canMoveFreely = locomotor.CanMoveFreelyInto(self, target, check, null); if (distance.LengthSquared < 3 && !canMoveFreely) { return new List <CPos> { } } ; if (source.Layer == target.Layer && distance.LengthSquared < 3 && canMoveFreely) { return new List <CPos> { target } } ; List <CPos> pb; using (var fromSrc = PathSearch.FromPoint(world, locomotor, self, target, source, check).WithIgnoredActor(ignoreActor)) using (var fromDest = PathSearch.FromPoint(world, locomotor, self, source, target, check).WithIgnoredActor(ignoreActor).Reverse()) pb = FindBidiPath(fromSrc, fromDest); return(pb); }
public List <CPos> FindUnitPath(CPos source, CPos target, Actor self, Actor ignoreActor, BlockedByActor check) { var mobile = self.Trait <Mobile>(); var locomotor = mobile.Locomotor; if (!cached) { domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); cached = true; } // If a water-land transition is required, bail early if (domainIndex != null && !domainIndex.IsPassable(source, target, locomotor.Info)) { return(EmptyPath); } var distance = source - target; var canMoveFreely = locomotor.CanMoveFreelyInto(self, target, check, null); if (distance.LengthSquared < 3 && !canMoveFreely) { return new List <CPos> { } } ; if (source.Layer == target.Layer && distance.LengthSquared < 3 && canMoveFreely) { return new List <CPos> { target } } ; List <CPos> pb; using (var fromSrc = PathSearch.FromPoint(world, locomotor, self, target, source, check).WithIgnoredActor(ignoreActor)) using (var fromDest = PathSearch.FromPoint(world, locomotor, self, source, target, check).WithIgnoredActor(ignoreActor).Reverse()) pb = FindBidiPath(fromSrc, fromDest); return(pb); }
public Move(Actor self, CPos destination, Actor ignoredActor) { mobile = self.Trait <Mobile>(); moveDisablers = self.TraitsImplementing <IDisableMove>().ToArray(); getPath = () => { List <CPos> path; using (var search = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.ToCell, destination, false) .WithIgnoredActor(ignoredActor)) path = self.World.WorldActor.Trait <IPathFinder>().FindPath(search); return(path); }; this.destination = destination; this.nearEnough = WDist.Zero; this.ignoredActor = ignoredActor; }
public List <CPos> FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WDist range, Actor self, BlockedByActor check) { if (!cached) { domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); cached = true; } // PERF: Because we can be sure that OccupiesSpace is Mobile here, we can save some performance by avoiding querying for the trait. var mobile = (Mobile)self.OccupiesSpace; var locomotor = mobile.Locomotor; var targetCell = world.Map.CellContaining(target); // Correct for SubCell offset target -= world.Map.Grid.OffsetOfSubCell(srcSub); var rangeLengthSquared = range.LengthSquared; var map = world.Map; // Select only the tiles that are within range from the requested SubCell // This assumes that the SubCell does not change during the path traversal var tilesInRange = map.FindTilesInCircle(targetCell, range.Length / 1024 + 1) .Where(t => (map.CenterOfCell(t) - target).LengthSquared <= rangeLengthSquared && mobile.Info.CanEnterCell(world, self, t)); // See if there is any cell within range that does not involve a cross-domain request // Really, we only need to check the circle perimeter, but it's not clear that would be a performance win if (domainIndex != null) { tilesInRange = new List <CPos>(tilesInRange.Where(t => domainIndex.IsPassable(source, t, locomotor))); if (!tilesInRange.Any()) { return(EmptyPath); } } using (var fromSrc = PathSearch.FromPoints(world, locomotor, self, tilesInRange, source, check)) using (var fromDest = PathSearch.FromPoint(world, locomotor, self, source, targetCell, check).Reverse()) return(FindBidiPath(fromSrc, fromDest)); }
List <CPos> CalculatePathToTarget(Actor self) { var targetCells = CandidateMovementCells(self); var searchCells = new List <CPos>(); var loc = self.Location; foreach (var cell in targetCells) { if (domainIndex.IsPassable(loc, cell, Mobile.Info, movementClass) && Mobile.CanEnterCell(cell)) { searchCells.Add(cell); } } if (!searchCells.Any()) { return(NoPath); } using (var fromSrc = PathSearch.FromPoints(self.World, Mobile.Info, self, searchCells, loc, true)) using (var fromDest = PathSearch.FromPoint(self.World, Mobile.Info, self, loc, targetPosition, true).Reverse()) return(pathFinder.FindBidiPath(fromSrc, fromDest)); }
Target SafePath(Actor capturer, Actor target) { var locomotor = capturer.Trait <Mobile>().Locomotor; if (!domainIndex.IsPassable(capturer.Location, target.Location, locomotor)) { return(Target.Invalid); } var path = pathfinder.FindPath( PathSearch.FromPoint(world, locomotor, capturer, capturer.Location, target.Location, BlockedByActor.None) .WithCustomCost(loc => world.FindActorsInCircle(world.Map.CenterOfCell(loc), Info.EnemyAvoidanceRadius) .Where(u => !u.IsDead && capturer.Owner.RelationshipWith(u.Owner) == PlayerRelationship.Enemy && capturer.IsTargetableBy(u)) .Sum(u => Math.Max(WDist.Zero.Length, Info.EnemyAvoidanceRadius.Length - (world.Map.CenterOfCell(loc) - u.CenterPosition).Length))) .FromPoint(capturer.Location)); if (path.Count == 0) { return(Target.Invalid); } return(Target.FromActor(target)); }
Target PathToNextcube(Actor collector, Actor cube) { var locomotor = collector.Trait <Mobile>().Locomotor; if (!domainIndex.IsPassable(collector.Location, cube.Location, locomotor)) { return(Target.Invalid); } var path = pathfinder.FindPath( PathSearch.FromPoint(world, locomotor, collector, collector.Location, cube.Location, BlockedByActor.Stationary) .WithCustomCost(loc => world.FindActorsInCircle(world.Map.CenterOfCell(loc), Info.EnemyAvoidanceRadius) .Where(u => !u.IsDead && collector.Owner.RelationshipWith(u.Owner) == PlayerRelationship.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.EnemyAvoidanceRadius.Length - (world.Map.CenterOfCell(loc) - u.CenterPosition).Length))) .FromPoint(collector.Location)); if (path.Count == 0) { return(Target.Invalid); } // Don't use the actor to avoid invalid targets when the cube disappears midway. return(Target.FromCell(world, cube.Location)); }
public List <CPos> FindUnitPath(CPos source, CPos target, Actor self) { var mi = self.Info.Traits.Get <MobileInfo>(); // If a water-land transition is required, bail early var domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); if (domainIndex != null) { var passable = mi.GetMovementClass(world.TileSet); if (!domainIndex.IsPassable(source, target, (uint)passable)) { return(EmptyPath); } } var pb = FindBidiPath( PathSearch.FromPoint(world, mi, self, target, source, true), PathSearch.FromPoint(world, mi, self, source, target, true).Reverse()); CheckSanePath2(pb, source, target); return(pb); }
Actor Location(Actor self, Player player, CPos target) { var possis = self.World.ActorsHavingTrait <Building>() .Where(a => { if (a.IsDead && !a.IsInWorld) { return(false); } if (a.Owner != player) { return(false); } return(true); }); List <Actor> enumerable = possis.ToList(); if (!enumerable.Any()) { return(null); } Repeat: if (enumerable.Any()) { var targetcell = enumerable.MinByOrDefault(a => (a.CenterPosition - self.World.Map.CenterOfCell(target)).LengthSquared); Actor fromhere = null; foreach (var actor in Army) { if (actor != null && actor.IsInWorld && !actor.IsDead) { fromhere = actor; break; } } if (fromhere != null) { var ip = fromhere.Info.TraitInfo <IPositionableInfo>(); var validcells = self.World.Map.FindTilesInCircle(target, 2, true).Where(c => ip.CanEnterCell(self.World, null, c)); var cPoses = validcells as CPos[] ?? validcells.ToArray(); if (cPoses.Any()) { var pickClosestCell = cPoses.MinByOrDefault(c => (self.World.Map.CenterOfCell(c) - fromhere.CenterPosition).LengthSquared); List <CPos> path; using (var thePath = PathSearch.FromPoint(self.World, fromhere.Info.TraitInfo <MobileInfo>(), self, fromhere.Location, pickClosestCell, true)) path = self.World.WorldActor.Trait <IPathFinder>().FindPath(thePath); if (path.Count > 0) { return(targetcell); } enumerable.Remove(targetcell); } goto Repeat; } } return(null); }
void Checkstartingcells(Actor self) { forbiddenCells = new HashSet <CPos>(); var cells = self.World.Map.FindTilesInAnnulus(self.Location, info.RadiusMin.Length, info.RadiusMax.Length) .Where(a => { var actor = self.World.Map.Rules.Actors[Info.Actors.First()]; if (actor.HasTraitInfo <IPositionableInfo>()) { var ip = actor.TraitInfo <IPositionableInfo>(); if (ip.CanEnterCell(self.World, null, a)) { return(true); } } else if (actor.HasTraitInfo <BuildingInfo>()) { var ip2 = actor.TraitInfo <BuildingInfo>(); if (self.World.CanPlaceBuilding(a, self.World.Map.Rules.Actors[Info.Actors.First()], ip2, null)) { return(true); } } else if (!actor.HasTraitInfo <BuildingInfo>() && !actor.HasTraitInfo <IPositionableInfo>()) { return(true); } return(false); }); var allaround = self.World.Map.FindTilesInCircle(self.Location, info.RadiusMax.Length, true) .Where(c => { if (cells.Contains(c)) { return(false); } return(true); }); var cPoses = allaround as CPos[] ?? allaround.ToArray(); if (cPoses.Any()) { foreach (var cell in cPoses) { forbiddenCells.Add(cell); } } HashSet <CPos> checkcells = new HashSet <CPos>(); if (cells != null && cells.Any()) { foreach (var cell in cells) { List <CPos> path; using (var thePath = PathSearch.FromPoint(self.World, self.World.Map.Rules.Actors[Info.CheckPathActor.ToLowerInvariant()].TraitInfo <MobileInfo>().LocomotorInfo, self, self.Location, cell, true)) path = self.World.WorldActor.Trait <IPathFinder>().FindPath(thePath); if (info.RadiusMax.Length < path.Count || path.Count == 0) { forbiddenCells.Add(cell); } else { checkcells.Add(cell); } } } if (checkcells.Any()) { foreach (var cell in cells) { if (!checkcells.Contains(cell)) { forbiddenCells.Add(cell); } } } }
public void FindPathOnRoughTerrainTest() { // Arrange // Create the MobileInfo Mock. Playing with this can help to // check the different paths and points a unit can walk into var mi = new FakeMobileInfo(pos => !(!IsValidPos(pos, Width, Height) || (pos.X == 50 && pos.Y < 100) || (pos.X == 100 && pos.Y > 50))); var from = new CPos(1, 1); var target = new CPos(125, 75); IPathSearch search; Stopwatch stopwatch; List <CPos> path5 = null; List <CPos> path6 = null; List <CPos> path7 = null; List <CPos> path8 = null; var pathfinder = new PathFinder(world); // Act stopwatch = new Stopwatch(); foreach (var a in Enumerable.Range(1, 50)) { search = PathSearch.FromPoint(world, mi, actor, from, target, true); stopwatch.Start(); path5 = pathfinder.FindPath(search); stopwatch.Stop(); search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(51, 100), true); stopwatch.Start(); path6 = pathfinder.FindPath(search); stopwatch.Stop(); search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(49, 50), true); stopwatch.Start(); path7 = pathfinder.FindPath(search); stopwatch.Stop(); search = PathSearch.FromPoint(world, mi, actor, new CPos(127, 0), new CPos(50, 101), true); stopwatch.Start(); path8 = pathfinder.FindPath(search); } Console.WriteLine("I took " + stopwatch.ElapsedMilliseconds + " ms with new pathfinder"); IPathSearch search2; stopwatch = new Stopwatch(); foreach (var a in Enumerable.Range(1, 50)) { search = PathSearch.FromPoint(world, mi, actor, from, target, true); search2 = PathSearch.FromPoint(world, mi, actor, target, from, true).Reverse(); stopwatch.Start(); path5 = pathfinder.FindBidiPath(search, search2); stopwatch.Stop(); search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(51, 100), true); search2 = PathSearch.FromPoint(world, mi, actor, new CPos(51, 100), new CPos(0, 0), true).Reverse(); stopwatch.Start(); path6 = pathfinder.FindBidiPath(search, search2); stopwatch.Stop(); search = PathSearch.FromPoint(world, mi, actor, new CPos(0, 0), new CPos(49, 50), true); search2 = PathSearch.FromPoint(world, mi, actor, new CPos(49, 50), new CPos(0, 0), true).Reverse(); stopwatch.Start(); path7 = pathfinder.FindBidiPath(search, search2); stopwatch.Stop(); search = PathSearch.FromPoint(world, mi, actor, new CPos(127, 0), new CPos(50, 101), true); search2 = PathSearch.FromPoint(world, mi, actor, new CPos(50, 101), new CPos(127, 0), true).Reverse(); stopwatch.Start(); path8 = pathfinder.FindBidiPath(search, search2); } Console.WriteLine("I took " + stopwatch.ElapsedMilliseconds + " ms with new FindBidipathfinder"); }
CPos MeetupPoint(Actor self, HashSet <Actor> hash, CPos target) { ; if (!hash.Any()) { return(CPos.Zero); } var fromhere = hash.ElementAt(self.World.SharedRandom.Next(hash.Count)); HashSet <CPos> alllocations = new HashSet <CPos>(); foreach (var acto in hash) { if (acto != null && !acto.IsDead && acto.IsInWorld) { alllocations.Add(acto.Location); } } if (!alllocations.Any()) { return(CPos.Zero); } if (fromhere != null && !fromhere.IsDead && fromhere.IsInWorld && fromhere.Info.HasTraitInfo <MobileInfo>()) { var ip = fromhere.Info.TraitInfo <IPositionableInfo>(); var validcells = self.World.Map.FindTilesInCircle(target, 3, true).Where(c => ip.CanEnterCell(self.World, null, c)); var cPoses = validcells as CPos[] ?? validcells.ToArray(); if (!cPoses.Any()) { return(CPos.Zero); } var pickClosestCell = cPoses.MinByOrDefault(c => (self.World.Map.CenterOfCell(c) - fromhere.CenterPosition).LengthSquared); List <CPos> path; using (var thePath = PathSearch.FromPoint(self.World, fromhere.Info.TraitInfo <MobileInfo>(), self, fromhere.Location, pickClosestCell, true)) path = self.World.WorldActor.Trait <IPathFinder>().FindPath(thePath); if (path.Any()) { foreach (var loco in path) { var owner = self.Owner; var position = owner.World.Map.CenterOfCell(loco); var beacon = self.Owner.PlayerActor.Info.TraitInfo <PlaceBeaconInfo>(); var playerBeacon = new Beacon(self.Owner, position, 20 * 25, beacon.Palette, beacon.IsPlayerPalette, beacon.BeaconImage, beacon.ArrowSequence, beacon.CircleSequence); self.Owner.PlayerActor.World.AddFrameEndTask(w => w.Add(playerBeacon)); } if (path.Count > 11) { return(path.ElementAt(10)); } return(path.Last()); } } return(CPos.Zero); }