ID:14266
 
I've been looking at trying to speed up Ruin, and one of the big slowdowns, having a look at Profile World, seems to be AI.

/proc/DoMonsterTurn - 0.292
/IsoDisplay/proc/UpdateDisplay - 0.268

That's average time/call. DoMonsterTurn() depends on the number of monsters around the player, but it takes a fair amount of time either way - as you can see, the average worked out to be greater then the time it takes to display the isometric display. In terms of total time, the display procs take longer, but I've already optimised the hell out of those, anyway, and DoMonsterTurn() seems to be the big one.

The current way I do AI is to loop through every mob within a certain distance of the player, and call their Ai() proc. Inside that proc, the monster checks if there's a player within its view - if there is, and the player is out of range, it steps towards it. If there is, and the player is in range, it attacks. If neither of those are true, the monster stays stationary. That can be overridden for various monsters, but so far everything uses the default.

Any ideas on how I can speed it up?

EDIT: One fairly major change to the way the game decides when to update various features of the display has sped it up significantly, but I'd still like to hear any optimisations you think I could apply to my AI procedures.
Do you have many creatures running AI around such that the slowdown is because of a mass accumulation of simple actions, or do you have a few things around but they have complex AI? If it's a lot of objects, then even seemingly simple things can help since they will amount to a small benefit multiplied by the hundred objects around.

For example, if you are calling the view function for every creature running on AI each AI iteration, you might consider calculating it from the player's point of view instead of the other objects' point of view and cycle through the views of a few players looking for in-range objects instead of a hundred other things looking for in-range players.

If you're looping through all the objects in the world at the moment to see which have players in their screen, this alternative would be especially beneficial in another way. Not only are you calling view fewer times and thereby creating/looping-through/destroying fewer lists, but you would completely ignore things that aren't in view anyway so that things not in range wouldn't even be considered and they would be skipped over completely by the very nature of such a loop, whereas doing it from the other objects' point of view you would end up looping through something off in nowhere land and taking a fraction of a second to decide that it has nothing around it. So that's actually making small increases in two ways.

You could also avoid updating AI-objects' at all when not necessary by linking it to movement of players instead of a timer. That is, when players move you could loop through AI-driven objects in their range and activate any of those objects which are not yet activated. Whether this is faster or not depends on how much people move and how often they are around the other creatures though.
Lots of creatures running AI, rather then one complex one.

you might consider calculating it from the player's point of view instead of the other objects' point of view and cycle through the views of a few players looking for in-range objects instead of a hundred other things looking for in-range players.

I'm not entirely sure how that would work out. Just because the player can see x, doesn't mean x can see the player. The monsters need to know whether they can see the player (It's single-player). I suppose in DoMonsterTurn(), I could call a different AI function for monsters that could conceivably see the player then for those that definitely can't, but I'm not sure how much of a help that would be, and it would certainly muddle the procs a lot.

I'm only looping through every monster within world.view of the player (using range, though), and the monsters only move when the player does - it's turnbased.
Use viewers() instead of view().