Пример #1
0
        public void TestMaskWithOverlapping()
        {
            var a = new int[, ] {
                { 1, 0 },
                { 0, 1 },
            };
            var model = OverlappingModel.Create(a, 2, false, 8);

            var mask = new bool[4 * 5];

            for (var x = 0; x < 5; x++)
            {
                for (var y = 0; y < 4; y++)
                {
                    if (x == 2 || x == 3)
                    {
                        mask[x + y * 5] = false;
                    }
                    else
                    {
                        mask[x + y * 5] = true;
                    }
                }
            }
            var topology = new GridTopology(5, 4, false).WithMask(mask);

            var propagator = new TilePropagator(model, topology);

            propagator.Select(0, 0, 0, new Tile(1));
            propagator.Select(4, 0, 0, new Tile(0));

            propagator.Run();

            Assert.AreEqual(Resolution.Decided, propagator.Status);
        }
Пример #2
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();
        }
Пример #3
0
        public void Mirror()
        {
            propagator7.Clear();
            propagator7.Run();

            Check(propagator7);
        }
Пример #4
0
        public void Count()
        {
            propagatorCount.Clear();
            propagatorCount.Run();

            Check(propagatorCount);
        }
        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();
        }
Пример #6
0
        public void Count()
        {
            propagator6.Clear();
            propagator6.Run();

            Check(propagator6);
        }
Пример #7
0
        public void QuickStartTest()
        {
            ITopoArray <char> sample = TopoArray.Create(new[, ]
            {
                { '_', '_', '_' },
                { '_', '*', '_' },
                { '_', '_', '_' },
            }, periodic: false);
            // Specify the model used for generation
            var model = new AdjacentModel(sample.ToTiles());
            // Set the output dimensions
            var topology = new Topology(10, 10, periodic: false);
            // Actually run the algorithm
            var propagator = new TilePropagator(model, topology);
            var status     = propagator.Run();

            if (status != Resolution.Decided)
            {
                throw new Exception("Undecided");
            }
            var output = propagator.ToValueArray <char>();

            // Display the results
            for (var y = 0; y < 10; y++)
            {
                for (var x = 0; x < 10; x++)
                {
                    System.Console.Write(output.Get(x, y));
                }
                System.Console.WriteLine();
            }
        }
Пример #8
0
        private Resolution RunAnimate(TileModel model, TilePropagator propagator, string dest, ExportOptions exportOptions)
        {
            if (!config.Animate)
            {
                return(propagator.Run());
            }
            // Animate is true - we run the propagator, and export after every step
            Resolution status   = Resolution.Undecided;
            var        allFiles = new List <string>();
            int        i        = 0;

            while (true)
            {
                status = propagator.Step();
                Directory.CreateDirectory(Path.GetDirectoryName(dest));
                var currentDest = Path.ChangeExtension(dest, i + Path.GetExtension(dest));
                allFiles.Add(currentDest);
                Exporter.Export(model, propagator, currentDest, config, exportOptions);
                i++;
                if (status != Resolution.Undecided)
                {
                    return(status);
                }
            }
        }
Пример #9
0
        public void Mirror()
        {
            propagatorMirror.Clear();
            propagatorMirror.Run();

            Check(propagatorMirror);
        }
Пример #10
0
        public void TestMask()
        {
            var a = new int[, ] {
                { 1, 0 },
                { 0, 1 },
            };
            var model = new AdjacentModel();

            model.AddSample(TopoArray.Create(a, true).ToTiles());

            var mask = new bool[5 * 5];

            for (var x = 0; x < 5; x++)
            {
                for (var y = 0; y < 5; y++)
                {
                    if (x == 2 || y == 2)
                    {
                        mask[x + y * 5] = false;
                    }
                    else
                    {
                        mask[x + y * 5] = true;
                    }
                }
            }
            var topology = new GridTopology(5, 5, true).WithMask(mask);

            var propagator = new TilePropagator(model, topology);

            propagator.Run();

            Assert.AreEqual(Resolution.Decided, propagator.Status);
        }
Пример #11
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);
        }
Пример #12
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);
                            }
                        }
                    }
                }
            }
        }
Пример #13
0
        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));
        }
Пример #14
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;
            }
        }
Пример #15
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));
        }
Пример #16
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);
        }
Пример #17
0
        public void Path()
        {
            propagator5.Clear();
            propagator5.Run();

            Check(propagator5);

            if (false)
            {
                var v = propagator5.ToValueArray <string>();
                for (var y = 0; y < v.Topology.Height; y++)
                {
                    for (var x = 0; x < v.Topology.Width; x++)
                    {
                        System.Console.Write(v.Get(x, y));
                    }
                    System.Console.WriteLine();
                }
            }
        }
Пример #18
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));
        }
        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);
        }
Пример #20
0
        public void TestToTopArray()
        {
            var a = new int[, ] {
                { 1, 0 },
                { 0, 1 },
            };
            var model = OverlappingModel.Create(a, 2, false, 8);

            var propagator = new TilePropagator(model, new GridTopology(4, 4, false));

            propagator.Select(0, 0, 0, new Tile(1));
            var status = propagator.Run();

            Assert.AreEqual(Resolution.Decided, status);

            var result = propagator.ToValueArray <int>().ToArray2d();

            Assert.AreEqual(4, result.GetLength(0));
            Assert.AreEqual(4, result.GetLength(1));

            Assert.AreEqual(1, result[0, 0]);
            Assert.AreEqual(1, result[3, 3]);
        }
Пример #21
0
        public void TestBorderConstraint()
        {
            var a = new int[, ] {
                { 1, 0, 0 },
                { 0, 1, 1 },
                { 0, 1, 1 },
            };

            var model      = AdjacentModel.Create(a, true);
            var propagator = new TilePropagator(model, new GridTopology(10, 10, false), true, constraints: new[] {
                new BorderConstraint {
                    Tiles = new [] { new Tile(0) },
                }
            });
            var status = propagator.Run();

            Assert.AreEqual(Resolution.Decided, status);
            var result = propagator.ToValueArray <int>().ToArray2d();

            Assert.AreEqual(0, result[0, 0]);
            Assert.AreEqual(0, result[9, 0]);
            Assert.AreEqual(0, result[0, 9]);
            Assert.AreEqual(0, result[9, 9]);
        }
Пример #22
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);
        }
Пример #23
0
        public void TestLoopConstraint()
        {
            var a = new int[, ] {
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 1, 1, 1, 1, 0, 0 },
                { 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0 }
            };

            var seed = Environment.TickCount;
            // TODO: This seed shows that this constraint can fail occasionally
            //seed = -1847040250;
            var r = new Random(seed);

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

            var model = OverlappingModel.Create(a, 3, false, 8);

            var constraint = new LoopConstraint
            {
                PathSpec = new PathSpec
                {
                    Tiles = new HashSet <Tile> {
                        new Tile(1)
                    },
                }
            };

            var topology   = new GridTopology(10, 10, false);
            var propagator = new TilePropagator(model, topology, new TilePropagatorOptions
            {
                BacktrackType = BacktrackType.Backtrack,
                Constraints   = new[] { constraint },
                RandomDouble  = r.NextDouble
            });
            var status = propagator.Run();

            Assert.AreEqual(Resolution.Decided, status);
            var result = propagator.ToValueArray <int>().ToArray2d();

            // Write out result for debugging
            for (var y = 0; y < topology.Height; y++)
            {
                for (var x = 0; x < topology.Width; x++)
                {
                    System.Console.Write(result[x, y]);
                }
                System.Console.WriteLine();
            }
            // Every cell should have exactly 2 neighbours
            for (var y = 0; y < topology.Height; y++)
            {
                for (var x = 0; x < topology.Width; x++)
                {
                    if (result[x, y] == 1)
                    {
                        var n = 0;
                        if (x > 0)
                        {
                            n += result[x - 1, y];
                        }
                        if (x < topology.Width - 1)
                        {
                            n += result[x + 1, y];
                        }
                        if (y > 0)
                        {
                            n += result[x, y - 1];
                        }
                        if (y < topology.Height - 1)
                        {
                            n += result[x, y + 1];
                        }
                        Assert.AreEqual(2, n, $"At {x},{y}");
                    }
                }
            }
        }
Пример #24
0
        public void TestGraphAdjacentModel()
        {
            // Define simple cube graph which unfolds and orients as follows
            //
            //    ┌─┐
            //    │4│
            //  ┌─┼─┼─┬─┐
            //  │3│0│1│2│
            //  └─┼─┼─┴─┘
            //    │5│
            //    └─┘
            // Neighbours (from top, clockwise)
            // 0: [4, 1, 5, 3]
            // 1: [4, 2, 5, 0]
            // 2: [4, 3, 5, 1]
            // 3: [4, 0, 5, 2]
            // 4: [2, 1, 0, 3]
            // 5: [0, 1, 2, 3]

            var meshBuilder = new MeshTopologyBuilder(DirectionSet.Cartesian2d);

            meshBuilder.Add(0, 1, Direction.XPlus);
            meshBuilder.Add(0, 3, Direction.XMinus);
            meshBuilder.Add(0, 5, Direction.YPlus);
            meshBuilder.Add(0, 4, Direction.YMinus);
            meshBuilder.Add(1, 2, Direction.XPlus);
            meshBuilder.Add(1, 0, Direction.XMinus);
            meshBuilder.Add(1, 5, Direction.YPlus);
            meshBuilder.Add(1, 4, Direction.YMinus);
            meshBuilder.Add(2, 3, Direction.XPlus);
            meshBuilder.Add(2, 1, Direction.XMinus);
            meshBuilder.Add(2, 5, Direction.YPlus);
            meshBuilder.Add(2, 4, Direction.YMinus);
            meshBuilder.Add(3, 0, Direction.XPlus);
            meshBuilder.Add(3, 2, Direction.XMinus);
            meshBuilder.Add(3, 5, Direction.YPlus);
            meshBuilder.Add(3, 4, Direction.YMinus);
            meshBuilder.Add(4, 1, Direction.XPlus);
            meshBuilder.Add(4, 3, Direction.XMinus);
            meshBuilder.Add(4, 0, Direction.YPlus);
            meshBuilder.Add(4, 2, Direction.YMinus);
            meshBuilder.Add(5, 1, Direction.XPlus);
            meshBuilder.Add(5, 3, Direction.XMinus);
            meshBuilder.Add(5, 2, Direction.YPlus);
            meshBuilder.Add(5, 0, Direction.YMinus);

            var topology = meshBuilder.GetTopology();

            var model = new GraphAdjacentModel(meshBuilder.GetInfo());

            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 tileRotationBuilder = new TileRotationBuilder(4, true, TileRotationTreatment.Missing);

            tileRotationBuilder.AddSymmetry(empty, TileSymmetry.X);
            tileRotationBuilder.AddSymmetry(straight1, TileSymmetry.I);
            tileRotationBuilder.AddSymmetry(straight2, TileSymmetry.I);
            tileRotationBuilder.AddSymmetry(corner1, TileSymmetry.L);
            tileRotationBuilder.AddSymmetry(corner2, TileSymmetry.Q);
            tileRotationBuilder.AddSymmetry(corner3, TileSymmetry.L);
            tileRotationBuilder.AddSymmetry(corner4, TileSymmetry.Q);
            tileRotationBuilder.Add(straight1, new Rotation(90), straight2);
            tileRotationBuilder.Add(corner1, new Rotation(90), corner2);
            tileRotationBuilder.Add(corner2, new Rotation(90), corner3);
            tileRotationBuilder.Add(corner3, new Rotation(90), corner4);
            tileRotationBuilder.Add(corner4, new Rotation(90), corner1);

            var tileRotation = tileRotationBuilder.Build();

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

            model.AddAdjacency(
                new[] { straight2, corner1, corner2 },
                new[] { straight2, corner3, corner4 },
                Direction.XPlus, tileRotation);

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

            model.AddAdjacency(
                new[] { straight1, corner2, corner3 },
                new[] { straight1, corner1, corner4 },
                Direction.YPlus, tileRotation);

            model.SetUniformFrequency();

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

            void PrintPropagator()
            {
                var a = propagator.ToValueArray("?", "!");

                var str = @"
                ┌─┐
                │4│
              ┌─┼─┼─┬─┐
              │3│0│1│2│
              └─┼─┼─┴─┘
                │5│
                └─┘";

                for (var i = 0; i < 6; i++)
                {
                    str = str.Replace(i.ToString(), (string)a.Get(i));
                }
                System.Console.Write(str);
            }

            propagator.Run();
            PrintPropagator();

            Assert.AreEqual(Resolution.Decided, 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);
        }
Пример #26
0
        public void TestAcyclicConstraint()
        {
            var a = new int[, ] {
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 1, 1, 1, 1, 0, 0 },
                { 0, 1, 0, 0, 0, 0 },
                { 0, 1, 0, 0, 0, 0 }
            };

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

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

            var model    = OverlappingModel.Create(a, 3, false, 8);
            var topology = new GridTopology(10, 10, false);

            /*
             * var pathSpec = new PathSpec
             * {
             *  Tiles = new HashSet<Tile> { new Tile(1) },
             * };
             */
            var pathSpec = new EdgedPathSpec
            {
                Exits = new Dictionary <Tile, ISet <Direction> > {
                    { new Tile(1), topology.Directions.ToHashSet() }
                },
            };
            var constraint = new AcyclicConstraint
            {
                PathSpec = pathSpec,
            };

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

            Assert.AreEqual(Resolution.Decided, status);
            var result = propagator.ToValueArray <int>().ToArray2d();

            // Write out result for debugging
            for (var y = 0; y < topology.Height; y++)
            {
                for (var x = 0; x < topology.Width; x++)
                {
                    Console.Write(result[x, y]);
                }
                Console.WriteLine();
            }
            var visited = new bool[topology.Width, topology.Height];

            for (var y = 0; y < topology.Height; y++)
            {
                for (var x = 0; x < topology.Width; x++)
                {
                    if (result[x, y] != 1)
                    {
                        continue;
                    }
                    if (visited[x, y])
                    {
                        continue;
                    }
                    void Visit(int x2, int y2, int dir)
                    {
                        if (x2 < 0 || x2 >= topology.Width || y2 < 0 || y2 >= topology.Height)
                        {
                            return;
                        }
                        if (result[x2, y2] != 1)
                        {
                            return;
                        }
                        if (visited[x2, y2])
                        {
                            Assert.Fail();
                        }
                        visited[x2, y2] = true;
                        if (dir != 0)
                        {
                            Visit(x2 - 1, y2, 2);
                        }
                        if (dir != 2)
                        {
                            Visit(x2 + 1, y2, 0);
                        }
                        if (dir != 1)
                        {
                            Visit(x2, y2 - 1, 3);
                        }
                        if (dir != 3)
                        {
                            Visit(x2, y2 + 1, 1);
                        }
                    }

                    Visit(x, y, -1);
                }
            }
        }
Пример #27
0
 public void Chess()
 {
     propagator2.Clear();
     propagator2.Run();
 }
Пример #28
0
        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);
            }
        }
Пример #29
0
        public void TestPathConstraint()
        {
            var a = new int[, ] {
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 1, 1, 1, 1, 0, 0 },
                { 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0 }
            };

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

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

            var model      = OverlappingModel.Create(a, 3, false, 8);
            var propagator = new TilePropagator(model, new Topology(10, 10, false), true, constraints: new[] {
                new PathConstraint(new HashSet <Tile> {
                    new Tile(1)
                }, new [] { new Point(0, 0), new Point(9, 9) })
            }, random: r);
            var status = propagator.Run();

            Assert.AreEqual(Resolution.Decided, status);
            var result = propagator.ToValueArray <int>().ToArray2d();

            // Write out result for debugging
            for (var y = 0; y < 10; y++)
            {
                for (var x = 0; x < 10; x++)
                {
                    Console.Write(result[x, y]);
                }
                Console.WriteLine();
            }
            // Simple flood fill algorithm to determine we have in fact got a path
            var stack   = new Stack <ValueTuple <int, int> >();
            var visited = new bool[10, 10];

            stack.Push((0, 0));
            while (stack.TryPop(out var current))
            {
                var(x, y) = current;
                if (x < 0 || x >= 10 || y < 0 || y >= 10)
                {
                    continue;
                }
                if (visited[x, y])
                {
                    continue;
                }
                visited[x, y] = true;
                if (result[x, y] == 1)
                {
                    if (x == 9 && y == 9)
                    {
                        return;
                    }
                    stack.Push((x + 1, y));
                    stack.Push((x - 1, y));
                    stack.Push((x, y + 1));
                    stack.Push((x, y - 1));
                }
            }
            Assert.Fail();
        }
        public void TestConnectedConstraintWithEdged()
        {
            var a = new int[, ] {
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 0, 0, 0, 1, 0, 0 },
                { 1, 1, 1, 1, 0, 0 },
                { 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0 }
            };

            var allDirections = DirectionSet.Cartesian2d.ToHashSet();

            var exits = new Dictionary <Tile, ISet <Direction> >()
            {
                { new Tile(1), allDirections },
            };

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

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

            var model = OverlappingModel.Create(a, 3, false, 8);

            var constraint = new ConnectedConstraint
            {
                PathSpec = new EdgedPathSpec
                {
                    Exits         = exits,
                    RelevantCells = new[] { new Point(0, 0), new Point(9, 9) },
                }
            };

            var propagator = new TilePropagator(model, new GridTopology(10, 10, false), new TilePropagatorOptions
            {
                BackTrackDepth = -1,
                Constraints    = new[] { constraint },
                RandomDouble   = r.NextDouble
            });
            var status = propagator.Run();

            Assert.AreEqual(Resolution.Decided, status);
            var result = propagator.ToValueArray <int>().ToArray2d();

            // Write out result for debugging
            for (var y = 0; y < 10; y++)
            {
                for (var x = 0; x < 10; x++)
                {
                    Console.Write(result[x, y]);
                }
                Console.WriteLine();
            }
            // Simple flood fill algorithm to determine we have in fact got a path
            var stack   = new Stack <ValueTuple <int, int> >();
            var visited = new bool[10, 10];

            stack.Push((0, 0));
            while (stack.TryPop(out var current))
            {
                var(x, y) = current;
                if (x < 0 || x >= 10 || y < 0 || y >= 10)
                {
                    continue;
                }
                if (visited[x, y])
                {
                    continue;
                }
                visited[x, y] = true;
                if (result[x, y] == 1)
                {
                    if (x == 9 && y == 9)
                    {
                        return;
                    }
                    stack.Push((x + 1, y));
                    stack.Push((x - 1, y));
                    stack.Push((x, y + 1));
                    stack.Push((x, y - 1));
                }
            }
            Assert.Fail();
        }