ID:159196
 
What I want to do is create a step_rand() but make it so the monster isn't constantly moving. I'd like it to have some "standing" periods and some periods where it walks a couple of steps and stops again. How can I achieve this?
proc/random_walk(low_long_pause, high_long_pause, low_short_pause, high_short_pause, low_steps, high_steps)
//low_long_pause is the lower bound of the pause between
// one series of steps and the next.
//high_long_pause is the upper bound of the above.
//low_short_pause is the lower bound of the pause between
// a single step and the next step.
//high_short_pause is the upper bound of the above.
//low_steps is the lower bound of the amount of steps
// that will be taken in a series of steps.
//high_steps is the upper bound of the above.

spawn()
while(1)
sleep(rand(low_long_pause, high_long_pause))

var/steps = rand(low_steps, high_steps)
for(var/a = 1, a <= steps, a ++)
sleep(rand(low_short_pause, high_short_pause))
step_rand(src)

return 1
Something like this could work(For really random movement)

step(src,pick(NORTH,SOUTH,WEST,EAST))
sleep(rand(1,10)


That just would make it randomly step in a cardinal direction and then wait 0.1 - 1 second. You could easily add that in or change any value, and to add in other directions just add NORTHEAST(etc...) to the pick part above.
Make a function that loops until you want it to stop happening.
Each iteration, either do nothing or take a random step.
atom/movable/sleepyRandomWalk()
var/global/sleepyRandomWalk = 1
if(sleepyRandomWalk)
sleepyRandomWalk = 0
return
while(sleepyRandomWalk)
if(prob(60))
sleep(10)
else
step_rand(src)
sleep(32/pixel_step_size)

In that example, calling an object's sleepyRandWalk() once would make it mope about, stopping and going; then, calling it a second time would make the object stop.
In response to Bakasensei
That's essentially the same as the step_rand() proc, minus the diagonal directional movements. Instead of applying a sleep() proc in there, just utilize the step() and walk() procs' third argument (Lag).
In response to Spunky_Girl
Practically every reply here except Lodu's has been unhelpful one way or another. So, yeah... to the other repliers... take that! :P

Spunky_Girl wrote:
That's essentially the same as the step_rand() proc, minus the diagonal directional movements.

Yeah.

Instead of applying a sleep() proc in there, just utilize the step() and walk() procs' third argument (Lag).

Well, step() being [one] step it has no Lag argument or a need for one, and as for walk()'s Lag, it wouldn't be so suitable either, if you pay close attention to what the OP wanted. walk() would have the delay consistently (unless you occasionally terminate it and start a new walk), but the OP wants to simulate 'realistic movement', that is, having a varying delay (rarely, even long - he referred to this as 'standing periods') between each step, not a constant same delay.
In response to Kaioken
Kaioken wrote:
...but the OP wants to simulate 'realistic movement', that is, having a varying delay...

I guess it was wrong of me to assume he had the brains to put an equation for the third argument to calculate the lag for the walk_rand() proc >_> (or even a rand() proc will do for this situation)

walk_rand(src,rand(1,5))
In response to Spunky_Girl
Well, I believe that in my post, I made it pretty clear, put plainly, that the walk_rand() proc is simply not sufficient.
In response to Kaioken
Actually, you said;

having a varying delay (rarely, even long - he referred to this as 'standing periods') between each step, not a constant same delay.

That's exactly what Spunky's saying. You just use rand(), or, as random as anything is after 10000 tries. walk_rand() will do the job unless you need to define actual paths or such.
In response to Mysame
That would work conventionally, but the delay is meant to vary "on a step-level", though, and not be consistent between every step. So step 2 may occur half a second after step 1, but step 3 may occur 5 seconds after step 2 (i.e. the NPC was 'standing'). As I've said, walking functions aren't really suitable for these because they're built for consistent (per-step) delays, though it's possible to work around this with multiple walk_rand() calls. Spunky just said to use the lag argument, to which I've replied appropriately; it's not enough for what the OP wanted.
In response to Mysame
Mysame wrote:
That's exactly what Spunky's saying. You just use rand(), or, as random as anything is after 10000 tries. walk_rand() will do the job unless you need to define actual paths or such.

Not quite. What Kaioken is getting at is the fact that the built-in random walking functions will always have a constant lag time. Even if you do the following
walk_rand(object, rand(low, high))

the time between steps will still be constant. That constant time will be randomly determined up front, but then it stays constant.

The original poster wanted something that would specifically cause an object to wait a random amount of time, take a random number of steps, wait a different random amount of time, take a different random number of steps, and continue in this fashion so that it looked more natural. That is, an object might wait for 4 seconds, take 1 step, wait for 2 seconds, take 3 steps in a row, wait for half a minute, take 1 step, wait for 1 second, take 5 steps, etc.

Granted, what I gave isn't the greatest solution for what was wanted either. It was just a crude example, however, I would hope that the user could change it to suit the required needs.

There are 3 main ways it could be altered. You could just change numbers to make it more or less likely for either walking or standing periods to occur, you could even randomize the numbers each iteration so that, not only is it all random to begin with, but the probability that it will either stand or walk itself has a random success rate achieved with a random roll, a kind of "doubly-random" approach. You could also, upon either a determination of walk or stand, have it walk a random number of steps or stand for a random amount of time before going to the next iteration. And you can combine all of the above.
...
while(randomlyWalking)
if(prob(50))
// stand still for 0 to 10 seconds, with longer periods being less likely than shorter periods
sleep(100-sqrt(rand(0,10000)))
else
// walk randomly for 0 to 10 steps, with longer walks being less likely
// the object is also most likely to continue forward instead of turning or reversing, and least likely to reverse direction
for(var i = 0 to (10-sqrt(rand(0,100))))
step(src, pick(turn(dir, 90), turn(dir, -90), prob(200);dir, prob(50);turn(dir, 180)))

(edit)
And obviously, don't forget to sleep() inside that walking loop.
In response to Loduwijk
Oooh. I totally didn't spot that part. But now that you mention it, yes it DOES work that way :< Sorry for the misunderstanding. So yeah, you need step(). :>