ID:1331173
 
(See the best response by Rushnut.)
So I've been using this for a while. It works really well, but I would really like to convert this down to a single loop or increase its performance in any way possible...

Here's some specs for the proc:
1. Must be called every tick, so it is always absolutely up to date with the actual state of the world.
2. Keeps track of mobs in two "ranges". A smaller "active" range, and a larger "inactive" range. When mobs go from the active range to the inactive, they are removed from the active mobs list.
3. wake() should only be called once when the mob awakened, so in other words, the mob will handle its own behavior, we're just telling it when to wake up or go to sleep
4. The mob will ignore extra wake calls if it is already awake... perhaps this should be handled here instead of at the mob level, though. Considered design choice.

mob/var/tmp/list/mobs_seen = list()
mob/var/tmp/list/mobs_awake = list()

mob/player/proc/ai_wake()
mobs_seen = ohearers(src)

for(var/mob/enemy/m in mobs_awake)
if(!m)
mobs_awake -= m
continue
if(!mobs_seen.Find(m))
m.unwake()
mobs_awake -= m

for(var/mob/enemy/m in mobs_seen)
if(!m) continue //not possible?
m.wake() //could add a check here to make sure wake() is only called once
mobs_awake += m


Extra thoughts:
1. maybe spawn the wake calls in case the ai has some heavy lifting to do (or to give it that right to do so)
2. could easily add distances as a feature / parameters, just need to make sure it will perform as added checks will increase cpu
3. would it be faster to set list entries to null instead of removing them from the list?
Best response
Surely you could use three lists, add a new list/mobs and loop through them, then just use if mobs_seen.Find() and do magic stuffs?
I have a few suggestions, albeit minuscule, it could potentially improve performance.

(1) Replace if(!mobs_seen.Find(m)) with if(!(m in mobs_seen)). A function that is invoked, no matter what, always uses some(a tiny bit) computational overhead.

(2) Funny enough, this one actually contradicts my first suggestion. mobs_awake -= m returns a new list after m is removed -- mobs_awake.Remove(m) does not.

(3) The larger the list, the longer it'll take to iterate through it; be cautious with how you're adding/remove mobs.