Speed Issues Resolved

I made use of a profiling tool to identify the major bottlenecks in my code. Two sections were causing most of my problems. The first has to do with my generic Map class.

The Map<T> class is used to represent all the 2-D structures in the game for example the dungeon, visibility map and light maps. For ease of use I had the following code to fill a map structure with an instance of a specific type.

        public void FillMap(Type tileType)

        {

            // Set each tile to the instance of the default tile

            foreach (var location in Locations)

                this[location] = (T)Activator.CreateInstance(tileType);

        }

Now the above code worked nicely, but is dog slow due to the reflection. As a rule I don’t do any premature optimisation, but the general slowness of my AI required me to address this slowness.

The solution was to use an anonymous delegate to pass in the actual new statement of the type to the function. The new code looks as follows

        public void FillMap(Func<T> cellFactory)

        {

            // Set each tile to the instance of the default tile

            foreach (var location in Locations)

                this[location] = cellFactory();

        }

The new function is used as follows

            // Fill the lightmap with black tiles

            FillMap(() => new LightMapTile());

This change gained a 50% speed improvement over the old code. Not too bad.

The next real bottleneck was in the actual AI logic. I have a piece of code that is responsible for identifying threats. The original code made use of a LINQ statement which was incorrect to begin with (the actual logic not the LINQ). The new code simplifies the threat logic into the following.

            // Find all actors that are visible threats

            return (from actor in Dungeon.Actors where IsThreat(actor) && VisibilityMap[actor.Location].IsVisible select actor)

                .ToList();

The new code flies and I now have multiple actors running around the dungeon finding each other. Pretty cool.

The next step is to add some evasion logic which should yield actors chasing each other around the map. Thereafter I should look at some simple combat and tweaking the main loop to defer decision making to the player when it’s his turn.

Advertisements

Refactoring for AI

Initially I started this project as a set of technologies such as dungeon generation, field of view, lighting, pathfinding, etc. My code was always from the perspective of the player and I made no provision for monsters and other gameplay elements. That’s why previous releases have always been in the form of tech-demo’s, because that is all the were.

For AI I have to rethink the whole thing. I don’t want to have the concept of a player and then some monsters, but would like the engine/game to deal with both in the same way. This adds some complexity, but also opens up a lot of possibilities.

The main update loop would be something along the lines of, for each actor, act. The AI controlled actors would act immediately and the player actor would do nothing until input (which is translated into an action) was received. All actors after the player would wait until the player completed his action. Rinse and repeat.

So far so good. I implemented a basic wandering monster with chase AI and let it loose in the dungeon. It looked cool with two little critters running around the dungeon and then converging on each other when they entered each other’s Fov. I added some more critters which promptly sent my framerate to 1Fps.

I guess it’s time to optimize.