Sunday, March 6, 2011

7DRL Day 2

   I mostly just worked on getting my map generator working today. While I like the maps it makes there are some leftover artifacts from the generation method and the code is currently slower than I want it but for the first map generator I have ever made it does incredibly well. I also have my bit of code that makes a text file of the map still in so I can continue to test it and see exactly what is going on.
    class Map
    {
        public int Height, Width;
        public Tile[,] tile;
        public Map(int Height, int Width)
        {
            this.Height = Height;
            this.Width = Width;
            this.tile = new Tile[Width, Height];
        }
    }
    class Tile
    {
        public bool Walkable;
        public bool Seethrough;
        public bool Room_Wall;
        public char Symbol;
        public Tile(bool Walkable, bool Seethrough, bool Room_Wall, char Symbol)
        {
            this.Walkable = Walkable;
            this.Seethrough = Seethrough;
            this.Room_Wall = Room_Wall;
            this.Symbol = Symbol;
        }
    }
    class Map_Generation
    {
        public Map map;
        private Random rand = new Random();
        private Rect Previous_Room,Starting_Room, hallway;
        private List rooms = new List();
        private int  Room_Count, Max_Size,Room_Fit, Hallway_Direction, BadRoom_Count, BackTrack;
        private bool Room_Made;
        private void New_Room(int x, int y)
        {
            rooms[Room_Count] = (new Rect(x, y, rand.Next(5, 11), rand.Next(5, 11)));
        }
        private void New_Room(int x, int y, int w, int h)
        {
            rooms[Room_Count] = (new Rect(x, y, w, h));
        }
        private void New_Hallway(int Offset)
        {
            switch (rand.Next(4))
            {
                case 0:
                    hallway = new Rect(rand.Next(Previous_Room.X + 1, Previous_Room.X + Previous_Room.Width - 1), Previous_Room.Y - Offset + 1, 1, Offset);
                    Hallway_Direction = 0;
                    break;
                case 1:
                    hallway = new Rect(Previous_Room.X + Previous_Room.Width - 1, rand.Next(Previous_Room.Y + 1, Previous_Room.Y + Previous_Room.Height - 1), Offset, 1);
                    Hallway_Direction = 1;
                    break;
                case 2:
                    hallway = new Rect(rand.Next(Previous_Room.X + 1, Previous_Room.X + Previous_Room.Width - 1), Previous_Room.Y + Previous_Room.Height - 1, 1, Offset);
                    Hallway_Direction = 2;
                    break;
                case 3:
                    hallway = new Rect(Previous_Room.X - Offset + 1, rand.Next(Previous_Room.Y + 1, Previous_Room.Y + Previous_Room.Height - 1), Offset, 1);
                    Hallway_Direction = 3;
                    break;
                default:
                    throw new InvalidOperationException();
            }
        }
        private void Transcribe_Room()
        {
            for (int a = 0; a < rooms[Room_Count].Height; a++)
            {
                for (int b = 0; b < rooms[Room_Count].Width; b++)
                {
                    if ((a == 0) || (a == rooms[Room_Count].Height - 1) || (b == 0) || (b == rooms[Room_Count].Width - 1))
                    {
                        map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Room_Wall = true;
                    }
                    else
                    {
                        map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Seethrough = true;
                        map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Walkable = true;
                        map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Symbol = '.';
                    }
                }
            }
        }
        private void Transcribe_Hallway()
        {
            for (int a = 0;a
            {
                for (int b = 0; b < hallway.Width; b++)
                {
                    map.tile[hallway.X + b, hallway.Y + a].Seethrough = true;
                    map.tile[hallway.X + b, hallway.Y + a].Walkable = true;
                    map.tile[hallway.X + b, hallway.Y + a].Symbol = '.';
                }
            }
        }
        private bool Check_Position()
        {
            if ((rooms[Room_Count].Y < 1) || (rooms[Room_Count].Y + rooms[Room_Count].Height >= map.Height - 1) || (rooms[Room_Count].X < 1) || (rooms[Room_Count].X + rooms[Room_Count].Width >= map.Width - 1))
            {
                return false;
            }
            else
            {
                for (int a = 0; a < rooms[Room_Count].Height; a++)
                {
                    for (int b = 0; b < rooms[Room_Count].Width; b++)
                    {
                        if (map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Room_Wall)
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
        }
        public Map_Generation(int Height, int Width)
        {
            this.map = new Map(Height, Width);
            this.Max_Size = 600;
            for (int a = 0; a < Height; a++) { for (int b = 0; b < Width; b++) { map.tile[a, b] = new Tile(false, false, false, '#'); } }
            rooms.Add(new Rect(0, 0, 0, 0));
            New_Room((rand.Next(Width - 15,Width - 10)), rand.Next(Height - 15,Height - 10));
            Starting_Room = rooms[Room_Count];
            Previous_Room = rooms[Room_Count];
            Transcribe_Room();
            Room_Count++;
            while (Room_Count < Max_Size)
            {
                Room_Made = false;
                BackTrack = 1;
                Previous_Room = rooms[Room_Count-BackTrack];
                rooms.Add(new Rect(0,0,0,0));
                while (!Room_Made)
                {
                    New_Hallway(rand.Next(2, 9));
                    New_Room(0, 0);
                    switch (Hallway_Direction)
                    {
                        case 0:
                            New_Room(hallway.X - (rooms[Room_Count].Width / 2), hallway.Y - rooms[Room_Count].Height + 1, rooms[Room_Count].Width, rooms[Room_Count].Height);
                            break;
                        case 1:
                            New_Room(hallway.X + hallway.Width - 1, hallway.Y - (rooms[Room_Count].Height / 2), rooms[Room_Count].Width, rooms[Room_Count].Height);
                            break;
                        case 2:
                            New_Room(hallway.X - (rooms[Room_Count].Width / 2), hallway.Y + hallway.Width - 1, rooms[Room_Count].Width, rooms[Room_Count].Height);
                            break;
                        case 3:
                            New_Room(hallway.X - rooms[Room_Count].Width + 1, hallway.Y - (rooms[Room_Count].Height / 2), rooms[Room_Count].Width, rooms[Room_Count].Height);
                            break;
                        default:
                            throw new InvalidOperationException();
                    }
                    if (Check_Position())
                    {
                        Transcribe_Room();
                        Transcribe_Hallway();
                        Room_Made = true;
                        Room_Count++;
                        BadRoom_Count = 0;
                    }
                    BadRoom_Count++;
                    if (BadRoom_Count > 20)
                    {
                        BackTrack++;
                        if (BackTrack > Room_Count) { BackTrack = 1; Room_Fit++; }
                        Previous_Room = rooms[Room_Count - BackTrack];
                        BadRoom_Count = 0;
                    }
                }
                if (Room_Fit >= 50)
                {
                    Max_Size = Room_Count;
                }
            }
            StreamWriter SW = new StreamWriter("Test.txt");
            for (int a = 0; a < map.Height; a++)
            {
                for (int b = 0; b < map.Width; b++)
                {
                    SW.Write(map.tile[a, b].Symbol);
                }
                SW.WriteLine();
            }
            SW.Close();
        }
    }

   I spent most of my time working on it trying to get placement working right till I figured out I needed to store all of the rooms instead not. I finally figured it out and decided on using a list which works out quite well for what I needed.
   The other thing that took a while was cutting features. I originally was going to have water and lava tiles but I ended up tossing that for this game because I had enough on my hands with just generating a regular map. I still need to add doors to it but this was a purposeful choice to not include it here. The way I have it planned I will need to add them later but that will be easy because I will only need to look for map tiles that are both using the '.' character and have Room_Wall as true. I have an example of the map output Here on the Bay12 forums thread for 7DRL 2011.

No comments:

Post a Comment