So in other words, I was only partially correct, you were optimizing something trivial but it wasn't being called thousands of times a frame, it wasn't even being called.
i hadn't gotten to optimizing yet, i was still in the speculation and educated guess phase. sometimes it can show obvious things like out of order trivial rejections in loops, constants being re-calculated inside loops, and other first pass - write it easy, not fast coding stuff. then you break bad with the timers and tracing once you've done the obvious stuff. inspecting the code and thinking about it first will give you a good idea what the timers will tell you. if not, then learn from the timers, and next time you'll do a better job of predicting the profile results, or not writing lazy code in the first place where you know its going to matter. just doing the obvious stuff got me from 22 seconds down to about 7 seconds. a trace indicates that no further speedups are possible with atan and range while target selection continues to be done at a rate of only once every five seconds. I'd like to do target selection once per second to make them more responsive. until then, atan and range are fast enough. i now need to look at setstate(), the expert system that sets AI state, and runstate(), the code that executes the various AI states. I know that setstate() can be sped up. for MAINTAIN_DISTANCE_AI herds, every frame it "rolls the dice" to determine if a critter changes AI state between wander, flock, and stand. and sometimes "rolls the dice" to determine what they do next (wander vs flock, etc). runstate() can be sped up too. i have't sliced the avian and non-avian AI into totally separate parts yet, so many of the move() routines (attack, run, etc) have two branches of code in them, one for avians and one for non-avians. splitting that up so its just one short clean shot of code will eliminate some flow control checks. but not potentially setting state every frame , and instead doing it once per sec or so will be the major speedup.