Grid/Base/GridGenerator.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace Sandbox.Grid.Base
{
    /// <summary>
    /// GridGenerator – pääluokka, joka orkestroi labyrintin generoinnin.
    /// Säilyttää grid-taulukon, RNG:n ja huonekeskipisteet.
    /// Delegoi varsinaisen työn HousePlacer-, GridFiller- ja GridEntityPlacer-luokille.
    /// 
    /// ' ' = ei käytössä / ei piirretä mitään
    /// '.' = lattia TALON ULKONA (piha, maa, kenttä)
    /// ',' = lattia TALON SISÄLLÄ
    /// '-' = talon seinä
    /// '#' = ulkoreunan seinä (map boundary, tuhoutumaton)
    /// '+' = ovi
    /// '^' = ansa
    /// '@' = spawn
    /// 'X' = vihollinen
    /// </summary>
    public class GridGenerator
    {
        const int W = 70;
        const int H = 70;

        char[,] grid = new char[W, H];
        Random rng = new Random();

        List<(int x, int y)> roomCenters = new();

        private HousePlacer housePlacer;
        private GridFiller gridFiller;
        private GridEntityPlacer entityPlacer;

        public GridGenerator()
        {
            housePlacer = new HousePlacer(grid, rng, W, H, roomCenters);
            gridFiller = new GridFiller(grid, W, H);
            entityPlacer = new GridEntityPlacer(grid, rng, W, H);
        }

        public char[,] Generate()
        {
            gridFiller.InitGrid();

            int houses = 0;
            int attempts = 0;

            while (houses < 6 && attempts++ < 50)
            {
                int w = rng.Next(12, 20);
                int h = rng.Next(12, 20);
                int x = rng.Next(2, W - w - 2);
                int y = rng.Next(2, H - h - 2);

                if (!housePlacer.CanPlaceRoom(x, y, w, h))
                    continue;

                housePlacer.CreateHouse(x, y, w, h);
                houses++;
            }

            gridFiller.BuildWallsFromRooms();
            gridFiller.FillWallCorners();
            gridFiller.BuildOuterBoundaryWall();

            gridFiller.FillOutsideWithGround();   // 👈 ennen ovia!

            //entityPlacer.PlaceHouseDoors();

            //entityPlacer.PlaceTrapSeeds();
            //entityPlacer.SpreadTrapsFromTraps();

            entityPlacer.PlaceEnemies(10);
            entityPlacer.PlaceSpawns(3);

            return grid;
        }

        public string Serialize()
        {
            int w = grid.GetLength(0);
            int h = grid.GetLength(1);

            var sb = new StringBuilder(h * (w + 1));

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                    sb.Append(grid[x, y]);

                sb.AppendLine();
            }

            return sb.ToString();
        }
    }
}