Return values help needed.

Podge

Member
Joined
Nov 10, 2019
Messages
61
Hello all,

I have another stupid problem that I can't get past.
Then code below is a simplified version of what I'm tring to do.

In the first working working method I am sending the direction the robot is facing and it is getting sucessfully turned 90 degrees to the left.

I don't know how to get the 2nd bit of code working. I'm getting confused with return values I think.

In the second piece of code I simply want to send the robots x, y co-ords and direction it's facing. I then want to get the return value of x+1/x-1 or y+1/y-1 depending on the facing direction.
Can someone please help me with the syntax/logic of this?

Code:
'------This works the direction is being correctly changed
Method Left:Void()
    Local direction:Int = AI_left(x, y, direction)
End Method

Method AI_left:Int(x:Int, y:Int, direction:Int)
    Select direction
        Case UP
            direction = LEFT
        Case DOWN
            direction = RIGHT
        Case LEFT
            direction = DOWN
        Case RIGHT
            direction = UP
    End Select
    Return 0
End Method



'------I can't figure this bit out
Method forward:Void()
    Local a:Int = AI_forward(x, y, direction)
End Method

Method AI_forward:Int(x:Int, y:Int, direction:Int)
    Select direction
        Case UP
            y = y - 1
        Case DOWN
            y = y + 1
        Case LEFT
            x = x - 1
        Case RIGHT
            x = x + 1
    End Select
    Return 0
End Method
 
Last edited by a moderator:

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
3,281
If the first version works, then only by accident. As both methods only return 0. Nothing else.
You return values via the Return statement or with objects that are give as parameters of a function/method and then changed.
 

Podge

Member
Joined
Nov 10, 2019
Messages
61
If the first version works, then only by accident. As both methods only return 0. Nothing else.
You return values via the Return statement or with objects that are give as parameters of a function/method and then changed.
I think the 1st example works because, 'direction' is a global var and it it changed, so there is no need to return anything.
What I am trying to figure out is how to return two values. Like the second method. I pass x, y and direction and I want an updated return value for the new x,y co-ords.
 

Podge

Member
Joined
Nov 10, 2019
Messages
61
How should the 1st example look if done properly? And do you see what I am trying to do with the second method?
 

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
3,281
Ok, another good example where the question leads then one who tries to answer into the wrong direction as only a portion of a code is shown. Please post a running example next time.

I think the 1st example works because, 'direction' is a global var and it it changed, so there is no need to return anything.

But then the Parameters of AI_left:Int(x:Int, y:Int, direction:Int) make no sense, as you give direction as a parameter and inside the fucntion, this LOCAL parameter called direction is used and not your global var.

I tested it with this code and it prints 1, just like I thought.

Cerberus:
Strict
Global direction:Int=1
Global y:Int=-1
Global x:Int=-1

Enumerate LEFT=1, RIGHT, DOWN, UP


Function Main:Int()


    Left()
    Print direction
    Return 0
End  

'------This works the direction is being correctly changed
Function Left:Void()
    Local direction:Int = AI_left(x, y, direction)
End

Function AI_left:Int(x:Int, y:Int, direction:Int)
    Select direction
        Case UP
            direction = LEFT
        Case DOWN
            direction = RIGHT
        Case LEFT
            direction = DOWN
        Case RIGHT
            direction = UP
    End Select
    Return 0
End



'------I can't figure this bit out
Function forward:Void()
    Local a:Int = AI_forward(x, y, direction)
End

Function AI_forward:Int(x:Int, y:Int, direction:Int)
    Select direction
        Case UP
            y = y - 1
        Case DOWN
            y = y + 1
        Case LEFT
            x = x - 1
        Case RIGHT
            x = x + 1
    End Select
    Return 0
End

I would do it this way, but that also depends on how you really store the values and so on:

Cerberus:
Strict
Enumerate LEFT=1, RIGHT, DOWN, UP
Global direction:Int=LEFT
Global y:Int= 1
Global x:Int=-1



Function Main:Int()

    Print ("Direction= "+direction)
    Left()
    Print ("Direction= "+direction)
    Left()
    Print ("Direction= "+direction)
   
    Print ("x="+x+"  y="+y)
    forward()
    Print ("x="+x+"  y="+y)
    forward()
    Print ("x="+x+"  y="+y)
    Return 0
End  

'------This works the direction is being correctly changed
Function Left:Void()
    AI_left()
End

Function AI_left:Int()
    Select direction
        Case UP
            direction = LEFT
        Case DOWN
            direction = RIGHT
        Case LEFT
            direction = DOWN
        Case RIGHT
            direction = UP
    End Select
    Return 0
End



'------I can't figure this bit out
Function forward:Void()
    Local xy:Int[] = AI_forward(x , y)
    x = xy[0]
    y = xy[0]
End

Function AI_forward:Int[](xp:Int, yp:Int)
    Local retXY:Int[2]
    Select direction
        Case UP
            retXY[1] = y - 1
        Case DOWN
            retXY[1] = y + 1
        Case LEFT
            retXY[0] = x - 1
        Case RIGHT
            retXY[0] = x + 1
    End Select
    Return retXY
End
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
895
@Podge
You've mentioned that you have a global variable defined called direction.
It's not a good idea to use the same variable name for a class field, global or local variable or a function parameter.
It's confusing and prone to causing errors.

Let's try to explain return values with what's going on with just this bit of code you have supplied.
Cerberus:
Method Left:Void()
    Local direction:Int = AI_left(x, y, direction)
End Method
This bit of code is passing the variable direction to the method AI_left and expecting a value back in return. As the method being called is not returning anything other than zero. It's pretty much pointless. If the variable direction is field in the class, then using it as a parameter is pointless as you can access it anywhere from inside the class; unless you want to make a change, but not affect the original in any way. See about the next method.

NOTE: If there is a field in the class with the same name and letter case as a global, then it would be passing the value in the field instead.
The only two ways I know of to get round this, is to use unique variable names, or wrap the global variables inside a class and access them via the scope operator. e.g.
Code:
Class Globals
Global direction:Int=1
End Class

Function Main:Int()
    Print Globals.direction
    Return 0
End

Now for this method
Code:
Method AI_left:Int(x:Int, y:Int, direction:Int)
    Select direction
        Case UP
            direction = LEFT
        Case DOWN
            direction = RIGHT
        Case LEFT
            direction = DOWN
        Case RIGHT
            direction = UP
    End Select
    Return 0
End Method

This is always going to return a value of 0. The parameter direction will be treated as a local variable and have absolutely no affect out side the AI_left method. This is down to only a copy being made of the value passed as the parameter and not the memory location of the variable, so it will not affect the original variable. With class objects, only the reference (aka it's address in memory) is being copied, so any change to that object affects that object directly.

To fix the method, the parameter direction needs to be returned.
Code:
Method AI_left:Int(x:Int, y:Int, direction:Int)
    Select direction
        Case UP
            direction = LEFT
        Case DOWN
            direction = RIGHT
        Case LEFT
            direction = DOWN
        Case RIGHT
            direction = UP
    End Select
    Return direction
End Method
Now you'll get the updated value back where you can assign it back to what ever variable you want.

NOTE: If there is a class field with the same name as a method parameter or local variable, the compiler will not change that field unless you explicitly let it know that you want this by using something like
Code:
Self.direction = LEFT

In the second piece of code I simply want to send the robots x, y co-ords and direction it's facing. I then want to get the return value of x+1/x-1 or y+1/y-1 depending on the facing direction.
Now the problem here depends on how the robots data is defined to start with, if the AI methods are part of the robots own data structure; and how you are going to handle the results.

For a single return value you would still have the problem of figuring out whether the return value is for the X or Y. Not considered the best option with the additional code required.

The first solution, which Mike has posted is to return an array with the two updated values and reassign them back to the X and Y variables.

The second depends on if the robots data is structured in a class and if the AI methods are part of the robots class. If the robot and AI are separate, then the robot should have dedicated public methods to access the X, Y and direction and you would pass the whole object to the AI side where it can read the direction and update the robots X and Y through those dedicated robot methods.
 

Podge

Member
Joined
Nov 10, 2019
Messages
61
Thanks to both of you!
I have a lot to learn. I will spend some time messing around with this until I get it. I really appreciate the help here.
 
Top Bottom