GML [SOLVED] Passing Scripts/Macros Through as Arguments

I am working on some scripts for terrain generation, and I have some functions which include arguments for a random chance of one instance changing into another instance. For example: "jen_change_change(obj_dirt, obj_sand, 50)" would turn 50% (about) of the dirt into sand.

I was considering the possibility of the ability to add functions, such as sin(), into the argument for percent chance that depend on local variables within the script to create more advanced distributions. Here is the code:
Code:
//Iterate through entire jen_grid
for (var yy = 0; yy < height; yy ++) {
for (var xx = 0; xx < width; xx ++) {
    //If the current value matches, it will change based on a certain chance
    if (jen_grid[# xx, yy] == replace || replace == all)
        {
        //If the chance ends up true (a percentage)
        if (random(100) <= percent_chance)
            {
            jen_grid[# xx, yy] = new_object;
            }
        }
} xx = 0; }
For example, if I could put "(100*sin(xx/10))" in replacement of the variable "percent_chance", I could create a distribution of changed instances that looked like a repeated series of vertical bars. Or "random(random(xx))" which would create a horizontal gradient. This would greatly increase the flexibility of my functions.

I tried doing it with macros, defining a function such as:
Code:
#macro function (100*sin(xx/10))
jen_change_change(obj_dirt, obj_sand, function)
(Please note, I literally learned about macros today because I thought they might work. My understanding is lacking I'm sure).

But the variable "xx" is not able to be pre-defined, as it's a temporary variable (var) to the script, and if I change it to an instance variable, I discovered that this code only runs it once when the variable percent_chance is defined. I have also considered passing script names through as the argument instead, but I don't expect this to be a feature used frequently, and I don't know if it's worth the extra effort to make it possible.

Any feedback on how to make it work with macros or scripts would be appreciated.
 

Paskaler

Member
Macros will take whatever you defined for them, in this case
Code:
(100*sin(xx/10))
Precompute the expression you put in, and, before any other code is compiled everywhere where you used their name, in this case "function", and simply replace it with the value that was computed. This means, you can't use local or instance variables. You can use global variables and resources.

What I recommend doing is something like this:
Code:
///distribution_callback_sin(x)

return (100*sin(argument0/10))
And then call jen_change_change like:
Code:
jen_change_change(obj_dirt, obj_sand, distribution_callback_sin)
You'd have to modify the jen_change_change script a bit:
Code:
//Iterate through entire jen_grid
var callback = argument2;

for (var yy = 0; yy < height; yy ++) {
for (var xx = 0; xx < width; xx ++) {
   //If the current value matches, it will change based on a certain chance
   if (jen_grid[# xx, yy] == replace || replace == all)
       {
       //If the chance ends up true (a percentage)
       if (random(100) <= script_execute(callback, xx))
           {
           jen_grid[# xx, yy] = new_object;
           }
       }
} xx = 0; }
 
Alright, thank you very much. With a little bit of work, I came up with a final system I like. I'll share it here in case anyone else comes looking for this. Basically, I set the function as an optional argument (so that people can just put a number in if they want). Then if that argument is used, the script passes the necessary values stored in an array so they can be one argument.

Here is the relevant parts of the jen_change_chance function:
Code:
var percent_chance = argument[2];
if (argument_count > 3)
    {
    var function = argument[3];
    var has_function = true;
    vars[2] = 0;
    }
else
    {
    var has_function = false;
    }

//Iterate through entire jen_grid
for (var yy = 0; yy < height; yy ++) {
for (var xx = 0; xx < width; xx ++) {
    //If the current value matches, it will change based on a certain chance
    if (jen_grid[# xx, yy] == replace || replace == all)
        {
        //If the chance ends up true (a percentage)
        if (!has_function) { chance = random(100); }
        else
            {
            vars[0] = xx;
            vars[1] = yy;
            vars[2] = percent_chance;
            //Etcetera for other functions with more variables.
            chance = script_execute(function, vars);
            }
     
        if (random(100) <= chance)
            {
            jen_grid[# xx, yy] = new_object;
            }
        }
} xx = 0; }
The array is a little less efficient to code, but it's nicer because I can keep the template (the part other people might actually want to change) to as simple as possible. Example: Only one line is required for every function of this type.
Code:
//Required code. You cannot accept more arguments, they are not incorporated within the jen functions.
var vars = argument0;

//Your own code here
var xx = vars[0];

return 75*sin(xx);
 
Last edited:
Top