示例#1
0
        public void TestDirectionality2()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(new Tile(1), new Tile(2), 1, 0, 0);
            model.SetUniformFrequency();

            var topology = new GridTopology(2, 1, false);

            var left  = Direction.XMinus;
            var right = Direction.XPlus;

#pragma warning disable CS0618 // Type or member is obsolete
            var edgedPathConstraint = new EdgedPathConstraint(
#pragma warning restore CS0618 // Type or member is obsolete
                new Dictionary <Tile, ISet <Direction> >()
            {
                { new Tile(1), new[] { left, right }.ToHashSet() },
                { new Tile(2), new[] { left, right }.ToHashSet() },
            }
                );

            var propagator = new TilePropagator(model, topology, constraints: new[] { edgedPathConstraint });

            propagator.Run();
        }
示例#2
0
        public void CountSetup()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);
            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tiles = new[] { tile1, tile2 };

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);
            model.SetUniformFrequency();

            var topology = new GridTopology(100, 100, false);

            var count = 30;

            var options = new TilePropagatorOptions
            {
                Constraints = new[]
                {
                    new CountConstraint
                    {
                        Tiles = new[] { tile1 }.ToHashSet(),
                Count      = count,
                Comparison = CountComparison.AtMost,
                Eager      = false,
                    }
                }
            };

            propagator6 = new TilePropagator(model, topology, options);
        }
        public void TestDirectionality2()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(new Tile(1), new Tile(2), 1, 0, 0);
            model.SetUniformFrequency();

            var topology = new GridTopology(2, 1, false);

            var left  = Direction.XMinus;
            var right = Direction.XPlus;

            var constraint = new ConnectedConstraint
            {
                PathSpec = new EdgedPathSpec
                {
                    Exits = new Dictionary <Tile, ISet <Direction> >()
                    {
                        { new Tile(1), new[] { left, right }.ToHashSet() },
                        { new Tile(2), new[] { left, right }.ToHashSet() },
                    }
                }
            };


            var propagator = new TilePropagator(model, topology, constraints: new[] { constraint });

            propagator.Run();
        }
示例#4
0
        public void TestDirectionality()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(new Tile(1), new Tile(2), 1, 0, 0);
            model.SetUniformFrequency();

            var topology = new Topology(2, 1, false);

            var up   = Direction.YPlus;
            var down = Direction.YMinus;

            var edgedPathConstraint = new EdgedPathConstraint(
                new Dictionary <Tile, ISet <Direction> >()
            {
                { new Tile(1), new[] { up, down }.ToHashSet() },
                { new Tile(2), new[] { up, down }.ToHashSet() },
            }
                );

            var propagator = new TilePropagator(model, topology, constraints: new[] { edgedPathConstraint });

            propagator.Run();

            Assert.AreEqual(Resolution.Contradiction, propagator.Status);
        }
示例#5
0
        public void Path2Setup()
        {
            var tileCount = 10;
            var topology  = new GridTopology(20, 20, false);

            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            var tiles = Enumerable.Range(0, tileCount).Select(x => new Tile(x)).ToList();;

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);

            model.SetUniformFrequency();
            var pathConstraint = new ConnectedConstraint {
                PathSpec = new PathSpec {
                    Tiles = tiles.Skip(1).ToHashSet()
                }
            };

            propagatorPath2 = new TilePropagator(model, topology, new TilePropagatorOptions
            {
                BackTrackDepth = -1,
                Constraints    = new[] { pathConstraint },
            });
        }
示例#6
0
        public void TestLargeSeparationConstraint()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);
            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tiles = new[] { tile1, tile2 };

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);
            model.SetUniformFrequency();

            var separationConstraint = new SeparationConstraint
            {
                Tiles = new[] { tile1 }.ToHashSet(),
                MinDistance = 10,
            };

            var topology = new GridTopology(100, 100, false);

            var options = new TilePropagatorOptions
            {
                Constraints   = new ITileConstraint[] { separationConstraint },
                BacktrackType = BacktrackType.Backtrack,
            };
            var propagator = new TilePropagator(model, topology, options);

            propagator.Run();

            Assert.AreEqual(Resolution.Decided, propagator.Status);

            var r = propagator.ToArray();

            for (var x = 0; x < 100; x++)
            {
                for (var y = 0; y < 100; y++)
                {
                    if (r.Get(x, y) != tile1)
                    {
                        continue;
                    }
                    for (var dx = -1; dx <= 1; dx += 2)
                    {
                        for (var dy = -1; dy <= 1; dy += 2)
                        {
                            var x2 = x + dx;
                            var y2 = y + dy;
                            if (x2 >= 0 && x2 < 100 && y2 >= 0 && y2 < 100)
                            {
                                Assert.AreNotEqual(r.Get(x2, y2), tile1);
                            }
                        }
                    }
                }
            }
        }
        public void TestPriority()
        {
            var t1    = new Tile(1);
            var t2    = new Tile(2);
            var t3    = new Tile(3);
            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(t1, t1, Direction.XPlus);
            model.AddAdjacency(t1, t2, Direction.XPlus);
            model.AddAdjacency(t2, t2, Direction.XPlus);
            model.AddAdjacency(t2, t3, Direction.XPlus);
            model.AddAdjacency(t3, t3, Direction.XPlus);

            model.SetUniformFrequency();

            var topology = new GridTopology(6, 1, false).WithMask(new bool[] { true, true, true, true, true, false });

            IDictionary <Tile, PriorityAndWeight> weights = new Dictionary <Tile, PriorityAndWeight>
            {
                { t1, new PriorityAndWeight {
                      Priority = 0, Weight = 1
                  } },
                { t2, new PriorityAndWeight {
                      Priority = 1, Weight = 1
                  } },
                { t3, new PriorityAndWeight {
                      Priority = 2, Weight = 1
                  } },
            };

            var weightsArray = TopoArray.CreateByIndex(_ => weights, topology);

            var propagator = new TilePropagator(model, topology, new TilePropagatorOptions
            {
                IndexPickerType  = IndexPickerType.ArrayPriorityMinEntropy,
                WeightSetByIndex = TopoArray.CreateByIndex(_ => 0, topology),
                WeightSets       = new Dictionary <int, IDictionary <Tile, PriorityAndWeight> > {
                    { 0, weights }
                },
            });

            propagator.Select(0, 0, 0, t1);

            propagator.Run();

            Assert.AreEqual(Resolution.Decided, propagator.Status);

            var r = propagator.ToValueArray <int>();

            Assert.AreEqual(1, r.Get(0, 0));
            Assert.AreEqual(2, r.Get(1, 0));
            Assert.AreEqual(3, r.Get(2, 0));
            Assert.AreEqual(3, r.Get(3, 0));
        }
示例#8
0
        public void TestCountConstraint(CountComparison comparison, bool eager)
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);
            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tiles = new[] { tile1, tile2 };

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);
            model.SetUniformFrequency();

            var topology = new GridTopology(10, 10, false);

            var count = 3;

            var options = new TilePropagatorOptions
            {
                Constraints = new[]
                {
                    new CountConstraint
                    {
                        Tiles = new[] { tile1 }.ToHashSet(),
                Count      = count,
                Comparison = comparison,
                Eager      = eager,
                    }
                }
            };
            var propagator = new TilePropagator(model, topology, options);

            propagator.Run();

            Assert.AreEqual(Resolution.Decided, propagator.Status);

            var actualCount = propagator.ToValueArray <int>().ToArray2d().OfType <int>().Count(x => x == 1);

            switch (comparison)
            {
            case CountComparison.AtMost:
                Assert.LessOrEqual(actualCount, count);
                break;

            case CountComparison.AtLeast:
                Assert.GreaterOrEqual(actualCount, count);
                break;

            case CountComparison.Exactly:
                Assert.AreEqual(count, actualCount);
                break;
            }
        }
示例#9
0
        public void WangSetup()
        {
            // Reproduces the wang tiles found at
            // https://en.wikipedia.org/wiki/Wang_tile
            // They only have aperiodic tiling, so they are a hard set to put down.
            // Clockwise from top
            var tileBorders = new[]
            {
                "rrrg",
                "brbg",
                "rggg",
                "wbrb",
                "bbwb",
                "wwrw",
                "rgbw",
                "bwbr",
                "brwr",
                "ggbr",
                "rwrg",
            };
            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            for (var tile1 = 0; tile1 < tileBorders.Length; tile1++)
            {
                var tile1Border = tileBorders[tile1];
                for (var i = 0; i < 4; i++)
                {
                    var d = new[] { 3, 0, 2, 1 }[i];
                    var o = (i + 2) % 4;
                    for (var tile2 = 0; tile2 < tileBorders.Length; tile2++)
                    {
                        var tile2Border = tileBorders[tile2];
                        if (tile2Border[o] != tile1Border[i])
                        {
                            continue;
                        }
                        model.AddAdjacency(new Tile(tile1), new Tile(tile2), (Direction)d);
                    }
                }
            }
            model.SetUniformFrequency();

            var topology = new GridTopology(15, 15, false);

            var options = new TilePropagatorOptions
            {
                BackTrackDepth = -1,
            };

            propagatorWang = new TilePropagator(model, topology, options);
        }
示例#10
0
        public PathModel(bool forks = true)
        {
            bool Filter(Tile t)
            {
                if (!forks && new[] { Fork1, Fork2, Fork3, Fork4 }.Contains(t))
                {
                    return(false);
                }
                return(true);
            }

            Model.AddAdjacency(
                new[] { Empty, Straight1, Corner3, Corner4, Fork3 }.Where(Filter).ToList(),
                new[] { Empty, Straight1, Corner1, Corner2, Fork1 }.Where(Filter).ToList(),
                Direction.XPlus);

            Model.AddAdjacency(
                new[] { Straight2, Corner1, Corner2, Fork1, Fork2, Fork4 }.Where(Filter).ToList(),
                new[] { Straight2, Corner3, Corner4, Fork2, Fork3, Fork4 }.Where(Filter).ToList(),
                Direction.XPlus);

            Model.AddAdjacency(
                new[] { Empty, Straight2, Corner1, Corner4, Fork4 }.Where(Filter).ToList(),
                new[] { Empty, Straight2, Corner2, Corner3, Fork2 }.Where(Filter).ToList(),
                Direction.YPlus);

            Model.AddAdjacency(
                new[] { Straight1, Corner2, Corner3, Fork1, Fork2, Fork3 }.Where(Filter).ToList(),
                new[] { Straight1, Corner1, Corner4, Fork1, Fork3, Fork4 }.Where(Filter).ToList(),
                Direction.YPlus);

            Model.SetUniformFrequency();

            Exits = new Dictionary <Tile, ISet <Direction> >
            {
                { Straight1, new [] { Direction.YMinus, Direction.YPlus }.ToHashSet() },
                { Straight2, new [] { Direction.XMinus, Direction.XPlus }.ToHashSet() },
                { Corner1, new [] { Direction.YMinus, Direction.XPlus }.ToHashSet() },
                { Corner2, new [] { Direction.YPlus, Direction.XPlus }.ToHashSet() },
                { Corner3, new [] { Direction.YPlus, Direction.XMinus }.ToHashSet() },
                { Corner4, new [] { Direction.YMinus, Direction.XMinus }.ToHashSet() },
                { Fork1, new [] { Direction.YMinus, Direction.XPlus, Direction.YPlus }.ToHashSet() },
                { Fork2, new [] { Direction.XPlus, Direction.YPlus, Direction.XMinus }.ToHashSet() },
                { Fork3, new [] { Direction.YPlus, Direction.XMinus, Direction.YMinus }.ToHashSet() },
                { Fork4, new [] { Direction.XMinus, Direction.YMinus, Direction.XPlus }.ToHashSet() },
            };
        }
示例#11
0
        public void MirrorSetup()
        {
            var trb = new TileRotationBuilder(4, true, TileRotationTreatment.Missing);

            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tile3 = new Tile(3);
            var tile4 = new Tile(4);
            var tile5 = new Tile(5);

            var tiles = new[] { tile1, tile2, tile3, tile4 };

            var reflectX = new Rotation(0, true);

            trb.Add(tile1, reflectX, tile2);
            trb.Add(tile3, reflectX, tile3);
            trb.Add(tile5, reflectX, tile5);

            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(new[] { tile5 }, tiles, Direction.XPlus);
            model.AddAdjacency(new[] { tile5 }, tiles, Direction.XMinus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);


            model.SetUniformFrequency();
            model.SetFrequency(tile5, 0.0);

            var tr = trb.Build();

            var constraints = new[] { new MirrorXConstraint {
                                          TileRotation = tr
                                      } };


            // NB: It's important that width is an odd number
            var topology = new GridTopology(31, 31, false);

            var options = new TilePropagatorOptions
            {
                Constraints = constraints,
            };

            propagator7 = new TilePropagator(model, topology, options);
        }
示例#12
0
        public void TestSeparationConstraint()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);
            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tiles = new[] { tile1, tile2 };

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);
            model.SetUniformFrequency();

            var separationConstraint = new SeparationConstraint
            {
                Tiles = new[] { tile1 }.ToHashSet(),
                MinDistance = 3,
            };

            var countConstraint = new CountConstraint
            {
                Tiles = new[] { tile1 }.ToHashSet(),
                Count      = 2,
                Comparison = CountComparison.Exactly,
            };

            var topology = new GridTopology(4, 1, false);

            var options = new TilePropagatorOptions
            {
                Constraints   = new ITileConstraint[] { separationConstraint, countConstraint },
                BacktrackType = BacktrackType.Backtrack,
            };
            var propagator = new TilePropagator(model, topology, options);

            propagator.Run();

            Assert.AreEqual(Resolution.Decided, propagator.Status);

            var r = propagator.ToArray();

            // Only possible solution given the constraints
            Assert.AreEqual(tile1, r.Get(0));
            Assert.AreEqual(tile2, r.Get(1));
            Assert.AreEqual(tile2, r.Get(2));
            Assert.AreEqual(tile1, r.Get(3));
        }
示例#13
0
        public void FreeSetup()
        {
            var tileCount = 10;
            var topology  = new GridTopology(10, 10, 10, false);

            var model = new AdjacentModel(DirectionSet.Cartesian3d);

            var tiles = Enumerable.Range(0, tileCount).Select(x => new Tile(x)).ToList();;

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);
            model.AddAdjacency(tiles, tiles, Direction.ZPlus);

            model.SetUniformFrequency();

            propagator1 = new TilePropagator(model, topology, new TilePropagatorOptions {
            });
        }
示例#14
0
        public void TestDoubleCountConstraint()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);
            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tile3 = new Tile(3);
            var tiles = new[] { tile1, tile2, tile3 };

            model.AddAdjacency(new[] { tile2 }, new[] { tile1 }, Direction.XPlus);
            model.AddAdjacency(new[] { tile1 }, new[] { tile3 }, Direction.XPlus);
            model.AddAdjacency(new[] { tile3 }, new[] { tile3 }, Direction.XPlus);
            model.AddAdjacency(new[] { tile3 }, new[] { tile2 }, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);
            model.SetUniformFrequency();

            var topology = new GridTopology(10, 10, false);

            var count = 10;

            var options = new TilePropagatorOptions
            {
                Constraints = new[]
                {
                    new CountConstraint
                    {
                        Tiles = new[] { tile1, tile2 }.ToHashSet(),
                Count      = count,
                Comparison = CountComparison.Exactly,
                Eager      = true,
                    }
                }
            };
            var propagator = new TilePropagator(model, topology, options);

            propagator.Run();

            Assert.AreEqual(Resolution.Decided, propagator.Status);

            var actualCount = propagator.ToValueArray <int>().ToArray2d().OfType <int>().Count(x => x == 1 || x == 2);

            Assert.AreEqual(count, actualCount);
        }
示例#15
0
        public void TestDirtyIndexPicker()
        {
            var t1    = new Tile(1);
            var t2    = new Tile(2);
            var t3    = new Tile(3);
            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(t1, t1, Direction.XPlus);
            model.AddAdjacency(t1, t2, Direction.XPlus);
            model.AddAdjacency(t2, t2, Direction.XPlus);
            model.AddAdjacency(t2, t3, Direction.XPlus);
            model.AddAdjacency(t3, t3, Direction.XPlus);
            model.AddAdjacency(t3, t2, Direction.XPlus);
            model.AddAdjacency(t2, t1, Direction.XPlus);

            model.SetUniformFrequency();

            var topology = new GridTopology(6, 1, false);

            var options = new TilePropagatorOptions
            {
                IndexPickerType = IndexPickerType.Dirty,
                TilePickerType  = TilePickerType.Ordered,
                CleanTiles      = TopoArray.FromConstant(t1, topology),
            };

            var propagator = new TilePropagator(model, topology, options);

            propagator.Select(3, 0, 0, t3);

            propagator.Run();

            var a = propagator.ToValueArray <int?>();

            Assert.AreEqual(null, a.Get(0, 0));
            Assert.AreEqual(null, a.Get(1, 0));
            Assert.AreEqual(2, a.Get(2, 0));
            Assert.AreEqual(3, a.Get(3, 0));
            Assert.AreEqual(2, a.Get(4, 0));
            Assert.AreEqual(null, a.Get(5, 0));
        }
示例#16
0
        public void ChessSetup()
        {
            var topology = new GridTopology(10, 10, 10, false);

            var model = new AdjacentModel(DirectionSet.Cartesian3d);

            var t1 = new Tile(1);
            var t2 = new Tile(2);

            model.AddAdjacency(t1, t2, Direction.XPlus);
            model.AddAdjacency(t2, t1, Direction.XPlus);
            model.AddAdjacency(t1, t2, Direction.YPlus);
            model.AddAdjacency(t2, t1, Direction.YPlus);
            model.AddAdjacency(t1, t2, Direction.ZPlus);
            model.AddAdjacency(t2, t1, Direction.ZPlus);

            model.SetUniformFrequency();

            propagator2 = new TilePropagator(model, topology, new TilePropagatorOptions {
            });
        }
        public void TestDirectionality()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(new Tile(1), new Tile(2), 1, 0, 0);
            model.SetUniformFrequency();

            var topology = new GridTopology(2, 1, false);

            var up   = Direction.YPlus;
            var down = Direction.YMinus;

            var seed = Environment.TickCount;
            var r    = new Random(seed);

            Console.WriteLine("Seed {0}", seed);

            var constraint = new ConnectedConstraint
            {
                PathSpec = new EdgedPathSpec
                {
                    Exits = new Dictionary <Tile, ISet <Direction> >()
                    {
                        { new Tile(1), new[] { up, down }.ToHashSet() },
                        { new Tile(2), new[] { up, down }.ToHashSet() },
                    }
                }
            };

            var propagator = new TilePropagator(model, topology, new TilePropagatorOptions
            {
                RandomDouble = r.NextDouble,
                Constraints  = new[] { constraint }
            });

            propagator.Run();

            Assert.AreEqual(Resolution.Contradiction, propagator.Status);
        }
示例#18
0
        public void TestRotationalAddAdjacenciesAdvanced()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);
            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tile3 = new Tile(3);
            var tile4 = new Tile(4);


            var rotationBuilder = new TileRotationBuilder(4, false, TileRotationTreatment.Missing);

            rotationBuilder.Add(tile1, new Rotation(90), tile3);
            rotationBuilder.Add(tile2, new Rotation(90), tile4);
            var rotations = rotationBuilder.Build();

            model.AddAdjacency(new[] { tile1 }, new[] { tile2 }, 1, 0, 0, rotations);

            model.SetUniformFrequency();

            var patternModel = model.GetTileModelMapping(new GridTopology(10, 10, false)).PatternModel;

            CollectionAssert.AreEquivalent(new int[] { 1 }, patternModel.Propagator[0][0]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[0][1]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[0][2]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[0][3]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[1][0]);
            CollectionAssert.AreEquivalent(new int[] { 0 }, patternModel.Propagator[1][1]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[1][2]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[1][3]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[2][0]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[2][1]);
            CollectionAssert.AreEquivalent(new int[] { 3 }, patternModel.Propagator[2][2]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[2][3]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[3][0]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[3][1]);
            CollectionAssert.AreEquivalent(new int[] {   }, patternModel.Propagator[3][2]);
            CollectionAssert.AreEquivalent(new int[] { 2 }, patternModel.Propagator[3][3]);
        }
示例#19
0
        public void PathSetup()
        {
            var tileCount = 10;
            var topology  = new GridTopology(20, 20, false);

            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            var tiles = Enumerable.Range(0, tileCount).Select(x => new Tile(x)).ToList();;

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);

            model.SetUniformFrequency();
#pragma warning disable CS0618 // Type or member is obsolete
            var pathConstraint = new PathConstraint(tiles.Skip(1).ToHashSet());
#pragma warning restore CS0618 // Type or member is obsolete

            propagatorPath = new TilePropagator(model, topology, new TilePropagatorOptions
            {
                BackTrackDepth = -1,
                Constraints    = new[] { pathConstraint },
            });
        }
示例#20
0
        public void TestUnassignableEager()
        {
            var model = new AdjacentModel(DirectionSet.Cartesian2d);
            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tiles = new[] { tile1, tile2 };

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(tiles, tiles, Direction.YPlus);
            model.SetUniformFrequency();

            var topology = new GridTopology(3, 1, false);

            var count = 3;

            var options = new TilePropagatorOptions
            {
                Constraints = new[]
                {
                    new CountConstraint
                    {
                        Tiles = new[] { tile1, }.ToHashSet(),
                Count      = count,
                Comparison = CountComparison.Exactly,
                Eager      = true,
                    }
                }
            };
            var propagator = new TilePropagator(model, topology, options);

            propagator.Select(1, 0, 0, tile2);

            propagator.Run();

            Assert.AreEqual(Resolution.Contradiction, propagator.Status);
        }
        public void TestPathPickHeuristic()
        {
            var topology = new GridTopology(15, 15, false);

            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            var empty     = new Tile(" ");
            var straight1 = new Tile("║");
            var straight2 = new Tile("═");
            var corner1   = new Tile("╚");
            var corner2   = new Tile("╔");
            var corner3   = new Tile("╗");
            var corner4   = new Tile("╝");
            var fork1     = new Tile("╠");
            var fork2     = new Tile("╦");
            var fork3     = new Tile("╣");
            var fork4     = new Tile("╩");

            model.AddAdjacency(
                new[] { empty, straight1, corner3, corner4, fork3 },
                new[] { empty, straight1, corner1, corner2, fork1 },
                Direction.XPlus);

            model.AddAdjacency(
                new[] { straight2, corner1, corner2, fork1, fork2, fork4 },
                new[] { straight2, corner3, corner4, fork2, fork3, fork4 },
                Direction.XPlus);

            model.AddAdjacency(
                new[] { empty, straight2, corner1, corner4, fork4 },
                new[] { empty, straight2, corner2, corner3, fork2 },
                Direction.YPlus);

            model.AddAdjacency(
                new[] { straight1, corner2, corner3, fork1, fork2, fork3 },
                new[] { straight1, corner1, corner4, fork1, fork3, fork4 },
                Direction.YPlus);

            model.SetUniformFrequency();

            var exits = new Dictionary <Tile, ISet <Direction> >
            {
                { straight1, new [] { Direction.YMinus, Direction.YPlus }.ToHashSet() },
                { straight2, new [] { Direction.XMinus, Direction.XPlus }.ToHashSet() },
                { corner1, new [] { Direction.YMinus, Direction.XPlus }.ToHashSet() },
                { corner2, new [] { Direction.YPlus, Direction.XPlus }.ToHashSet() },
                { corner3, new [] { Direction.YPlus, Direction.XMinus }.ToHashSet() },
                { corner4, new [] { Direction.YMinus, Direction.XMinus }.ToHashSet() },
                { fork1, new [] { Direction.YMinus, Direction.XPlus, Direction.YPlus }.ToHashSet() },
                { fork2, new [] { Direction.XPlus, Direction.YPlus, Direction.XMinus }.ToHashSet() },
                { fork3, new [] { Direction.YPlus, Direction.XMinus, Direction.YMinus }.ToHashSet() },
                { fork4, new [] { Direction.XMinus, Direction.YMinus, Direction.XPlus }.ToHashSet() },
            };

#pragma warning disable CS0618 // Type or member is obsolete
            var pathConstraint = new ConnectedConstraint
#pragma warning restore CS0618 // Type or member is obsolete
            {
                PathSpec = new EdgedPathSpec {
                    Exits = exits
                },
                UsePickHeuristic = true
            };

            var propagator = new TilePropagator(model, topology, new TilePropagatorOptions
            {
                BackTrackDepth = -1,
                Constraints    = new[] { pathConstraint },
            });

            propagator.Run();

            Assert.AreEqual(propagator.Status, Resolution.Decided);
        }
示例#22
0
        public void EdgedPathSetup()
        {
            var topology = new GridTopology(15, 15, false);

            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            var empty     = new Tile(" ");
            var straight1 = new Tile("║");
            var straight2 = new Tile("═");
            var corner1   = new Tile("╚");
            var corner2   = new Tile("╔");
            var corner3   = new Tile("╗");
            var corner4   = new Tile("╝");
            var fork1     = new Tile("╠");
            var fork2     = new Tile("╦");
            var fork3     = new Tile("╣");
            var fork4     = new Tile("╩");

            model.AddAdjacency(
                new[] { empty, straight1, corner3, corner4, fork3 },
                new[] { empty, straight1, corner1, corner2, fork1 },
                Direction.XPlus);

            model.AddAdjacency(
                new[] { straight2, corner1, corner2, fork1, fork2, fork4 },
                new[] { straight2, corner3, corner4, fork2, fork3, fork4 },
                Direction.XPlus);

            model.AddAdjacency(
                new[] { empty, straight2, corner1, corner4, fork4 },
                new[] { empty, straight2, corner2, corner3, fork2 },
                Direction.YPlus);

            model.AddAdjacency(
                new[] { straight1, corner2, corner3, fork1, fork2, fork3 },
                new[] { straight1, corner1, corner4, fork1, fork3, fork4 },
                Direction.YPlus);

            model.SetUniformFrequency();

            var exits = new Dictionary <Tile, ISet <Direction> >
            {
                { straight1, new [] { Direction.YMinus, Direction.YPlus }.ToHashSet() },
                { straight2, new [] { Direction.XMinus, Direction.XPlus }.ToHashSet() },
                { corner1, new [] { Direction.YMinus, Direction.XPlus }.ToHashSet() },
                { corner2, new [] { Direction.YPlus, Direction.XPlus }.ToHashSet() },
                { corner3, new [] { Direction.YPlus, Direction.XMinus }.ToHashSet() },
                { corner4, new [] { Direction.YMinus, Direction.XMinus }.ToHashSet() },
                { fork1, new [] { Direction.YMinus, Direction.XPlus, Direction.YPlus }.ToHashSet() },
                { fork2, new [] { Direction.XPlus, Direction.YPlus, Direction.XMinus }.ToHashSet() },
                { fork3, new [] { Direction.YPlus, Direction.XMinus, Direction.YMinus }.ToHashSet() },
                { fork4, new [] { Direction.XMinus, Direction.YMinus, Direction.XPlus }.ToHashSet() },
            };

            var pathConstraint = new EdgedPathConstraint(exits);

            propagator4 = new TilePropagator(model, topology, new TilePropagatorOptions
            {
                BackTrackDepth = -1,
                Constraints    = new[] { pathConstraint },
            });
        }
        public void TestMirrorConstraint()
        {
            var trb = new TileRotationBuilder(4, true, TileRotationTreatment.Missing);

            var tile1 = new Tile(1);
            var tile2 = new Tile(2);
            var tile3 = new Tile(3);
            var tile4 = new Tile(4);
            var tile5 = new Tile(5);

            var tiles = new[] { tile1, tile2, tile3, tile4 };

            var reflectX = new Rotation(0, true);

            trb.Add(tile1, reflectX, tile2);
            trb.Add(tile3, reflectX, tile3);
            trb.Add(tile5, reflectX, tile5);

            var model = new AdjacentModel(DirectionSet.Cartesian2d);

            model.AddAdjacency(tiles, tiles, Direction.XPlus);
            model.AddAdjacency(new[] { tile5 }, tiles, Direction.XPlus);
            model.AddAdjacency(new[] { tile5 }, tiles, Direction.XMinus);

            model.SetUniformFrequency();
            model.SetFrequency(tile5, 0.0);

            var tr = trb.Build();

            var constraints = new[] { new MirrorXConstraint {
                                          TileRotation = tr
                                      } };

            // tile1 reflects to tile 2
            {
                var t2 = new GridTopology(2, 1, false);
                var p2 = new TilePropagator(model, t2, constraints: constraints);
                p2.Select(0, 0, 0, tile1);
                var status = p2.Run();
                Assert.AreEqual(Resolution.Decided, status);
                Assert.AreEqual(tile2, p2.ToArray().Get(1, 0));
            }

            // tile3 reflects to tile3
            {
                var t2 = new GridTopology(2, 1, false);
                var p2 = new TilePropagator(model, t2, constraints: constraints);
                p2.Select(0, 0, 0, tile3);
                var status = p2.Run();
                Assert.AreEqual(Resolution.Decided, status);
                Assert.AreEqual(tile3, p2.ToArray().Get(1, 0));
            }

            // tile3 only tile that can go in a central space
            // (tile5 can go, but has zero frequency)
            // So tile3 should be selected reliably
            {
                var t2     = new GridTopology(3, 1, false);
                var p2     = new TilePropagator(model, t2, constraints: constraints);
                var status = p2.Run();
                Assert.AreEqual(Resolution.Decided, status);
                Assert.AreEqual(tile3, p2.ToArray().Get(1, 0));
            }

            // tile5 can be reflected, but cannot
            // be placed adjacent to it's own reflection
            {
                var t2 = new GridTopology(2, 1, false);
                var p2 = new TilePropagator(model, t2, constraints: constraints);
                p2.Select(0, 0, 0, tile5);
                var status = p2.Run();
                Assert.AreEqual(Resolution.Contradiction, status);
            }

            {
                var t2 = new GridTopology(4, 1, false);
                var p2 = new TilePropagator(model, t2, constraints: constraints);
                p2.Select(0, 0, 0, tile5);
                var status = p2.Run();
                Assert.AreEqual(Resolution.Decided, status);
            }
        }