Ejemplo n.º 1
0
        public CPos Expand(World world)
        {
            var p = Queue.Pop();

            while (CellInfo[p.Location].Seen)
            {
                if (Queue.Empty)
                {
                    return(p.Location);
                }

                p = Queue.Pop();
            }

            var pCell = CellInfo[p.Location];

            pCell.Seen           = true;
            CellInfo[p.Location] = pCell;

            var thisCost = mobileInfo.MovementCostForCell(world, p.Location);

            if (thisCost == int.MaxValue)
            {
                return(p.Location);
            }

            if (customCost != null)
            {
                var c = customCost(p.Location);
                if (c == int.MaxValue)
                {
                    return(p.Location);
                }
            }

            // This current cell is ok; check all immediate directions:
            Considered.Add(p.Location);

            for (var i = 0; i < nextDirections.Length; ++i)
            {
                var d = nextDirections[i].First;
                nextDirections[i].Second = int.MaxValue;

                var newHere = p.Location + d;

                // Is this direction flat-out unusable or already seen?
                if (!world.Map.Contains(newHere))
                {
                    continue;
                }

                if (CellInfo[newHere].Seen)
                {
                    continue;
                }

                // Now we may seriously consider this direction using heuristics:
                var costHere = mobileInfo.MovementCostForCell(world, newHere);

                if (costHere == int.MaxValue)
                {
                    continue;
                }

                if (!mobileInfo.CanEnterCell(world, self, newHere, IgnoreBuilding, CheckForBlocked ? CellConditions.TransientActors : CellConditions.None))
                {
                    continue;
                }

                if (customBlock != null && customBlock(newHere))
                {
                    continue;
                }

                var est = Heuristic(newHere);
                if (est == int.MaxValue)
                {
                    continue;
                }

                var cellCost = costHere;
                if (d.X * d.Y != 0)
                {
                    cellCost = (cellCost * 34) / 24;
                }

                var userCost = 0;
                if (customCost != null)
                {
                    userCost  = customCost(newHere);
                    cellCost += userCost;
                }

                // directional bonuses for smoother flow!
                if (laneBias != 0)
                {
                    var ux = newHere.X + (InReverse ? 1 : 0) & 1;
                    var uy = newHere.Y + (InReverse ? 1 : 0) & 1;

                    if (ux == 0 && d.Y < 0)
                    {
                        cellCost += laneBias;
                    }
                    else if (ux == 1 && d.Y > 0)
                    {
                        cellCost += laneBias;
                    }

                    if (uy == 0 && d.X < 0)
                    {
                        cellCost += laneBias;
                    }
                    else if (uy == 1 && d.X > 0)
                    {
                        cellCost += laneBias;
                    }
                }

                var newCost = CellInfo[p.Location].MinCost + cellCost;

                // Cost is even higher; next direction:
                if (newCost > CellInfo[newHere].MinCost)
                {
                    continue;
                }

                var hereCell = CellInfo[newHere];
                hereCell.Path     = p.Location;
                hereCell.MinCost  = newCost;
                CellInfo[newHere] = hereCell;

                nextDirections[i].Second = newCost + est;
                Queue.Add(new PathDistance(newCost + est, newHere));

                if (newCost > MaxCost)
                {
                    MaxCost = newCost;
                }

                Considered.Add(newHere);
            }

            // Sort to prefer the cheaper direction:
            // Array.Sort(nextDirections, (a, b) => a.Second.CompareTo(b.Second));
            return(p.Location);
        }
Ejemplo n.º 2
0
        public CPos Expand(World world)
        {
            var p = queue.Pop();

            while (cellInfo[p.Location.X, p.Location.Y].Seen)
            {
                if (queue.Empty)
                {
                    return(p.Location);
                }
                else
                {
                    p = queue.Pop();
                }
            }

            cellInfo[p.Location.X, p.Location.Y].Seen = true;

            var thisCost = mobileInfo.MovementCostForCell(world, p.Location);

            if (thisCost == int.MaxValue)
            {
                return(p.Location);
            }

            if (customCost != null)
            {
                int c = customCost(p.Location);
                if (c == int.MaxValue)
                {
                    return(p.Location);
                }
            }

            // This current cell is ok; check all immediate directions:
            considered.Add(p.Location);

            for (int i = 0; i < nextDirections.Length; ++i)
            {
                CVec d = nextDirections[i].First;
                nextDirections[i].Second = int.MaxValue;

                CPos newHere = p.Location + d;

                // Is this direction flat-out unusable or already seen?
                if (!world.Map.IsInMap(newHere.X, newHere.Y))
                {
                    continue;
                }
                if (cellInfo[newHere.X, newHere.Y].Seen)
                {
                    continue;
                }

                // Now we may seriously consider this direction using heuristics:
                var costHere = mobileInfo.MovementCostForCell(world, newHere);

                if (costHere == int.MaxValue)
                {
                    continue;
                }

                if (!mobileInfo.CanEnterCell(world, self, newHere, ignoreBuilding, checkForBlocked, false))
                {
                    continue;
                }

                if (customBlock != null && customBlock(newHere))
                {
                    continue;
                }

                var est = heuristic(newHere);
                if (est == int.MaxValue)
                {
                    continue;
                }

                int cellCost = costHere;
                if (d.X * d.Y != 0)
                {
                    cellCost = (cellCost * 34) / 24;
                }

                int userCost = 0;
                if (customCost != null)
                {
                    userCost  = customCost(newHere);
                    cellCost += userCost;
                }

                // directional bonuses for smoother flow!
                if (LaneBias != 0)
                {
                    var ux = (newHere.X + (inReverse ? 1 : 0) & 1);
                    var uy = (newHere.Y + (inReverse ? 1 : 0) & 1);

                    if (ux == 0 && d.Y < 0)
                    {
                        cellCost += LaneBias;
                    }
                    else if (ux == 1 && d.Y > 0)
                    {
                        cellCost += LaneBias;
                    }
                    if (uy == 0 && d.X < 0)
                    {
                        cellCost += LaneBias;
                    }
                    else if (uy == 1 && d.X > 0)
                    {
                        cellCost += LaneBias;
                    }
                }

                int newCost = cellInfo[p.Location.X, p.Location.Y].MinCost + cellCost;

                // Cost is even higher; next direction:
                if (newCost > cellInfo[newHere.X, newHere.Y].MinCost)
                {
                    continue;
                }

                cellInfo[newHere.X, newHere.Y].Path    = p.Location;
                cellInfo[newHere.X, newHere.Y].MinCost = newCost;

                nextDirections[i].Second = newCost + est;
                queue.Add(new PathDistance(newCost + est, newHere));

                if (newCost > maxCost)
                {
                    maxCost = newCost;
                }
                considered.Add(newHere);
            }

            // Sort to prefer the cheaper direction:
            //Array.Sort(nextDirections, (a, b) => a.Second.CompareTo(b.Second));

            return(p.Location);
        }
Ejemplo n.º 3
0
 public bool CanEnterCell(CPos cell, Actor ignoreActor, bool checkTransientActors)
 {
     return(Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors, true));
 }
Ejemplo n.º 4
0
        public CPos Expand(World world)
        {
            var p = queue.Pop();

            while (cellInfo[p.Location.X, p.Location.Y].Seen)
            {
                if (queue.Empty)
                {
                    return(p.Location);
                }
                else
                {
                    p = queue.Pop();
                }
            }

            cellInfo[p.Location.X, p.Location.Y].Seen = true;

            var thisCost = mobileInfo.MovementCostForCell(world, p.Location);

            if (thisCost == int.MaxValue)
            {
                return(p.Location);
            }

            if (customCost != null)
            {
                int c = customCost(p.Location);
                if (c == int.MaxValue)
                {
                    return(p.Location);
                }
            }

            foreach (CVec d in directions)
            {
                CPos newHere = p.Location + d;

                if (!world.Map.IsInMap(newHere.X, newHere.Y))
                {
                    continue;
                }
                if (cellInfo[newHere.X, newHere.Y].Seen)
                {
                    continue;
                }

                var costHere = mobileInfo.MovementCostForCell(world, newHere);

                if (costHere == int.MaxValue)
                {
                    continue;
                }

                if (!mobileInfo.CanEnterCell(world, self, newHere, ignoreBuilding, checkForBlocked, false))
                {
                    continue;
                }

                if (customBlock != null && customBlock(newHere))
                {
                    continue;
                }

                var est = heuristic(newHere);
                if (est == int.MaxValue)
                {
                    continue;
                }

                int cellCost = costHere;
                if (d.X * d.Y != 0)
                {
                    cellCost = (cellCost * 34) / 24;
                }

                if (customCost != null)
                {
                    cellCost += customCost(newHere);
                }

                // directional bonuses for smoother flow!
                if (LaneBias != 0)
                {
                    var ux = (newHere.X + (inReverse ? 1 : 0) & 1);
                    var uy = (newHere.Y + (inReverse ? 1 : 0) & 1);

                    if (ux == 0 && d.Y < 0)
                    {
                        cellCost += LaneBias;
                    }
                    else if (ux == 1 && d.Y > 0)
                    {
                        cellCost += LaneBias;
                    }
                    if (uy == 0 && d.X < 0)
                    {
                        cellCost += LaneBias;
                    }
                    else if (uy == 1 && d.X > 0)
                    {
                        cellCost += LaneBias;
                    }
                }

                int newCost = cellInfo[p.Location.X, p.Location.Y].MinCost + cellCost;

                if (newCost >= cellInfo[newHere.X, newHere.Y].MinCost)
                {
                    continue;
                }

                cellInfo[newHere.X, newHere.Y].Path    = p.Location;
                cellInfo[newHere.X, newHere.Y].MinCost = newCost;

                queue.Add(new PathDistance(newCost + est, newHere));
            }
            return(p.Location);
        }
Ejemplo n.º 5
0
 public bool CanEnterCell(int2 cell, Actor ignoreActor, bool checkTransientActors)
 {
     return(Info.CanEnterCell(self.World, self.Owner, cell, ignoreActor, checkTransientActors));
 }
Ejemplo n.º 6
0
 public bool CanEnterCell(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
 {
     return(Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors ? CellConditions.All : CellConditions.BlockedByMovers));
 }