ID:155017
 
Edit: How would I output the same output() message to two outputs at once on different windows instead of using 2 lines of code for separate messages that are the same?

I profiled my AI system for a duration of 1 hour with around 20 players casually fighting mobs.

It reached the highest CPU usage, even more than my RSC procs that I heavily reduced with object recycling.

                                  Profile results (total time)(duration: 1 hour)
Proc Name Self CPU Total CPU Real Time Calls
-------------------------------------------- --------- --------- --------- ---------
/mob/Antagonist/proc/intelligence_system 15.358 17.317 10704.060 334
/mob/Antagonist/proc/fight_back 1.816 1.954 1.957 5786
/mob/Antagonist/proc/antagonist_death 0.009 0.250 0.252 4279
/mob/Antagonist/proc/reset_antagonist 0.000 0.000 0.000 299
/icon/proc/RscFile 3.283 3.283 3.283 521


Here's the code(Ignore my annotations/comments, they're for someone learning.):

        proc

intelligence_system()

set background = /* cpu intensive proc(?) */ 1

if( already_reacting /* check if the bully is reacting. */ ) return

if( isbully ( src ) /* check if the source is a bully. */ ) already_reacting = 1

while( 1 /* forever true. */ )

if( dead /* check for death. */ || !target /* check for the target. */ || ! ( target in view ( 7 , src ) /* check for the target. */ ) ) break

if( stamina >= stamina_percentage /* check their stamina. */ )

if( get_dist ( src , target ) > 1 /* check the distance. */ )

step_to( src , target )

else if( world.time > on_delay /* check punch delay. */ )

on_delay = world.time + 13 ; fight_back()

else step_away( src , target )

sleep( 4 /* wait 4 ticks to move again. */ )

if( !dead /* check for death. */ ) reset_antagonist()
Neimo wrote:
Edit: How would I output the same <code>output()</code> message to two outputs at once on different windows instead of using 2 lines of code for separate messages that are the same?

I'm not sure if you can do this with a single call to output(), but you can create your own proc that takes a single message and calls output() twice.

I profiled my AI system for a duration of 1 hour with around 20 players casually fighting mobs.

If I'm reading it correctly, I don't see a problem. 17 seconds of CPU time spread over 1 hour is less than 1% CPU usage.

The only things that look costly in the intelligence_system proc are the call to step_to() and "target in view ( 7 , src )". If you can change those to step_towards() and "get_dist(src, target) <= 7" that'll help.

You might also want to take a look at this: http://www.byond.com/developer/Forum_account/EnemyAI
In response to Forum_account
I have seen your AI library and it helped me quite a lot earlier this year.

I also thought the CPU usage the Profile returned was the exact percent it was using at the time.

-- Thanks, 'preciate it.

Oh, I use <code>step_to()</code> so the mob can move around obstacles.
In response to Neimo
Neimo wrote:
I have seen your AI library and it helped me quite a lot earlier this year.

Glad to hear!

I also thought the CPU usage the Profile returned was the exact percent it was using at the time.

The numbers are measures of time. I'm pretty sure it's always in seconds, though you can make it display the total time or average time.

Oh, I use <code>step_to()</code> so the mob can move around obstacles.

The problem is that when there aren't obstacles step_to() and step_towards() have the same result, but step_to() takes more time. I'd only bother to make this change if CPU usage is an issue, but you can have the mob temporarily switch to using step_to() when step_towards() fails.
In response to Forum_account
Seems as if I have tumbled into a flaw, the mobs do actually get stuck. Whenever I'm at the corner of a wall, the mobs get stuck on the other side of the wall when trying to chase me.

Once I fix something it seems like I've broken hundreds more things.

<small>
                while( 1 /* forever true. */ )

if( dead /* check for death. */ || !target /* check for the target. */ || get_dist ( src , target ) > 7 ) break

if( stamina >= stamina_percentage /* check their stamina. */ )

if( get_dist ( src , target ) > 1 /* check the distance. */ )

step_to( src , target )

else if( world.time > on_delay /* check punch delay. */ )

on_delay = world.time + 13 ; fight_back()

else step_away( src , target )

sleep( 4 /* wait 4 ticks to move again. */ )
</small>
In response to Neimo
I'd put some output statements in there to see what's actually happening. Maybe step_to() isn't being called due to other circumstances (ex: target became null, stamina is less than stamina_percentage). If the AI is somehow alternating between calling step_to() and calling step_away(), that'd explain it getting stuck. Just put world << "step_to" and world << "step_away" before each call so you can see exactly what's happening.
In response to Forum_account
I made the AI output the next turf it would step to and it was outputting "turf". (The object on the turf are dense buildings.)

About 3-4 minutes of profiling with the mob being stuck against the wall trying to follow me gets this:

<small>
                         Profile results (total time)
Proc Name Self CPU Total CPU Real Time Calls
--------------------------- --------- --------- --------- ---------
/mob/Antagonist/proc/stalk 4.610 4.610 141.744 1
</small>
In response to Neimo
I thought that step_to() would go around dense obstacles, but you might need to make the turf dense for step_to() to go around the obstacle.

Provided the building doesn't move, you can just do this:

obj/building
New()
..()
var/turf/t
if(t) t.density = 1
In response to Forum_account
Forum_account wrote:
I thought that step_to() would go around dense obstacles, but you might need to make the turf dense for step_to() to go around the obstacle.

Provided the building doesn't move, you can just do this:

> obj/building
> New()
> ..()
> var/turf/t
> if(t) t.density = 1
>


Wouldn't that be:

var/turf/turf = loc


I tried <code>var/turf/turf = loc ; if( turf && !turf.density ) turf.density = 1</code> and the AI now moves around the buildings.

-- Thanks
In response to Neimo
yep that's what I meant, glad I could help.