ID:170363
 
I am currently making an RPG (World of Albion) for the Roleplaying website World of Albion (http://theworldoalbion.proboards31.com/index.cgi) and am a little floundered by monster AI.

I can make my monsters wander randomly, and chase players (very unintelligently) and run away. But there are a few things I am unsure of.

I want several Orc monsters to stay near their camp. I surrounded their camp with an area that only allows clients passed. But now, if a player walks within 6 squares of an Orc, the Orc runs to the wall of area, and then just stands there. How can I tell the Orc to ignore anything unless it is within its own area?

Also, if a monster's path is blocked by an obstacle, they won't take a route around. How can I get them to realise they can't go forward, and go around instead?

Here is my current code;

        proc//core procs for the system
ai_random_wander()//random wander if no mobs are in range to attack
if(src.key)//if the source is human
return//don't call the rest
else
walk_rand(src,7)//walk randomly with 7 lag
src.ai_run_away()//checks for run away
spawn(10)//delay for one tick
ai_random_wander()//wander some more

ai_run_away()//used for checking to see if it should run or attack
if(src.client)
return
else
for(var/mob/chars/M in oview(4,src))//loops over all mobs within 4 tiles of the monster
if(M.client)//if the mob is human
if(get_dist(src,M) <= 5 && src.HP < src.HP/3)//if the player is close, and the monster is weaker
walk_away(src,M,5,6)//run away
else
src.ai_walk_to()//calls the walk_to (for attacking) proc
else
continue//if it's a monster keep looping

ai_walk_to()
if(src.client)
return 0
else
for(var/mob/chars/M in oview(5,src))
if(M.client)
if(get_dist(src,M) <= 5)//within 5 tiles
walk_to(src,M,1,6)//walk to the player
if(get_dist(src,M) <= 1)
Attackproc()
break//stops the loop
else
continue


Thank you.

~Ease~
Bump!
Ease wrote:

How can I tell the Orc to ignore anything unless it is within its own area?

mob/orc/proc/check_target(mob/target)
if(target.loc.loc=loc.loc)return 1
return 0


Also, if a monster's path is blocked by an obstacle, they won't take a route around. How can I get them to realise they can't go forward, and go around instead?

I'm not sure. walk_to specifically states that it takes obstacles into account, so it should walk around them.
In response to Loduwijk
Loduwijk wrote:
Ease wrote:
Also, if a monster's path is blocked by an obstacle, they won't take a route around. How can I get them to realise they can't go forward, and go around instead?

I'm not sure. walk_to specifically states that it takes obstacles into account, so it should walk around them.

I [b]think[/b] that's only the case when the obstacle is an obj/mob/turf, as it doesn't seem to work when the only obstacle is an area (and there is a clear path around). Perhaps because the area stops it using "Enter()" procs, instead of density.
In response to Ease
Ease wrote:
I [b]think[/b] that's only the case when the obstacle is an obj/mob/turf, as it doesn't seem to work when the only obstacle is an area (and there is a clear path around). Perhaps because the area stops it using "Enter()" procs, instead of density.

I'm not quite sure what that last sentence was supposed to mean. If you meant that you altered area/Enter so that it does not appear as an obstacle because of a false density and so tries to enter despite a repeated failure do to a change you made in Enter, then yes that may well be the case. In such a case you would just need to change things around to sidestep that problem.

I am not sure how obstacle calculation is figured, but I would hope it is based off of Enter and not just a loop through objects to check their density. You can check that out and find out easily enough with a small test program.
In response to Loduwijk
I am now trying to get the monster to stay in its own area. Before I was just using "walk_rand" but now I need more. I don't want the monster to walk randomly until it reaches its border, where it occasionally moves if the direction is not off the border. So I tried this:

            ai_random_wander()//random wander if no mobs are in range to attack
if(src.key)//if the source is human
return//don't call the rest
else
var/Dir = "NORTH"
Rand_Dir:
var/ran = rand(1,8)
if(ran==1)
Dir = "NORTH"
if(ran==2)
Dir = "NORTHWEST"
if(ran==3)
Dir = "NORTHEAST"
if(ran==4)
Dir = "EAST"
if(ran==5)
Dir = "WEST"
if(ran==6)
Dir = "SOUTH"
if(ran==7)
Dir = "SOUTHWEST"
if(ran==8)
Dir = "SOUTHEAST"
var/turf/T = get_step(src,Dir)
if(T.density||T.loc!=loc.loc)
goto Rand_Dir
else
walk_towards(src,T)
src.ai_run_away()//checks for run away
spawn(7)//delay for one tick
ai_random_wander()//wander some more ai_random_wander()//random wander if no mobs are in range to attack
if(src.key)//if the source is human
return//don't call the rest
else
var/Dir = "NORTH"
Rand_Dir:
var/ran = rand(1,8)
if(ran==1)
Dir = "NORTH"
if(ran==2)
Dir = "NORTHWEST"
if(ran==3)
Dir = "NORTHEAST"
if(ran==4)
Dir = "EAST"
if(ran==5)
Dir = "WEST"
if(ran==6)
Dir = "SOUTH"
if(ran==7)
Dir = "SOUTHWEST"
if(ran==8)
Dir = "SOUTHEAST"
var/turf/T = get_step(src,Dir)
if(T.density||T.loc!=loc.loc)
goto Rand_Dir
else
walk_towards(src,T)
src.ai_run_away()//checks for run away
spawn(7)//delay for one tick
ai_random_wander()//wander some more


But it doesn't seem to "walk_towards"! Ever! I put a "world<<"BOO"" in after walk_towards (to test the If) and it Boo shows every single time! What is happening?

~Ease~
In response to Ease
Well rule of thumb is to try not to use Goto. Maybe you should try to figure out a way with out using Goto. Try a "while" loop.
In response to N1ghtW1ng
The Goto doesn't affect it. At all =P The Goto is only called if the If is true. But in nearly all test case, the If was false. Only the Else was true.
In response to Ease
Sorry to bump again, but still stuck!
In response to Ease
You don't need that long line of if statements. Try this instead.
            ai_random_wander
if(src.client) //I prefer checking client since it is more accurate
return
var/turf/T
var/Dir=0
do
Dir=pick(1,2,4,8,5,6,9,10)
T=get_step(src,Dir)
while(!T||T.density||T.loc!=loc.loc)
walk_towards(src,T)
src.ai_run_away()//checks for run away
spawn(7)
ai_random_wander()

A couple other things need mentioning as well.

If you plan on leaving the code as is, with the target turf being walked to always one tile away, I would use step(src,Dir instead of walk_towards(src,T).

Your comment says spawn(7) is supposed to delay for one tick. Putting 7 in there will make it delay for 7 ticks, not one. spawn(1) would be 1 tick.

As for your walking failure, it is because you are passing a text string to get_step. You have to pass a direction, which is a number. You can use NORTH, SOUTH, ect. because those are defined as numbers, but you cannot use "NORTH" or "SOUTH" since those are text strings.
NORTH!="NORTH"
In response to Loduwijk
Thank you so much! The spawn(7) was just a mistake in the commenting. Thank you!

~Ease~
In response to Ease
I believe that bumping is no longer allowed. I'm pretty sure you have to actually add something to your old post.