Thursday, July 30, 2009

Bot AI Enhancements

After the new bot code is merged into trunk, I am thinking about re-writing the BOT AI in hopes of getting better results, like a bot cleric that doesn't let my tank die.

A concept I will probably build the new AI around is what I am calling "role-based decisions". What this means is I would added a property to a Bot object called "GroupRole" and it could be one of the following:


  • TANK
  • HEALER
  • HEALER-ONLY
  • DPS
  • CROWD CONTROL
  • CROWD CONTROL-ONLY
  • DEBUFFER


The idea being that instead of developing the AI decisions around what class a bot is, the first decision the AI makes is based on what job the bot is required to do. This is the bot's "GroupRole". For example, if a Bot has a GroupRole = TANK then if its a Warrior class then it taunts to get aggro. If its a shadowknight and has GroupRole of tank, then the SK will taunt AND it will cast it's snare spells to get aggro.

If a Bot has a GroupRole of HEALER then it is looking to heal ahead of anything else, obviously. But if its a HEALER-ONLY then it never wastes mana or does anything else except heal and meditate.

Of course, we can mix these roles up so a Bot can have a primary role and also a secondary role. I was thinking of a role pattern like the following as I think it replicates the classic eq group pattern:


  • TANK
  • HEALER, DPS or HEALER-ONLY
  • DPS, HEALER
  • DEBUFFER, HEALER, DPS
  • CROWD CONTROL, DEBUFFER, DPS or CROWD CONTROL-ONLY


For bots with a secondary role, like say a Ranger who has Group Role of DPS and HEALER then the ranger would always look to do DPS first, but if say a party member has fallen to under 20% of health, then it would attempt to perform a ranger healer (laugh if you will, but i recall on live many of a druid, ranger, beastlord or shaman saving a party member when the cleric was taking a nap!)

Of course, I also envision some other AI enhancements like the HEALER role for example. Right now I am seeing my Bot cleric trying to cast a slow complete heal spell when my tank is at 20% health, so of course the heal is too late and the tank gets owned. I plan to refine this AI so the healer can decide that if the health is too low then it picks the fastest heal available and then go to a complete heal when it has the time necessary to perform the cast.

Finally, I think it's not only possible but important for the bot AI to consider WHERE the bot is in relation to the mob it is attacking, when in combat or to the Client it is owned by when not engaged. Right now, bots are pretty stupid about how they move and where they go. I am looking forward to implementing improvements that will allow a bot who is a rogue class to attack its target from behind when it can and for a bot a bot who is has a role of HEALER to stay out of melee range.

Tuesday, July 28, 2009

Official Community BETA of the EQEmu Server Bots Begins Today!

Official Community BETA of the EQEmu Server Bots Begins Today!


I am pleased to announce that the community beta of the EQEmu Server Bots is ready for QA testing and begins today. This means that this code base that is going to replace what has been refereed to as “EQOffline” in about 7 days and before this happens, this beta period is the communities opportunity to try out this code and post issues that need to be addressed. Even if you do not use bots at all, you will want to download this code and try it as a lot of code was re-factored that could possibly impact that standard code, though I know of no issues right now nor do I expect any.


If you would like to try this code, simple download the source code from the EQEmuServerBOTS branch, located here:


http://code.google.com/p/projecteqemu/source/browse/#svn/branches/EQEmuServerBOTS


After you have have it, you can either select the normal debug/release configuration to compile or you can select the BOTS configuration as either debug or release, though I recommend you use debug in case you are a code stud and happen across an issue and you can actually send me a stack or something.


Before you run the bots code you will need to change all your “EQOffline” rule values to “Bots” by simply renaming them in the rule_values table. Next, you will need to source the “bots.sql” file that can be found in the /utils/sql/svn sub-directory. Please note that bots are no longer stored in the npc_types table so you will need to backup all of your EQOffline bots BEFORE you source this file. If you choose not to backup your bots (bad idea), then you can expect this script to drop your existing botsinventory table, leaving your bots naked.


While I do not provide any type of data transformation script to migrate EQOffline bots to the new bots system, I am confident that there is someone in the community who has the time to do this task (I don't, at the moment).


After you have your database ready, go ahead and execute your server and enjoy the bots and please report any bugs to “Development::Bugs” and specifically mention in your bug reports that this is a bug in EQEmu Server Bots branch.

Saturday, July 18, 2009

Making The Mob Object Be Abstract

Because I am working to re-implement the existing "bots" subsystem into the EQEmu Server code, I have decided it was time to recognize the "Mob" object as what it really is. An abstract base class. This was necessary to allow objects like "Bot" to exist without having a good many of those dreaded "#ifdef EQBOTS" statements littered all over the code as now objects that are built upon the "Mob" object will now be required to implement specific methods that all of these type of game entities ought to have to work in the game. These include "no brainer" methods like "Death()" and "FinishTrade()", for example.

What this means to other developers who want to work in the server's code is you will be required to implement these abstract virtual methods if you extend the Mob class, or any other class that is built upon the Mob class, such as the new Bot object I am implementing. If you look at the source code, you will see that classes like NPC and Client inherit from the Mob class, but the new Bot class inherits from the NPC object, not Mob.

Another consideration is where you add logic in the future. Until now, the server code has usually implemented a single function or method that several objects would "share". As a consequence of this design, these methods had to make liberal use of class methods like "IsClient()" or "IsNPC()". Obviously, this can be burdensome to read and easy to make a code change meant for a Client object, but accidently negatively affect other objects, like NPC. Using the approach of the Mob class as an abstract object, this code can now be seperated into its own appropriate classes so when the server executes a statement such as:

myMobObject->Death();

The server will call upon the appropriate object's "Death()" method. In other words, at run time, if "myMobObject" is a NPC object, then NPC::Death() is executed and not Client::Death() or even Bot::Death().