NoAI API requests

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
Xycor
Engineer
Engineer
Posts: 29
Joined: 17 Mar 2014 01:28

NoAI API requests

Post by Xycor »

After writing my first AI there are several functions which would be very helpful. Do I add them myself and hope they are accepted as a patch? Is there a procedure to make acceptance more likely? Do any experts have any insight into how difficult they would be to add? Any current developers willing to take some on?

AICargoList_StationProducing
This is the missing counterpart to the already existing AICargoList_StationAccepting function. Currently superlib implements this function by iterating through tiles around the station. However the process is very time consuming and ideally my AI should respond between the point where a vehicle enters and leaves a station.

AIMap.TravelDistance(tile, tile, AITile::TransportType)
Returns the travel distance between two tiles using only the specified road type. Returns -1 (or other appropriate failure value) if journey is not possible.

AIVehicle.EstimatedTravelTime(vehicle, tile)
Returns the number of ticks a vehicle will require to reach the specified tile. May not be needed if Travel distance is known. I was thinking of the case of needing to take elevation change into account for travel time along a path.

AIStation.PredictedStockpile(cargo_type, ticks_in_future)
I am having a hard time predicting how much cargo will be at a station at some point in the future. If there is a way to translate LastMonthsProduction into ticks that may be something I can do myself.

AIIndustry.ProductionPerTick(cargo_type)
It may be possible to translate last months production into ticks, but going to a uniform time constant seems reasonable.

AIIndustryList_AtStation
Returns the list of industries within a station's area.

Any insight is appreciated, Thanks
Last edited by Xycor on 10 Apr 2014 17:01, edited 1 time in total.
R2dical
Traffic Manager
Traffic Manager
Posts: 163
Joined: 18 Mar 2013 22:22

Re: NoAPI requests

Post by R2dical »

Xycor wrote:AIMap.TravelDistance(tile, tile, AITile::TransportType)
AIVehicle.EstimatedTravelTime(vehicle, tile)
I remember a old post asking for API access to the games pathfinders (basically what you are asking for), and a Dev replied saying this will not be implemented (can't recall the exact reason but it was an understandable one). SuperLib has a function to check for an existing road, but its limited in the length it searches for. Coincidentally I have been working on AI pathfinders to do various things and have flagged a way to do a fast, decent A* search for existing roads/rails. Start a new thread if you wish to discuss this further :)
Xycor wrote:AIIndustryList_AtStation
I asked some similar questions here.
krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: NoAPI requests

Post by krinn »

AICargoList_StationProducing
if you want cargo produce at that station :
foreach (crg, _ in AICargoList) { if (AIStation.HasCargoRating(stationID, crg) stationproducing.push(crg); }

if you want industry producing cargo at that station (including cargos you aren't already handling): check every tiles within catchment area for production.

AIMap.TravelDistance(tile, tile, AITile::TransportType)
This will never appears, noai api doesn't provide interface with openttd pathfinding, and the reason would just be because while it's "easy" for A* to travel x->y using a road type it's a pain with less strict conditions (using a road, you follow it, you're not trying to avoid object in the way). Without even an optimize algo and rought walking the path, the solve is nearly instant.
If they do that, ai will slow down openttd pathfinding, i don't think anyone would appreciate openttd moving slowly trains and buses because it is busy with a complex A* search (just look at boats where the costal part add already lot of pain).

AIStation.PredictedStockpile(cargo_type, ticks_in_future)
Someone will correct me, but if i remember well it's 71ticks/day should be in the wiki for the real answer.

AIIndustryList_AtStation
Can be easy made in squirrel. tiles within station catchment area, keep tiles that are AIIndustry.IsValidIndustry(AIIndustry.GetIndustryID(tile))
Xycor
Engineer
Engineer
Posts: 29
Joined: 17 Mar 2014 01:28

Re: NoAI API requests

Post by Xycor »

One reason for wanting these API's is performance. I have an AI which ideally handles vehicles in the time window between arriving and departing a station. Superlib implements a couple of these functions, but iterating through tile lists to find industries is very slow. However I know at least some of these queries have to be easily accessible to OpenTTD under the hood and the answer should be nearly instant. Numerous parts of superlib should be ported to the NoAI api in my opinion but that should be another post.
krinn wrote:AICargoList_StationProducing
if you want cargo produce at that station :
foreach (crg, _ in AICargoList) { if (AIStation.HasCargoRating(stationID, crg) stationproducing.push(crg); }

if you want industry producing cargo at that station (including cargos you aren't already handling): check every tiles within catchment area for production.
The stations don't have ratings until the first pickup. AI's have to iterate all station tiles, which is in the superlib version. The problem is speed. After optimizing the superlb function my run-time went from 400 ticks/cycle to 100 ticks/cycle. However I still have to do an O(n) search when the AI should have an O(1) operation available. This means my AI response slows as the company grows. It is also a bit strange to have the opposite function for StationAccepting in the API but not this one.
krinn wrote: AIMap.TravelDistance(tile, tile, AITile::TransportType)
This will never appears, noai api doesn't provide interface with openttd pathfinding, and the reason would just be because while it's "easy" for A* to travel x->y using a road type it's a pain with less strict conditions (using a road, you follow it, you're not trying to avoid object in the way). Without even an optimize algo and rought walking the path, the solve is nearly instant.
If they do that, ai will slow down openttd pathfinding, i don't think anyone would appreciate openttd moving slowly trains and buses because it is busy with a complex A* search (just look at boats where the costal part add already lot of pain).
In the water case I see your point, but in every other case this API imposes the exact restriction for A* to work quickly.

Without this we're asking AI authors to replicate the internal data structures and algorithms. That duplication is a net loss in performance, an additional barrier to authoring AI's, and an increase in bugs. If AI is slowing down the game too much it seems simple for players not to use the badly written AI's.

If the performance was unbearable the API could be simplified AIMap.TravelDistance(station, station, AITile::TransportType)? That could be easily cached but is more specific to my problems so I thought the general solution was better.
krinn wrote: AIStation.PredictedStockpile(cargo_type, ticks_in_future)
Someone will correct me, but if i remember well it's 71ticks/day should be in the wiki for the real answer.
Good to know, thanks. Can we make those values accessible from NoAI with this API?

AITime.TicksPerDay
AITime.TicksPerMonth
AITime.TilesTraveledPerTick(speed)
krinn wrote: AIIndustryList_AtStation
Can be easy made in squirrel. tiles within station catchment area, keep tiles that are AIIndustry.IsValidIndustry(AIIndustry.GetIndustryID(tile))
Agreed, possible in squirrel, but with 100 stations walking all of the tiles is very time consuming for an AI's limited tick budget.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: NoAI API requests

Post by Zuu »

Xycor wrote:The stations don't have ratings until the first pickup. AI's have to iterate all station tiles, which is in the superlib version. The problem is speed. After optimizing the superlb function my run-time went from 400 ticks/cycle to 100 ticks/cycle. However I still have to do an O(n) search when the AI should have an O(1) operation available. This means my AI response slows as the company grows. It is also a bit strange to have the opposite function for StationAccepting in the API but not this one.
If you've optimized SuperLib code (without limiting use case of that method), I would be happy to accept your patch into next SuperLib version.

Supply of cargo from station to industry vs from industry to station works differently under the hood. This is why acceptance and supply work differently when you join station parts. Currently as far as I know all API calls have the same cost to the AI. Thus combined commands that are very slow may cause OpenTTD to lag when abused. I don't know if this is an argument here, it needs someone looking at it.
krinn wrote:AIStation.PredictedStockpile(cargo_type, ticks_in_future)
Someone will correct me, but if i remember well it's 71ticks/day should be in the wiki for the real answer.
It is 74 ticks per day.
Xycor wrote:Good to know, thanks. Can we make those values accessible from NoAI with this API?

AITime.TicksPerDay
AITime.TicksPerMonth
AITime.TilesTraveledPerTick(speed)
If you look at the game mechanics page, there are lots of constants that are not exposed via the API. Eg. making all available will take some time and so far noone have thought that exposing those constants have been top of their agenda. Usually constants are exposed when new APIs are added that relate to the constant.
Xycor wrote:
krinn wrote: AIIndustryList_AtStation
Can be easy made in squirrel. tiles within station catchment area, keep tiles that are AIIndustry.IsValidIndustry(AIIndustry.GetIndustryID(tile))
Agreed, possible in squirrel, but with 100 stations walking all of the tiles is very time consuming for an AI's limited tick budget.
If you do it often, you could cache the results and only re-compute at some interval.

Xycor wrote:One reason for wanting these API's is performance. I have an AI which ideally handles vehicles in the time window between arriving and departing a station.
What are you trying to achieve. Micro management all vehicles when they load at stations? That sounds like a feature request to expose time tables to AIs (missing today). Or you are trying to do something not possible for humans which is not really in line with the idea that AIs and humans should compete on similar conditions as far as possible. (of course its hard to give AIs the same brain as human got)
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Xycor
Engineer
Engineer
Posts: 29
Joined: 17 Mar 2014 01:28

Re: NoAI API requests

Post by Xycor »

If you've optimized SuperLib code (without limiting use case of that method), I would be happy to accept your patch into next SuperLib version.
I'll try to get it packaged up nicely. It uses the distance measurement of industries from stations to reduce the number of stations which need all tiles examined.

Code: Select all

   local producerlist = AIIndustryList_CargoProducing(cargotype) 
   producerlist.Valuate(AIIndustry.GetAmountOfStationsAround)
   producerlist.KeepAboveValue(0)
	producerlist.Valuate(AIIndustry.GetLocation)	
	
	local stationlist = AIStationList(stationtype)
	stationlist.Valuate(IndustryPossiblyWithinStationRadius, producerlist)
	stationlist.RemoveValue(0)
	
	stationlist.Valuate(SLStation.IsCargoSupplied, cargotype)
	stationlist.RemoveValue(0)
If you look at the game mechanics page, there are lots of constants that are not exposed via the API. Eg. making all available will take some time and so far noone have thought that exposing those constants have been top of their agenda. Usually constants are exposed when new APIs are added that relate to the constant.
Ok, I need to find that page then. Maybe that is a good starting patch to submit if I get free time to build OpenTTD...
Xycor wrote:One reason for wanting these API's is performance. I have an AI which ideally handles vehicles in the time window between arriving and departing a station.
What are you trying to achieve. Micro management all vehicles when they load at stations? That sounds like a feature request to expose time tables to AIs (missing today). Or you are trying to do something not possible for humans which is not really in line with the idea that AIs and humans should compete on similar conditions as far as possible. (of course its hard to give AIs the same brain as human got)
This is for my OrdersAI. When a vehicle arrives at a station the AI needs to figure out where to send it next. Right now I have these issues:
1. When the game has 50+ stations and 100+ vehicles the AI becomes sluggish and vehicles can wander around before getting updated orders.
2. It is hard to intelligently assign vehicles to tasks without knowing travel time, transport distance, and production rates. Making path information easily accessible gets to the traveling salesman problem which is where the fun starts.
3. Vehicles have to live in a completely connected network or they may be assigned unreachable stations.
4. I could cache... but I am trying to keep my AI entirely stateless. I'm trying to avoid complexity and bugs. It is best to interrogate the state directly from OpenTTD if it already exists.

Originally I was thinking the AI could be a library to delegate the work of scheduling for other AI's. In a big game there won't be cycles left for other AI tasks.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 19 guests