ID:140803
 
Code:
            check_walls(mob/m)
var/target_location=m.loc
var/obj/path_checker=new/obj(loc)
path_checker.density=1
path_checker.icon='mob.dmi'
var/obstacle_true
path_checker.dir=get_dir(path_checker,target_location)
var/temprange=Arange
var/old_path_checker_location
while(temprange)
temprange--
old_path_checker_location=path_checker.loc
step(path_checker,path_checker.dir)
if(old_path_checker_location==path_checker.loc)
obstacle_true=1
del path_checker
break
if(obstacle_true)
obstacle=1
else
del path_checker
obstacle=0
damage_process(mob/m)
missile('bullet.dmi',src,m)


Problem description:

So basically the idea is, for the AI calling this procedure, is checking to see if anything is obstructing a long ranged attack before going. I'm not sure if there's a better way of checking, because right now I'm just having an object run the path to check. Is there a better way? Because this doesn't work.

Anyways, the mob/m argument is the target of course.

Another question I would love to know the answer to:

If you'd take note of the "obstacle" variable, you'd notice it's purpose is not even used in this block of code. It's actually because the lines of code for AI() call the "check walls proc" and immediatly after checks to see if check walls was true or not by checking the obstacle variable. Is there anyway to check if it returned it or not without checking with a variable? It seems ugly.

Here's the rest of the code, just to maybe clear up my jumbled explanation..

    soldier
icon='mob.dmi'
icon_state="Rsoldier"
var
mob/owner
Arange=5
obstacle

New(mob/owner)
owner=owner
ai_attack()

proc
ai_attack()
spawn for()
sleep(10)
for(var/mob/m in oview(src,Arange))
if(m.team!=team)
check_walls(m)
if(!obstacle)
damage_process(m)


Currently, (even though this

Instead of setting a var, just return a true or false value from the proc.

Actually one other thing I'm unsure about is why you're using an obj as the path checker. You can just use a var that keeps track of what turf the path starts on and where the target is, and then your pathfinding routine can check if there's a path from point A to point B or not.

Lummox JR
In response to Lummox JR
I don't know how to do either of these things, sorry.

EDIT:

I've never really understood the 'return' function (I've read it in help multiple times... -.-) and what do you mean use a pathfind method for the variables of start and end?
In response to Speedro
Speedro wrote:
I've never really understood the 'return' function (I've read it in help multiple times...)

Every proc returns a value that can be used by whatever called it. For instance, the built-in sqrt() proc sends back the square root. If you write a simple proc to add two numbers, you can return the result.

proc/Add(a, b)
return a + b

mob/verb/Test(a as num, b as num)
"[a] + [b] = [Add(a,b)]"


The value that the proc sends back in the return statement is used in the place the proc was called. The . var also works this way; whatever you put into that var is sent back by the proc.

and what do you mean use a pathfind method for the variables of start and end?

Simply put, the pathfinder should not be a physical object you try to move from A to B. All you need is a var that says what turf you started on, another var to say what turf you'll end on, and then use an appropriate pathginding algorithm to get from one to the other. This is a very simple example:

/*
Possible return values:

-1 Arrived at destination (A == B)
0 No path to destination
dir Take a step in this direction
*/

proc/BasicPath(turf/A, turf/B)
if(A == B) return -1 // a value of -1 means we have arrived
if(A.z != B.z) return 0 // no way to form a path
. = get_dir(A, B) // the first step to take
while(A != B)
var/turf/C = get_step(A, get_dir(A,B))
if(C.density) return 0 // there's a wall in the way
A = C // use this as the new starting point


That's a very simplistic pathfinder. BYOND has a better one built in, called get_step_to(), which will send back either a turf for the next step or null. The only major drawback to get_step_to() is its range, which is limited by world.view*2.

There are other pathfinding algorithms out there, but I think they might be a little too advanced for you at the moment. It is crucial that you understand how the return statement works before venturing on. Once you do that, my recommendation would actually be to try out one of the pathfinding libraries already in use, like the one Theodis wrote.

Lummox JR
In response to Lummox JR
So is this how I would check a return value?

                            if(BasicAttackPath(src,m.loc,src.loc)==-1)
damage_process(m)


And why would the return value be -1? Oh, and when I call a proc that uses a return value in a loop, wouldn't the return end the loop? Like so:

proc
that_loop()
for()
sleep()
my_suspicion()
my_suspicion()
if(rand(1,4)==4)
return
Would that end the proc "that_loop"? What if I returned it as true, or -1 (whatever that is!)

Did I check the proc return value correctly in the first piece of code? Is there a better way?

The final thing: .=..(), and .=whatever

What is this dot? I don't understand it. I've had people try to explain it to me before. Could you possibly provide a few examples of how it's used, and describe it to me as if I was an idiot? Thanks for doing so much already, this is all I need :)
In response to Speedro
. is what a proc returns at its end by default.
In response to Metamorphman
Not sure exactly what you mean :/
In response to Speedro
Well, look at it this way, <code>return</code> will return a value, but will end the proc immediately , whereas . is a variable you can set which will not interfere with the proc at all. And at the end of the proc, if return hasn't been called yet, . is returned by the proc.
In response to Metamorphman
Could you use it in an example? There are so many things I could ask about it... I grasp the return function maybe 10%, I grasp the . function probably 6%, and the return values like 2%.. Made up numbers, but it's probably pretty accurate.


For example,

atom
Enter(atom/o)
o.trigger()
..()
atom
proc
trigger()


Why does that not work? I'm calling the parent procedure of Enter. It only works if I use .=..(), although I have absolutely no idea what that means or how to use it.
In response to Speedro
proc/areAligned( list/objects, method = "VERTICALLY" ) 
// This proc checks if a list of objects are aligned with eachother,
// either vertically or horizontally.

. = TRUE // Set the proc to return TRUE by default.

ASSERT( objects.len >= 2 ) // Make sure we have two or more objects to compare.

for( var/x = 2 to objects.len )
var/atom/a1 = objects[x]
var/atom/a2 = objects[x-1]
switch( method )
if( "VERTICALLY" )
if( a1.x != a2.x )
return FALSE // Uh oh, these two objects are not aligned, stop the whole proc and return FALSE!

if( "HORIZONTALLY" )
if( a1.y != a2.y )
return FALSE

else return FALSE // Uh oh, the method provided isn't valid! Stop the proc!"
In response to Speedro
Speedro wrote:
So is this how I would check a return value?

                            if(BasicAttackPath(src,m.loc,src.loc)==-1)
> damage_process(m)

And why would the return value be -1?

That's just a value I chose arbitrarily. The main thing is you need to be able to tell the difference between no-path and already-there states.

Oh, and when I call a proc that uses a return value in a loop, wouldn't the return end the loop? Like so:

proc
> that_loop()
> for()
> sleep()
> my_suspicion()
> my_suspicion()
> if(rand(1,4)==4)
> return
Would that end the proc "that_loop"? What if I returned it as true, or -1 (whatever that is!)

Nope, that won't end the loop. The return statement only ends the proc that it's currently in, not the one that called it.

You can think of every proc in DM by the way as ending with this line:

return .


That's what all procs do on their own.

The final thing: .=..(), and .=whatever

What is this dot? I don't understand it. I've had people try to explain it to me before. Could you possibly provide a few examples of how it's used, and describe it to me as if I was an idiot? Thanks for doing so much already, this is all I need :)

Every proc returns a value at the end; usually that value is null because most procs don't care what they send back. The . var is used to set the default return value. So if you set .=5, then the proc will return a value of 5 unless you tell it to do otherwise.

Lummox JR
In response to Metamorphman
Ok, so this might make sense: How would I utilize the block of code you have provided to check return values?

if(check_alignment returned true)


How would I do what I wrote above? Also, what's the default return value of a procedure you made yourself, true unless otherwise declared false?

Does that mean .=..() means return the default value?

Then why doesn't ..() do that anyways?

Answer these to win the million dollar prize ;)


EDIT: Lummox Jr has answered many of my previous questions; I'm only wondering now how to check the return value?
In response to Speedro
You can do simple boolean checks to see if a variable is true or false, or if a proc returned true or false like so:
 // If hasMagicWand() returns true
world << "OMG IT'S A BOY!"

if( !hasMagicWand() ) // Is hasMagicWand returns false
world << "OMG IT'S A BOY!"


..() has nothing to do with .
.=..() just means that the proc should call its parent proc at the end of execution unless told to return anything else.
In response to Metamorphman
ok, and if I did something like if(!THISISTRUE()), would it run the THISISTRUE() proc? I assume it does.


Thanks for your help guys!
In response to Speedro
It does call the proc.
Thanks for your help guys!
No problem.
In response to Metamorphman
Metamorphman wrote:
.=..() just means that the proc should call its parent proc at the end of execution unless told to return anything else.

Actually, the parent proc is called instantly, and its return value is stored in the variable . It's what you use when the default action of a procedure has a meaningful return value that you want to preserve.
In response to Garthor
Garthor wrote:
Metamorphman wrote:
.=..() just means that the proc should call its parent proc at the end of execution unless told to return anything else.

Actually, the parent proc is called instantly, and its return value is stored in the variable . It's what you use when the default action of a procedure has a meaningful return value that you want to preserve.


Such as procedures like Enter() :D
In response to Speedro
Speedro wrote:
Garthor wrote:
Metamorphman wrote:
.=..() just means that the proc should call its parent proc at the end of execution unless told to return anything else.

Actually, the parent proc is called instantly, and its return value is stored in the variable . It's what you use when the default action of a procedure has a meaningful return value that you want to preserve.

Such as procedures like Enter() :D

Exactly. Enter() really only exists for the sake of returning a value, which is true or false. So if you override Enter(), .=..() means that your override will return the default value, but ..() won't do much good because it will just discard what the original version of Enter() returned.

Very often procs boil down into three categories:

1) Based on the information I give, return a value calculated from it.

2) Perform some kind of action.

3) Perform some kind of action and tell me something about the result, like if it worked or not. I may or may not care about the return value.

Enter() is an example of the first kind of proc; it's supposed to return a true or false value depending on if the atom specified is allowed to enter or not. Bump() and Entered() are the second kind of proc. And then something like SetMedal() would be the third kind, where it does something but it also sends you back information about whether it worked.

Lummox JR