Thursday, March 31, 2011

I am just asking for it...


   Well why not? Grognardia is doing it which is how I saw it first. Really if I can't hack it out for 26 days with 2 whole categories to talk about then I am not meant to blog.
   As of Friday I will be once a day(except Sunday for some reason) make a post that is themed after a letter. I predict failure and the gnashing of teeth but then again my life likes to prove me wrong so who know? Anyway I needed something to get me started.

Monday, March 28, 2011

the "Why"

   I have Why in the name but have yet to say much about it. Why am I doing this? I have said some things about it but nothing concrete enough. Its not like I am blogging about stuff everyday though I should. My programming skills are not anything exciting and I am only in a single roleplaying game at the moment despite desires for this to be otherwise. I also have not been linking here from other places like I could be. I don't even have a link in my Bay12 forum signature.
   This has been getting to me and I believe that I need to either step up the quality and focus on something or demote this to a diary of sorts that is accidentally on the internet. I want to blog and such but my problem is lack of a steady focus. One week I am all about the roleplaying then next week I can't tear myself away from some game or what not then the third week its something else. I made this blog to unfocused to properly do anything with it that may attract attention.
   I currently have two specific things that I would blog about and luckily they are what this place was orignially set up for. The first is roleplaying with a sub focus on my actual gaming. While the second is programming with a slight focus on roguelikes. Yes I know that's all I have blogged about here but what you see is only a miniscule percentage of what I consider putting here. I managed to go a whole week of almost consistent posting about my try at a 7DRL. Sure the times were weird and generally after midnight but that's fine as I almost never go to sleep by then anyway.
   I can after next week or maybe the week after that post about my weekly D&D game depending on when the DM gets back from vacation. This means a weakly post mostly likely on Sunday or Monday but greedy as I am I want more. This means I need something to hold my attention. I have two things ironically similar that I am thinking of doing. First is make some dungeon generation code along the lines of what I had for my 7DRL only, well, better. This would be generic code that I would be able to reuse as needed so next time I make a game its already there and I can work on the stuff I don't quite know that well. The second option is to make a dungeon for D&D. This would mean probably an exciting first to third level encounter stretching through a cavern or some such with stats for both 3.5 and one of the rules sets like Labyrinth Lord because I simply love the older editions of D&D. Either way I make a dungeon. I hope to start soon with next Monday being the latest though I do not know which I will do. The programming one will be fun in a way because I will be able to go on and on about how I want a dungeon to be but the roleplaying one will be something that I can stretch my art muscles on which is something I need to do lest they atrophy away to nothing. It will probably be D&D in the end seeing as I have been thinking about it quite a bit and have not had an actual game session in many months.

Monday, March 21, 2011

D&D Campaign, first session

   Mostly flavor text because we ran out of time. I was actually allowed about 15ish gold back because a lot of stuff like regular ammo and food the GM considers things you just have which is nice.
   The story is that we are currently in the capital of some nation with a weird name that just recently the eldest son of the king disappeared followed by the king dying of (insert generic death here) and the queen quickly following by "suicide" from grief and the youngest son took over. Of course he is a real dick and has all kinds of new laws made to control the kingdom including laws against magic of any kind including arcane, divine, psionics, and incarnum so it covers the whole party. The Magic academy and the churches are allowed to control it on their own land but because the upstart prince is a wizard and all friendly with the Archmage probably controls it on the magic academy as well. Later on I accurately guessed we will be going out and finding the eldest prince to and taking the throne back for him. I would personally want to try for the throne but I am a dwarf and the most normal race in the party so I can't really rule a human kingdom and it probably conflicts with my neutral good alignment. The law against magic means more of a as long as you don't get caught its fine but we know that "some"(read that as all that we meet) of the guards will be able to detect magic so its good none of us have any magic items. Our first mission will be to clear the local temple of Pelor's crypt of some turn resistant undead. Of course why one of the main churches for the god that hates undead would need some visiting people to clear it for them is up in the air. The DM say's it is because of the turn resistance but the church should have at least a couple clerics of 1st or greater level and undead still die to healing so whatever. I personally am blaming it on the ban on magic so all the combat types moved out to the country side where they can get away with helping people with their magic off of church grounds. All we know that is down there actually is skeletal rats at this point and I think that was more of a flavor text thing then anything else. Sadly the DM will not be around next week and maybe not the week after that so no D&D for at the least a couple weeks.

Saturday, March 19, 2011

Finaly some D&D

   Tomorrow my group is starting a D&D 3.5 campaign. We gave up on the World of Darkness finally. Not that I did not like it but in a roleplay heavy game system if you are allowed to say in response to an NPC asking about the group say "We explain our situation" and have it slide then its not going to work well.
   I will be a dwarf cleric that worships Palor. My domains will be healing and sun. Healing for the boost to healing spells and Sun so that I have a second level fire spell. The fire spell is so I can take the reserve feat Fiery Burst at level 3 because mini fireballs on command is awesome. My first level feat is extend spell which I will not be able to use till 3rd level. Here is my character(we are using 44 point buy):

Urist Zilir        Cleric 1
Dwarf              Neutral Good     Diety: Pelor

STR: 16     +3     BASE: +0                    stat  Clr
DEX: 10     +0     Init: +0               FORT: +4    2  /+6
CON: 18     +4     HP: 12                 REF : +0    0  /+0
INT: 14     +2                            WILL: +4    2  /+6
WIS: 18     +4
CHA:  6     -2     Turning: 1/day   TurningDamage: 2d6-1

AC: 16 (10 +4[Armor] +2[Shield])
Touch: 10   Flatfooted: 16

Morningstar [1d8, crit x2, 8lb, one-handed, bludgeoning&piercing]
Light Crossbow [1d8, crit 19-20/x2, range 80', 4lb, piercing]
Scale Mail [+4 AC, max dex +3, check penalty -4, 30lb]
Heavy Steel Shield [+2 AC, check penalty -2, 15lb]

Feats: Extend Spell
Skills: Knowledge[Arcana] 4(6), Spellcraft 4(2),
      Heal 4(8), Concentration 4(8)
Abilities: Dwarf racials

Domains: Healing(+1 healing CL), Sun(Gr turning)

Default Memorizations:
Level 0(3):
Detect Poison, Light, Resistance
Level 1(2+D):
2x Lesser Vigor(CDiv) - standard action, touch, 12(10+lvl) rounds fast heal 1
Endure Elements(D)

Equipment:               GP         lb
Weapons/Armor/Shield    113          55
20x Crossbow Bolts        2           2
Backpack                  2           2
Bedroll                   0.1         5
10x Candles               0.1         -
10x Chalk                 0.1         -
Flint and Steal           1           -
Grappling Hook            1           4
10x Rations(1 day)        5          10
100' Hempen Rope          2          20
10x Torches               0.1        10
5x Waterskins             5          20
Holy Symbol(wooden)       1           -
Spell Component Pouch     5           2
Total                   137.4gp     140lb
2 gold, 6 silver

Thursday, March 17, 2011

7DRL - Rook - Review

Rook
By:
Joshua Day

   A fun little game to play. You start game with an orb that prevents you from accidentally killing yourself and a ring that makes all damage fatal.

ASCII Use: 10/20
   Basic and understandable though not much else to say here. Average enough.

Ease of Use: 11/20
   You move with hjklyubn or the numpad. Items are activated with a then the letter. All of your items are listed on the side of the screen and if use of one would mean death its highlighted red. The same for the movement keys which are also listed on the side and highlighted red if they would mean death.

Sparkly Bits: 11/20
   Based on chess somewhat though it is hard to see at times. This has been done before, still interesting but not enough to get above an average rating.

Difficulty: 13/20
   An interesting challenge with a moving goal. Kill the King if you can, it may take you a few tries to get there. Above average but still not Hard.

Addictiveness/Replayability: 10/20
   Good draw once you start so you will want to finish it and being a quick game you will finish before it wears off but the replay is not much to talk about.

Overall: 65/100
   A fun quick game to play through once though you probably won't play it again after you win. I advise it for someone looking for a quick play of something new before going back to whatever you where doing.

Sunday, March 13, 2011

7DRL - Vicious Orcs - Review

By:
Jeff Lait

   Once again Jeff has made a wonderful game. The story is that recently an earthquake opened up a cave where Orcs live and your to go and preemptively strike at them. There's a little more to it but that is what it comes down to.

Disclaimer: I have not actually finished this game so not all I say may be accurate all the way through!

ASCII Use: 17/20
   The use of characters works quite well even when he uses some non-traditional ones such as '&' for trees. For the setting these actually look better then the normal "T"ree's that you see. Rats, Bats, and other such traditional creatures will be attacking you and barring a few jarring colors here and there the characters and colors match. The one thing that is a little off but helpful is that the walls change colors the farther in you get to represent the areas toughness. Its useful to know where you are but pink walls? Really? Maybe it is supposed to be purple but from here it looks like I am sneaking around barbies house. Overall though its well done.

Ease of Use: 13/20
   A limited number of keys that do all that they need to. Simple easy to understand controls are out in force here though I do have a thing I did not like. I can understand the inclusion of a command to rotate the map seeing as the map is special but it only confused me when I tried it. I probably could have used it for something or other but because the map is weird it only got me lost.
   The map seems to either warp space to work or assumes that the tunnels are not flat so you go up and down because you end up going down hallways that on a normal roguelike would intersect the ones you just came from. Because its all persistent though this actually is quite fun to explore and actually lets you get lost if you not careful.
   In the town you talk to people by the bump method and you go through text by just pressing space so it fits together nicely but brings us to something I find quite annoying. When ever you buy something or use something in you inventory it kicks you out of the menu. This means that if your eating all that food you just found to gain some health back you have to press "i", go to the item, press enter, and press the correct key for what you want to do for every single thing. Ranged combat is useful but having to buy a dozen arrows at a time over and over by bumping into a moving target is not as fun.
   Another thing is that everything that is a weapon or armor is broken and you need to go to town and get it fixed before you can use it except for the first weapon upgrade. At least it only keeps the most up to date weapon/armor so you don't have to worry about that.
   For the simple commands and easy actual combat it fun but for the becoming ready to do battle is a little tedious so overall a bit above average.

Sparkly Bits: 15/20
   It has gold you collect fall down the side of you screen and collect in a pile! This is the most Dynamic system for keeping track of money in a roguelike I have seen recently. Quite fun to watch.


Difficulty: 18/20
   Except for the first wall color transition the Difficulty builds quite nicely. The only reason for the first jump is because that is when the first ranged opponents show up. Quite a satisfying experience. Even the lowly rat has an interesting strategy that you will find out for yourself. Seeing as I have not actually completed the game I can not comment on the overall toughness but what I have seen is well worth the time.

Addictiveness/Replayability: 10/20
   Even though the dungeon is new every game I must admit the first bit can be tedious. The game once you get going is quite Addictive but dieing and having to restart is a let down. This is probably because of the start being the same every time even if the dungeon is different. Once you start playing you won't stop till you die but when you do it might take a little to start over so I am going average on this one.

Overall: 73/100
   Quite a fun game to play once you get going though restarting after dieing can be annoying and the keeping your character geared up is tedious seeing as you have to go back to town to fix the latest weapon or armor upgrade. A decent game with above average quality. Works on Windows and Linux so if you have one of those I advise trying it out.

7DRL - Reviewing format

   To start before I get on with this I will explain how I will be rating a number of other 7DRL games in the days to come. I have 5 different categories that I will grade on a 1 to 20 scale, 1 being bad.

   First is Ascii/Graphics use, This will be how well they where able to say what they meant with the their display and how well it came across. This means some simple things like using understandable thing such as a brown 'r' to mean a rat and not a rust monster. This will be genre based partly seeing as a science fiction game might have the brown 'r' meaning a type of robot. For the graphics I will be looking at the images and seeing how well they match the content. I understand that 7 days is not enough to make custom tiles for everything but if you do I will treat you better then the guy who grabbed a free bunch of tiles and stuck them wherever because no matter how pretty if you are using a picture of a rat to represent a robot.

   Next is Ease of use which will be about various things that could be better or are better. This will probably be biased but not because of key configurations unless the game does not come with a way to change them. Things that would fall under this category is stuff like if it takes to many keystrokes for important features or not asking if you really want to attack that town guard.

   Sparkly Bits is next on the list and it is what it is. It it sparkles and or is shiny it goes here.

    Difficulty will be the strategy type stuff and not stuff about control layouts or whatever, thats up in Ease of use. This is all about having to think before you bump into that 'D' over there. If I could be replaced by a 4 set of those drinking birds pressing the direction keys you will fail this category

   The final category is a combo of Addictiveness and replay value.  This will mean more then just having random dungeon levels because it may help but a boring room will be boring whether its the same one as last time or its a brand new boring room.

Friday, March 11, 2011

7DRL Day 7 - End

   Well only a tech demo sadly. At least I was able to get the goblin to follow you even if can't do anything but. The map works fine as well as the FoV. There is also a speed difference between you and the goblin.
Tech Demo is Here

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.