ID:140017
 
Code:
proc
get_steps_to(atom/a,atom/b)
if(istype(a,/atom/movable)) a = a.loc
if(istype(b,/atom/movable)) b = b.loc
var/list/result=list()
var/atom/current=a
while(current!=b)
result += get_step_to(current,get_dir(current,b),0)
current = get_step_to(current,get_dir(current,b),0)
return result
proc
get_steps(atom/a,atom/b)
if(istype(a,/atom/movable)) a = a.loc
if(istype(b,/atom/movable)) b = b.loc
var/list/result=list()
var/atom/current=a
while(current!=b)
result += get_step(current,get_dir(current,b))
current = get_step(current,get_dir(current,b))
return result


Problem description:
So, basically, the code above simply multiplies get_step and get_step_to many times, so you have the entire path to a certain point returned.

When I do a test verb like this,
mob/verb
steps_to()
for(var/turf/t in get_steps_to(locate(1,1,1),locate(10,10,1)))
t.icon_state = "blue"
steps()
for(var/turf/t in get_steps(locate(1,1,1),locate(10,10,1)))
t.icon_state = "blue"

steps() works just fine.
steps_to() doesn't. Dream Seeker crashes if I run this proc.

There are no obstacles between (1,1,1) and (10,10,1).

Apprently, the variable current in get_steps_to() becomes null, and I have no idea of why this happens.

What the heck?
Your parameters for get_step_to() are incorrect. The second parameter is supposed to be an atom, not a direction.

So:
            result += get_step_to(current,get_dir(current,b),0)
current = get_step_to(current,get_dir(current,b),0)


Should be:
            current = get_step_to(current,b,0)
result += current //No need to calculate it twice



Also, you can use get_step_towards() for get_steps(), and then not need the get_dir().
In response to DarkCampainger
a = the turf(1.1), b = the turf(10,10)
runtime error: Cannot read null.x
proc name: get steps to (/proc/get_steps_to)
source file: quick attempt.dm,12
usr: Gooseheaded (/mob)
src: null
call stack:
get steps to(the turf (1,1,1) (/turf), the turf (10,10,1) (/turf))
Gooseheaded (/mob): steps to()

#define DEBUG
proc
get_steps_to(atom/a,atom/b)
if(istype(a,/atom/movable)) a = a.loc
if(istype(b,/atom/movable)) b = b.loc
var/list/result=list()
var/atom/current=a
world << "a = [a]([a.x].[a.y]), b = [b]([b.x],[b.y])"
while(current!=b)
current = get_step_to(current,b,0)
result += current
world << "current = [current] ([current.x],[current.y])" // This is the line.
sleep(2)
return result
proc
get_steps(atom/a,atom/b)
if(istype(a,/atom/movable)) a = a.loc
if(istype(b,/atom/movable)) b = b.loc
var/list/result=list()
var/atom/current=a
while(current!=b)
current = get_step_towards(current,b)
result += current
return result
turf
icon = 'icon.dmi'
icon_state = "green"
mob/verb
steps_to()
for(var/turf/t in get_steps_to(locate(1,1,1),locate(10,10,1)))
t.icon_state = "blue"
steps()
for(var/turf/t in get_steps(locate(1,1,1),locate(10,10,1)))
t.icon_state = "blue"


Still, current = null, for some reason.
What's going on?
In response to Gooseheaded
Which version of BYOND are you using?
There seems to have been a little bug with get_step_rand (and likely get_step_to). If you're running the latest stable beta (version 469) and the issue persists, I'd file a bug report.

I just confirmed that get_step_to returns null in 497.

proc
get_steps(var/atom/_start, var/atom/_end)
if(_start && istype(_start) && _end && istype(_end))
. = list()
if(istype(_start, /atom/movable))
_start = _start.loc
if(istype(_end, /atom/movable))
_end = _end.loc
var/turf/_current = _start
while(_end && (_current != _end))
_current = get_step(_current, get_dir(_current, _end))
if(!_current)
break
. += _current

get_steps_to(var/atom/_start, var/atom/_end)
if(_start && istype(_start) && _end && istype(_end))
world << "1"
. = list()
if(istype(_start, /atom/movable))
_start = _start.loc
if(istype(_end, /atom/movable))
_end = _end.loc
world << "2"
var/turf/_current = _start
world << "3"
while(_end && (_current != _end))
world << "4"
_current = get_step_to(_current, _end)
if(!_current)
world << "5"
break
. += _current

get_steps_towards(var/atom/_start, var/atom/_end)
if(_start && istype(_start) && _end && istype(_end))
. = list()
if(istype(_start, /atom/movable))
_start = _start.loc
if(istype(_end, /atom/movable))
_end = _end.loc
var/turf/_current = _start
while(_end && (_current != _end))
_current = get_step_towards(_current, _end)
if(!_current)
break
. += _current
In response to Schnitzelnagler
I'm using v467.106, and get_steps_to() doesn't return anything, even when using your code.

Should I file the report, then?
Are we 100% sure that we're not doing something wrong?
In response to Gooseheaded
'My code' just added a few security checks (to prevent runtime errors as you experience them). It would be kind of important to see if the problem persists in 469, since there was a fix to the very similar function get_step_rand(), which could mean that the fix included get_step_to.

I'll ask around and see if I can get a hold of somebody willing to test the function in 469.
In response to Gooseheaded
Schnitzelnagler asked me to test the function under 469 and it works, so once you update your BYOND version, the issue should be resolved.
In response to Schnitzelnagler
I just updated to v469.107, and the result is still null.
#define DEBUG
turf
icon = 'icon.dmi'
icon_state = "green"
proc
get_steps(var/atom/_start, var/atom/_end)
if(_start && istype(_start) && _end && istype(_end))
. = list()
if(istype(_start, /atom/movable))
_start = _start.loc
if(istype(_end, /atom/movable))
_end = _end.loc
var/turf/_current = _start
while(_end && (_current != _end))
_current = get_step(_current, get_dir(_current, _end))
if(!_current)
break
. += _current

get_steps_to(var/atom/_start, var/atom/_end)
if(_start && istype(_start) && _end && istype(_end))
world << "1"
. = list()
if(istype(_start, /atom/movable))
_start = _start.loc
if(istype(_end, /atom/movable))
_end = _end.loc
world << "2"
var/turf/_current = _start
world << "3"
while(_end && (_current != _end))
world << "4"
_current = get_step_to(_current, _end)
if(!_current)
world << "5"
break
. += _current

get_steps_towards(var/atom/_start, var/atom/_end)
if(_start && istype(_start) && _end && istype(_end))
. = list()
if(istype(_start, /atom/movable))
_start = _start.loc
if(istype(_end, /atom/movable))
_end = _end.loc
var/turf/_current = _start
while(_end && (_current != _end))
_current = get_step_towards(_current, _end)
if(!_current)
break
. += _current
mob/verb
steps_to()
for(var/turf/t in get_steps_to(locate(1,1,1),locate(10,10,1)))
t.icon_state = "blue"


That is literally all the code I'm running.

When I run the project, some debugging messages (lines 22,28,30,25,25) show up:

1
2
3
4
5

So, again, if(!_current) is true (it return 1 on first interation of the loop).
Any suggestions?
Gooseheaded wrote:

> proc
> get_steps_to(atom/a,atom/b)
> if(istype(a,/atom/movable)) a = a.loc
> if(istype(b,/atom/movable)) b = b.loc
> var/list/result=list()
> var/atom/current=a
> while(current!=b)
> result += get_step_to(current,get_dir(current,b),0)
> current = get_step_to(current,get_dir(current,b),0)
> return result
> proc
> get_steps(atom/a,atom/b)
> if(istype(a,/atom/movable)) a = a.loc
> if(istype(b,/atom/movable)) b = b.loc
> var/list/result=list()
> var/atom/current=a
> while(current!=b)
> result += get_step(current,get_dir(current,b))
> current = get_step(current,get_dir(current,b))
> return result
>



> mob/verb
> steps_to()
> for(var/turf/t in get_steps_to(locate(1,1,1),locate(10,10,1)))
> t.icon_state = "blue"
> steps()
> for(var/turf/t in get_steps(locate(1,1,1),locate(10,10,1)))
> t.icon_state = "blue"
>




I think I found your problem in this line
if(istype(a,/atom/movable)) a = a.loc


Your test code gives the argument locate(1,1,1) and locate(10,10,1). Which are turfs. Turfs are /atom. But they aren't /atom/movable, making the value null.

This is all a theory, I am not exactly an expert in DM but I believe that this is the problem. I may in fact be horribly wrong.
In response to Froggersucks
You're horribly wrong.
In response to Froggersucks
In that case, a = turf.

All it does is, basically,

if(a==obj) a=obj.loc
if(a==mob) a=mob.loc
else world << "We're cool."
In response to Gooseheaded
I suggest you create a bug report. As you're not a BYOND member, I compiled and uploaded a test world for you, which you can link to for ease of use.
http://www.byond.com/members/Schnitzelnagler/files/ Goosehead_src.zip
I just ran into this problem too. I mentioned a workaround on the bug report page, but figured I'd mention it here too.

The problem is that the first argument to get_step_to cannot be a turf. The reference says the first arg must be a "starting point or object", but apparently a turf is not a starting point. To get around this you can create an invisible mob and place it on the turf, then pass that mob as the first argument.

Your code would look something like this:
proc
get_steps_to(atom/a, atom/b)
var/list/result = list()

var/mob/m = new /mob()
if(isturf(a))
m.loc = a
else
m.loc = a.loc

while(m.loc != b)
var/turf/next = get_step_to(m, b)
result += next
m.loc = next
del m
return result


Edit: get_step_to should return null in this case when b is not reachable from m's location, so you'd need to handle that.