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?