Beispiel #1
0
        public void Init(TilePropagator propagator)
        {
            tileSet         = propagator.CreateTileSet(Tiles);
            endPointTileSet = EndPointTiles != null?propagator.CreateTileSet(EndPointTiles) : null;

            graph = PathConstraintUtils.CreateGraph(propagator.Topology);
        }
Beispiel #2
0
        public void Init(TilePropagator propagator)
        {
            ISet <Tile> actualTiles;
            ISet <Tile> actualEndPointTiles;

            if (TileRotation != null)
            {
                actualTiles         = new HashSet <Tile>(TileRotation.RotateAll(Tiles));
                actualEndPointTiles = EndPointTiles == null ? null : new HashSet <Tile>(TileRotation.RotateAll(EndPointTiles));
            }
            else
            {
                actualTiles         = Tiles;
                actualEndPointTiles = EndPointTiles;
            }

            tileSet         = propagator.CreateTileSet(actualTiles);
            selectedTracker = propagator.CreateSelectedTracker(tileSet);
            endPointTileSet = EndPointTiles != null?propagator.CreateTileSet(actualEndPointTiles) : null;

            endPointSelectedTracker = EndPointTiles != null?propagator.CreateSelectedTracker(endPointTileSet) : null;

            graph = PathConstraintUtils.CreateGraph(propagator.Topology);

            Check(propagator, true);
        }
Beispiel #3
0
        public void Check(TilePropagator propagator)
        {
            var topology = propagator.Topology;
            var indices  = topology.Width * topology.Height * topology.Depth;
            // Initialize couldBePath and mustBePath based on wave possibilities
            var couldBePath = new bool[indices];
            var mustBePath  = new bool[indices];

            for (int i = 0; i < indices; i++)
            {
                topology.GetCoord(i, out var x, out var y, out var z);
                propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var isSelected);
                couldBePath[i] = !isBanned;
                mustBePath[i]  = isSelected;
            }

            // Select relevant cells, i.e. those that must be connected.
            bool[] relevant;
            if (EndPoints == null)
            {
                relevant = mustBePath;
            }
            else
            {
                relevant = new bool[indices];
                if (EndPoints.Length == 0)
                {
                    return;
                }
                foreach (var endPoint in EndPoints)
                {
                    var index = topology.GetIndex(endPoint.X, endPoint.Y, endPoint.Z);
                    relevant[index] = true;
                }
            }
            var walkable = couldBePath;

            var isArticulation = PathConstraintUtils.GetArticulationPoints(graph, walkable, relevant);

            if (isArticulation == null)
            {
                propagator.SetContradiction();
                return;
            }


            // All articulation points must be paths,
            // So ban any other possibilities
            for (var i = 0; i < indices; i++)
            {
                if (isArticulation[i])
                {
                    topology.GetCoord(i, out var x, out var y, out var z);
                    propagator.Select(x, y, z, tileSet);
                }
            }
        }
        public void Check(TilePropagator propagator)
        {
            pathView.Update();

            var info           = PathConstraintUtils.GetArticulationPoints(pathView.Graph, pathView.CouldBePath, pathView.MustBeRelevant);
            var isArticulation = info.IsArticulation;

            for (var i = 0; i < pathView.Graph.NodeCount; i++)
            {
                if (isArticulation[i])
                {
                    propagator.SetContradiction("Loop constraint found articulation point.", this);
                    return;
                }
            }
        }
Beispiel #5
0
        public PathView(PathSpec spec, TilePropagator propagator)
        {
            if (spec.TileRotation != null)
            {
                tiles         = new HashSet <Tile>(spec.TileRotation.RotateAll(spec.Tiles));
                endPointTiles = spec.RelevantTiles == null ? null : new HashSet <Tile>(spec.TileRotation.RotateAll(spec.RelevantTiles));
            }
            else
            {
                tiles         = spec.Tiles;
                endPointTiles = spec.RelevantTiles;
            }

            tileSet         = propagator.CreateTileSet(tiles);
            selectedTracker = propagator.CreateSelectedTracker(tileSet);

            Graph           = PathConstraintUtils.CreateGraph(propagator.Topology);
            this.propagator = propagator;

            CouldBePath = new bool[propagator.Topology.IndexCount];
            MustBePath  = new bool[propagator.Topology.IndexCount];

            hasEndPoints = spec.RelevantCells != null || spec.RelevantTiles != null;

            if (hasEndPoints)
            {
                CouldBeRelevant = new bool[propagator.Topology.IndexCount];
                MustBeRelevant  = new bool[propagator.Topology.IndexCount];
                endPointIndices = spec.RelevantCells == null ? null :
                                  spec.RelevantCells.Select(p => propagator.Topology.GetIndex(p.X, p.Y, p.Z)).ToList();
                endPointTileSet = spec.RelevantTiles != null?propagator.CreateTileSet(endPointTiles) : null;

                endPointSelectedTracker = spec.RelevantTiles != null?propagator.CreateSelectedTracker(endPointTileSet) : null;
            }
            else
            {
                CouldBeRelevant = CouldBePath;
                MustBeRelevant  = MustBePath;
                endPointTileSet = tileSet;
            }
        }
        public void Check(TilePropagator propagator)
        {
            pathView.Update();

            var info           = PathConstraintUtils.GetArticulationPoints(pathView.Graph, pathView.CouldBePath, pathView.MustBeRelevant);
            var isArticulation = info.IsArticulation;

            if (info.ComponentCount > 1)
            {
                propagator.SetContradiction();
                return;
            }

            // All articulation points must be paths,
            // So ban any other possibilities
            for (var i = 0; i < pathView.Graph.NodeCount; i++)
            {
                if (isArticulation[i] && !pathView.MustBePath[i])
                {
                    pathView.SelectPath(i);
                }
            }

            // Any path tiles / EndPointTiles not in the connected component aren't safe to add.
            // Disabled for now, unclear exactly when it is needed
            if (info.ComponentCount > 0)
            {
                var component = info.Component;
                for (int i = 0; i < pathView.Graph.NodeCount; i++)
                {
                    if (component[i] == null && pathView.CouldBeRelevant[i])
                    {
                        pathView.BanRelevant(i);
                    }
                }
            }
        }
Beispiel #7
0
        private void Check(TilePropagator propagator, bool init)
        {
            var topology = propagator.Topology;
            var indices  = topology.IndexCount;
            // Initialize couldBePath and mustBePath based on wave possibilities
            var couldBePath = new bool[indices];
            var mustBePath  = new bool[indices];

            for (int i = 0; i < indices; i++)
            {
                var ts = selectedTracker.GetQuadstate(i);
                couldBePath[i] = ts.Possible();
                mustBePath[i]  = ts.IsYes();
            }

            // Select relevant cells, i.e. those that must be connected.
            var hasEndPoints = EndPoints != null || EndPointTiles != null;

            bool[] relevant;
            if (!hasEndPoints)
            {
                relevant = mustBePath;
            }
            else
            {
                relevant = new bool[indices];
                var relevantCount = 0;
                if (EndPoints != null)
                {
                    foreach (var endPoint in EndPoints)
                    {
                        var index = topology.GetIndex(endPoint.X, endPoint.Y, endPoint.Z);
                        relevant[index] = true;
                        relevantCount++;
                    }
                }
                if (EndPointTiles != null)
                {
                    for (int i = 0; i < indices; i++)
                    {
                        if (endPointSelectedTracker.IsSelected(i))
                        {
                            relevant[i] = true;
                            relevantCount++;
                        }
                    }
                }
                if (relevantCount == 0)
                {
                    // Nothing to do.
                    return;
                }
            }

            if (init)
            {
                for (int i = 0; i < indices; i++)
                {
                    if (relevant[i])
                    {
                        topology.GetCoord(i, out var x, out var y, out var z);
                        propagator.Select(x, y, z, tileSet);
                    }
                }
            }

            var walkable = couldBePath;

            var info           = PathConstraintUtils.GetArticulationPoints(graph, walkable, relevant);
            var isArticulation = info.IsArticulation;

            if (info.ComponentCount > 1)
            {
                propagator.SetContradiction("Path constraint found multiple components", this);
                return;
            }

            // All articulation points must be paths,
            // So ban any other possibilities
            for (var i = 0; i < indices; i++)
            {
                if (isArticulation[i] && !mustBePath[i])
                {
                    topology.GetCoord(i, out var x, out var y, out var z);
                    propagator.Select(x, y, z, tileSet);
                }
            }

            // Any path tiles / EndPointTiles not in the connected component aren't safe to add.
            if (info.ComponentCount > 0)
            {
                var component             = info.Component;
                var actualEndPointTileSet = hasEndPoints ? endPointTileSet : tileSet;
                if (actualEndPointTileSet != null)
                {
                    for (int i = 0; i < indices; i++)
                    {
                        if (component[i] == null)
                        {
                            topology.GetCoord(i, out var x, out var y, out var z);
                            propagator.Ban(x, y, z, actualEndPointTileSet);
                        }
                    }
                }
            }
        }
        private void Check(TilePropagator propagator, bool init)
        {
            var topology = propagator.Topology;
            var indices  = topology.Width * topology.Height * topology.Depth;

            var nodesPerIndex = topology.DirectionsCount + 1;

            // Initialize couldBePath and mustBePath based on wave possibilities
            var couldBePath    = new bool[indices * nodesPerIndex];
            var mustBePath     = new bool[indices * nodesPerIndex];
            var exitMustBePath = new bool[indices * nodesPerIndex];

            foreach (var kv in trackerByExit)
            {
                var exit    = kv.Key;
                var tracker = kv.Value;
                for (int i = 0; i < indices; i++)
                {
                    var ts = tracker.GetQuadstate(i);
                    couldBePath[i * nodesPerIndex + 1 + (int)exit] = ts.Possible();
                    // Cannot put this in mustBePath these points can be disconnected, depending on topology mask
                    exitMustBePath[i * nodesPerIndex + 1 + (int)exit] = ts.IsYes();
                }
            }
            for (int i = 0; i < indices; i++)
            {
                var pathTs = pathSelectedTracker.GetQuadstate(i);
                couldBePath[i * nodesPerIndex] = pathTs.Possible();
                mustBePath[i * nodesPerIndex]  = pathTs.IsYes();
            }
            // Select relevant cells, i.e. those that must be connected.
            var hasEndPoints = EndPoints != null || EndPointTiles != null;

            bool[] relevant;
            if (!hasEndPoints)
            {
                // Basically equivalent to EndPoints = pathTileSet
                relevant = mustBePath;
            }
            else
            {
                relevant = new bool[indices * nodesPerIndex];

                var relevantCount = 0;
                if (EndPoints != null)
                {
                    foreach (var endPoint in EndPoints)
                    {
                        var index = topology.GetIndex(endPoint.X, endPoint.Y, endPoint.Z);
                        relevant[index * nodesPerIndex] = true;
                        relevantCount++;
                    }
                }
                if (EndPointTiles != null)
                {
                    for (int i = 0; i < indices; i++)
                    {
                        if (endPointSelectedTracker.IsSelected(i))
                        {
                            relevant[i * nodesPerIndex] = true;
                            relevantCount++;
                        }
                    }
                }
                if (relevantCount == 0)
                {
                    // Nothing to do.
                    return;
                }
            }

            if (init)
            {
                for (int i = 0; i < indices; i++)
                {
                    if (relevant[i * nodesPerIndex])
                    {
                        topology.GetCoord(i, out var x, out var y, out var z);
                        propagator.Select(x, y, z, pathTileSet);
                    }
                }
            }

            var walkable = couldBePath;

            var info           = PathConstraintUtils.GetArticulationPoints(graph, walkable, relevant);
            var isArticulation = info.IsArticulation;

            if (info.ComponentCount > 1)
            {
                propagator.SetContradiction("Edged path constraint found multiple connected components.", this);
                return;
            }


            // All articulation points must be paths,
            // So ban any other possibilities
            for (var i = 0; i < indices; i++)
            {
                topology.GetCoord(i, out var x, out var y, out var z);
                if (isArticulation[i * nodesPerIndex] && !mustBePath[i * nodesPerIndex])
                {
                    propagator.Select(x, y, z, pathTileSet);
                }
                for (var d = 0; d < topology.DirectionsCount; d++)
                {
                    if (isArticulation[i * nodesPerIndex + 1 + d] && !exitMustBePath[i * nodesPerIndex + 1 + d])
                    {
                        if (tilesByExit.TryGetValue((Direction)d, out var exitTiles))
                        {
                            propagator.Select(x, y, z, exitTiles);
                        }
                    }
                }
            }

            // Any path tiles / EndPointTiles not in the connected component aren't safe to add.
            if (info.ComponentCount > 0)
            {
                var component             = info.Component;
                var actualEndPointTileSet = hasEndPoints ? endPointTileSet : pathTileSet;
                if (actualEndPointTileSet != null)
                {
                    for (int i = 0; i < indices; i++)
                    {
                        if (component[i * nodesPerIndex] == null)
                        {
                            topology.GetCoord(i, out var x, out var y, out var z);
                            propagator.Ban(x, y, z, actualEndPointTileSet);
                        }
                    }
                }
            }
        }
Beispiel #9
0
        public void Check(TilePropagator propagator)
        {
            var topology = propagator.Topology;
            var indices  = topology.Width * topology.Height * topology.Depth;
            // Initialize couldBePath and mustBePath based on wave possibilities
            var couldBePath = new bool[indices];
            var mustBePath  = new bool[indices];

            for (int i = 0; i < indices; i++)
            {
                var ts = selectedTracker.GetTristate(i);
                couldBePath[i] = ts.Possible();
                mustBePath[i]  = ts.IsYes();
            }

            // Select relevant cells, i.e. those that must be connected.
            bool[] relevant;
            if (EndPoints == null && EndPointTiles == null)
            {
                relevant = mustBePath;
            }
            else
            {
                relevant = new bool[indices];
                var relevantCount = 0;
                if (EndPoints != null)
                {
                    foreach (var endPoint in EndPoints)
                    {
                        var index = topology.GetIndex(endPoint.X, endPoint.Y, endPoint.Z);
                        relevant[index] = true;
                        relevantCount++;
                    }
                }
                if (EndPointTiles != null)
                {
                    for (int i = 0; i < indices; i++)
                    {
                        if (endPointSelectedTracker.IsSelected(i))
                        {
                            relevant[i] = true;
                            relevantCount++;
                        }
                    }
                }
                if (relevantCount == 0)
                {
                    // Nothing to do.
                    return;
                }
            }
            var walkable = couldBePath;

            var component = EndPointTiles != null ? new bool[indices] : null;

            var isArticulation = PathConstraintUtils.GetArticulationPoints(graph, walkable, relevant, component);

            if (isArticulation == null)
            {
                propagator.SetContradiction();
                return;
            }

            // All articulation points must be paths,
            // So ban any other possibilities
            for (var i = 0; i < indices; i++)
            {
                if (isArticulation[i] && !mustBePath[i])
                {
                    topology.GetCoord(i, out var x, out var y, out var z);
                    propagator.Select(x, y, z, tileSet);
                }
            }

            // Any EndPointTiles not in the connected component aren't safe to add
            if (EndPointTiles != null)
            {
                for (int i = 0; i < indices; i++)
                {
                    if (!component[i])
                    {
                        topology.GetCoord(i, out var x, out var y, out var z);
                        propagator.Ban(x, y, z, endPointTileSet);
                    }
                }
            }
        }
        public void Check(TilePropagator propagator)
        {
            var topology = propagator.Topology;
            var indices  = topology.Width * topology.Height * topology.Depth;

            var nodesPerIndex = topology.DirectionsCount + 1;

            // Initialize couldBePath and mustBePath based on wave possibilities
            var couldBePath    = new bool[indices * nodesPerIndex];
            var mustBePath     = new bool[indices * nodesPerIndex];
            var exitMustBePath = new bool[indices * nodesPerIndex];

            foreach (var kv in trackerByExit)
            {
                var exit    = kv.Key;
                var tracker = kv.Value;
                for (int i = 0; i < indices; i++)
                {
                    var ts = tracker.GetTristate(i);
                    couldBePath[i * nodesPerIndex + 1 + (int)exit] = ts.Possible();
                    // Cannot put this in mustBePath these points can be disconnected, depending on topology mask
                    exitMustBePath[i * nodesPerIndex + 1 + (int)exit] = ts.IsYes();
                }
            }
            for (int i = 0; i < indices; i++)
            {
                var pathTs = pathSelectedTracker.GetTristate(i);
                couldBePath[i * nodesPerIndex] = pathTs.Possible();
                mustBePath[i * nodesPerIndex]  = pathTs.IsYes();
            }
            // Select relevant cells, i.e. those that must be connected.
            bool[] relevant;
            if (EndPoints == null && EndPointTiles == null)
            {
                relevant = mustBePath;
            }
            else
            {
                relevant = new bool[indices * nodesPerIndex];

                var relevantCount = 0;
                if (EndPoints != null)
                {
                    foreach (var endPoint in EndPoints)
                    {
                        var index = topology.GetIndex(endPoint.X, endPoint.Y, endPoint.Z);
                        relevant[index * nodesPerIndex] = true;
                        relevantCount++;
                    }
                }
                if (EndPointTiles != null)
                {
                    for (int i = 0; i < indices; i++)
                    {
                        if (endPointSelectedTracker.IsSelected(i))
                        {
                            relevant[i * nodesPerIndex] = true;
                            relevantCount++;
                        }
                    }
                }
                if (relevantCount == 0)
                {
                    // Nothing to do.
                    return;
                }
            }
            var walkable = couldBePath;

            var component = EndPointTiles != null ? new bool[indices] : null;

            var isArticulation = PathConstraintUtils.GetArticulationPoints(graph, walkable, relevant, component);

            if (isArticulation == null)
            {
                propagator.SetContradiction();
                return;
            }


            // All articulation points must be paths,
            // So ban any other possibilities
            for (var i = 0; i < indices; i++)
            {
                topology.GetCoord(i, out var x, out var y, out var z);
                if (isArticulation[i * nodesPerIndex] && !mustBePath[i * nodesPerIndex])
                {
                    propagator.Select(x, y, z, pathTileSet);
                }
                for (var d = 0; d < topology.DirectionsCount; d++)
                {
                    if (isArticulation[i * nodesPerIndex + 1 + d] && !exitMustBePath[i * nodesPerIndex + 1 + d])
                    {
                        propagator.Select(x, y, z, tilesByExit[(Direction)d]);
                    }
                }
            }

            // Any EndPointTiles not in the connected component aren't safe to add
            if (EndPointTiles != null)
            {
                for (int i = 0; i < indices; i++)
                {
                    if (!component[i * nodesPerIndex])
                    {
                        topology.GetCoord(i, out var x, out var y, out var z);
                        propagator.Ban(x, y, z, endPointTileSet);
                    }
                }
            }
        }
Beispiel #11
0
 public void Init(TilePropagator propagator)
 {
     tileSet = propagator.CreateTileSet(Tiles);
     graph   = PathConstraintUtils.CreateGraph(propagator.Topology);
 }
        public void Check(TilePropagator propagator)
        {
            var topology = propagator.Topology;
            var indices  = topology.Width * topology.Height * topology.Depth;

            // TODO: This shouldn't be too hard to implement
            if (topology.Directions.Type != Topo.DirectionSetType.Cartesian2d)
            {
                throw new Exception("EdgedPathConstraint only supported for Cartesiant2d");
            }

            var nodesPerIndex = topology.Directions.Count + 1;

            // Initialize couldBePath and mustBePath based on wave possibilities
            var couldBePath = new bool[indices * nodesPerIndex];
            var mustBePath  = new bool[indices * nodesPerIndex];

            for (int i = 0; i < indices; i++)
            {
                topology.GetCoord(i, out var x, out var y, out var z);

                couldBePath[i * nodesPerIndex] = false;
                foreach (var kv in actualExits)
                {
                    var tile  = kv.Key;
                    var exits = kv.Value;

                    propagator.GetBannedSelected(x, y, z, tile, out var isBanned, out var isSelected);

                    if (!isBanned)
                    {
                        couldBePath[i * nodesPerIndex] = true;
                        foreach (var exit in exits)
                        {
                            couldBePath[i * nodesPerIndex + 1 + (int)exit] = true;
                        }
                    }
                }
                // TODO: There's probably a more efficient way to do this
                propagator.GetBannedSelected(x, y, z, pathTileSet, out var allIsBanned, out var allIsSelected);
                mustBePath[i * nodesPerIndex] = allIsSelected;
            }

            // Select relevant cells, i.e. those that must be connected.
            bool[] relevant;
            if (EndPoints == null && EndPointTiles == null)
            {
                relevant = mustBePath;
            }
            else
            {
                relevant = new bool[indices * nodesPerIndex];

                var relevantCount = 0;
                if (EndPoints != null)
                {
                    foreach (var endPoint in EndPoints)
                    {
                        var index = topology.GetIndex(endPoint.X, endPoint.Y, endPoint.Z);
                        relevant[index * nodesPerIndex] = true;
                        relevantCount++;
                    }
                }
                if (EndPointTiles != null)
                {
                    for (int i = 0; i < indices; i++)
                    {
                        topology.GetCoord(i, out var x, out var y, out var z);
                        propagator.GetBannedSelected(x, y, z, endPointTileSet, out var isBanned, out var isSelected);
                        if (isSelected)
                        {
                            relevant[i * nodesPerIndex] = true;
                            relevantCount++;
                        }
                    }
                }
                if (relevantCount == 0)
                {
                    // Nothing to do.
                    return;
                }
            }
            var walkable = couldBePath;

            var component = EndPointTiles != null ? new bool[indices] : null;

            var isArticulation = PathConstraintUtils.GetArticulationPoints(graph, walkable, relevant, component);

            if (isArticulation == null)
            {
                propagator.SetContradiction();
                return;
            }


            // All articulation points must be paths,
            // So ban any other possibilities
            for (var i = 0; i < indices; i++)
            {
                topology.GetCoord(i, out var x, out var y, out var z);
                if (isArticulation[i * nodesPerIndex])
                {
                    propagator.Select(x, y, z, pathTileSet);
                }
                for (var d = 0; d < topology.Directions.Count; d++)
                {
                    if (isArticulation[i * nodesPerIndex + 1 + d])
                    {
                        propagator.Select(x, y, z, tilesByExit[(Direction)d]);
                    }
                }
            }

            // Any EndPointTiles not in the connected component aren't safe to add
            if (EndPointTiles != null)
            {
                for (int i = 0; i < indices; i++)
                {
                    if (!component[i * nodesPerIndex])
                    {
                        topology.GetCoord(i, out var x, out var y, out var z);
                        propagator.Ban(x, y, z, endPointTileSet);
                    }
                }
            }
        }