Page 1 of 1

API changes at 2009-01-14

Posted: 14 Jan 2009 18:31
by TrueBrain
Sorry, yet an other API change. Well, not so much of a change, more a bug fix, but something you as AI writer might want to know about:

Valuators can no longer execute DoCommands, not even indirectly. This because we removed the need for threads (which removed a lot of bugs (read: race-conditions)). In the future we might revisit this, and reintroduce DoCommands in Valuators, but it is a hard thing to add. So for now I suggest everyone who uses it (which in fact is a bit abusing of Valuator functions), to make a simple loop around their list and execute it outside that loop (which still works perfectly).

Any questions or problems related to this issue, let me know here.

Re: API changes at 2009-01-14

Posted: 14 Jan 2009 19:10
by Zuu
A workaround is to implement the Valuate function in Squirrel like this:

Code: Select all

function MyValuate(list, valuator)
{
	for(local item = list.Begin(); list.HasNext(); item = list.Next())
	{
		list.SetValue(item, valuator(item));
	}
}
Then call it like this:

Code: Select all

MyValuate(my_list, MyValuatorFunction);
In your MyValuatorFunction you can now call functions that result in DoCommands such as AISign.BuildSign(..) for debuging etc.

Re: API changes at 2009-01-14

Posted: 15 Jan 2009 20:17
by Yexo
And here is my version:

Code: Select all

function Utils_Valuator::Valuate(list, valuator, ...)
{
	assert(typeof(list) == "instance");
	assert(typeof(valuator) == "function");

	for(local item = list.Begin(); list.HasNext(); item = list.Next()) {
		local value = null;
		switch (vargc) {
			case 0: value = valuator(item); break;
			case 1: value = valuator(item, vargv[0]); break;
			case 2: value = valuator(item, vargv[0], vargv[1]); break;
			case 3: value = valuator(item, vargv[0], vargv[1], vargv[2]); break;
			case 4: value = valuator(item, vargv[0], vargv[1], vargv[2], vargv[3]); break;
			default: assert(0);
		}
		if (typeof(value) == "bool") {
			value = value ? 1 : 0;
		} else if (typeof(value) != "integer") {
			throw("Invalid return type from valuator");
		}
		list.SetValue(item, value);
	}
}
It also accepts extra parameter that'll be given to the valuator function, just like AIAbstractList::Valuate does. Currently it's limited to 4 extra parameters, but it's easy to extend that to a higher value :).

Re: API changes at 2009-01-14

Posted: 15 Jan 2009 20:46
by Zutty
Yexo wrote:And here is my version:
You could make a more generic version using Squirrel's higher order function capabilities. I also happen to like foreach!

Code: Select all

function Utils_Valuator::Valuate(list, valuator, ...)
{
	assert(typeof(list) == "instance");
	assert(typeof(valuator) == "function");

	foreach(item, _ in list) {
		local args = [item];

		for(local c = 0; c < vargc; c++) {
			args.append(vargv[c]);
		}

		local value = valuator.acall(args);

		if (typeof(value) == "bool") {
			value = value ? 1 : 0;
		} else if (typeof(value) != "integer") {
			throw("Invalid return type from valuator");
		}
		list.SetValue(item, value);
	}
}
Edit: Oops. Fixed a little mistake in foreach.

Re: API changes at 2009-01-14

Posted: 15 Jan 2009 21:02
by Yexo
Nice Zutty :) I didn't know about acall.

Edit: Your function didn't work (you also need to pass 'this' to the function). This one does:

Code: Select all

function Utils_Valuator::Valuate(list, valuator, ...)
{
	assert(typeof(list) == "instance");
	assert(typeof(valuator) == "function");
	
	local args = [this, null];
	
	for(local c = 0; c < vargc; c++) {
		args.append(vargv[c]);
	}

	foreach(item, _ in list) {
		args[1] = item;
		local value = valuator.acall(args);
		if (typeof(value) == "bool") {
			value = value ? 1 : 0;
		} else if (typeof(value) != "integer") {
			throw("Invalid return type from valuator");
		}
		list.SetValue(item, value);
	}
}

Re: API changes at 2009-01-14

Posted: 17 Mar 2009 12:09
by Zuu
Yexo: The crash I was talking about some time ago: Whenever I use your Valuate function with functions that execute a do-command, OpenTTD crashes. (as opposed to commands that run in test-mode)

Does this happen to you?