Thursday, April 24, 2014

AI System Progress with Video

Video: https://www.youtube.com/watch?v=RTzLlRFga_M

These days, I've been making a lot of progress on my AI engine. The basic framework is running now and you can see that in this video. The AI system is telling the little bot where to go. I'm still in the early stages of development so the path is still hard coded into the demo but I'm happy that I'm now at a place where I can concentrate on actual AI code more.

My goal going into to this was to build an AI system that would be useful for different types of games. As you can see in the video, the AI system is working on a simple 2D game. I also have a text based sample project and the main game that I am building this for will be a 3D multiplayer game. Internally, how does this all work? Games are so different that it's not easy to make a unified AI system so my goal was merely to provide the parts needed for AI that could be used in various game types and still allow the developer to build the AI by adding code directly to the system using C++ or by using scripting languages such as AngelScript or Lua. The AI system works like this:
  • Retrieve inputs from the game engine
  • Process the current AI states
  • Send simple tasks to the game engine for each AI agent
The tasks that the AI system sends to the game engine should be very easy to complete. For example, if the AI system sends a "goto" command, the engine should be able to move to that location without worrying about obstacles. To navigate around obstacles, the AI system will send a series of "goto" commands marking points along the path.

Next Steps:
Currently everything is hard coded, but I want to provide a C++ interface so the AI programmer will be able to code custom behaviors. Then I want to expand that to include use a scripting language. After that, I'll start working on the navigation system. I'll continue to post information on my blog. For more videos, you can check out my YouTube channel. You can also visit ai.squaredprogramming.com. 

Sunday, April 13, 2014

More Interface Updates

After a lot of tinkering, I think I finally have the initial interface for the AI system. I've been building a simple example program.  Here's the main() function from that example program. You can get a general idea of the AI interface from it. I think it'll be quite simple to use.


int main()
{
 srand(time(NULL));
 // create an initialize our map ---------------------------------------------
 Map game_map(64, 12);

 // Set up the entity Manager ------------------------------------------------
 EntityManager entity_manager;
 EntityControllerPlayer player(entity_manager.InsertEntity('P', game_map));

 // start the AI sytem
 sdp_rootai::AIEngineCreateParams desc;
 sdp_rootai::AIEngine *the_ai_engine;

 if(sdp_rootai::CreateAIEngine(desc, the_ai_engine) != sdp_rootai::AIResult_OK)
 {
  PrintError("Unable to create the AI engine");
  return 0;
 }

 // create the world
 sdp_rootai::AIWorldCreationParams world_desc;
 sdp_rootai::WORLD_HANDLE world_handle;
 if(the_ai_engine->CreateWorld(world_desc, world_handle) != sdp_rootai::AIResult_OK)
 {
  PrintError("Unable to create the AI world");
  return 0;
 }

 // create the AI agent
 sdp_rootai::AIAgentCreationParams agent_desc;
 sdp_rootai::AIAgent *aiagent;
 if(the_ai_engine->GetWorldByHandle(world_handle).CreateAgent(agent_desc, aiagent) != sdp_rootai::AIResult_OK)
 {
  PrintError("Unable to create the AI agent");
  return 0;
 }

 // add the AI entity
 EntityControllerAI enemy(entity_manager.InsertEntity('E', game_map), aiagent);

 // the game loop
 do
 {
  // send agent position data to the AI system
  the_ai_engine->PushCurrentAIData();
  
  // update the AI
  the_ai_engine->UpdateSystem(1000.0f / 60.0f);

  // clear the screen ---------------------------------------------------------
  ClearScreen();

  // render the map
  game_map.Render();

  // get results of AI update
  the_ai_engine->PopCurrentAIData();

  // update the enemy AI
  enemy.OnUpdate(entity_manager, game_map);

 } while (player.OnUpdate(entity_manager, game_map));

 return 0;
}

Friday, March 28, 2014

Developing the AI Middleware's Interface

As I explained in my last post, I've developed a text-based sample game that I'll use to build the initial version of the AI system. Then I'll get it to work on my 2D engine, and then finally on my 3D engine for Auxnet:Battlegrounds. I'm at the stage now where I need to develop the AI systems public interface. The AI system is still very early in its development so things will probably change, but this is how I invision using the code in a real application.

// Startup
RootAI::Engine *ai_engine = RootAI::CreateAIEngine();

RootAI::WorldDesc worlddesc;
...
RootAI::World *world = ai_engine->CreateWorld(worlddesc);

RootAI::AgentDesc aidesc;
...
RootAI::Agent *agent = world->CreateAgent(aidesc);

...

// Shutdown
world->DestroyAgent(agent);
ai_engine->DestroyWorld(world);
RootAI::DestroyEngine(ai_engine);

I haven't decided if I want to force the developer to have to explicitly destroy the agents and the world or allow just destroying the engine and have that take care of cleaning up everything. My current thoughts are to let the engine take care of cleaning things up and returning a message if there are any AI objects that weren't properly destroyed before the engine.

 Here's the preliminary code for the AI agents and their tasks. The task should be basic enough so that the AI system can tell the game engine what in a way that will be easy to implement.

struct AIAgentDesc
{
    // the initial position and orientation of the entity
    Pose initial_pose;

    // set to true if the agent can move on more than one
    // axis at a time
    bool diagonal_movement;
};

enum AITaskType
{
    TaskIdle, // The AI should wait in an idle state
    TaskGoto, // The AI should go to a point (path will be unblocked)
    TaskAttack, // The an attack
    TaskTurnTo  // turn to face a direction
};

struct AITask
{
    AITaskType type;
    union
    {
        struct
        {
            int animation_num; // index of idle animation to run
        } IdleTaskOptions;

        struct
        {
            Vector location; // location to go to
        } GotoTaskOptions;

        struct
        {
            int attack_number; // index of attack to do
            Vector direction;  // direction to attack in
        } AttackTaskOptions;

        struct
        {
            Vector direction;  // direction to turn to
        } TurnToTaskOptions;
    };
};

class Agent
{
    public:
        virtual ~Agent() {}
        virtual void SetAgentPose(Pose pose) = 0;
        virtual void GetCurrentAITask(AITask &out) const = 0;
        virtual void SetTaskDone() = 0;
};

The task currently just use unions. The reason why I decided to do it this way instead of using inheritance was I want to be able to easily copy data back and forth between the AI system and the game engine without creating new objects task objects and I can process the task without casting.

Another design choice that I've made is completely separating the public interface from the implementation. That's why the agent class is an abstract base class. The same will be true of the world and engine classes.

Let me know if you have any questions or suggestions.

Thursday, March 27, 2014

AI System Progress

Things have been going well on the AI front. I'm still hoping to have a strong enough foundation in a few weeks to be able to put my source code up on GitHub. It'll still be very early in the process, but I think I should have more than just a skeleton before I allow others to see the code.

I've been looking at various middleware SDKs, namely RakNet, NVidia PhysX, and AngelScript, just to get a feel of what makes a good SDK. I've decided for now to go the RakNet and AngelScript route and have all of my samples be console applications and not graphics applications. I still will make a 2D version of the sample, but it won't be an official part of the Root AI SDK.

Here's a screenshot of the console based example game. The AI system isn't being used yet so the AI bot just uses simple code to move left. Soon it will still just move left, but it'll be the AI engine telling it to do so.


Sunday, March 23, 2014

Latest Updates

I've started coding my new AI engine. I'm still in the early stages of development now so my decisions now can mean the difference between minor or very major refactoring down the line. So while I don't want to think too far ahead, there are some long term and short term goals that I need to keep in mind.

Long term

  • Support for multiple AI architectures, including univented ones
  • Support for scripts written in Lua or AngelScript
  • Multi-threaded support
  • Multiplatform
  • Static C++ library or DLL
  • Open Source

Short term goals

  • Develop the framework
  • Simple Path finding in a 2D enviroment
  • Develop to work in 3D enviroments as well.
  • Add simple path finding to Auxnet.

I'm hoping to get the AI to start doing something in a week or two. First, I just want to get the AI to make an agent move forward. Then I'll add more functionality from there.

I've mostly been working on foundation code that the rest of the AI engine will be built off of.  I've built a simple vector class, axis-aligned bounding box struct, and the shell of the public interface. I'm writing a simple text-based sample now and I hope to get the entire foundation up on GitHub in a couple of weeks.

Blog Comment with Useful Suggestions

The following comment was written by Ashaman73 on my Gamedev.net blog. I thought it was good and wanted to share it here.

Good idea, sofar. Thought, I would always sugguest to implement a general approach in combination with a concrete usecase (a game actually). This avoids a lot of refactoring later on :D

Nevertheless, here are some thoughts from my experiences, because I use a similar system:
1. Multithreading and scripting languages like lua are really hard. Lua do not really support multithreading, therefor consider this in your design early on. Remember, that the state of a single VM can't be really shared between different threads as long as the VM doesnt support it , which is the case with lua (I use multiple stateless VMs to cover multi-core support).

2. You will need a lot of communication between engine and AI. The go-to command is a good idea and the right direction, but you will need to react to external events too. E.g. the entity movement is blocked by an other entity etc.  Therefor use an asynchroniously , delayable message/event system.

3. There are some basic AI algorithm which are really performance critical and should be part of the engine:
- pathfinding (your have some navigation map/waypoint system already in the engine).
- sensory data/scanning (build a query system to send async scan requests, you will need this a lot)
- steering (your go-to command which will result in the steering of the AI, including common steering behavior).

4. It is really important for an AI to be aware of the surrounding, its state, and current events. A good way to handle this is the use of a stimuli system. External events, internal states etc. can trigger a time restricted stimuli on your entity, which will help the AI to make further decisions. Scanning the surround all the time is just to performance demanding and scanning it just every X ms is too slow. The latter will result in clearly visible delay in the decision making process.
Eg a sound from a gun could propagate a 'gun_sound' stimuli in all close npcs. The npc ai can then decide what to do with it (one ai is running away from it, an other will approach the last know position of the sound, an other entity will be more careful as long as the stimuli is active etc.)

Thursday, March 20, 2014

Building My AI Engine

These days, I've been turning my attention towards AI. In the past, I spent so much time working on graphics components of the engine in the past, that I've never put the effort into building a good AI system. When I was developing Genesis SEED, I wrote a complex AI system, but it was too unwieldy and complicated so I decided to start from scratch when working on the AI system that would go into Auxnet. It’s still in its beginning stages but in the long term, I’d like to release the AI system as an open source project. I want to build a general AI framework that will work on many different game types.

How and why do I want to make a general AI framework? I want to build this game engine in a modular way to allow for future expansion. To achieve this modular approach, the code will naturally take a framework with attached plug-ins design. I know that AI is very game specific, but what I want to do is provide a collection of techniques that the AI agents can have to complete their task. After that, the main architectural design issues will come down to how to separation of responsibilities between the AI engine and the game engine. I'm not an AI expert, but I have experience in designing architectures and feel that I'll be able to put together a good system.

The AI system will have three main parts, the engine, worlds, and agents. The engine holds the worlds and is responsible for initialization and the destruction the system. Multithreading support will also be handled in the engine. Worlds contain agents and also the navigation system and world geometry. Keeping separate worlds will an application to use one AI engine to process the AI for agents in unrelated and unconnected areas. Agents are the actual AI entities and are connected to an entity in  the game engine. There is no direct link between game engine entities and AI system agents in code so the agents will need to store copies of some of the the game engine entity's data such as position and health information. I've given a very simple UML diagram below with some of my current thoughts. This will grow by leaps and bounds by the time end of the project.


I want to model my AI system like other middleware SDKs. I've used many different kinds of middleware including, graphics APIs, physics SDKs, networking engines, and scripting languages. Of all of the different middleware libraries that I've used, which system is most like the AI engine that I want to build? Believe it or not, this system will be most similar to a physics engine. Think about it, in a physics engine, first, you should set up the world or scene, then add actors and physics bodies. After that you run the simulation, checking to see the new position and orientation of your actors and then updating them in the engine. An AI engine in many ways is quite similar. First you have to setup the world and tell the AI engine how the level is laid out and what potential colliders and dangers are in the world. Then you should create AI agents that are connected to game entities to populate the world. The AI engine will run the simulation, and then the entities in the game engine should check their AI components to see what state changes have been made. That's the entire system in a nutshell.

For this to work, I'll need a very simple interface. The AI engine will be responsible for all decisions. It will tell the game entity to do simple task like move forward, turn, or shoot, and then game engine should do task and tell that AI engine when it has completed the task. The task that the AI engine will relay to the game engine should be simple enough to not need any complex intermediary AI. For example, if the AI engine returns a "go to" command, the entity should be able to go to that point by walking in a straight line and without worrying about path finding. For complex paths, the AI engine should give a series of “go to” commands until that agent has reached its destination. In this way, the AI engine will be the brains and the game engine will act like the nervous system and make the agent's body move. So the game engine to receive instructions from the AI engine, and for the AI engine to receive position information and whether or not the instruction has been completed. This information will not need to be sent back and forth every frame, but either as needed or at set regular intervals as decided by the developer. Game engines that used a component-based entity system can add an AI component to process instructions from the AI engine and to pass on the entity's location information to the AI engine. The game engine should also be able to send events to the AI engine that are not directly tied to a specific entity such as level events, so the AI agents will be able to respond to those events as well.

There's no way I'll be able to program all types of AI algorithms so the AI engine will need to not only be flexible but expandable. I'll have to build it so it can take add-ons written in either C++ or in scripting languages such as AngelScript and Lua. The add-on system should not be limited to giving support for different types of levels and path finding. There should be a way to make add-ons that will affect how decisions are made so there should be add-ons for using Ad-hoc rules, finite state machines, behavior trees, neural networks, and so on. Once a large library of add-ons has been created, building complex AIs will be a matter of choosing the proper base AI architecture (Ad-hoc rules, finite state machines, etc), adding skills, and performing some game specific tweaking. These are my AI goals.

To help me build all of this, I've created a small 2D game with a little robot that should navigate through a simple maze. I'll develop this demo more and more and post updates on my blog and on YouTube.