示例#1
0
        /// <summary>
        /// Finds the closest harvestable pos between the current position of the harvester
        /// and the last order location
        /// </summary>
        CPos?ClosestHarvestablePos(Actor self)
        {
            var mobile = self.Trait <Mobile>();

            // Determine where to search from and how far to search:
            Func <CPos, bool> canHarvest = pos =>
            {
                var resType = resourceLayer.GetResourceType(pos);
                if (resType != null && string.Compare(resType.Info.Name, Info.TargetResourceType, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    return(true);
                }

                return(false);
            };

            // 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) && canHarvest(loc) && claimLayer.CanClaimCell(self, loc))
                                .FromPoint(self.Location))
                path = pathFinder.FindPath(search);

            if (path.Count > 0)
            {
                return(path[0]);
            }

            return(null);
        }
示例#2
0
        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 res        = self.World.WorldActor.Trait <ResourceLayer>();
            var path       = self.World.WorldActor.Trait <PathFinder>().FindPath(PathSearch.Search(self.World, mobileInfo, self.Owner, true)
                                                                                 .WithHeuristic(loc => (res.GetResource(loc) != null && harvInfo.Resources.Contains(res.GetResource(loc).info.Name)) ? 0 : 1)
                                                                                 .FromPoint(self.Location));

            if (path.Count == 0)
            {
                return(NextActivity);
            }

            self.SetTargetLine(Target.FromCell(path[0]), Color.Red, false);
            return(Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(), this));
        }
示例#3
0
        /// <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 searchFromLoc       = lastHarvestedCell ?? GetSearchFromLocation(self);
            var searchRadius        = lastHarvestedCell.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius;
            var searchRadiusSquared = searchRadius * searchRadius;

            // Find any harvestable resources:
            List <CPos> path;

            using (var search = PathSearch.Search(self.World, locomotorInfo, self, true, loc =>
                                                  domainIndex.IsPassable(self.Location, loc, locomotorInfo) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc))
                                .WithCustomCost(loc =>
            {
                if ((loc - searchFromLoc).LengthSquared > searchRadiusSquared)
                {
                    return(int.MaxValue);
                }

                return(0);
            })
                                .FromPoint(searchFromLoc)
                                .FromPoint(self.Location))
                path = pathFinder.FindPath(search);

            if (path.Count > 0)
            {
                return(path[0]);
            }

            return(null);
        }
示例#4
0
        static CPos?FindNextResourceForBot(Actor self)
        {
            // NOTE: This is only used for the AI to find the next available resource to harvest.
            var harvInfo   = self.Info.Traits.Get <HarvesterInfo>();
            var mobileInfo = self.Info.Traits.Get <MobileInfo>();
            var resLayer   = self.World.WorldActor.Trait <ResourceLayer>();
            var territory  = self.World.WorldActor.TraitOrDefault <ResourceClaimLayer>();

            // Find any harvestable resources:
            var path = self.World.WorldActor.Trait <PathFinder>().FindPath(
                PathSearch.Search(self.World, mobileInfo, self, true)
                .WithHeuristic(loc =>
            {
                // 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);
                }

                // Another harvester has claimed this resource:
                if (territory != null)
                {
                    ResourceClaim claim;
                    if (territory.IsClaimedByAnyoneElse(self, loc, out claim))
                    {
                        return(1);
                    }
                }

                return(0);
            })
                .FromPoint(self.Location)
                );

            if (path.Count == 0)
            {
                return((CPos?)null);
            }

            return(path[0]);
        }
        /// <summary>
        /// Using LastOrderLocation and self.Location as starting points,
        /// perform A* search to find the nearest accessible and harvestable cell.
        /// </summary>
        CPos?ClosestHarvestablePos(Actor self, int searchRadius)
        {
            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       = harv.LastOrderLocation ?? self.Location;
            var searchRadiusSquared = searchRadius * searchRadius;

            BaseSpawnerSlaveEntry choosenSlave = null;
            var slaves = harv.GetSlaves();

            if (slaves.Length > 0)
            {
                choosenSlave = slaves[0];

                var mobile     = choosenSlave.Actor.Trait <Mobile>();
                var mobileInfo = choosenSlave.Actor.Info.TraitInfo <MobileInfo>();
                // Find any harvestable resources:
                // var passable = (uint)mobileInfo.GetMovementClass(self.World.Map.Rules.TileSet);
                List <CPos> path;
                using (var search = PathSearch.Search(self.World, mobile.Locomotor, self, true,
                                                      loc => domainIndex.IsPassable(self.Location, loc, mobileInfo.LocomotorInfo) &&
                                                      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);
        }
示例#6
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]));
        }
示例#7
0
        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]);
        }
示例#8
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]);
        }
示例#9
0
        /// <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);
        }
示例#10
0
        /// <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);
        }
示例#11
0
文件: Mobile.cs 项目: cjshmyr/OpenRA
        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);
        }
        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]));
        }
示例#13
0
        /// <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);
        }
示例#14
0
        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()));
        }
示例#15
0
        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;
            var searchRadius        = harv.LastOrderLocation.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius;
            var searchRadiusSquared = searchRadius * searchRadius;

            // Find harvestable resources nearby:
            var path = self.World.WorldActor.Trait <IPathFinder>().FindPath(
                PathSearch.Search(self.World, mobileInfo, self, true)
                .WithHeuristic(loc =>
            {
                // Avoid this cell:
                if (avoidCell.HasValue && loc == avoidCell.Value)
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                }

                // Don't harvest out of range:
                var distSquared = (loc - searchFromLoc).LengthSquared;
                if (distSquared > searchRadiusSquared)
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost * 2);
                }

                // Get the resource at this location:
                var resType = resLayer.GetResource(loc);
                if (resType == null)
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                }

                // Can the harvester collect this kind of resource?
                if (!harvInfo.Resources.Contains(resType.Info.Name))
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                }

                if (territory != null)
                {
                    // Another harvester has claimed this resource:
                    ResourceClaim claim;
                    if (territory.IsClaimedByAnyoneElse(self, loc, out claim))
                    {
                        return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                    }
                }

                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);
                    var 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(self.World, path[0]), Color.Red, false);

            var notify = self.TraitsImplementing <INotifyHarvesterAction>();
            var next   = new FindResources();

            foreach (var n in notify)
            {
                n.MovingToResources(self, path[0], next);
            }

            return(Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(), new FindResources()));
        }