NoAI Branch - An AI Framework

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

Locked
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

Post by TrueBrain »

griffin71 wrote:
TrueLight wrote:For now I think it is more important that we make tools that allow you to make good road-based AIs :)
Sure thing, TrueLight.
Eager to start writing an AI, I face the problem of debugging the squirrel script. I often get runtimes like

Code: Select all

dbg: [misc] Your script made an error: the index '0' does not exist
Is there any way to get the linenumber displayed where that error occurs? That would be an enormous help.
In the latest SVN that is already fixed. Did you use the latest binaries?
The only thing necessary for the triumph of evil is for good men to do nothing.
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

Post by griffin71 »

I still used 9570, because I added some functions in the API. I'll port them to the latest SVN, and then post a diff file too.

Thanks!
A game worth playing is a game worth modding :-)
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

townfunctions

Post by griffin71 »

The attached diff file adds the following functions to the town class of the API:

Code: Select all

uint32 GetMaxPass(TownID town_id); 
uint32 GetMaxMail(TownID town_id); 
uint32 GetNewMaxPass(TownID town_id); 
uint32 GetNewMaxMail(TownID town_id); 
uint32 GetActPass(TownID town_id); 
uint32 GetActMail(TownID town_id); 
uint32 GetNewActPass(TownID town_id); 
uint32 GetNewActMail(TownID town_id); 
byte GetPctPassTransported(TownID town_id); 
byte GetPctMailTransported(TownID town_id);
I'd be most happy if these could be added to the development branch.
Attachments
MSV_AI_r9629_02.diff
extra town API functions r9629
(4.67 KiB) Downloaded 162 times
A game worth playing is a game worth modding :-)
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

bugreport r9629

Post by griffin71 »

Dear developers,

I noticed the following bug -- after the function AICompany::SetCompanyName has been successfully called, the current tick is finished. So, openttd behaves as if after calling AICompany::SetCompanyName, sleep(1) were called.
The impact of this is very low, but it has confused me for some time, before I found this. :?
A game worth playing is a game worth modding :-)
Rubidium
OpenTTD Developer
OpenTTD Developer
Posts: 3815
Joined: 09 Feb 2006 19:15

Re: bugreport r9629

Post by Rubidium »

griffin71 wrote:after the function AICompany::SetCompanyName has been successfully called, the current tick is finished
This is by design. We can only tell whether the function worked correctly once it is actually executed. In a single player game that would be instantanious, but for multi player games it will take a few ticks. Therefor we chose to make it wait at least one tick for every function that actually changes something in the game state.

The advantage of this approach is that you always know whether the command actually succeeded. It futhermore makes it easier to develop an AI for multi player games as the single player game behaves almost exactly the same.
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

Post by TrueBrain »

So short to say: never rely on the tick counter. It isn't there to be used like that. It is just as indication of where you are in the game :) Many commands hold the ticker for a while, and the more advanced functions we design, the longer it will be.

This also gives a fairness to the game. AIs just can't build all at once, it is a slow process, even for them :) Anyway, I see this is documented correctly yet, so I will make it more clear on the wiki :)
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

Post by TrueBrain »

And finally tilelist and townlist are there. Industrylist should be added soon, and valuators for it too. Also soon there will be wiki-pages about them, explaining their design :) I hope you all like it ;) I personally find it very useful! See the regression-test for now to see how it works :)
The only thing necessary for the triumph of evil is for good men to do nothing.
Finaldeath
Engineer
Engineer
Posts: 72
Joined: 09 Apr 2006 23:49
Location: UK
Contact:

Post by Finaldeath »

Totally passed me by that -a flag, will possibly have a look at it earlier then I thought.

That is, if I can get to grips with it. Looking good so far, pretty simple and whatnot to start with. I have some good ideas on making some industry things AI's can cope with, would be nice to have a go.

I'd be interested in testing AI's being developed/the new AI code too when I get some time to spare.
Finaldeath
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Post by Zuu »

Finaldeath wrote:Totally passed me by that -a flag, will possibly have a look at it earlier then I thought.

That is, if I can get to grips with it. Looking good so far, pretty simple and whatnot to start with. I have some good ideas on making some industry things AI's can cope with, would be nice to have a go.

I'd be interested in testing AI's being developed/the new AI code too when I get some time to spare.
Unless things have changed the existence of the "-a"-flag is not documented in --help, though the available AIs and their identifiers are listed in --help. Also unless things have changed "-a" is not very good documented elsewhere. (no criticism against anyone, just a statement)
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

Post by TrueBrain »

Zuu wrote:(..)

Unless things have changed the existence of the "-a"-flag is not documented in --help, though the available AIs and their identifiers are listed in --help. Also unless things have changed "-a" is not very good documented elsewhere. (no criticism against anyone, just a statement)
Nah, it is criticism, and you are 100% right :) It should be documented! My job for tomorrow will be exactly this: document the behavior of NoAI in more detail :) If you have any suggestions about what should be documented, feel free to tell us, or to just add it to the wiki :)

Ps: -a is documented in --help
Pps: a program, or in this case a branch, is only as good as his documentation :)
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

Post by Zuu »

TrueLight:
I would suggest a page on the wiki with common pitfalls of SQ. I'm aware of some things that can lead to hard too track errors which would be good if we can document, even if it is not a part of the NoAI-API.

Or just keep in mind that we will have a such page, when someone creates it. (Maybe place links to this yet too create page, when you work with the wiki-pages.)
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
kaan
Route Supervisor
Route Supervisor
Posts: 399
Joined: 02 Apr 2007 20:13
Location: Nørup, Denmark

Post by kaan »

Suggestion:

How about putting the API in a namespace?
it would make life much easyer to only need to reference a namespace :)

using namespace NoAIAPI; (better name might be needed though ;) )
kaan
Route Supervisor
Route Supervisor
Posts: 399
Joined: 02 Apr 2007 20:13
Location: Nørup, Denmark

Post by kaan »

Code: Select all

/**
 * class to control the buildmode of the AI.
 * This class is a singelton class that handles the 3 buildmodes
 * For this a statemachine is used. There are currently 3 states to choose from.
 * This is a hack that has never been compiled, its only purpose is to be an 
 * inspiration to the dev team. The goal is to propose using a state machine to 
 * handle the different build states. This pseudoimplementation is nowhere near 
 * beeing the best solution to using a state machine in the api. The current 
 * wrapper form has been choosen to illustrate the state machine function in 
 * relation to the existing code.
 * Any code i wrote in here can be freely used by anyone (as opposed to the code 
 * i have stolen).
 * Klaus Kaan
 */
Attachments
ai_build_statemachine.zip
(2.17 KiB) Downloaded 151 times
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

Post by TrueBrain »

kaan wrote:

Code: Select all

/**
 * class to control the buildmode of the AI.
 * This class is a singelton class that handles the 3 buildmodes
 * For this a statemachine is used. There are currently 3 states to choose from.
 * This is a hack that has never been compiled, its only purpose is to be an 
 * inspiration to the dev team. The goal is to propose using a state machine to 
 * handle the different build states. This pseudoimplementation is nowhere near 
 * beeing the best solution to using a state machine in the api. The current 
 * wrapper form has been choosen to illustrate the state machine function in 
 * relation to the existing code.
 * Any code i wrote in here can be freely used by anyone (as opposed to the code 
 * i have stolen).
 * Klaus Kaan
 */
We in fact talked about taking this road you draw, or the current one, while designing. We favor the current way over this way, as the current way is much more flexible. I understand the need for a simple 'set' to switch between modes, but when creating an AI it is found much more easier to use instances to switch between modes, mostly because you fall back to the current mode rather automatically. In implementations we did before NoAI, we in fact took the way you draw, and was found rather annoying to use. An example of why this is useful:

AIExecMode e;
{
AITestMode t;
<do test stuff here>
}
<build stuff here>

This is much more safe :) Also, in your case, you really want a pop and push to walk between modes. The current implementation solves that all :)

I hope this clears it up a bit :)
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

Post by TrueBrain »

As promised: http://wiki.openttd.org/index.php/AI:Need_To_Know
If I missed anything you find important, feel free to add or to tell me.
Zuu wrote:TrueLight:
I would suggest a page on the wiki with common pitfalls of SQ. I'm aware of some things that can lead to hard too track errors which would be good if we can document, even if it is not a part of the NoAI-API.

Or just keep in mind that we will have a such page, when someone creates it. (Maybe place links to this yet too create page, when you work with the wiki-pages.)
I have created such a page, please do fill it with things you are aware of:

http://wiki.openttd.org/index.php/AI:SQ_pitfalls
The only thing necessary for the triumph of evil is for good men to do nothing.
kaan
Route Supervisor
Route Supervisor
Posts: 399
Joined: 02 Apr 2007 20:13
Location: Nørup, Denmark

Post by kaan »

TrueLight wrote:
We in fact talked about taking this road you draw, or the current one, while designing. We favor the current way over this way, as the current way is much more flexible. I understand the need for a simple 'set' to switch between modes, but when creating an AI it is found much more easier to use instances to switch between modes, mostly because you fall back to the current mode rather automatically. In implementations we did before NoAI, we in fact took the way you draw, and was found rather annoying to use. An example of why this is useful:

AIExecMode e;
{
AITestMode t;
<do test stuff here>
}
<build stuff here>

This is much more safe :) Also, in your case, you really want a pop and push to walk between modes. The current implementation solves that all :)

I hope this clears it up a bit :)
You have me convinced :D
The last bit i did on this mockup was to implement the transaction functions and somehow they didnt fit in there. I have been giving this quite a bit of thought and i have come to the conclusion that it is because the transaction isnt really a state for building but rather a clever use of the test and exec states. So that leaves us with the transaction class fully justified in my little world ;)
Right then, about those two states that are classes:
Pro:
They get the job done.
Inexperienced programmers will find it easy to understand how they are used.
They are flexible.

Con:
They are ugly
They take up too much space in the api documentation
Inexperienced programmers might f**k it up good.
They make it easy to make bad programming.

These 4 issues are however, very minor. The first one is purely a matter of my personal taste. The second is where im hard pressed to accept it, but everything has its ups and downs. The third doesnt matter because these days ram is plentyfull in every computer. The last one? ... well, bad programming is going to happen. I just have to cope with that ;)

Thank you for the explanation truelight :)
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

Post by griffin71 »

TrueLight wrote:As promised: http://wiki.openttd.org/index.php/AI:Need_To_Know
If I missed anything you find important, feel free to add or to tell me.
Great! This clarifies a lot. It's good those things you have posted here and there are now to be found at a locigal place.

Question: Is there anybody who can explain to me the proper use of classes? I'm new when it comes to object oriented programming, so my code is basically just C-style with an object oriented flavour, as the language compells me. The squirrel reference manual merely describes how classes are manipulated, but not what they are conceptually about.
Thanks aforehand.
A game worth playing is a game worth modding :-)
kaan
Route Supervisor
Route Supervisor
Posts: 399
Joined: 02 Apr 2007 20:13
Location: Nørup, Denmark

Post by kaan »

griffin71 wrote:
TrueLight wrote:As promised: http://wiki.openttd.org/index.php/AI:Need_To_Know
If I missed anything you find important, feel free to add or to tell me.
Great! This clarifies a lot. It's good those things you have posted here and there are now to be found at a locigal place.

Question: Is there anybody who can explain to me the proper use of classes? I'm new when it comes to object oriented programming, so my code is basically just C-style with an object oriented flavour, as the language compells me. The squirrel reference manual merely describes how classes are manipulated, but not what they are conceptually about.
Thanks aforehand.
Well, basicly a class is just a struct with functions in it.
The idea is that you put things that is logically related into a class.
For example you could choose to make a town class for ottd. It would contain some variables that would act as properties (like name and location, population and such) and some functions to interact with the town from other classes. It would the be logical to make a new class instance for each town in the game and put them in a container class (a class that knows about all the objects it contain) and give the container class some functions that other classes can use when they need to interact with all the town objects, like searching for towns with a population > 1000 or what else might be needed to iterate over all the townobjects.
So the town class is a blueprint for how towns are and an instance of the town class is an object that represents a specific town and can answer questions about its name etc.

If you findt this a bit strange then rest assured that you dont have to use one bit of it to make a perfectly good ai in this framework :)

This might not be the best explanation, but i hope its usefull anyway.
-klaus
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

container class

Post by griffin71 »

Thank you, Kaan.
You have invoked a follow-up question, because how do you make a container class?
Continuing with the example you give, suppose I have a town defined the following class,

Code: Select all

class TOWNCLASS {
	simpletown = null;
	simpletowntable = null;
	maxtownid = null;

	constructor() {
		simpletown = { location=0 name="" inhabitants=0};
		simpletowntable = [];
		maxtownid = 0; // max town id; id's below this one could still be empty
	}

	function GetNumTowns();
	function GetTown(TownId);
	function NewTown(location, name, inhabitants);
}

function TOWNCLASS::GetNumTowns() {
	return(this.simpletowntable.len());
}

function TOWNCLASS::GetTown(TownId) {
	if (simpletowntable.len()<=TownId) {
				return(null);
			}
	return(simpletowntable[TownId]);
}

function TOWNCLASS::NewTown(_location, _name, _inhabitants) {
	this.simpletowntable.extend(["some value"]); //(this.simpletown);
	this.simpletowntable[this.maxtownid]={
			name=_name, location=_location, inhabitants=_inhabitants};
	this.maxtownid++;
	return(this.maxtownid-1);
}
and a function test, to test it:

Code: Select all

function Test() {
/* Tester for TOWNCLASS */
	local townclassInst = TOWNCLASS();
	print ("Adding town1");
	local NewId;
	NewId=townclassInst.NewTown(1250, "Town1", 499);
	print ("Num towns: "+townclassInst.GetNumTowns());
	print ("Pop town "+NewId+" : "+townclassInst.GetTown(NewId).inhabitants);
}
This way, it's merely the TOWNCLASS itself that holds all the instances of towns, rather than that each town is represented by an instance of that class.
So I still feel I miss something essential about classes, especially about container classes. Maybe, you could shed some more light on this.
(I agree this is getting a bit off-topic (though still AI related through squirrel).)
Last edited by griffin71 on 19 Apr 2007 22:50, edited 1 time in total.
A game worth playing is a game worth modding :-)
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Post by Zuu »

Note: From my experiens you must use a constructor to set all variables or evil things might happen.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Locked

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 5 guests