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

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

Post by TrueBrain »

And finally it is there: binaries! You can get them here:

http://nightly.openttd.org/noai/scoreboard.php

It gives you a pretty nice set of API functions. Although you won't be able to do anything fancy with it, you can at least make primitive bus-routes. Soon more and more functions will be added, but this at least should get your on your way. If you detect any problems/errors/bugs, feel free to tell us about it! Have fun writing your own AI :)
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

AI: Clueless

Post by Zuu »

Note: I'm just playing around with the API. This is not meant to be the next big thing.

Posting a shot of my AI, now named Clueless.

Out of 7 AIs four of them make profit, and then we should remember that they all play on the same quite small map with 14 towns of various sizes.

[EDIT: in year 1957 of the same game: 6 of 7 AIs make profit]

Yep, the road-network don't look pretty with several AIs. With the current API it is hard to make use of existing road-networks since you can't tell if two tiles actually are connected with each other by road. Even if two adjacent tiles have road they might not be connected.

The world-information available though the current API:
* Location of towns/cities and their population.
* If a given tile have road on it or not
* If the company can or can not build roads from center to center of tiles.
* If the company can or can not build stations and/or depots on a given tile.


Clueless basically chooses two cities to connect. Build a road-station and a depot in each city. Find a road tile in the border of each town. Connect the border-tiles with an inter-city road. Currently each border-tile is marked with a sign. (for debug purpose) You see there is 56 signs => 56/2 = 28 inter-city-connections.

At some point Clueless will meet the public audience in person (as much as an AI can! :p), but for now he have chosen to only show a picture of himself.


A funny side note, If Clueless find other clueless companies it think that it is not so clueless after all and name himself something less clueless. :p The more other clueless companies he finds, the smarter Clueless think that he is. :D :D
Attachments
scenario.scn
The scenario if someone wants to use it.
(47.09 KiB) Downloaded 248 times
clueless.png
(178.87 KiB) Downloaded 376 times
Last edited by Zuu on 27 Mar 2007 18:45, edited 2 times in total.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Post by Zuu »

I tough I post the VIM syntax file I've made by modifying a copy of the C++ syntax file.

It is just a hack, it is not complete in any sense. I've just added most of the Squirrel keywords to the syntax-file and removed some C++-keywords that are not present in Squirrel.

However there are lot of more stuff to do to if you want all Squirrel language features to be included and highlighted in the correct way. Also lot of C/C++ stuff are highlighted which are not present in Squirrel.


If you want it use it, use it. If you find my hack too much of a hack then you're welcome to make something better.
Attachments
squirrel.vim.txt
Place this file in ~/.vim/syntax/ and remove the .txt-extension.
(1.8 KiB) Downloaded 248 times
filetype.vim.txt
Place this file in ~/.vim/ to make VIM use squirrel.vim automatically on '.not'-files. (remember to remove the .txt extension)
(155 Bytes) Downloaded 229 times
kaan
Route Supervisor
Route Supervisor
Posts: 399
Joined: 02 Apr 2007 20:13
Location: Nørup, Denmark

Post by kaan »

Great work you have done here :)

After just looking things over i had a few ideas, but dont worry, i wont bother you with all of them.

A suggestion for expanding the AIIndustry class:

Static IndustryID getRandomIndustry()
Static IndustryID getRandomIndustry(IndustryType type)
Static IndustryID getIndustryIndex(TileIndex tile)
Static IndustryType getIndustryType(IndustryID id)
Static TileIndex getIndustryTile(IndustryID id)
Static byte getIndustryType(IndustryID id)
Static CargoID[3] getAcceptedCargo(IndustryID id)
Static CargoID[2] getCargoProduced(IndustryID id)
Static byte[2] getLastMonthCargoProduction(IndustryID id)
Static byte[2] getPctTransported(IndustryID id)

This is a result of a brainstorm and maybe some of this is not viable, but most should be pretty straightforward to implement.

-klaus
Rubidium
OpenTTD Developer
OpenTTD Developer
Posts: 3815
Joined: 09 Feb 2006 19:15

Post by Rubidium »

kaan wrote:Static IndustryID getRandomIndustry()
Static IndustryID getIndustryIndex(TileIndex tile)
I agree with those
kaan wrote:Static IndustryID getRandomIndustry(IndustryType type)
Static IndustryType getIndustryType(IndustryID id)
The industry type is an internal value that doesn't mean anything solid once newindustries gets introduced.
kaan wrote:Static TileIndex getIndustryTile(IndustryID id)
Already implemented (GetLocation)
kaan wrote:Static CargoID[3] getAcceptedCargo(IndustryID id)
Static CargoID[2] getCargoProduced(IndustryID id)
I was rather thinking about returning the accepted cargo for a given tile (as that 'merges' it with towns), especially because not all industry tiles accept cargo. However, it makes it harder (for an AI) to determine the types. I'm rather thinking about adding bool industry.Cargo[Produced|Accepted](CargoID) to make iterating industries a little easier, i.e. simplifying AIs that want to check for a single cargo type.
kaan wrote:Static byte[2] getLastMonthCargoProduction(IndustryID id)
Static byte[2] getPctTransported(IndustryID id)
The same problem as with the previous one exists, however this might be more troublesome as you need to know the cargo types to get any usefull information... I'm not really sure what to do with these functions.
kaan
Route Supervisor
Route Supervisor
Posts: 399
Joined: 02 Apr 2007 20:13
Location: Nørup, Denmark

Post by kaan »

Rubidium wrote:
kaan wrote:Static IndustryID getRandomIndustry()
Static IndustryID getIndustryIndex(TileIndex tile)
I agree with those
Great :)
Rubidium wrote:
kaan wrote:Static IndustryID getRandomIndustry(IndustryType type)
Static IndustryType getIndustryType(IndustryID id)
The industry type is an internal value that doesn't mean anything solid once newindustries gets introduced.
No reason to do this then. Alternatly we could define our own industrytype but it is hardly worth the trouble.
Rubidium wrote:
kaan wrote:Static TileIndex getIndustryTile(IndustryID id)
Already implemented (GetLocation)
There is no arguing with that ;)
Rubidium wrote:
kaan wrote:Static CargoID[3] getAcceptedCargo(IndustryID id)
Static CargoID[2] getCargoProduced(IndustryID id)
I was rather thinking about returning the accepted cargo for a given tile (as that 'merges' it with towns), especially because not all industry tiles accept cargo. However, it makes it harder (for an AI) to determine the types. I'm rather thinking about adding bool industry.Cargo[Produced|Accepted](CargoID) to make iterating industries a little easier, i.e. simplifying AIs that want to check for a single cargo type.
a bool would be usefull for iterating for a match among many industries, but if you want to exploit a specific industry it really makes no sence to iterate through all cargotypes (twice) just to obtain accepts/produces.
Rubidium wrote:
kaan wrote:Static byte[2] getLastMonthCargoProduction(IndustryID id)
Static byte[2] getPctTransported(IndustryID id)
The same problem as with the previous one exists, however this might be more troublesome as you need to know the cargo types to get any usefull information... I'm not really sure what to do with these functions.
I think a well formatted struct would be a good solution to these kinds of information.
The reason i picked this format was that i lifted it from the industry struct in industry.h

Code: Select all

/**
 * Defines the internal data of a functionnal industry
 */
struct Industry {
	TileIndex xy;                   ///< coordinates of the primary tile the industry is built one
	byte width;
	byte height;
	const Town* town;               ///< Nearest town
	CargoID produced_cargo[2];      ///< 2 production cargo slots
	uint16 cargo_waiting[2];        ///< amount of cargo produced per cargo
	byte production_rate[2];        ///< production rate for each cargo
	CargoID accepts_cargo[3];       ///< 3 input cargo slots
	byte prod_level;                ///< general production level
	uint16 last_mo_production[2];   ///< stats of last month production per cargo
	uint16 last_mo_transported[2];  ///< stats of last month transport per cargo
	byte pct_transported[2];        ///< percentage transported per cargo
	uint16 total_production[2];     ///< total units produced per cargo
	uint16 total_transported[2];    ///< total units transported per cargo
	uint16 counter;                 ///< used for animation and/or production (if available cargo)

	byte type;                      ///< type of industry. see IT_COAL_MINE and others
	OwnerByte owner;                ///< owner of the industry.  Which SHOULD always be (imho) OWNER_NONE
	byte random_color;              ///< randomized colour of the industry, for display purpose
	Year last_prod_year;            ///< last year of production
	byte was_cargo_delivered;       ///< flag that indicate this has been the closest industry chosen for cargo delivery by a station. see DeliverGoodsToIndustry

	IndustryID index;               ///< index of the industry in the pool of industries
};
It is not documented but im guessing that the way to tell what cargotype is in byte pct_transported[2] is by using the same index in CargoID produced_cargo[2].

Thanks for commenting :)
-klaus
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

Console

Post by griffin71 »

Hello,

I've tried to run the example AI that comes with the binary. But it does not seem to do anything. A new company is indeed started, called NoAI. So that works.
I do not see any output from it. I'd expect this to go to the console, but I have noticed no output there. So where are its messages printed instead?
I'm 100% assured it runs; I forgot to sleep(1), and the game hung in an infinite while loop in main.nut. After I added it, it did not hang (had to restart the game in this case, of couse).

Is there a way to obtain information about the AI through the
console?

Is there a manual or wiki for the console?

Is there a list with API functions, and their functioning? Of course, I found the functions as used in regression.nut, but as I do not see where the output goes, it's kinda blind programming like this.

Anyway, the whole idea of this is simply marvellous!
A game worth playing is a game worth modding :-)
User avatar
glx
OpenTTD Developer
OpenTTD Developer
Posts: 622
Joined: 02 Dec 2005 15:43
Location: Drancy(93) - France
Contact:

Post by glx »

run "openttd -d" to see the output
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Post by Zuu »

Unless things have changed the last week you need to watch the terminal-window, not the in-game console. If you start openTTD using other means than a terminal-window, I'm afraid you need to start openTTD via a terminal window to receive the output.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

Post by griffin71 »

Thanks, Zuu and glx!

I got it running, and I now have an AI intelligent enough to print the tick value every 1000 ticks :-)

I noticed some unexpected behaviour though: contrary to what I had expected, squirrel also inteprets files that are not named main.nut. Actually, it does not even seem to need the extension .nut. It seems to me that it looks into each subdirectory of ai for an intepretable file....
So, which files does squirrel consider when it chooses an AI?

Is it going to be possible in the future that (for debugging purposes) the user can restart or stop an AI?
TrueBrain
OpenTTD Developer
OpenTTD Developer
Posts: 1370
Joined: 31 May 2004 09:21

Post by TrueBrain »

griffin71 wrote:Thanks, Zuu and glx!

I got it running, and I now have an AI intelligent enough to print the tick value every 1000 ticks :-)

I noticed some unexpected behaviour though: contrary to what I had expected, squirrel also inteprets files that are not named main.nut. Actually, it does not even seem to need the extension .nut. It seems to me that it looks into each subdirectory of ai for an intepretable file....
So, which files does squirrel consider when it chooses an AI?

Is it going to be possible in the future that (for debugging purposes) the user can restart or stop an AI?
OpenTTD scans the ai/ dir for files called 'main.nut' and opens them. It doesn't check for any other file, it doesn't try to open any file, 'main.nut' is the only thing it does. Even more: it needs to be in the FIRST subdir of ai/. So if you think it loads an AI even if you don't have a main.nut, I would suggest to look really close once more :)

In the future there will be a GUI to control several aspects of an AI, one being the debug-information of an AI, the other being able to configure which AI to start. But all this in the future.
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

still confused...

Post by griffin71 »

TrueLight wrote:OpenTTD scans the ai/ dir for files called 'main.nut' and opens them. It doesn't check for any other file, it doesn't try to open any file, 'main.nut' is the only thing it does. Even more: it needs to be in the FIRST subdir of ai/. So if you think it loads an AI even if you don't have a main.nut, I would suggest to look really close once more :)
Thanks for your respons in the first place. After spending 3 more hours on this, I conclude, that it seems that no other files are being interpreted; my earlier observations were due to the faulty assumption that which AIs are present is determined when a new game is started, but this is done when openttd is started. The main.nut files are (re-)read when a new AI is started in-game. Correct?
However, without that there is another AI main.nut present, sometimes, there seems to be a default AI called NoAI that gives massive output like
[terminal]
NoAI Transport has loaned 90000
NoAI 525425600 Transport has loaned 80000
Town Prinnton [11 of 25] at (73, 201) with 733 inhabitants
[/terminal]
For sake of clarity, I have added my current ai directory that shows this behaviour.
In the future there will be a GUI to control several aspects of an AI, one being the debug-information of an AI, the other being able to configure which AI to start. But all this in the future.
Sounds great!
Attachments
ai.rar
Does this contain an AI called NoAI?
(95.39 KiB) Downloaded 217 times
A game worth playing is a game worth modding :-)
User avatar
glx
OpenTTD Developer
OpenTTD Developer
Posts: 622
Joined: 02 Dec 2005 15:43
Location: Drancy(93) - France
Contact:

Post by glx »

NoAI is a c++ AI :)
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

Post by griffin71 »

glx wrote:NoAI is a c++ AI :)
glx, you can smile about that, but how do I get rid of it? Since there is no sourcefile available, I cannot recompile without NoAI active?
Or am I making a major stupid remark? (could be, of course, I'm still new on this forum....)
A game worth playing is a game worth modding :-)
User avatar
glx
OpenTTD Developer
OpenTTD Developer
Posts: 622
Joined: 02 Dec 2005 15:43
Location: Drancy(93) - France
Contact:

Post by glx »

For now the only way to disable it is to comment a line in openttd source and recompile it. But as TrueLight said, there will be a GUI to control that later.
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

Post by griffin71 »

I would still need the API sourcefiles to compile, but they are not in the nightlies.... :?
You're quite mystifying...
A game worth playing is a game worth modding :-)
User avatar
XeryusTC
Tycoon
Tycoon
Posts: 15415
Joined: 02 May 2005 11:05
Skype: XeryusTC
Location: localhost

Post by XeryusTC »

[url]svn://svn.openttd.org/branches/noai/[/url]
Don't panic - My YouTube channel - Follow me on twitter (@XeryusTC) - Play Tribes: Ascend - Tired of Dropbox? Try SpiderOak (use this link and we both get 1GB extra space)
Image
OpenTTD: manual #openttdcoop: blog | wiki | public server | NewGRF pack | DevZone
Image Image Image Image Image Image Image
griffin71
Traffic Manager
Traffic Manager
Posts: 142
Joined: 31 Mar 2007 13:11
Location: Amsterdam

Post by griffin71 »

Ah!
Great!
8)
User avatar
glx
OpenTTD Developer
OpenTTD Developer
Posts: 622
Joined: 02 Dec 2005 15:43
Location: Drancy(93) - France
Contact:

Post by glx »

the source is also available there, along with binaries for all platforms (same as nightlies)
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Post by Zuu »

griffin71 wrote:
glx wrote:NoAI is a c++ AI :)
glx, you can smile about that, but how do I get rid of it? Since there is no sourcefile available, I cannot recompile without NoAI active?
Or am I making a major stupid remark? (could be, of course, I'm still new on this forum....)
There is a command line option (-a "ai name") to specify one AI that openTTD will use so that you don't have to wait untill the randomness starts your AI. (by default openTTD starts a random AI when an AI-company is started).

for example I start my AI by

Code: Select all

./openttd -a "Clueless" -g "ai/Clueless/scenario.scn"
The -g option selects my test-scenario so that the same map is used each time. In this scenario I've turned of build on slopes and have set other important switches too.

EDIT: I guess you wanted to remove NoAI so that you're AI become the only AI because of the issue described above. If your reasons are other, I'm sorry I've misinterpreted you.
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 40 guests