static void InitializePlayerStartingArea()
{
    int baseX = (int)Math.Floor(posX);
    int baseY = (int)Math.Floor(posY);
    Random random = new Random(1);

    // Define the radius of the open area
    int openRadius = 500;

    // Clear the base area
    for (int x = baseX - openRadius; x <= baseX + openRadius; x++)
    {
        for (int y = baseY - openRadius; y <= baseY + openRadius; y++)
        {
            map[(x, y)] = ' ';
        }
    }

    // Add random walls
    for (int x = baseX - openRadius + 1; x < baseX + openRadius; x++)
    {
        for (int y = baseY - openRadius + 1; y < baseY + openRadius; y++)
        {
            if (random.Next(100) < 30) // 30% chance of placing a wall
            {
                map[(x, y)] = '#';
            }
        }
    }

    // Add random 3x3 rooms
    int numRooms = random.Next(3, 6); // 3 to 5 rooms
    for (int i = 0; i < numRooms; i++)
    {
        int roomX = random.Next(baseX - openRadius + 2, baseX + openRadius - 2);
        int roomY = random.Next(baseY - openRadius + 2, baseY + openRadius - 2);

        for (int x = roomX - 1; x <= roomX + 1; x++)
        {
            for (int y = roomY - 1; y <= roomY + 1; y++)
            {
                map[(x, y)] = ' '; // Clear the room area
            }
        }
    }

    // Ensure the player's starting position is clear
    map[(baseX, baseY)] = ' ';

    // Add walls around the perimeter
    for (int x = baseX - openRadius - 1; x <= baseX + openRadius + 1; x++)
    {
        for (int y = baseY - openRadius - 1; y <= baseY + openRadius + 1; y++)
        {
            if (Math.Abs(x - baseX) == openRadius + 1 || Math.Abs(y - baseY) == openRadius + 1)
            {
                map[(x, y)] = '#';
            }
        }
    }
}

static void RenderFrame()
{
    StringBuilder sb = new StringBuilder();

    // Initialize a 2D character array for the screen
    char[,] screenBuffer = new char[screenHeight, screenWidth];
    string[,] colorBuffer = new string[screenHeight, screenWidth];

    // Fill screen buffer with default characters and colors
    for (int y = 0; y < screenHeight; y++)
        for (int x = 0; x < screenWidth; x++)
        {
            screenBuffer[y, x] = ' ';
            colorBuffer[y, x] = "\u001b[0m"; // Reset color
        }

    // Calculate the vertical center shift based on pitch
    // Positive pitch means looking up, so shift center down
    // Negative pitch means looking down, so shift center up
    // Define a maximum shift based on the pitch range
    double pitchFactor = screenHeight; // Adjust as needed
    int pitchShift = (int)(pitch / maxPitch * pitchFactor);

    // Raycasting
    for (int x = 0; x < screenWidth; x++)
    {
        // Calculate ray position and direction
        double cameraX = 2 * x / (double)screenWidth - 1; // x-coordinate in camera space
        double rayDirX = dirX + planeX * cameraX;
        double rayDirY = dirY + planeY * cameraX;

        // Which box of the map we're in
        int mapX = (int)Math.Floor(posX);
        int mapY = (int)Math.Floor(posY);

        // Length of ray from current position to next x or y-side
        double sideDistX;
        double sideDistY;

        // Length of ray from one x or y-side to next x or y-side
        double deltaDistX = (rayDirX == 0) ? 1e30 : Math.Abs(1 / rayDirX);
        double deltaDistY = (rayDirY == 0) ? 1e30 : Math.Abs(1 / rayDirY);
        double perpWallDist;

        // What direction to step in x or y-direction (either +1 or -1)
        int stepX, stepY;

        bool hit = false; // Was a wall hit?
        int side = 0; // Was the wall vertical or horizontal?

        // Calculate step and initial sideDist
        if (rayDirX < 0)
        {
            stepX = -1;
            sideDistX = (posX - mapX) * deltaDistX;
        }
        else
        {
            stepX = 1;
            sideDistX = (mapX + 1.0 - posX) * deltaDistX;
        }
        if (rayDirY < 0)
        {
            stepY = -1;
            sideDistY = (posY - mapY) * deltaDistY;
        }
        else
        {
            stepY = 1;
            sideDistY = (mapY + 1.0 - posY) * deltaDistY;
        }

        // Perform DDA
        while (!hit)
        {
            // Jump to next map square, either in x-direction or y-direction
            if (sideDistX < sideDistY)
            {
                sideDistX += deltaDistX;
                mapX += stepX;
                side = 0;
            }
            else
            {
                sideDistY += deltaDistY;
                mapY += stepY;
                side = 1;
            }

            // Check if ray has hit a wall
            if (map.ContainsKey((mapX, mapY)))
            {
                if (map[(mapX, mapY)] == '#') hit = true;
            }
            else
            {
                // Treat unknown areas as walls
                hit = true;
            }
        }

        // Calculate distance to the point of impact
        if (side == 0)
            perpWallDist = (sideDistX - deltaDistX);
        else
            perpWallDist = (sideDistY - deltaDistY);

        // Calculate height of line to draw on screen
        int lineHeight = (int)(screenHeight / perpWallDist);

        // Calculate lowest and highest pixel to fill in current stripe
        // **Modified to include pitchShift**
        int drawStart = Math.Max(-lineHeight / 2 + screenHeight / 2 + pitchShift, 0);
        int drawEnd = Math.Min(lineHeight / 2 + screenHeight / 2 + pitchShift, screenHeight - 1);

        if (wallTexture)
        {
            // Base color components for #9e9a56
            int baseR = 158; // 0x9e
            int baseG = 154; // 0x9a
            int baseB = 86;  // 0x56

            // Adjust color intensity based on distance
            float distanceFactor = (float)Math.Clamp(1.0 / (perpWallDist * 1.5), 0.0, 1.0);
            int colorR = (int)(baseR * distanceFactor);
            int colorG = (int)(baseG * distanceFactor);
            int colorB = (int)(baseB * distanceFactor);

            string baseWallColor = $"\u001b[38;2;{colorR};{colorG};{colorB}m";
            string darkWallColor = $"\u001b[38;2;{Math.Max(colorR - 30, 0)};{Math.Max(colorG - 30, 0)};{Math.Max(colorB - 30, 0)}m";

            // Darken colors for y-sides to add depth
            if (side == 1)
            {
                colorR = Math.Max(colorR - 30, 0);
                colorG = Math.Max(colorG - 30, 0);
                colorB = Math.Max(colorB - 30, 0);
                baseWallColor = $"\u001b[38;2;{colorR};{colorG};{colorB}m";
                darkWallColor = $"\u001b[38;2;{Math.Max(colorR - 20, 0)};{Math.Max(colorG - 20, 0)};{Math.Max(colorB - 20, 0)}m";
            }

            for (int y = drawStart; y <= drawEnd; y++)
            {
                if (IsInScreenBounds(x, y))
                {
                    // Create a simple pattern
                    bool isAlternateColor = ((y + x) % 2 == 0);

                    // Set wall color and pattern
                    colorBuffer[y, x] = isAlternateColor ? darkWallColor : baseWallColor;
                    screenBuffer[y, x] = '█'; // Full block for texture
                }
            }
        }
        else
        {
            // Base color components for #9e9a56
            int baseR = 158; // 0x9e
            int baseG = 154; // 0x9a
            int baseB = 86;  // 0x56

            // Adjust color intensity based on distance
            float distanceFactor = (float)Math.Clamp(1.0 / (perpWallDist * 1.5), 0.0, 1.0);
            int colorR = (int)(baseR * distanceFactor);
            int colorG = (int)(baseG * distanceFactor);
            int colorB = (int)(baseB * distanceFactor);

            string wallColor = $"\u001b[38;2;{colorR};{colorG};{colorB}m";

            // Darken colors for y-sides to add depth
            if (side == 1)
            {
                colorR = Math.Max(colorR - 30, 0);
                colorG = Math.Max(colorG - 30, 0);
                colorB = Math.Max(colorB - 30, 0);
                wallColor = $"\u001b[38;2;{colorR};{colorG};{colorB}m";
            }

            for (int y = drawStart; y <= drawEnd; y++)
            {
                if (IsInScreenBounds(x, y))
                {
                    // Set wall color
                    colorBuffer[y, x] = wallColor;
                    screenBuffer[y, x] = '\u2588'; // Full block character
                }
            }
        }

        // **Modified Ceiling Rendering Based on Pitch**
        for (int y = 0; y < drawStart; y++)
        {
            if (IsInScreenBounds(x, y))
            {
                colorBuffer[y, x] = "\u001b[38;2;111;99;39m"; // Bright yellow
                screenBuffer[y, x] = '\u2588'; // Full block character
            }
        }

        // **Modified Floor Rendering Based on Pitch**
        for (int y = drawEnd + 1; y < screenHeight; y++)
        {
            if (IsInScreenBounds(x, y))
            {
                //65541e
                colorBuffer[y, x] = "\u001b[38;2;101;84;30m"; // Dark yellow
                screenBuffer[y, x] = '\u2588'; // Full block character
            }
        }
    }

    if (showUI)
    {
        // Overlay Minimap at bottom-right corner
        RenderMinimap(screenBuffer, colorBuffer);
        // Overlay Debug Information at bottom-left corner
        RenderDebugInfo(screenBuffer, colorBuffer);
    }

    // Build the final string with colors
    for (int y = 0; y < screenHeight; y++)
    {
        for (int x = 0; x < screenWidth; x++)
        {
            sb.Append($"{colorBuffer[y, x]}{screenBuffer[y, x]}");
        }
        sb.Append(resetColor); // Reset color at end of line
        if (y != screenHeight - 1)
        {
            sb.Append('\n');
        }
    }

    // Output to console
    try
    {
        Console.SetCursorPosition(0, 0);
        Console.Write(sb.ToString());
    }
    catch (ArgumentOutOfRangeException)
    {
        // Handle potential exceptions when writing outside the buffer
    }
}

Instruction: render white square lights in the center on the ceiling transformed and skewed based on perspective and pitch if there's an L in that place on the map
Instruction 2: add Ls randomly to the character map