API changes at 2009-01-14

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
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

API changes at 2009-01-14

Post 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.
The only thing necessary for the triumph of evil is for good men to do nothing.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: API changes at 2009-01-14

Post 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.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: API changes at 2009-01-14

Post 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 :).
User avatar
Zutty
Director
Director
Posts: 565
Joined: 22 Jan 2008 16:33

Re: API changes at 2009-01-14

Post 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.
PathZilla - A networking AI - Now with tram support.
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: API changes at 2009-01-14

Post 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);
	}
}
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: API changes at 2009-01-14

Post 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?
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 6 guests