public void TestBannedSelected() { var a = new int[, ] { { 1, 2, 3 }, { 3, 1, 2 }, { 2, 3, 1 }, }; var model = AdjacentModel.Create(a, true); var topology = new GridTopology(10, 10, false); var propagator = new TilePropagator(model, topology); var tile1 = new Tile(1); var set1 = propagator.CreateTileSet(new[] { new Tile(1) }); var set12 = propagator.CreateTileSet(new[] { new Tile(1), new Tile(2) }); { propagator.GetBannedSelected(0, 0, 0, tile1, out var isBanned1, out var isSelected1); propagator.GetBannedSelected(0, 0, 0, set1, out var isBanned2, out var isSelected2); propagator.GetBannedSelected(0, 0, 0, set12, out var isBanned3, out var isSelected3); Assert.AreEqual(false, isBanned1); Assert.AreEqual(false, isBanned2); Assert.AreEqual(false, isBanned3); Assert.AreEqual(false, isSelected1); Assert.AreEqual(false, isSelected2); Assert.AreEqual(false, isSelected3); } propagator.Ban(0, 0, 0, new Tile(3)); { propagator.GetBannedSelected(0, 0, 0, tile1, out var isBanned1, out var isSelected1); propagator.GetBannedSelected(0, 0, 0, set1, out var isBanned2, out var isSelected2); propagator.GetBannedSelected(0, 0, 0, set12, out var isBanned3, out var isSelected3); Assert.AreEqual(false, isBanned1); Assert.AreEqual(false, isBanned2); Assert.AreEqual(false, isBanned3); Assert.AreEqual(false, isSelected1); Assert.AreEqual(false, isSelected2); Assert.AreEqual(true, isSelected3); } propagator.Ban(0, 0, 0, new Tile(1)); { propagator.GetBannedSelected(0, 0, 0, tile1, out var isBanned1, out var isSelected1); propagator.GetBannedSelected(0, 0, 0, set1, out var isBanned2, out var isSelected2); propagator.GetBannedSelected(0, 0, 0, set12, out var isBanned3, out var isSelected3); Assert.AreEqual(true, isBanned1); Assert.AreEqual(true, isBanned2); Assert.AreEqual(false, isBanned3); Assert.AreEqual(false, isSelected1); Assert.AreEqual(false, isSelected2); Assert.AreEqual(true, isSelected3); } }
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 Point GetRandomPoint(TilePropagator propagator, TilePropagatorTileSet tileSet) { var topology = propagator.Topology; var points = new List <Point>(); for (var z = 0; z < topology.Depth; z++) { for (var y = 0; y < topology.Height; y++) { for (var x = 0; x < topology.Width; x++) { if (topology.Mask != null) { var index = topology.GetIndex(x, y, z); if (!topology.Mask[index]) { continue; } } propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var _); if (isBanned) { continue; } points.Add(new Point(x, y, z)); } } } // Choose a random point to select if (points.Count == 0) { throw new System.Exception($"No legal placement of {tileSet}"); } var i = (int)(propagator.RandomDouble() * points.Count); return(points[i]); }
public void Check(TilePropagator propagator) { var topology = propagator.Topology; var width = topology.Width; var height = topology.Height; var depth = topology.Depth; if (Axes == null || Axes.Contains(Axis.X)) { int y = 0, z = 0; var sm = new StateMachine((x) => propagator.Ban(x, y, z, tileSet), propagator.Topology.PeriodicX, width, MaxCount); for (z = 0; z < depth; z++) { for (y = 0; y < height; y++) { sm.Reset(); for (var x = 0; x < width; x++) { propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var isSelected); if (sm.Next(x, isBanned, isSelected)) { propagator.SetContradiction(); return; } } if (propagator.Topology.PeriodicX) { for (var x = 0; x < MaxCount && x < width; x++) { propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var isSelected); if (sm.Next(x, isBanned, isSelected)) { propagator.SetContradiction(); return; } } } } } } // Same thing as XAxis, just swizzled if (Axes == null || Axes.Contains(Axis.Y)) { int x = 0, z = 0; var sm = new StateMachine((y) => propagator.Ban(x, y, z, tileSet), propagator.Topology.PeriodicY, height, MaxCount); for (z = 0; z < depth; z++) { for (x = 0; x < width; x++) { sm.Reset(); for (var y = 0; y < height; y++) { propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var isSelected); if (sm.Next(y, isBanned, isSelected)) { propagator.SetContradiction(); return; } } if (propagator.Topology.PeriodicY) { for (var y = 0; y < MaxCount && y < height; y++) { propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var isSelected); if (sm.Next(y, isBanned, isSelected)) { propagator.SetContradiction(); return; } } } } } } // Same thing as XAxis, just swizzled if (Axes == null || Axes.Contains(Axis.Z)) { int x = 0, y = 0; var sm = new StateMachine((z) => propagator.Ban(x, y, z, tileSet), propagator.Topology.PeriodicZ, depth, MaxCount); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { sm.Reset(); for (var z = 0; z < depth; z++) { propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var isSelected); if (sm.Next(z, isBanned, isSelected)) { propagator.SetContradiction(); return; } } if (propagator.Topology.PeriodicZ) { for (var z = 0; z < MaxCount && z < depth; z++) { propagator.GetBannedSelected(x, y, z, tileSet, out var isBanned, out var isSelected); if (sm.Next(z, isBanned, isSelected)) { propagator.SetContradiction(); return; } } } } } } }
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); } } } }