Wierd Squirrel Bug re: array.sort(compare_func)

Discuss the new AI features ("NoAI") introduced into OpenTTD 0.7, allowing you to implement custom AIs, and the new Game Scripts available in OpenTTD 1.2 and higher.

Moderator: OpenTTD Developers

Post Reply
User avatar
Zutty
Director
Director
Posts: 565
Joined: 22 Jan 2008 16:33

Wierd Squirrel Bug re: array.sort(compare_func)

Post by Zutty »

Hi all,

I've discovered a rather odd bug when using array.sort() with a comparison function. If I call an API function from within a comparison function I get the following error...

Code: Select all

dbg: [ai] [1] [S] Your script made an error: parameter 0 has an invalid type 'table' ; expected: 'instance'
For instance the following code will cause this bug. Assume that array contains objects with an id member variable...

Code: Select all

array.sort(function (a,b) {
	local aval = AITown.GetPopulation(a.id);
	local bval = AITown.GetPopulation(b.id);
		
	if(aval > bval) return 1
	else if(aval < bval) return -1
	return 0;
});
This is because when a squirrel function is called it requires a this environment object to work from. It would seem that an object of type table is being used, rather than an object of type instance. I can remedy this with a simple hack, by forcing my own environment object using the call() function...

Code: Select all

array.sort(function (a,b) {
	local aval = AITown.GetPopulation.call(a, a.id);
	local bval = AITown.GetPopulation.call(b, b.id);
	
	if(aval > bval) return 1
	else if(aval < bval) return -1
	return 0;
});
This works perfectly. The objects a and b aren't very smart choices of environment, but at least they are of the right type. Perhaps a fix for this would be to somehow cast the table that is causing this error to type instance, or just to create an instance of a dummy class.

This is in r15379. And yes I know that the above could sort of be done with an AIList valuator, but I need to sort objects not integers. The actual comparison function I'm using is more complex than this. I have just boiled it down to an example that demonstrates the bug neatly.

Just thought you'd like to know. Thanks for your attention. :)

----------------

Edit: by the way, if anyone is scratching their heads like I was, trying to figure out how to sort an array of objects by a variable that is not in scope, squirrel provides a thing called free variables...

Code: Select all

local cargo = ......

array.sort(function (a,b):(cargo) {
	return ...
}
PathZilla - A networking AI - Now with tram support.
jui-feng
Engineer
Engineer
Posts: 35
Joined: 01 Feb 2009 15:20
Location: Germany

Re: Wierd Squirrel Bug re: array.sort(compare_func)

Post by jui-feng »

Ah, free variables! I just passed that in as an extra parameter, but I guess free variables are the better way to go. This is a little off topic, but still: thanks!
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

Re: Wierd Squirrel Bug re: array.sort(compare_func)

Post by TrueBrain »

jui-feng wrote:Ah, free variables! I just passed that in as an extra parameter, but I guess free variables are the better way to go. This is a little off topic, but still: thanks!
In fact, free variables are your worst nightmare ;) Using lambda functions too, btw ;)
The only thing necessary for the triumph of evil is for good men to do nothing.
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

Re: Wierd Squirrel Bug re: array.sort(compare_func)

Post by TrueBrain »

Zutty wrote:Hi all,

I've discovered a rather odd bug when using array.sort() with a comparison function. If I call an API function from within a comparison function I get the following error...

Code: Select all

dbg: [ai] [1] [S] Your script made an error: parameter 0 has an invalid type 'table' ; expected: 'instance'
For instance the following code will cause this bug. Assume that array contains objects with an id member variable...
One of the big design flaws of Squirrel (in my opinion, that is), is that the 'root' scope/class is in fact a 'table', where every other object you create, is an instance. So this happens from time to time. That is why we make you put everything in a class, which makes most calls with an instance .. but clearly this lambda function breaks out and is put in the root scope, with as result that the static function call is done with a table as 'self', instead of a random 'instance'. As the NoAI API is mostly static calls, it really doesn't matter what you give as first param .. it just is a bit silly that you have to worry about it ;)

Maybe Yexo or Rubidium can find a simple way to fix it ;)
The only thing necessary for the triumph of evil is for good men to do nothing.
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Wierd Squirrel Bug re: array.sort(compare_func)

Post by Yexo »

This problem was fixed in r15460.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 20 guests