Best way to do monster AI...

06/12/2011 16:13 CptSky#1
My project is almost finished, but I'm stuck on the part I always hate... And it's why I always add monsters at the end :rolleyes: I search the best way to process monster's actions. Like targeting and moving...

Creating a thread for each monster will produce an OutOfMemory Exception. Creating a timer for each monster will result on a big CPU usage... Any suggestions?
06/12/2011 16:49 Korvacs#2
Have the characters trigger ai on monsters.

Ie. if a character detects a monster it tells the monster to register itself into an AI threadpool which handles the AI untill theres no more characters nearby at which point it removes it from the threadpool.

If you want something simpler you could do Map/Spawn based AI.
06/12/2011 17:14 _DreadNought_#3
I dont know much but if I were to do it i'd leave all the monsters in one thread and possibly one thread per city? So.. the monsters are "roaming" around looking for shit to kill and i'd do it so when a character jumps into view of a monster it adds to the monster targetting. ie, Dictionary<uint, GameCliemnt> Targets; Add a client into it and then trigger Monster.RunAI(); which it then goes thru the targets and decides what target to murder =p
06/12/2011 19:18 { Angelius }#4
the server im working on well be a multiple server just like real co or at least that was the plan but what made me stop to rethink about it is monsters :)

almost 136k monsters jumping/walking randomly looking for any target near by to attack and its all in (one thread)

CPU usage is about 36 to 45 as max and the only thing that made it that high is the (TOO LONG foreach as its looping like 136k times)

other than that its no problem .

atm i have like 6k mobs (Glory server) and yet its all in one thread and the cpu usage is no more than 1/3 Ram is no more than 56 MB and thats A ok thought .

im my opinion 1 safe thread that is well coded (0% Exceptions Chance) to ensure that the thread well never stop working at a point wold be ok .
06/13/2011 00:14 pro4never#5
Korvs is right. Triggering things based on PLAYERS is the best bet really. If you are dead set on having mobs that 'roam' why not just have a 'roam' action that occurs randomly ONLY IF PLAYERS EXIST ON THE MAP.

You can use what korv is talking with modified a bit to create fairly dynamic roaming patterns still.

IE: player screen code causes the mobs to perform the chase/attack actions but you can use say... double screen size to control more robust behavior like boss reactions to players, mob groupings, wanders, etc as well as RARE movements of the entire mobs on the map.

As for the actual AI... I've been messing with more advanced AI recently (not going that well but it's interesting). Depending on what you're wanting to do with your server I'd personally prefer to run a more generic type of AI system such as a utility based decision model so that you can apply it to more advanced types of AI (duelist bots, purchasable 'minions', event bots, advanced boss fights, PVE dungeon type events). If you write the entire system under a deterministic model of AI you'll have to re-write most if not all of it every time you want to do anything new that involves AI for your server.

All depends on how much work you wanna put into your ai system though.
06/13/2011 02:17 { Angelius }#6
Quote:
Originally Posted by pro4never View Post
Korvs is right. Triggering things based on PLAYERS is the best bet really.
Quote:
public Dictionary<uint, Mob> ActiveMobs = new Dictionary<uint, Mob>();


and than when the player moves im adding the new in range mobs to the activemobs .as its gonna be checked to be spawned any way .

if (!ActiveMobs.ContainsKey(M.UID)) { Add it }

and then in the active thread i go

foreach (Mob M in ThreadSafeDictionary(ActiveMobs).Values)
{
find Target/attack/move/etc

if (M.Targets == null)
{
ActiveMobs.Remove(M.UID);
}
}
is that close enough to what you guys are talking about ?
06/13/2011 09:51 Korvacs#7
I dunno about close enough, thats a way of doing it, but its not scaleable in the slightest, if you have 10,000 mobs with targets you will have 1 thread working through the AI, some of which will be pathing which is alot slower compared to sending an attack packet.

Mob AI is something that would benefit from a threadpool massively, with a system like the one you have posted if the server starts to get busy then you will rapidly start seeing latency between mob movements etc etc.
06/13/2011 12:44 -impulse-#8
The method I am using is one timer / player. Instead of having a thread to run through all monsters(which might error in case you do add/remove from the collection while going through it), I use a timer which will do something like that but on very small collections. I don't suggest using system.threading.timer if you have your sockets using async since they both use I/O threads. Use system.timers and it should be fine. Whenever a players moves and a monster is spawned to the player, it is registered into a screen class on which the timer will work.
06/13/2011 12:48 { Angelius }#9
Quote:
Originally Posted by -impulse- View Post
The method I am using is one timer / player. Instead of having a thread to run through all monsters(which might error in case you do add/remove from the collection while going through it), I use a timer which will do something like that but on very small collections. I don't suggest using system.threading.timer if you have your sockets using async since they both use I/O threads. Use system.timers and it should be fine. Whenever a players moves and a monster is spawned to the player, it is registered into a screen class on which the timer will work.
what about the memory leak using the system.timers?
06/13/2011 13:00 Korvacs#10
Quote:
Originally Posted by -impulse- View Post
The method I am using is one timer / player. Instead of having a thread to run through all monsters(which might error in case you do add/remove from the collection while going through it), I use a timer which will do something like that but on very small collections. I don't suggest using system.threading.timer if you have your sockets using async since they both use I/O threads. Use system.timers and it should be fine. Whenever a players moves and a monster is spawned to the player, it is registered into a screen class on which the timer will work.
I honestly believe that having a timer running on every client is over kill given that you could just use a threadpool with a maximum of 5 threads running can easily do the job.
06/13/2011 14:10 -impulse-#11
Quote:
Originally Posted by Korvacs View Post
I honestly believe that having a timer running on every client is over kill given that you could just use a threadpool with a maximum of 5 threads running can easily do the job.
I agree.
06/15/2011 00:37 CptSky#12
Thanks for the answers, I will check this during the weekend. I will probably go for the idea of Korvacs.