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 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) }) }); 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(); }
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 GridTopology(10, 10, false), new TilePropagatorOptions { BackTrackDepth = -1, Constraints = new[] { #pragma warning disable CS0618 // Type or member is obsolete new PathConstraint(new HashSet <Tile> { new Tile(1) }, new [] { new Point(0, 0), new Point(9, 9) }) #pragma warning restore CS0618 // Type or member is obsolete }, 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(); }
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); } } }
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); 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 { 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(); } // 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}"); } } } }