public void Existing_path() { g.Insert(new Edge{v = 0, w = 1}); g.Insert(new Edge{v = 1, w = 2}); g.Insert(new Edge{v = 2, w = 3}); var path = new PathSearch(g, 0, 3); Assert.That(path.Exists, Is.True); }
public static PathSearch Search(World world, MobileInfo mi, Actor self, bool checkForBlocked) { var search = new PathSearch(world, mi, self) { CheckForBlocked = checkForBlocked }; return search; }
public static PathSearch FromPoint(World world, MobileInfo mi, Actor self, CPos from, CPos target, bool checkForBlocked) { var search = new PathSearch(world, mi, self) { Heuristic = DefaultEstimator(target), CheckForBlocked = checkForBlocked }; search.AddInitialCell(from); return search; }
public static PathSearch FromPoints(World world, MobileInfo mi, Actor self, IEnumerable<CPos> froms, CPos target, bool checkForBlocked) { var search = new PathSearch(world, mi, self) { Heuristic = DefaultEstimator(target), CheckForBlocked = checkForBlocked }; foreach (var sl in froms) search.AddInitialCell(sl); return search; }
public void Path_with_circles() { g.Insert(new Edge{v = 0, w = 1}); g.Insert(new Edge{v = 1, w = 2}); g.Insert(new Edge{v = 2, w = 3}); g.Insert(new Edge{v = 1, w = 0}); g.Insert(new Edge{v = 2, w = 0}); g.Insert(new Edge{v = 3, w = 0}); // g.ShowGraph(); var path = new PathSearch(g, 0, 3); Assert.That(path.Exists, Is.True); }
void Start() { selectedTileIndex = 0; TGMap tempMap = (TGMap)FindObjectOfType(typeof(TGMap)); tileSizeX = tempMap.size_x; myPathSearch = GetComponent <PathSearch>(); pathSolution = new List <TDTile>(); pathMarkerList = new List <GameObject>(); Component selectedTile = transform.FindChild("SelectedTile"); selectedTile.GetComponent <Renderer>().enabled = false; showMarker = false; moveCharacter = false; }
Actor ClosestProc(Actor self, Actor ignore) { // Find all refineries and their occupancy count: var refs = ( from r in self.World.ActorsWithTrait <IAcceptOre>() where r.Actor != ignore && r.Actor.Owner == self.Owner let linkedHarvs = self.World.ActorsWithTrait <Harvester>().Where(a => a.Trait.LinkedProc == r.Actor).Count() select new { Location = r.Actor.Location + r.Trait.DeliverOffset, Actor = r.Actor, Occupancy = linkedHarvs } ).ToDictionary(r => r.Location); // Start a search from each refinery's delivery location: var mi = self.Info.Traits.Get <MobileInfo>(); var path = self.World.WorldActor.Trait <PathFinder>().FindPath( PathSearch.FromPoints(self.World, mi, self, refs.Values.Select(r => r.Location), self.Location, false) .WithCustomCost((loc) => { if (!refs.ContainsKey(loc)) { return(0); } int occupancy = refs[loc].Occupancy; // 4 harvesters clogs up the refinery's delivery location: if (occupancy >= 3) { return(int.MaxValue); } // Prefer refineries with less occupancy (multiplier is to offset distance cost): return(occupancy * 12); }) ); // Reverse the found-path to find the refinery location instead of our location: path.Reverse(); if (path.Count != 0) { return(refs[path[0]].Actor); } return(null); }
private void HandleMove() { if (!Input.GetMouseButtonDown(0)) { return; } var cameraRay = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(cameraRay, out RaycastHit hitInfo, 100, LayerMask.GetMask("Floor"))) { var search = new PathSearch(transform.position, hitInfo.point, MapObj.Air | MapObj.Enemy); var path = search.Solve(); if (path != null && path.Count > 1) { StartCoroutine(SmoothMove(path)); } } }
public Actor ClosestProc(Actor self, Actor ignore) { // Find all refineries and their occupancy count: var refineries = self.World.ActorsWithTrait <IAcceptResources>() .Where(r => r.Actor != ignore && r.Actor.Owner == self.Owner && IsAcceptableProcType(r.Actor)) .Select(r => new { Location = r.Actor.Location + r.Trait.DeliveryOffset, Actor = r.Actor, Occupancy = self.World.ActorsHavingTrait <Harvester>(h => h.LinkedProc == r.Actor).Count() }).ToLookup(r => r.Location); // Start a search from each refinery's delivery location: List <CPos> path; using (var search = PathSearch.FromPoints(self.World, mobile.Locomotor, self, refineries.Select(r => r.Key), self.Location, BlockedByActor.None) .WithCustomCost(location => { if (!refineries.Contains(location)) { return(0); } var occupancy = refineries[location].First().Occupancy; // Too many harvesters clogs up the refinery's delivery location: if (occupancy >= Info.MaxUnloadQueue) { return(PathGraph.CostForInvalidCell); } // Prefer refineries with less occupancy (multiplier is to offset distance cost): return(occupancy * Info.UnloadQueueCostModifier); })) path = mobile.Pathfinder.FindPath(search); if (path.Count != 0) { return(refineries[path.Last()].First().Actor); } return(null); }
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.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 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); }
// 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> 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)); }
public Actor ClosestDestination(Actor self) { var refineries = self.World.ActorsWithTrait <AcceptsDeliveredResources>() .Where(r => r.Actor.Owner == self.Owner); List <CPos> path; using (var search = PathSearch.FromPoints(self.World, mobile.Locomotor, self, refineries.Select(r => r.Actor.Location), self.Location, BlockedByActor.None) .WithCustomCost(loc => self.World.FindActorsInCircle(self.World.Map.CenterOfCell(loc), Info.EnemyAvoidanceRadius) .Where(u => !u.IsDead && self.Owner.Stances[u.Owner] == Stance.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.EnemyAvoidanceRadius.Length - (self.World.Map.CenterOfCell(loc) - u.CenterPosition).Length)))) path = self.World.WorldActor.Trait <IPathFinder>().FindPath(search); if (path.Count != 0) { return(refineries.First(r => r.Actor.Location == path.Last()).Actor); } return(null); }
public Actor ClosestDestination(Actor self) { var actors = string.IsNullOrEmpty(ResourceType) ? self.World.ActorsHavingTrait <ResourceCollector>().Where(r => r.Owner == self.Owner) : self.World.ActorsHavingTrait <AcceptsDeliveredResources>().Where(r => r.Owner == self.Owner); List <CPos> path; using (var search = PathSearch.FromPoints(self.World, mobile.Locomotor, self, actors.Select(a => a.Location), self.Location, BlockedByActor.None) .WithCustomCost(loc => self.World.FindActorsInCircle(self.World.Map.CenterOfCell(loc), Info.EnemyAvoidanceRadius) .Where(u => !u.IsDead && self.Owner.RelationshipWith(u.Owner) == PlayerRelationship.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.EnemyAvoidanceRadius.Length - (self.World.Map.CenterOfCell(loc) - u.CenterPosition).Length)))) path = self.World.WorldActor.Trait <IPathFinder>().FindPath(search); if (path.Count != 0) { return(actors.First(r => r.Location == path.Last())); } return(null); }
CPos FindNextResource(Actor harvester) { var harvInfo = harvester.Info.TraitInfo <HarvesterInfo>(); var mobileInfo = harvester.Info.TraitInfo <MobileInfo>(); var passable = (uint)mobileInfo.GetMovementClass(World.Map.Rules.TileSet); var path = pathfinder.FindPath( PathSearch.Search(World, mobileInfo, harvester, true, loc => domainIndex.IsPassable(harvester.Location, loc, passable) && harvester.CanHarvestAt(loc, resLayer, harvInfo, territory)) .WithCustomCost(loc => World.FindActorsInCircle(World.Map.CenterOfCell(loc), Info.HarvesterEnemyAvoidanceRadius) .Where(u => !u.IsDead && harvester.Owner.Stances[u.Owner] == Stance.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.HarvesterEnemyAvoidanceRadius.Length - (World.Map.CenterOfCell(loc) - u.CenterPosition).Length))) .FromPoint(harvester.Location)); if (path.Count == 0) { return(CPos.Zero); } return(path[0]); }
Target FindNextResource(Actor actor, HarvesterTraitWrapper harv) { Func <CPos, bool> isValidResource = cell => domainIndex.IsPassable(actor.Location, cell, harv.Locomotor) && harv.Harvester.CanHarvestCell(actor, cell) && claimLayer.CanClaimCell(actor, cell); var path = pathfinder.FindPath( PathSearch.Search(world, harv.Locomotor, actor, BlockedByActor.Stationary, isValidResource) .WithCustomCost(loc => world.FindActorsInCircle(world.Map.CenterOfCell(loc), Info.HarvesterEnemyAvoidanceRadius) .Where(u => !u.IsDead && actor.Owner.RelationshipWith(u.Owner) == PlayerRelationship.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.HarvesterEnemyAvoidanceRadius.Length - (world.Map.CenterOfCell(loc) - u.CenterPosition).Length))) .FromPoint(actor.Location)); if (path.Count == 0) { return(Target.Invalid); } return(Target.FromCell(world, path[0])); }
CPos FindNextResource(Actor actor, Harvester harv) { var mobileInfo = actor.Info.TraitInfo <MobileInfo>(); var passable = (uint)mobileInfo.GetMovementClass(World.Map.Rules.TileSet); Func <CPos, bool> isValidResource = cell => domainIndex.IsPassable(actor.Location, cell, mobileInfo, passable) && harv.CanHarvestCell(actor, cell) && claimLayer.CanClaimCell(actor, cell); var path = pathfinder.FindPath( PathSearch.Search(World, mobileInfo, actor, true, isValidResource) .WithCustomCost(loc => World.FindActorsInCircle(World.Map.CenterOfCell(loc), Info.HarvesterEnemyAvoidanceRadius) .Where(u => !u.IsDead && actor.Owner.Stances[u.Owner] == Stance.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.HarvesterEnemyAvoidanceRadius.Length - (World.Map.CenterOfCell(loc) - u.CenterPosition).Length))).FromPoint(actor.Location)); if (path.Count == 0) { return(CPos.Zero); } return(path[0]); }
public List <CPos> FindUnitPathToRange(CPos source, SubCell srcSub, WPos target, WDist range, Actor self) { if (!cached) { domainIndex = world.WorldActor.TraitOrDefault <DomainIndex>(); cached = true; } var mobile = self.Trait <Mobile>(); var mi = mobile.Info; 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 if (domainIndex != null) { tilesInRange = new List <CPos>(tilesInRange.Where(t => domainIndex.IsPassable(source, t, li))); if (!tilesInRange.Any()) { return(EmptyPath); } } var locomotor = mobile.Locomotor; using (var fromSrc = PathSearch.FromPoints(world, locomotor, self, tilesInRange, source, true)) using (var fromDest = PathSearch.FromPoint(world, locomotor, self, source, targetCell, true).Reverse()) return(FindBidiPath(fromSrc, fromDest)); }
public Actor ClosestProc(Actor self, Actor ignore) { // Find all refineries and their occupancy count: var refs = ( from r in self.World.ActorsWithTrait <IAcceptResources>() where r.Actor != ignore && r.Actor.Owner == self.Owner && IsAcceptableProcType(r.Actor) let linkedHarvs = self.World.ActorsWithTrait <Harvester>().Count(a => a.Trait.LinkedProc == r.Actor) select new { Location = r.Actor.Location + r.Trait.DeliveryOffset, Actor = r.Actor, Occupancy = linkedHarvs }).ToDictionary(r => r.Location); // Start a search from each refinery's delivery location: var mi = self.Info.Traits.Get <MobileInfo>(); var path = self.World.WorldActor.Trait <IPathFinder>().FindPath( PathSearch.FromPoints(self.World, mi, self, refs.Values.Select(r => r.Location), self.Location, false) .WithCustomCost(loc => { if (!refs.ContainsKey(loc)) { return(0); } var occupancy = refs[loc].Occupancy; // 4 harvesters clogs up the refinery's delivery location: if (occupancy >= 3) { return(Constants.InvalidNode); } // Prefer refineries with less occupancy (multiplier is to offset distance cost): return(occupancy * 12); })); if (path.Count != 0) { return(refs[path.Last()].Actor); } return(null); }
public List<CPos> FindUnitPath(CPos source, CPos target, Actor self, Actor ignoreActor) { var li = self.Info.TraitInfo<MobileInfo>().LocomotorInfo; // If a water-land transition is required, bail early var domainIndex = world.WorldActor.TraitOrDefault<DomainIndex>(); if (domainIndex != null && !domainIndex.IsPassable(source, target, li)) return EmptyPath; var distance = source - target; if (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); CheckSanePath2(pb, source, target); return pb; }
/// <summary> /// Finds the closest harvestable pos between the current position of the harvester /// and the last order location /// </summary> CPos?ClosestHarvestablePos(Actor self) { if (harv.CanHarvestCell(self, self.Location) && claimLayer.CanClaimCell(self, self.Location)) { return(self.Location); } // Determine where to search from and how far to search: var searchFromLoc = GetSearchFromLocation(self); var searchRadius = harv.LastOrderLocation.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius; var searchRadiusSquared = searchRadius * searchRadius; // Find any harvestable resources: var passable = (uint)mobileInfo.GetMovementClass(self.World.Map.Rules.TileSet); List <CPos> path; using (var search = PathSearch.Search(self.World, mobileInfo, self, true, loc => domainIndex.IsPassable(self.Location, loc, mobileInfo, passable) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc)) .WithCustomCost(loc => { if ((avoidCell.HasValue && loc == avoidCell.Value) || (loc - self.Location).LengthSquared > searchRadiusSquared) { return(int.MaxValue); } return(0); }) .FromPoint(self.Location) .FromPoint(searchFromLoc)) path = pathFinder.FindPath(search); if (path.Count > 0) { return(path[0]); } return(null); }
public void mapCompute() { //声源离散 Layer sourceLayer = getSource(); PathSearch pathbean = new PathSearch(); //接收点离散 Queue <Geometry> receiveList = PolygonPartition.staticPartition(m_gridSize, m_computationalGrid, m_receiveHeight); //障碍物优化 DataSource barrierSource = Ogr.Open(m_barrierPath, 0); Layer barrierLayer = barrierSource.GetLayerByIndex(0); Geometry receivePoint = null; Geometry sourcePoint = null; Feature sourceFeature = null; Geometry[] pathList = null; List <float[]> sourceLineList = new List <float[]>(); //路径计算,循环接收点 while (receiveList.Count > 0) { //声源点和接收点 receivePoint = receiveList.Dequeue(); sourceLayer.SetSpatialFilter(receivePoint.Buffer(m_range, 30)); //循环声源点 while ((sourceFeature = sourceLayer.GetNextFeature()) != null) { sourcePoint = sourceFeature.GetGeometryRef(); //获取路径 pathList = pathbean.getPath(barrierLayer, sourcePoint, receivePoint, m_range); } } //衰减计算 }
Actor ClosestProc(Actor self, Actor ignore) { var refs = self.World.ActorsWithTrait <IAcceptOre>() .Where(x => x.Actor != ignore && x.Actor.Owner == self.Owner) .ToList(); var mi = self.Info.Traits.Get <MobileInfo>(); var path = self.World.WorldActor.Trait <PathFinder>().FindPath( PathSearch.FromPoints(self.World, mi, self.Owner, refs.Select(r => r.Actor.Location + r.Trait.DeliverOffset), self.Location, false)); path.Reverse(); if (path.Count != 0) { return(refs.Where(x => x.Actor.Location + x.Trait.DeliverOffset == path[0]) .Select(a => a.Actor).FirstOrDefault()); } else { return(null); } }
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 FindNextResource(Actor actor, HarvesterTraitWrapper harv) { Func <CPos, bool> isValidResource = cell => harv.Harvester.CanHarvestCell(actor, cell) && claimLayer.CanClaimCell(actor, cell); List <CPos> path; using (var search = PathSearch.ToTargetCellByPredicate( world, harv.Locomotor, actor, new[] { actor.Location }, isValidResource, BlockedByActor.Stationary, loc => world.FindActorsInCircle(world.Map.CenterOfCell(loc), Info.HarvesterEnemyAvoidanceRadius) .Where(u => !u.IsDead && actor.Owner.RelationshipWith(u.Owner) == PlayerRelationship.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.HarvesterEnemyAvoidanceRadius.Length - (world.Map.CenterOfCell(loc) - u.CenterPosition).Length)))) path = pathfinder.FindPath(search); if (path.Count == 0) { return(Target.Invalid); } return(Target.FromCell(world, path[0])); }
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)); }
/// <summary> /// Finds the closest harvestable pos between the current position of the harvester /// and the last order location /// </summary> CPos?ClosestHarvestablePos(Actor self) { if (IsHarvestable(self, self.Location)) { return(self.Location); } // Determine where to search from and how far to search: var searchFromLoc = harv.LastOrderLocation ?? (harv.LastLinkedProc ?? harv.LinkedProc ?? self).Location; var searchRadius = harv.LastOrderLocation.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius; var searchRadiusSquared = searchRadius * searchRadius; var search = PathSearch.Search(self.World, mobileInfo, self, true, loc => IsHarvestable(self, loc)) .WithCustomCost(loc => { if ((avoidCell.HasValue && loc == avoidCell.Value) || (loc - self.Location).LengthSquared > searchRadiusSquared) { return(int.MaxValue); } return(0); }) .FromPoint(self.Location) .FromPoint(searchFromLoc); // Find any harvestable resources: var path = pathFinder.FindPath(search); if (path.Count > 0) { return(path[0]); } return(null); }
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)); }
Target FindNextResource(Actor actor, MinerTraitWrapper miner) { var towerInfo = AIUtils.GetInfoByCommonName(Info.DeployedActorTypes, player); var buildingInfo = towerInfo.TraitInfo <BuildingInfo>(); Func <CPos, bool> isValidResource = cell => domainIndex.IsPassable(actor.Location, cell, miner.Locomotor.Info) && Info.DeployableTerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type) && miner.Locomotor.CanStayInCell(cell) && world.CanPlaceBuilding(cell + miner.Transforms.Info.Offset, towerInfo, buildingInfo, actor); var path = pathfinder.FindPath( PathSearch.Search(world, miner.Locomotor, actor, BlockedByActor.Stationary, isValidResource) .WithCustomCost(loc => world.FindActorsInCircle(world.Map.CenterOfCell(loc), Info.EnemyAvoidanceRadius) .Where(u => !u.IsDead && actor.Owner.Stances[u.Owner] == Stance.Enemy) .Sum(u => Math.Max(WDist.Zero.Length, Info.EnemyAvoidanceRadius.Length - (world.Map.CenterOfCell(loc) - u.CenterPosition).Length))) .FromPoint(actor.Location)); if (path.Count == 0) { return(Target.Invalid); } return(Target.FromCell(world, path[0])); }
CPos?ClosestGroundCell() { var above = new CPos(TopLeft.X, TopLeft.Y); if (CanEnterCell(above)) { return(above); } var pathFinder = self.World.WorldActor.Trait <IPathFinder>(); List <CPos> path; using (var search = PathSearch.Search(self.World, Info, self, true, loc => loc.Layer == 0 && CanEnterCell(loc)) .FromPoint(self.Location)) path = pathFinder.FindPath(search); if (path.Count > 0) { return(path[0]); } return(null); }
public async Task <List <Path> > GetPathsByProperty(PathSearch locationSearch) { Path path = new Path(); PropertyInfo info = path .GetType() .GetProperty(locationSearch.searchByProperty.ToString()); PropertyInfo info1 = locationSearch .GetType() .GetProperty(locationSearch.searchByProperty.ToString()); List <Path> pathsInPropery = await _dbcontext.Paths.ToListAsync(); if (pathsInPropery == null) { // Log.Warning("Couldn't find any paths"); throw new Exception("NotFound:Couldn't find any paths"); } List <Path> newPathsInPropery = new List <Path>(); for (int i = 0; i < pathsInPropery.Count(); i++) { if (string.Compare(info.GetValue(pathsInPropery[i]).ToString(), info1.GetValue(locationSearch).ToString()) == 0) { newPathsInPropery.Add(pathsInPropery[i]); } } if (newPathsInPropery == null) { // Log.Warning("Couldn't find any paths in property {@pathSearchByCity}", locationSearch.searchByProperty); throw new Exception($"NotFound:Couldn't find any paths for property {locationSearch.searchByProperty}"); } return(newPathsInPropery); }
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); }
/// <summary> /// Finds the closest harvestable pos between the current position of the harvester /// and the last order location /// </summary> CPos?ClosestHarvestablePos(Actor self) { // Harvesters should respect an explicit harvest order instead of harvesting the current cell. if (orderLocation == null) { if (harv.CanHarvestCell(self, self.Location) && claimLayer.CanClaimCell(self, self.Location)) { return(self.Location); } } else { if (harv.CanHarvestCell(self, orderLocation.Value) && claimLayer.CanClaimCell(self, orderLocation.Value)) { return(orderLocation); } orderLocation = null; } // Determine where to search from and how far to search: var procLoc = GetSearchFromProcLocation(self); var searchFromLoc = lastHarvestedCell ?? procLoc ?? self.Location; var searchRadius = lastHarvestedCell.HasValue ? harvInfo.SearchFromHarvesterRadius : harvInfo.SearchFromProcRadius; var searchRadiusSquared = searchRadius * searchRadius; var map = self.World.Map; var procPos = procLoc.HasValue ? (WPos?)map.CenterOfCell(procLoc.Value) : null; var harvPos = self.CenterPosition; // Find any harvestable resources: List <CPos> path; using (var search = PathSearch.Search(self.World, mobile.Locomotor, self, BlockedByActor.Stationary, loc => domainIndex.IsPassable(self.Location, loc, mobile.Locomotor) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc)) .WithCustomCost(loc => { if ((loc - searchFromLoc).LengthSquared > searchRadiusSquared) { return(PathGraph.PathCostForInvalidPath); } // Add a cost modifier to harvestable cells to prefer resources that are closer to the refinery. // This reduces the tendency for harvesters to move in straight lines if (procPos.HasValue && harvInfo.ResourceRefineryDirectionPenalty > 0 && harv.CanHarvestCell(self, loc)) { var pos = map.CenterOfCell(loc); // Calculate harv-cell-refinery angle (cosine rule) var b = pos - procPos.Value; if (b != WVec.Zero) { var c = pos - harvPos; if (c != WVec.Zero) { var a = harvPos - procPos.Value; var cosA = (int)(512 * (b.LengthSquared + c.LengthSquared - a.LengthSquared) / b.Length / c.Length); // Cost modifier varies between 0 and ResourceRefineryDirectionPenalty return(Math.Abs(harvInfo.ResourceRefineryDirectionPenalty / 2) + harvInfo.ResourceRefineryDirectionPenalty * cosA / 2048); } } } return(0); }) .FromPoint(searchFromLoc) .FromPoint(self.Location)) path = mobile.Pathfinder.FindPath(search); if (path.Count > 0) { return(path[0]); } return(null); }
void FindMoreResource(Actor self) { var res = self.World.WorldActor.traits.Get<ResourceLayer>(); var harv = self.Info.Traits.Get<HarvesterInfo>(); self.QueueActivity(new Move( () => { var search = new PathSearch(self.World) { heuristic = loc => (res.GetResource(loc) != null && harv.Resources.Contains( res.GetResource(loc).Name )) ? 0 : 1, umt = UnitMovementType.Wheel, checkForBlocked = true }; search.AddInitialCell(self.World, self.Location); return self.World.PathFinder.FindPath(search); })); self.QueueActivity(new Harvest()); }
public override Activity Tick(Actor self) { if (IsCanceled || NextActivity != null) { return(NextActivity); } var harv = self.Trait <Harvester>(); if (harv.IsFull) { return(Util.SequenceActivities(new DeliverResources(), NextActivity)); } var harvInfo = self.Info.Traits.Get <HarvesterInfo>(); var mobile = self.Trait <Mobile>(); var mobileInfo = self.Info.Traits.Get <MobileInfo>(); var resLayer = self.World.WorldActor.Trait <ResourceLayer>(); var territory = self.World.WorldActor.TraitOrDefault <ResourceClaimLayer>(); // Determine where to search from and how far to search: var searchFromLoc = harv.LastOrderLocation ?? (harv.LastLinkedProc ?? harv.LinkedProc ?? self).Location; int searchRadius = harv.LastOrderLocation.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius; int searchRadiusSquared = searchRadius * searchRadius; // Find harvestable resources nearby: // Avoid enemy territory: // TODO: calculate weapons ranges of units and factor those in instead of hard-coding 8. var path = self.World.WorldActor.Trait <PathFinder>().FindPath( PathSearch.Search(self.World, mobileInfo, self, true) .WithCustomCost(loc => self.World.FindActorsInCircle(loc.CenterPosition, WRange.FromCells(8)) .Where(u => !u.Destroyed && self.Owner.Stances[u.Owner] == Stance.Enemy) .Sum(u => Math.Max(0, 64 - (loc - u.Location).LengthSquared))) .WithHeuristic(loc => { // Avoid this cell: if (avoidCell.HasValue && loc == avoidCell.Value) { return(1); } // Don't harvest out of range: int distSquared = (loc - searchFromLoc).LengthSquared; if (distSquared > searchRadiusSquared) { return(int.MaxValue); } // Get the resource at this location: var resType = resLayer.GetResource(loc); if (resType == null) { return(1); } // Can the harvester collect this kind of resource? if (!harvInfo.Resources.Contains(resType.Info.Name)) { return(1); } if (territory != null) { // Another harvester has claimed this resource: ResourceClaim claim; if (territory.IsClaimedByAnyoneElse(self, loc, out claim)) { return(1); } } return(0); }) .FromPoint(self.Location) ); if (path.Count == 0) { if (!harv.IsEmpty) { return(new DeliverResources()); } else { // Get out of the way if we are: harv.UnblockRefinery(self); int randFrames = 125 + self.World.SharedRandom.Next(-35, 35); if (NextActivity != null) { return(Util.SequenceActivities(NextActivity, new Wait(randFrames), new FindResources())); } else { return(Util.SequenceActivities(new Wait(randFrames), new FindResources())); } } } // Attempt to claim a resource as ours: if (territory != null) { if (!territory.ClaimResource(self, path[0])) { return(Util.SequenceActivities(new Wait(25), new FindResources())); } } // If not given a direct order, assume ordered to the first resource location we find: if (harv.LastOrderLocation == null) { harv.LastOrderLocation = path[0]; } self.SetTargetLine(Target.FromCell(path[0]), Color.Red, false); return(Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(), new FindResources())); }
public void Path_to_self() { var path = new PathSearch(g, 42, 42); Assert.That(path.Exists, Is.True); }
public void Empty_graph() { var path = new PathSearch(g, 0, 1); Assert.That(path.Exists, Is.False); }