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!");
        }
예제 #3
0
        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()}");
        }
예제 #5
0
        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());
        }
예제 #6
0
        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);
     }
 }
예제 #8
0
        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();
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
     }
 }
예제 #12
0
        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);
                }
            }
        }
예제 #14
0
 public bool CanModuleBePlaced(WfcCell <WfcGraphTile <TTileData>, int> currentCell,
                               WfcSpace <WfcGraphTile <TTileData>, int> wfcSpace)
 {
     return(_canModuleBePlacedFunction.Invoke(this, currentCell, wfcSpace));
 }
예제 #15
0
 private static bool NeighborHasRoadLikeStructure(WfcCell <WfcGraphTile <WorldData>, int> neighbor)
 {
     return(NeighborHasOneOfTheseTiles(neighbor, new() { TileType.Forrest, TileType.Road, TileType.Cave }));
 }