Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Joe on Sat 09/05/2009 13:28:50

Title: Params by reference... is it possible?
Post by: Joe on Sat 09/05/2009 13:28:50
Does AGS let you do something like the known params by reference in C++?

in C++ you can do this:


void Read(int *p, int *c){
*p=GetSomethig();
*c=GetAnotherThing();
}

//And then you call the function like this:

Read(&myInt1, &myInt2);



This is very useful to make a function return more than one value so I'd like to do it in AGS, is it possible?

Thanks.
Title: Re: Params by reference... is it possible?
Post by: monkey0506 on Sat 09/05/2009 13:37:20
Unfortunately this isn't something supported by AGS at this time. There's not really even a comparable workaround. You could possibly define it as a member function of a struct and then reassign the struct members, but other than that you would have to manually assign the global variables.

Edit: Actually another possibility would be to use dynamic arrays. Then instead of global variables myInt1 and myInt2 you could have the array myInt:

int myInt[];

int[] Read() {
  int arr[] = new int[2];
  arr[0] = GetSomething();
  arr[1] = GetAnotherThing();
  return arr;
}

myInt = Read();
Title: Re: Params by reference... is it possible?
Post by: Joe on Fri 15/05/2009 16:59:24
Hmmm interesting... never knew you could do that (int[]) with a function

Thanks monkey.
Title: Re: Params by reference... is it possible?
Post by: monkey0506 on Fri 15/05/2009 20:41:44
Sure thing. Oh and just in case you did ever want to use a struct, you cannot have dynamic arrays as struct members or even import a function that returns a dynamic array into a struct. You can however have a struct extender method return a dynamic array, i.e.:

// script.ash
struct my_type {
  int my_int1;
  int my_int2;
  bool LoadFromArray(int arr[]);
};

import int[] GetArray(this my_type*);

// script.asc
bool LoadFromArray(int arr[]) {
  if (arr == null) return false;
  this.my_int1 = arr[0];
  this.my_int2 = arr[2];
  return true;
}

int[] GetArray(this my_type*) {
  int arr[] = new int[2];
  arr[0] = this.my_int1;
  arr[1] = this.my_int2;
  return arr;
}


With this you could even emulate a copy constructor as well:

my_type my_var1;
my_type my_var2;
int vals[] = new int[2];
vals[0] = 55;
vals[1] = 37;
my_var1.LoadFromArray(vals);
my_var2.LoadFromArray(my_var1.GetArray());


Not strictly the best example, but you get the idea, and it's some food for thought. ;)
Title: Re: Params by reference... is it possible?
Post by: Sephiroth on Sat 16/05/2009 13:22:27
Sorry if I'm wrong but I thought the variable scope would allow you to do something like this to simulate a "return several values":


struct Example {
String Name;
int coord_x;
int coord_y;
};

/* --------------- */

Example ex1;

function ReadStuff()
{
//blabla
ex1.Name    =  char.Name;
ex1.coord_x =  char.X;
ex1.coord_y =  char.Y;
}

ReadStuff();
Display( "My name's %s and I'm standing at X:%d / Y:%d .", ex1.Name,  ex1.coord_x,  ex1.coord_y );



You can modify a global var inside a local scope, so you can return as many values as you want if you simply fill up a struct that contains all the return values you need. Maybe you already know that and just wanted to check if a reference would work, anyways I hope it helps a bit.
Title: Re: Params by reference... is it possible?
Post by: Joe on Sat 16/05/2009 13:39:24
Yeah that's right but it's not a global function, I mean, you cant use it with each "Exaple" you create but only with ex1.

BTW, You don't need to use String.Format in a Display function.
Title: Re: Params by reference... is it possible?
Post by: Sephiroth on Sat 16/05/2009 13:50:44
What if you use ex1 as a global return value like I did and then use this whenever you create another 'example':


Example ex2;

ReadStuff();
ex2 = ex1;

Example ex3;

ReadStuff();
ex3 = ex1;


Would that work?

Edit: Yeah it was cEgo.Say when I wrote it, then I just changed to display, sorry. Btw I'd love to see an update so we could use this instead: Example ex1 = ReadStuff(); heh.
Title: Re: Params by reference... is it possible?
Post by: GarageGothic on Sat 16/05/2009 14:21:09
This is really interesting, I had no idea you return an array. This will make a couple of my functions that return coordinate sets much easier to write, possibly also linebreaking code.
Title: Re: Params by reference... is it possible?
Post by: Sephiroth on Sat 16/05/2009 15:02:54
Actually you 'return' a struct, so it could contain an array of int (e.g for tiles), a string, a bool and anything you define into one var. This is what I'm using for Tileset, Magics, Loots Tables structures in my code. But maybe monkey_05_06 's example is better, depends on the context and needs I think.

-Regards
Title: Re: Params by reference... is it possible?
Post by: monkey0506 on Sat 16/05/2009 17:13:36
GG was actually referencing my code Sephiroth. ;) However, AGS currently doesn't support returning a struct from a function or the "ex2 = ex1" functionality you wrote earlier.

What you could do is use a struct member function like this:

struct Example {
  String Name;
  int coord_x;
  int coord_y;
  import void ReadStuff();
};

void Example::ReadStuff() {
  //blabla
  this.Name = char.Name;
  this.coord_x = char.X;
  this.coord_y = char.Y;
}

Example ex1;

ex1.ReadStuff();
Display("My name's %s and I'm standing at (X:%d, Y:%d).", ex1.Name,  ex1.coord_x,  ex1.coord_y);


Edit: Oh crap, I forgot to update to use the this pointer. Fixed that. Duh, that was the whole point of the member function.

P.S. GG, if you're interested my StringPlus module has several different String-splitting functions that all return a String[]. Feel free to take a look and copy/paste/edit/etc. whatever you like. Oh and on the note of dynamic arrays since there's currently no way of getting the size you'll need to track it separately. You can do this with a simple int variable, however I much prefer to pad the array by one index and store the size in arr[0].
Title: Re: Params by reference... is it possible?
Post by: Sephiroth on Sat 16/05/2009 17:26:30
Yeah right, member function will do, I don't know why we can't assign 2 struct variables of the same type  :-\
Same as passing a custom struct as a parameter I guess, sadly... 

But you could still do:


ex2.coord_x = ex1.coord_x;


Or directly use ex1 as in:

SetPosition();
Draw(ex1.Name, ex1.coord_x, ex1.coord_y);

Wait(100);

SetPosition();
Draw(ex1.Name, ex1.coord_x, ex1.coord_y);



Heh okay I thought he was talking about mine, sorry ;)
Title: Re: Params by reference... is it possible?
Post by: monkey0506 on Sat 16/05/2009 17:41:10
This type of thing has been requested several, several times before and it's always been marked as low-priority for various understandable reasons.

One of the most beneficial changes that could be made in this respect is if we could have pointers to custom structs which would open up whole new doors as far as the possibilities. However as CJ has said before there's one major road block here, specifically with regard to save games and the issue of custom pointer scope.

It's the reason AGS currently has managed types which CJ has specifically and explicitly dealt with. Implementing this would not be a simple change and would require a lot of work on CJ's part modifying several key parts of the compiler (which could inherently produce a lot of issues in itself) as well as the way that save game files are written (again holding the potential to open a huge can of worms).

Sure I'd love to see it happen, but it's no small venture and I think the recent developments Chris has been making very much outweigh the trouble he would have to go through, the time it would take for that feature to be released, the hours of debugging on everyone's part...we'll see it eventually, but for right now we just have to work around it. Honestly it's not that difficult, so it's not that big a deal IMO. ;)
Title: Re: Params by reference... is it possible?
Post by: Sephiroth on Sat 16/05/2009 19:17:38
QuoteOne of the most beneficial changes that could be made in this respect is if we could have pointers to custom structs which would open up whole new doors as far as the possibilities.

Operators support on custom types would help here, but I like how I can get the struct filled as a return value instead of having to deal with arrays and pointers this way I'm not restricted to one type as a return value and each of the function can 'return' a custom struct, in the example I did 'ex1' is a temp buffer to hold the return values, you can save the data it contains into other vars or use it in checks.

The problem is passing it directly as argument but it works as a retrun value holder to me.

-Regards
Title: Re: Params by reference... is it possible?
Post by: GarageGothic on Sat 16/05/2009 19:51:08
Thanks monkey! I was aware of your module, but hadn't taken a closer look at it since I already had my own linebreak code. Now I'll definitely check out how you've set up the String array returns.

My problem was that I wanted to write a linebreaker that returned the first part of the broken String and updated the original String to only contain the remaining text, but as it turned out you can't change the String that the function was called on. This way I could simply return an String[2] array containing both Strings (I'm not interested in breaking the entire String at once because line length may change between lines, and the calling function needs to parse some html like tags that influence the rendering and text width).

Once again, thanks for pointing me in the right direction!