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); }
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(); }
public List <ITileConstraint> GetConstraints(DirectionSet directions, TileRotation tileRotation) { var is3d = directions.Type == DirectionSetType.Cartesian3d; var constraints = new List <ITileConstraint>(); if (Config.Ground != null) { var groundTile = Parse(Config.Ground); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, }); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, InvertArea = true, Ban = true, }); } if (Config.Constraints != null) { foreach (var constraint in Config.Constraints) { if (constraint is PathConfig pathData) { var tiles = new HashSet <Tile>(pathData.Tiles.Select(Parse)); #pragma warning disable CS0618 // Type or member is obsolete var p = new PathConstraint(tiles, pathData.EndPoints, tileRotation) #pragma warning restore CS0618 // Type or member is obsolete { EndPointTiles = pathData.EndPointTiles == null ? null : new HashSet <Tile>(pathData.EndPointTiles.Select(Parse)) }; constraints.Add(p); } else if (constraint is EdgedPathConfig edgedPathData) { var exits = edgedPathData.Exits.ToDictionary( kv => Parse(kv.Key), x => (ISet <Direction>) new HashSet <Direction>(x.Value.Select(ParseDirection))); #pragma warning disable CS0618 // Type or member is obsolete var p = new EdgedPathConstraint(exits, edgedPathData.EndPoints, tileRotation) #pragma warning restore CS0618 // Type or member is obsolete { EndPointTiles = edgedPathData.EndPointTiles == null ? null : new HashSet <Tile>(edgedPathData.EndPointTiles.Select(Parse)) }; constraints.Add(p); } else if (constraint is BorderConfig borderData) { var tiles = borderData.Tiles.Select(Parse).ToArray(); var sides = borderData.Sides == null ? BorderSides.All : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.Sides, true); var excludeSides = borderData.ExcludeSides == null ? BorderSides.None : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.ExcludeSides, true); if (!is3d) { sides = sides & ~BorderSides.ZMin & ~BorderSides.ZMax; excludeSides = excludeSides & ~BorderSides.ZMin & ~BorderSides.ZMax; } constraints.Add(new BorderConstraint { Tiles = tiles, Sides = sides, ExcludeSides = excludeSides, InvertArea = borderData.InvertArea, Ban = borderData.Ban, }); } else if (constraint is FixedTileConfig fixedTileConfig) { constraints.Add(new FixedTileConstraint { Tiles = fixedTileConfig.Tiles.Select(Parse).ToArray(), Point = fixedTileConfig.Point, }); } else if (constraint is MaxConsecutiveConfig maxConsecutiveConfig) { var axes = maxConsecutiveConfig.Axes?.Select(ParseAxis); constraints.Add(new MaxConsecutiveConstraint { Tiles = new HashSet <Tile>(maxConsecutiveConfig.Tiles.Select(Parse)), MaxCount = maxConsecutiveConfig.MaxCount, Axes = axes == null ? null : new HashSet <Axis>(axes), }); } else if (constraint is MirrorXConfig mirrorYConfig) { constraints.Add(new MirrorXConstraint { TileRotation = tileRotation, }); } else if (constraint is MirrorYConfig mirrorXConfig) { constraints.Add(new MirrorYConstraint { TileRotation = tileRotation, }); } else if (constraint is CountConfig countConfig) { constraints.Add(new CountConstraint { Tiles = new HashSet <Tile>(countConfig.Tiles.Select(Parse)), Comparison = countConfig.Comparison, Count = countConfig.Count, Eager = countConfig.Eager, }); } else if (constraint is SeparationConfig separationConfig) { constraints.Add(new SeparationConstraint { Tiles = new HashSet <Tile>(separationConfig.Tiles.Select(Parse)), MinDistance = separationConfig.MinDistance, }); } else if (constraint is ConnectedConfig connectedConfig) { constraints.Add(new ConnectedConstraint { PathSpec = GetPathSpec(connectedConfig.PathSpec), }); } else if (constraint is LoopConfig loopConfig) { constraints.Add(new LoopConstraint { PathSpec = GetPathSpec(loopConfig.PathSpec), }); } else if (constraint is AcyclicConfig acyclicConfig) { constraints.Add(new AcyclicConstraint { PathSpec = GetPathSpec(acyclicConfig.PathSpec), }); } else { throw new NotImplementedException($"Unknown constraint type {constraint.GetType()}"); } } } return(constraints); }
public List <ITileConstraint> GetConstraints(DirectionSet directions, TileRotation tileRotation) { var is3d = directions.Type == DirectionSetType.Cartesian3d; var constraints = new List <ITileConstraint>(); if (Config.Ground != null) { var groundTile = Parse(Config.Ground); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, }); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, InvertArea = true, Ban = true, }); } if (Config.Constraints != null) { foreach (var constraint in Config.Constraints) { if (constraint is PathConfig pathData) { var tiles = new HashSet <Tile>(pathData.Tiles.Select(Parse)); var p = new PathConstraint(tiles, pathData.EndPoints); constraints.Add(p); } else if (constraint is EdgedPathConfig edgedPathData) { var exits = edgedPathData.Exits.ToDictionary( kv => Parse(kv.Key), x => (ISet <Direction>) new HashSet <Direction>(x.Value.Select(ParseDirection))); var p = new EdgedPathConstraint(exits, edgedPathData.EndPoints, tileRotation); constraints.Add(p); } else if (constraint is BorderConfig borderData) { var tiles = borderData.Tiles.Select(Parse).ToArray(); var sides = borderData.Sides == null ? BorderSides.All : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.Sides, true); var excludeSides = borderData.ExcludeSides == null ? BorderSides.None : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.ExcludeSides, true); if (!is3d) { sides = sides & ~BorderSides.ZMin & ~BorderSides.ZMax; excludeSides = excludeSides & ~BorderSides.ZMin & ~BorderSides.ZMax; } constraints.Add(new BorderConstraint { Tiles = tiles, Sides = sides, ExcludeSides = excludeSides, InvertArea = borderData.InvertArea, Ban = borderData.Ban, }); } else if (constraint is FixedTileConfig fixedTileConfig) { constraints.Add(new FixedTileConstraint { Tiles = fixedTileConfig.Tiles.Select(Parse).ToArray(), Point = fixedTileConfig.Point, }); } else if (constraint is MaxConsecutiveConfig maxConsecutiveConfig) { var axes = maxConsecutiveConfig.Axes?.Select(ParseAxis); constraints.Add(new MaxConsecutiveConstraint { Tiles = new HashSet <Tile>(maxConsecutiveConfig.Tiles.Select(Parse)), MaxCount = maxConsecutiveConfig.MaxCount, Axes = axes == null ? null : new HashSet <Axis>(axes), }); } else if (constraint is MirrorConfig mirrorConfig) { constraints.Add(new MirrorConstraint { TileRotation = tileRotation, }); } else { throw new NotImplementedException($"Unknown constraint type {constraint.GetType()}"); } } } return(constraints); }
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 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 EdgedPathConstraint(exits) #pragma warning restore CS0618 // Type or member is obsolete { UsePickHeuristic = true }; var propagator = new TilePropagator(model, topology, new TilePropagatorOptions { BackTrackDepth = -1, Constraints = new[] { pathConstraint }, }); propagator.Run(); Assert.AreEqual(propagator.Status, Resolution.Decided); }