Monster AI Timer Loop

Started by
1 comment, last by WombatTurkey 8 years, 7 months ago

Long story short, my gameserver is written in V8 JS (nodejs).

It's a instanced based game similar to Diablo 2. Players can join and leave games and when a player joins a game, then goes to a dungeon (specific map) the temporary monster data (chp/position/id) are loaded into the buffer.

A player can move around the map (X,Y) ordinates so I do check collision and range for melee and ranged skills so I check against that serverside for each mob to see if the player is in range.

With that said, when a player get's close to a mob, monster agro and AI attacking starts. This is where the Monster AI timer comes into play. So basically the monster's position in the buffer get's synced to that map instance/object and then sent to the client.

My question is: Do I just run one main loop to handle all positioning updates and synchronization, or do I need each game Instance Object to have their own specific timer?

Advertisement

It depends :)

If everything runs at the same speed, one timer is sufficient.

If some monsters are faster than others, or you have timeout timers running etc, then in case of a single timer, each monster must have some "skip-acount" (ie wait 3 turns before moving again). Slow enemies just decrement the skip-count until they hit 0, then do something.

The latter is quite similar to having a timer for each monster, where you basically throw away the central timer, and convert all counters to timers.

A 'new' problem with decentralized timers is that you have to decide how long to wait before the next loop over the monsters (since there is no single timer that you can query). You decide by inspecting all timers, and finding the smallest value. This costs an extra iteration over all timers. The benefit is however that you never loop over all monsters without knowing there is at least one timer finished.

If you have long timer values, the costs of repeatedly finding there is nothing to do, as all counters or timers of monsters are still counting down, may be more costly than the one iteration to decide the next point in time where one timer is expired.

Another option is to store all timeouts in a central set ordered by timeout value, but that takes memory space.

You can of course also use hybrid forms, have a number of "fast" enemies that you poll each time, and a number of "slow" enemies where you check beforehand at what moment in time it's useful to visit them again.


The benefit is however that you never loop over all monsters without knowing there is at least one timer finished.

Yeah, this is what I was thinking! For example, if a player joins a game then goes to a dungeon and leaves. Those mobs will still be in that games object buffer until the game's object is deleted ( I do that every 5 minutes if no one joins ), and the loop will be iterating over those mobs and that's extra wasted memory sad.png

I havn't really got into the attack speed or movement of them yet and don't think I will. My game is DOM based, and it's just not going to end well with fast movements haha.

I'm going to do the global timeout thing now and do some tests with large amounts of objects being iterated over in node and see some memory limits. If it becomes too much, I think I'll do the timer for each map (although, that has some performance issues as well because there would be more timers running instead of just one) or just one running but a large object it has to iterate over.. First World Problems Much?! smile.png

Thanks for the response, and I'm glad you brang up the monster movement issue as well.

This topic is closed to new replies.

Advertisement