API extensions for cargo distribution?

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
User avatar
fonso
President
President
Posts: 945
Joined: 13 Oct 2007 08:28

API extensions for cargo distribution?

Post by fonso »

Currently the game state associated with cargo distribution is invisible to AIs and Game Scripts. I'd like to change that in order to enable authors of AIs and Game Scripts to set up interesting challenges related to cargo distribution. For example a game script could monitor how large a player's network is or if certain routes are overloaded and make that part of the player's "score". The best way to go about that is asking those authors: What kind of API would you like?

Some things are already implemented:
  • static int32 GSStation::GetCargoWaitingVia(...) takes the next hop into account when querying waiting cargo
  • static DistributionType GSCargo::GetDistributionType(...) queries the distribution type for a cargo.
Some things would be fairly simple to implement:
  • Waiting cargo, given both origin and next hop.
  • Planned monthly cargo flow at a station, with or without origin and/or next hop of the cargo (the case with only next hop would be comparable to capacity)
  • If some share of planned flow is restricted. That means it can only be used by passing cargo, not by cargo originating or transferring at that station. That's the effect of "no load" orders.
  • Monthly capacity of a link between two stations
  • If the capacity is totally restricted, totally unrestriced, or mixed.
  • Monthly usage of a link
  • ID of the link graph a station is part of for a certain cargo
  • Total size of a link graph in stations
  • List of stations in a link graph
  • List of cargo producing stations in a link graph
  • List of cargo consuming stations in a link graph
  • List of stations a station has links to or from
Should we define some events, too? E.g. "distribution updated" for a certain link graph.
The guy on the picture is not me, it's Alonso.
R2dical
Traffic Manager
Traffic Manager
Posts: 163
Joined: 18 Mar 2013 22:22

Re: API extensions for cargo distribution?

Post by R2dical »

Very nice list, GS will open up a whole new element and I think AIs will benefit too in being able to anticipate cargo amounts, vehicle, etc too. Will those all work for asynchronous, synchronous and manual modes?
frosch
OpenTTD Developer
OpenTTD Developer
Posts: 988
Joined: 20 Dec 2006 13:31
Location: Aschaffenburg

Re: API extensions for cargo distribution?

Post by frosch »

I discussed some things with Zuu last month: Generally AIs are interested in detecting overloaded/underloaded links. While GS are rather interested in the routes.
Both are interested in the vehicles involved.

For GS I am in particulary looking for a method to track what routes cargo takes, and which vehicles serve those routes.
  • Planned flows from/to a station (next hop only). Something like:
    • GSStationList_NextHop(StationID, CargoID) returning a list/map: station id -> planned flow
    • GSStationList_PreviousHop(StationID, CargoID) returning a list/map: station id -> planned flow
    Wrt. multiple hops, I think scripts can traverse the graph themself.
  • Vehicles involved in a route between two stations (distance = one hop). Something like:
    • GSVehicleList_Link(StationID, StationID, CargoID) returning a list/map: vehicle id -> ???? (capacity? expected usage?)
For AIs: Would it be possible to ask for the expected flow before a station is constructed? As in: If I build a connection from existing station X to tile Y, how many passengers are expected per month? (effectively evaluating demand and distance and putting them into relation to the existing link graph)

Wrt. your suggestions:
ID of the link graph a station is part of for a certain cargo
How permanent would such an ID be? Do they change meaning every calculation?
Since scripts do not exactly know when they are suspended, it may be easier to address connected graph components only indirectly via one of StationIDs of their members.
List of cargo producing stations in a link graph
List of cargo consuming stations in a link graph
I think scripts can figure this out themself with the other methods (stations in component + production queries).
Should we define some events, too? E.g. "distribution updated" for a certain link graph.
I think events are quite useless. They are not saved in savegames, so are not usable for state updates. They can only be used to trigger some update while the script is idling otherwise. But IMHO scripts never idle.
⢇⡸⢸⠢⡇⡇⢎⡁⢎⡱⢸⡱⢸⣭⠀⢸⢜⢸⢸⣀⢸⣀⢸⣭⢸⡱⠀⢰⠭⡆⣫⠰⣉⢸⢸⠀⢰⠭⡆⡯⡆⢹⠁⠀⢐⠰⡁
User avatar
fonso
President
President
Posts: 945
Joined: 13 Oct 2007 08:28

Re: API extensions for cargo distribution?

Post by fonso »

Exposing cargo flows is not a problem, I just have to wrap the FlowStat thing into an API. Exposing link capacities isn't a problem either. They're right there in the link graph.
Generally AIs are interested in detecting overloaded/underloaded links. While GS are rather interested in the routes.
Both are interested in the vehicles involved.

For GS I am in particulary looking for a method to track what routes cargo takes, and which vehicles serve those routes.
  • Planned flows from/to a station (next hop only). Something like:
    • GSStationList_NextHop(StationID, CargoID) returning a list/map: station id -> planned flow
    • GSStationList_PreviousHop(StationID, CargoID) returning a list/map: station id -> planned flow
Next hop is fairly cheap, previous hop requires looping over the nodes in the link graph to figure out which ones have a link to the requested station. Both aren't difficult to implement.
Wrt. multiple hops, I think scripts can traverse the graph themself.
[*]Vehicles involved in a route between two stations (distance = one hop). Something like:
  • GSVehicleList_Link(StationID, StationID, CargoID) returning a list/map: vehicle id -> ???? (capacity? expected usage?)
[/list]
This is possible but pretty expensive. We have to loop over all order lists, examine each one for a pair of matching orders (with all the fun about conditionals and depot stops and whatnot), and if found add all the vehicles following that order list to the returned map. Capacity or expected usage doesn't make much sense for single vehicles. The capacity of a link has no direct connection to the capacity of a vehicle, so I'd explicitly not expose vehicle capacity there as that will only confuse people.
For AIs: Would it be possible to ask for the expected flow before a station is constructed? As in: If I build a connection from existing station X to tile Y, how many passengers are expected per month? (effectively evaluating demand and distance and putting them into relation to the existing link graph)
That requires the simulation of a link graph job with certain modifications. It's definitely an interesting idea, but I'd leave that for later. Running link graph jobs is too expensive to do inline in the script, so the script would need some way to asynchronously trigger it and then get callbacks at certain stages where it could examine or modify the state of the link graph job. That would be totally awesome, of course, but also quite a bit of work.
Wrt. your suggestions:
ID of the link graph a station is part of for a certain cargo
How permanent would such an ID be? Do they change meaning every calculation?
Since scripts do not exactly know when they are suspended, it may be easier to address connected graph components only indirectly via one of StationIDs of their members.
The IDs only change if two link graphs are merged. We could notify the script about that.
Should we define some events, too? E.g. "distribution updated" for a certain link graph.
I think events are quite useless. They are not saved in savegames, so are not usable for state updates. They can only be used to trigger some update while the script is idling otherwise. But IMHO scripts never idle.
So how do we do notifications? What happens if an AI's truck is overrun by a train? Does the AI get some callback for that? Or is it just constantly polling all vehicles?

In general, I'd provide the above methods and some additional ones that are computationally cheap and still make sense (for example capacity of a link, given two station IDs). Then I'd add some information on the complexity of those methods to the documentation.
The guy on the picture is not me, it's Alonso.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: API extensions for cargo distribution?

Post by Zuu »

fonso wrote:
Should we define some events, too? E.g. "distribution updated" for a certain link graph.
I think events are quite useless. They are not saved in savegames, so are not usable for state updates. They can only be used to trigger some update while the script is idling otherwise. But IMHO scripts never idle.
So how do we do notifications? What happens if an AI's truck is overrun by a train? Does the AI get some callback for that? Or is it just constantly polling all vehicles?

In general, I'd provide the above methods and some additional ones that are computationally cheap and still make sense (for example capacity of a link, given two station IDs). Then I'd add some information on the complexity of those methods to the documentation.
As events are not stored in the save game, AIs/GSs can not only rely on events for detecting changes in the game. However they can still be useful to get notifications about things faster. For example a route that frequently loses trucks will sooner or later get new trucks because the AI detect that here are too few trucks compared to supply. However with help of the event, the AI can know that a crash has occured, if it is lucky enough to read the event before the vehicle is gone, it will even know the location and may be able to replace that level crossing with a bridge. If the vehicle is gone, it will need to use the path finder from A to B to locate the rail crossing. Or if the event is lost due to save/load, oh well, it will eventually build new trucks due to waiting cargo getting to high and if a crash occurs later on it can perhaps catch that event. This whole is quite self regulating. If there are a lot of crashes, there will be more events, and higher chance that the AI catch an event. If it is only once every 10+ years, oh well if it failed to catch the event, it is just one lost truck. Not too bad.

I should perhaps also note that AIs/GSes have an event queue and OpenTTD can push events to this queue. The AI/GS itself needs to make an API call to pop events from the queue. Most AIs/GSs do this at one point of the main loop and if they are stuck with path finding for a in-game year, then it will not read any events during that time. However it is possible to write the code such that the pathfinder is not a blocking task. Its all up to the author how he/she writes the code.

That being said, I don't know if an event "distribution being updated" is really useful. An AI/GS will probably just look at the current data at given intervals. If a huge amount of towns/industries/stations are watched it cannot do everything instantly, but rather over the phase of eg. an in-game month. And well how that relate to the update frequency inside OpenTTD of the data provided to AI/GS is often not something the AI/GS can care about as it anyway needs to distribute its work over time.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: API extensions for cargo distribution?

Post by krinn »

That distribution event can also be a killer.
If an AI handle that event and react to it by checking what route was update, if the event appears too much, the AI will keep answering to that event. So you endup with an AI that really fine tune any route needs, at the cost of plenty other tasks AI has to do.
It won't help any AI to be 100% aware of needs on any route if the AI take months to see all vehicles on that route are too old and need to be replace.

So in real, i don't think anyone would react to that event but keep relaying on its "stations need handling" functionality that is trigger every X intervals.
The crash event is a good example, some just blindly replace the crashed vehicle with a newer one, some just ignore it, some handle it by checking crossing and fixing it.
In theory everyone should reevaluate the route needs to see if route need new vehicle or not, in real, nobody do that as you would put too much time just for that route. AI just replace/ignore or fix cause of the crash, but don't really handle consequences of the crash when the event is catch ; leaving that to the common handling that will be run later.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 12 guests