Method
There are two primary methods of detecting argument count in pre-8.1 version, being ascending and descending loop.Obviously,
Descending loop
This is a preferred method of finding number of arguments. Code is as follows:var argc; if (gamemaker_version < 810) { var v, c; c = 15 repeat (16) { v = argument[c] if (is_string(v)) break if (v != 0) break c -= 1 } argc = c + 1 } else argc = argument_count... or a more compact version, if you're going to use if often:
var argc; if (gamemaker_version < 810) { var v; argc = 15; repeat (16) { v = argument[argc]; if (is_string(v)) break; if (v != 0) break; argc -= 1 }; argc += 1 } else argc = argument_countSo, what's going on in there:
- Variable “argc†is defined. This is later to be used instead of argument_count to determine number of arguments.
- An “if†branch follows, depending on GameMaker version. Despite of what one would've thought, version numbers are actually 800 and 810 (no other options - constant has been added in 8.0 and went missing in GameMaker: Studio). For later versions, detection is pretty trivial, being assignment of argument_count to a variable.
- A slightly strangely looking repeat-loop is intended to loop through values [16, 15, 14, ..., 2, 1, 0].
- At each iteration, next argument is pulled by index, and check is performed - if it's either a string (default value for arguments is 0, number) or a non-zero number, program “breaks out of loopâ€.
- Argument number “argc†variable is set to value, one larger than last valid index (if argument[2] was non-zero, there were 3 arguments).
Ascending loop
This is a slightly different method of achieving the same goal. It wins some extra (probably not so meaningful on it's scale) performance at expense of a flaw:var argc; if (gamemaker_version < 810) { var v; argc = 0 repeat (16) { v = argument[argc] if (is_real(v)) if (v == 0) break argc += 1 } } else argc = argument_countIt works similarly to above method, with exception of looping 'upwards' [0, 1, 2, ..., 13, 14, 15], and having slightly different exit condition.
Looping from first argument, it will perform less iterations than first method, if script is given only a few arguments.
It's flaw is, that if a zero argument is passed “in the middle†of argument list, it will stop at that point, thus loosing further arguments.
Though, if it is certain that such conditions will be satisfied, and number of arguments is kept low (e.g. script takes 3-5 strings), this will work faster than descending loop.
Usage
Extra variable
This is method of usage, illustrated in both of examples above. Going this way, you need to replace all occurrences of “argument_count†by “argcâ€. Such can take some time, but is a preferred method.If you are porting a script from version 8.1 to an earlier version, you can as well just replace “argc†by “argument_countâ€, and throw out “else†branch of condition.
And there's even a few ways of doing that, each with it's own pros and cons.
Overriding “instance†variable
After doing replacement, mentioned above, you can as well leave it as-is. This allows to simplify process to copying & pasting code into start of each of affected scripts, at expense of “argument_count†variable “leaking†into instances, and possibly affecting forgotten code that uses it.Global variable
Issue with extra variables in above method can be solved by making variable “argument_count†global. A downside here is, that declaration line will cause an error in >= 8.1, requiring it to be removed manually.Local variable
This method involves declaring “argument_count†as a local variable, “varâ€, and will actually get scripts compatible while still keeping modification process simple. However, a problem comes - alike to global variables, declaration will have to be removed for >= 8.1... except this time it will need to be removed separately in every affected script.Pre-8.0 versions
It may not be obvious, but to work-around the fact that versions, prior to GameMaker 8.0, did not have a gamemaker_version constant, you can just make your own (a constant, or globalvar).Example of usage
As an example of usage, a script, that uses first method to display all given arguments in a message, follows:/// show_values(...values) // Displays a message, listing all given values var argc; if (gamemaker_version < 810) { var v, c; c = 15 repeat (16) { v = argument[c] if (is_string(v)) break if (v != 0) break c -= 1 } argc = c + 1 } else argc = argument_count // if (argc == 0) return show_message('(no values given)') // no arguments var i, r; r = string(argument[0]) // first argument for (i = 1; i < argc; i += 1) { // other arguments r += ', ' + string(argument[i]) } return show_message('[' + r + ']')
Maybe this way? But I don’t know if it’s a good idea…
First we can create a constant with a value that indicates the end of the check:
null (chr(0)+chr(0))
And then, at the beginning of every script that requires argument_count, we put this:
var argument_count, v, c;
c = 0;
repeat (16) {
v = argument[c];
if ( string(v) != null ) { c += 1; }
else
{ break; }
}
argument_count = c;
The tedious thing is that we should place our constant at the end of the script that requires it:
a = script…(34,67,0,”Felicia”,noone,null) //return 5
b = script…(chr(127),0,”Cat”,null) //return 3
c = script…(chr(0),chr(32),2,3,4,5,6,7,8,9,10,11,12,13,14,15) //return 16
d = script…(null) //return 0
That would maybe work, much like passing the argument count number manually
I think at this time the real question would be whether you would really need to support a 10-year-old version of GM for your scripts.
It’s nothing serious, it’s a way to kill time and remember or (exhume) old times. Haha! Thank you for answering!
To differentiate a zero value from an empty argument, you can replace this line:
if (v! = 0) break
, for this one:if (frac (v)) break.
I think…I’m not sure if that would have the desirable effect – frac(x) returns the fractional part of x, and GM evaluates number truth-ness as (x > 0.5) so that condition would yield false for values such as 1.1 (and true for 1.6)