using System; using System.Collections.Generic; using System.Linq; using System.Text; using Unity.VisualScripting; using UnityEngine; using Random = System.Random; namespace DungeonGenerator { public class DungeonGenerator { private const int SIDE_LENGTH_OF_MONSTER = 4; private const int SIDE_LENGTH_OF_NORMAL = 2; private List _monsterRooms = new List(); private int _xLength = 40; private int _yLength = 28; public void GenerateDungeon(int length, float monsterRoomRatio) { _xLength = 40; _yLength = 28; Random random = new Random(); List entrancePoints = GenerateEntrancePoints(_xLength, _yLength, random.Next(1,4)); EvenDisperser disperser = new EvenDisperser(_xLength, _yLength, entrancePoints); //TODO calculate L and W from length int numberOfMonsterRooms = 7; // TODO: Calculate from ratio for (var i = 0; i < numberOfMonsterRooms; i ++) { Point newSpot = disperser.GetPoint(SIDE_LENGTH_OF_MONSTER, SIDE_LENGTH_OF_MONSTER); _monsterRooms.Add(new Room( RoomType.Monster, SIDE_LENGTH_OF_MONSTER, SIDE_LENGTH_OF_MONSTER, newSpot)); } } public void PrintMap() { char[,] mapMatrix = new Char[_xLength, _yLength]; for (int x = 0; x < _xLength; x++) { for (int y = 0; y < _yLength; y++) { if (_monsterRooms.Any(room => room.PositionOfTopLeft.Equals(new Point(x,y)))) { mapMatrix[x, y] = 'X'; } else { mapMatrix[x, y] = 'O'; } } } StringBuilder sb = new StringBuilder(); for (int j = 0; j < mapMatrix.GetLength(1); j++) { for (int i = 0; i < mapMatrix.GetLength(0); i++) { sb.Append(mapMatrix[i, j] + " "); } sb.Append(Environment.NewLine); } Debug.Log(sb.ToString()); } private enum Side { Top, Right, Bottom, Left } private List GenerateEntrancePoints(int xLengthOfDungeon, int yLengthOfDungeon, int numberOfEntranceLines) { if (numberOfEntranceLines > 4) { throw new Exception("Number of entrance lines cannot be greater than 4"); } const int entranceSpaces = 12; List entrancePoints = new List(); Random random = new Random(); Dictionary sidesToEnterOn = new() { { Side.Top, 0}, { Side.Right, 0}, { Side.Bottom, 0}, { Side.Left, 0} }; // Randomly assign starting lines to sides of dungeon for (var i = 0; i < numberOfEntranceLines; i++) { while (true) { Side side = (Side)random.Next(0, 4); if (sidesToEnterOn[side] < 2) { sidesToEnterOn[side] += 1; break; } } } int pointsPerLine = entranceSpaces / numberOfEntranceLines; // Generate entrance lines on each side switch (sidesToEnterOn[Side.Top]) { case 2: // Add half of points for this entrance line to the top left side for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(i,0)); } // Add the rest of the points for this entrance line to the top right side. int pointsRemaining = pointsPerLine; for (var i = 0; i < pointsRemaining; i++) { entrancePoints.Add(new Point((xLengthOfDungeon - 1) - i,0)); } break; case 1: int midpoint = xLengthOfDungeon / 2; int startOfLine = midpoint - (pointsPerLine / 2); for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(startOfLine + i, 0)); } break; } switch (sidesToEnterOn[Side.Right]) { case 2: // Add points for this entrance line to the top right side for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(xLengthOfDungeon - 1, i + 1)); } // Add the rest of the points for this entrance line to the bottom right side. for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(xLengthOfDungeon - 1, (yLengthOfDungeon - 1) - i)); } break; case 1: int midpoint = yLengthOfDungeon / 2; int startOfLine = midpoint - (pointsPerLine / 2); for (int i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(xLengthOfDungeon - 1, startOfLine + i)); } break; } switch (sidesToEnterOn[Side.Bottom]) { case 2: // Add half of points for this entrance line to the bottom left side for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(i, yLengthOfDungeon - 1)); } // Add the rest of the points for this entrance line to the bottom right side. for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point((xLengthOfDungeon - 1) - i, yLengthOfDungeon - 1)); } break; case 1: int midpoint = xLengthOfDungeon / 2; int startOfLine = midpoint - (pointsPerLine / 2); for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(startOfLine + i, yLengthOfDungeon - 1)); } break; } switch (sidesToEnterOn[Side.Left]) { case 2: // Add half of points for this entrance line to the top left side for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(0, i + 1)); } // Add the rest of the points for this entrance line to the bottom left side. for (var i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(0, (yLengthOfDungeon - 1) - i)); } break; case 1: int midpoint = yLengthOfDungeon / 2; int startOfLine = midpoint - (pointsPerLine / 2); for (int i = 0; i < pointsPerLine; i++) { entrancePoints.Add(new Point(0, startOfLine + i)); } break; } return entrancePoints; } } }