public Graph ExecuteStep(Graph graph) { Graph graphCopy = graph.Clone(); Blackboard blackboardCopy = _blackboard.Copy(); WfcGraphSpace <TTileData> wfcGraphSpace = new(graphCopy, _availableModules, blackboardCopy, wfcNeighborLayerName : _wfcNeighborLayerName); while (!wfcGraphSpace.GenerationFinished()) { WfcCell <WfcGraphTile <TTileData>, int> selectedCell = SelectCell(wfcGraphSpace); Collapse(wfcGraphSpace, selectedCell); if (_requiresGlobalPropagation) { wfcGraphSpace.PropagateGlobally(); } } if (wfcGraphSpace.GenerationSuccessful()) { _blackboard = blackboardCopy; wfcGraphSpace.PropagateToGraphAndCleanup(); return(graphCopy); } ; return(ExecuteStep(graph)); }
public void GenerateSimpleGraphWorldTest() { Graph worldGraph = YamlGraphStorage.LoadGraph(FileUtilities.LoadFile("graph_map_simple.yaml")); Blackboard blackboard = new Blackboard(); List <WfcGraphTile <WorldData> > availableTiles = PokeWorldGraphTiles.GetPocketWorldGraphTiles(blackboard, 3, 2, 0); WfcGraphSpace <WorldData> wfcGraphSpace = new WfcGraphSpace <WorldData>(worldGraph, availableTiles, blackboard); while (!wfcGraphSpace.GenerationFinished()) { Console.WriteLine("--- Current Map: ---"); Debugging.PrintWfcGraphModules <WorldData>(worldGraph.Entities); Console.WriteLine("----"); WfcCell <WfcGraphTile <WorldData>, int> selectedCell = wfcGraphSpace.SelectCell(); Console.WriteLine($"Selected Position: {selectedCell.Position}"); wfcGraphSpace.Collapse(selectedCell, (space, tile) => { Console.WriteLine($"Selected Type: {tile.Graph.Name}"); wfcGraphSpace.Blackboard.Increment($"{tile.Graph.Name}_count", -1); }); } Console.WriteLine("--- Final Map: ---"); Debugging.PrintWfcGraphModules <WorldData>(worldGraph.Entities); Console.WriteLine("Generation finished!"); }
public override List <WfcCell <TModule, Position2D> > GetNeighbors(WfcCell <TModule, Position2D> cell) { int index = Grid.IndexOf(cell); (int centerX, int centerY) = Grid.GetPosition(index); List <WfcCell <TModule, Position2D> > neighbors = new(); var child = GetCell(centerX + 1, centerY); if (child != null) { neighbors.Add(child); } child = GetCell(centerX - 1, centerY); if (child != null) { neighbors.Add(child); } child = GetCell(centerX, centerY + 1); if (child != null) { neighbors.Add(child); } child = GetCell(centerX, centerY - 1); if (child != null) { neighbors.Add(child); } return(neighbors); }
public void GeneratePocketWorldTest() { Graph worldGraph = YamlGraphStorage.LoadGraph(FileUtilities.LoadFile("graph_pokemon_map.yaml")); Blackboard blackboard = new Blackboard(); List <WfcGraphTile <WorldData> > availableTiles = PokeWorldGraphTiles.GetPocketWorldGraphTiles(blackboard); WfcGraphSpace <WorldData> wfcGraphSpace = new WfcGraphSpace <WorldData>(worldGraph, availableTiles, blackboard); wfcGraphSpace.PropagateGlobally(); while (!wfcGraphSpace.GenerationFinished()) { //Console.WriteLine("--- Current Map: ---"); //Debugging.PrintWfcGraphModules<WorldData>(worldGraph.Nodes); Console.WriteLine("----"); WfcCell <WfcGraphTile <WorldData>, int> selectedCell = wfcGraphSpace.SelectCell(cell => Int32.MaxValue - cell.AvailableModules.Count); Console.WriteLine($"Selected Position: {selectedCell.Position}"); wfcGraphSpace.Collapse(selectedCell, (space, tile) => { Console.WriteLine($"Selected Type: {tile.Graph.Name}"); wfcGraphSpace.Blackboard.Increment($"{tile.Graph.Name}_count", -1); }); wfcGraphSpace.PropagateGlobally(); } Console.WriteLine("--- Final Map: ---"); Debugging.PrintWfcGraphModules <WorldData>(worldGraph.Entities); Console.WriteLine("---"); Console.WriteLine($"Generation finished! Valid Map: {wfcGraphSpace.GenerationSuccessful()}"); }
public override List <WfcCell <WfcGraphTile <TTileData>, int> > GetNeighbors(WfcCell <WfcGraphTile <TTileData>, int> cell) { var layer = _graph.GetLayer(_wfcNeighborLayerName); if (layer == null) { throw new ArgumentException($"Data Structure Graph is missing the neighbor layer '{_wfcNeighborLayerName}'"); } var relationsContainingEntity = layer.GetRelationsContainingEntity(GetWfcEntities().ToList()[cell.Position]); return(relationsContainingEntity.SelectMany(relation => { var neighbors = new List <WfcCell <WfcGraphTile <TTileData>, int> >(); neighbors.AddRange(relation.Entities .Where(entity => GetWfcCellFromEntity(entity) != cell) .SelectMany(entity => new List <WfcCell <WfcGraphTile <TTileData>, int> >() { GetWfcCellFromEntity(entity) }) ); return neighbors; }).ToList()); }
private static bool NeighborHasOneOfTheseTiles(WfcCell <WfcGraphTile <WorldData>, int> neighbor, List <TileType> possibleTiles) { return(neighbor.AvailableModules.Exists(tile => { WorldData worldData = tile.TileDescriptor.AdditionalTileData; return possibleTiles.Contains(worldData.TileType); })); }
public void DrawWfcGrid(WfcSpaceGrid2D <TileInfo2D> grid2D, Image tileSheet) { _graphics.Clear(Color.SkyBlue); for (int index = 0; index < grid2D.Grid.Count; index++) { (int x, int y) = grid2D.Grid.GetPosition(index); WfcCell <TileInfo2D, Position2D> cell = grid2D.GetCell(x, y); int renderingY = grid2D.Height - 1 - y; // Y axis is down when generating the image DrawCell(cell, tileSheet, x, renderingY); } }
public void PropagateToGraphAndCleanup() { foreach (var targetEntity in GetWfcEntities()) { WfcCell <WfcGraphTile <TTileData>, int> cell = GetWfcCellFromEntityOrThrow(targetEntity); var selectedTemplateTile = cell.AvailableModules[0]; InstantiateTemplate(selectedTemplateTile.Graph, targetEntity); } RemoveWfcComponents(); }
private bool CanConnectToAnyNeighborTile(WfcCell <TileInfo2D, Position2D> currentCell, WfcCell <TileInfo2D, Position2D> neighborCell) { Direction2D directionToNeighbor = currentCell.Position.Delta(neighborCell.Position); var allowedSockets = AllowedSockets[directionToNeighbor]; if (!neighborCell.AvailableModules.Exists(module => (module.AllowedSockets[directionToNeighbor.Opposite()] & allowedSockets) != 0)) { return(false); } return(true); }
public bool CanModuleBePlaced(WfcCell <TileInfo2D, Position2D> currentCell, WfcSpace <TileInfo2D, Position2D> wfcSpace) { foreach (var neighbor in wfcSpace.GetNeighbors(currentCell)) { if (!CanConnectToAnyNeighborTile(currentCell, neighbor)) { return(false); } } return(true); }
private void Collapse(WfcGraphSpace <TTileData> wfcGraphSpace, WfcCell <WfcGraphTile <TTileData>, int> selectedCell) { if (_moduleSelectionFunc != null && _onModuleSelected != null) { wfcGraphSpace.Collapse(selectedCell, _moduleSelectionFunc, _onModuleSelected); } else if (_onModuleSelected != null) { wfcGraphSpace.Collapse(selectedCell, _onModuleSelected); } else { wfcGraphSpace.Collapse(selectedCell); } }
protected override IEnumerable <WfcCell <WfcGraphTile <TTileData>, int> > GetCells() { return(GetWfcEntities().Select(entity => { WfcCell <WfcGraphTile <TTileData>, int>?cell = GetWfcCellFromEntity(entity); if (cell == null) { throw new NullReferenceException("WfcCell not properly initialized!"); } return cell; } )); }
private void DrawCell(WfcCell <TileInfo2D, Position2D> cell, Image tileSheet, int cellX, int cellY) { if (cell.AvailableModules.Count > 0) { int elements = (int)Math.Ceiling(Math.Sqrt(cell.AvailableModules.Count)); for (int moduleIndex = 0; moduleIndex < cell.AvailableModules.Count; moduleIndex++) { var module = cell.AvailableModules[moduleIndex]; Rectangle drawRect = new Rectangle(0, 0, module.Region.Width, module.Region.Height); var cellOffset = new Point(cellX * drawRect.Width, cellY * drawRect.Height); var innerCellOffset = new Point((moduleIndex % elements) * (drawRect.Width / elements), (moduleIndex / elements) * (drawRect.Height / elements)); drawRect.Offset(cellOffset); drawRect.Offset(innerCellOffset); drawRect.Width = drawRect.Width / elements; drawRect.Height = drawRect.Height / elements; DrawImageRegion(tileSheet, module.Region, drawRect); _graphics.DrawRectangle(new Pen(Color.Black), drawRect); } } }
public bool CanModuleBePlaced(WfcCell <WfcGraphTile <TTileData>, int> currentCell, WfcSpace <WfcGraphTile <TTileData>, int> wfcSpace) { return(_canModuleBePlacedFunction.Invoke(this, currentCell, wfcSpace)); }
private static bool NeighborHasRoadLikeStructure(WfcCell <WfcGraphTile <WorldData>, int> neighbor) { return(NeighborHasOneOfTheseTiles(neighbor, new() { TileType.Forrest, TileType.Road, TileType.Cave })); }