Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        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));
        }
Example #5
0
        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));
        }
Example #6
0
        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));
        }
Example #7
0
        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);
        }
Example #8
0
        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);
            }
        }
Example #9
0
        // 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;
        }
Example #10
0
        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;
        }
Example #11
0
        // 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;
        }
Example #12
0
        // 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;
        }
Example #13
0
        // 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;
        }
Example #14
0
        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);
        }
Example #15
0
        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);
        }
Example #16
0
        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;
        }
Example #17
0
        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));
        }
Example #18
0
        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));
        }
Example #19
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));
        }
Example #20
0
        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));
        }
Example #21
0
        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);
        }
Example #23
0
        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);
                    }
                }
            }
        }
Example #24
0
        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);
        }