Friday, March 11, 2011

7DRL Day 6

   Today I was once again stalled at the AI. I could not manage the code I started yesterday so I tried to mock up a simple come at me AI but did not manage even that. Tomorrow I will learn some more and in the least put out my thing as is at the end of the day. I think I accidentally put the hardest part off till last and am regretting it.

Thursday, March 10, 2011

7DRL Day 5

   Today was collage so once again not much done. I did not finish the simple ai I was working on...   Well I have not finished debugging it. My creatures cheat a little in that they simply check a line between the player and them out to their sight range to see if anything is blocking its view or the player is out of range. So while it technically knows where you are at all times it only sees you when it should, or rather that is how it should work and right now it does not even see you all the time though that may be a problem with some other part of my code. At least I have it so I can only see the monster when it is in sight though that was simply checking if the monster location was visible.

Tuesday, March 8, 2011

7DRL Day 4

   Today I mostly wrestled with FOV and failed to track down the last bug.
The red should be lit just like the green is.

Monday, March 7, 2011

7DRL Day 3


   Today I worked on getting the map to display right and shift along when the player gets to the edge. I also did the start screen and detailed the flavor for the game. The '<' in the screen just represents the place you start at and nothing more.
   I was able to use the following code to place the start area in the upper left corner and plan to use an inversion of it to place the Boss in the other corner.

bool testwalk = false; int startX=0, startY=0;
while (!testwalk)
{
    if (map.tile[startY, startX].Walkable) { testwalk = true; }
    else if (startY < startX) { startY++; }
    else { startX++; }
}
map.tile[startY, startX].Symbol = '<';
map.tile[startY, startX].Walkable = false;
player = new Player(10, true, startX, startY, '@', TermColor.White);


   I set the map.tile.walkable that the player is on to start so that monsters an stuff do not walk onto it. When you move it resets it to true and your new position to back to false. the "player"  has in order hp, alive, x, y, symbol, and the color. Tomorrow or the next day there will also be soul strength.
   I did not do all that I wanted today but because of collage I did not have the time. My '@' now walks in rooms and hallways only and not in the walls so once I get it so it does not automatically show the whole map it will at least be interesting to explore. Because of how I set it up Visibility is its own thing so you will be able to see through monsters but not walk into their square and stand on them.

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.

Saturday, March 5, 2011

7DRL Day 1

   I have mostly just been setting up my project so far. I have the '@' walking around the screen at least. Most of my time was taken by figuring out Malison which is a C# terminal graphics library similar to curses. I also set up a few classes including an important one that will be of much help. It is a Direction class that I basically took from These Two articles on the blog "Writing Kode". Here is the Direction class I have:
    class Direction
    {
        private int Index, DX, DY;
        private string Name;
        public static readonly Direction North = new Direction() { Index = 0, DX = 0, DY = -1, Name = "North" };
        public static readonly Direction East = new Direction() { Index = 1, DX = 1, DY = 0, Name = "East" };
        public static readonly Direction South = new Direction() { Index = 2, DX = 0, DY = 1, Name = "South" };
        public static readonly Direction West = new Direction() { Index = 3, DX = -1, DY = 0, Name = "West" };
        public static readonly Direction Northeast = new Direction() { Index = 4, DX = 1, DY = -1, Name = "Norhteast" };
        public static readonly Direction Southeast = new Direction() { Index = 5, DX = 1, DY = 1, Name = "Southeast" };
        public static readonly Direction Northwest = new Direction() { Index = 6, DX = -1, DY = -1, Name = "Northwest" };
        public static readonly Direction Southwest = new Direction() { Index = 7, DX = -1, DY = 1, Name = "Southwest" };
        public Vec ApplyTransform(Vec Location)
        {
            return new Vec(Location.X + DX, Location.Y + DY);
        }
        public Direction Inverse
        {
            get
            {
                switch (Name)
                {
                    case "North":
                        return Direction.South;
                    case "Northeast":
                        return Direction.Southwest;
                    case "East":
                        return Direction.West;
                    case "Southeast":
                        return Direction.Northwest;
                    case "South":
                        return Direction.North;
                    case "Southwest":
                        return Direction.Northeast;
                    case "West":
                        return Direction.East;
                    case "Northwest":
                        return Direction.Southeast;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }
        public Direction NextPerpendicular
        {
            get
            {
                switch (Name)
                {
                    case "North":
                        return Direction.East;
                    case "Northeast":
                        return Direction.Southeast;
                    case "East":
                        return Direction.South;
                    case "Southeast":
                        return Direction.Southwest;
                    case "South":
                        return Direction.West;
                    case "Southwest":
                        return Direction.Northeast;
                    case "West":
                        return Direction.North;
                    case "Northwest":
                        return Direction.Northeast;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }
        public Direction PreviousPerpendicular
        {
            get
            {
                switch (Name)
                {
                    case "North":
                        return Direction.West;
                    case "Northeast":
                        return Direction.Northwest;
                    case "East":
                        return Direction.North;
                    case "Southeast":
                        return Direction.Northeast;
                    case "South":
                        return Direction.East;
                    case "Southwest":
                        return Direction.Southeast;
                    case "West":
                        return Direction.South;
                    case "Northwest":
                        return Direction.Southwest;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }
        public Direction Next
        {
            get
            {
                switch (Name)
                {
                    case "North":
                        return Direction.Northeast;
                    case "Northeast":
                        return Direction.East;
                    case "East":
                        return Direction.Southeast;
                    case "Southeast":
                        return Direction.South;
                    case "South":
                        return Direction.Southwest;
                    case "Southwest":
                        return Direction.West;
                    case "West":
                        return Direction.Northwest;
                    case "Northwest":
                        return Direction.North;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }
        public Direction Previous
        {
            get
            {
                switch (Name)
                {
                    case "North":
                        return Direction.Northwest;
                    case "Northeast":
                        return Direction.North;
                    case "East":
                        return Direction.Northeast;
                    case "Southeast":
                        return Direction.East;
                    case "South":
                        return Direction.Southeast;
                    case "Southwest":
                        return Direction.South;
                    case "West":
                        return Direction.Southwest;
                    case "Northwest":
                        return Direction.West;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }
    }
   The "Vec" in ApplyTransform is a Point that is special to Malison. By using it I can simply put
Vec a = new Vec(1,0);
Terminal[a].Write("Hello World");
and it will write at 1,0. Vec is nice because you can add it to another so I could do a = a + a; and it would print at 2,0. Points can not be added together so this is quite useful because I can just for movement put Player.Location += Direction.West.ApplyTransform(Player.Location); and it would move the location west. I can do this anytime I need to move something.
   Another useful thing with the Direction class is those things with the switches in them. Direction.Next will get the next clockwise direction so when a monster wants to get to the player if the way is blocked I can easily check other directions. There is also previous, inverse, next perpendicular, and previous perpendicular.
   Of course till I have more than a lame tech demo this is all just hot air but at the least I can fly high in my hot air balloon.

I have started my 7DRL

   Well its official, no backing out now. I will be using
C# to create a roguelike in 7 days. I plan to call it "The
Soul Lord" for reason of how plot and play. The thread
for announcing intent to enter is Here at Usenet.