Station location, industry location and GetCoverageRadius
Moderator: OpenTTD Developers
Station location, industry location and GetCoverageRadius
Greetings,
I just started playing around with the NoAI framework, but I have a few difficulties with things that
should be quite basic.
Let's say that I want to find out where I can build a station that can receive wood for a nearby sawmill.
What should I be looking for ? I tried a couple approaches but all of them failed
- Extract from the map the tiles belonging to the industry, and use GetCoverageRadius to build the
tiles where build my station (let's say a simple 1x1 truck station). Doesn't work because not all the tiles
of the sawmill accept wood (and what's more, tiles not belonging to the sawmill will produce goods. Go figure).
- Use AITile::GetCargoAcceptance/AITile::GetCargoProduction, starting from the location of the factory
and expanding while I keep finding a positive response. Problem is, this will get also production from
other factories, am I right ? What if I want production from/to _that_ factory ?
For the moment I kept the first approach, with a couple of "fixes" that make it work with the default set,
but I think there is a better solution... any idea ?
Marco
edit: ouch, wrong section, was meant to go in NoAI discussion subsection
I just started playing around with the NoAI framework, but I have a few difficulties with things that
should be quite basic.
Let's say that I want to find out where I can build a station that can receive wood for a nearby sawmill.
What should I be looking for ? I tried a couple approaches but all of them failed
- Extract from the map the tiles belonging to the industry, and use GetCoverageRadius to build the
tiles where build my station (let's say a simple 1x1 truck station). Doesn't work because not all the tiles
of the sawmill accept wood (and what's more, tiles not belonging to the sawmill will produce goods. Go figure).
- Use AITile::GetCargoAcceptance/AITile::GetCargoProduction, starting from the location of the factory
and expanding while I keep finding a positive response. Problem is, this will get also production from
other factories, am I right ? What if I want production from/to _that_ factory ?
For the moment I kept the first approach, with a couple of "fixes" that make it work with the default set,
but I think there is a better solution... any idea ?
Marco
edit: ouch, wrong section, was meant to go in NoAI discussion subsection
Re: Station location, industry location and GetCoverageRadiu
In most cases, this will work perfectly:
At least it will work with the default industry set.
However, there are cases when an industry accepts multiple types of cargo, but at different tiles. See http://www.tt-forums.net/viewtopic.php?p=950891#p950891.
To avoid this, you will have to filter the above tilelist afterwards by acceptance. (note that AITileList_IndustryAccepting doesn't have a cargo parameter)
Code: Select all
tiles = AITileList_IndustryAccepting(the_sawmill, coverage_radius_of_station);
However, there are cases when an industry accepts multiple types of cargo, but at different tiles. See http://www.tt-forums.net/viewtopic.php?p=950891#p950891.
To avoid this, you will have to filter the above tilelist afterwards by acceptance. (note that AITileList_IndustryAccepting doesn't have a cargo parameter)
Code: Select all
tiles.Valuate(AITile.GetCargoAcceptance, crg, 1, 1, coverage_radius_of_station);
tiles.RemoveBelowValue(8);
Re: Station location, industry location and GetCoverageRadiu
For that part it's not undoable but the solve might be too tweaky while the solve won't produce really interresting results.marco.r wrote:Problem is, this will get also production from
other factories, am I right ? What if I want production from/to _that_ factory ?
Say you wish to only get wood acceptance from industryA, you'll have to assign an accepting radius, then add any other industries that also accept wood within that radius*2 (because if radius of industryB touch radius of industryA you will have a shared tile with both accepting the wood)
Now that you have that, you need to remove all tiles that are shared by both, remain will be tiles not shared and own by industryA that accept wood: your goal is reach.
As you see, not undoable, just weak benefits (making sure only industryA is feed) vs a weak "bad" effect (you may feed more than just one industry, but you will get paid anyway).
Except if your goal is to feed only 1 industry to higher as much as possible its producing of another good you wish to make big money out of it (an openttdcoopAI ?) i don't think that's a good idea (because removing shared tiles = removing possible places to find a spot to build your station)
Re: Station location, industry location and GetCoverageRadiu
First of all, thanks to both for you answers.krinn wrote:For that part it's not undoable but the solve might be too tweaky while the solve won't produce really interresting results.marco.r wrote:Problem is, this will get also production from
other factories, am I right ? What if I want production from/to _that_ factory ?
Say you wish to only get wood acceptance from industryA, you'll have to assign an accepting radius, then add any other industries that also accept wood within that radius*2 (because if radius of industryB touch radius of industryA you will have a shared tile with both accepting the wood)
Now that you have that, you need to remove all tiles that are shared by both, remain will be tiles not shared and own by industryA that accept wood: your goal is reach.
As you see, not undoable, just weak benefits (making sure only industryA is feed) vs a weak "bad" effect (you may feed more than just one industry, but you will get paid anyway).
Except if your goal is to feed only 1 industry to higher as much as possible its producing of another good you wish to make big money out of it (an openttdcoopAI ?) i don't think that's a good idea (because removing shared tiles = removing possible places to find a spot to build your station)
Actually what I wanted to be sure was that I would not get also the tiles of the "area of interest" of another factory, ending up outside of the area of the original one.
But with the solution proposed it is a non-issue.
Now it works just fine. thanks again !
Re: Station location, industry location and GetCoverageRadiu
Reviving the thread because the topic fits my question
Trying to find a nice function to get a square ready to build a station close to an industry. The purpose is to find a square of sufficient space within the area of coverage of so I do not need to terraform or demolish anything. I am currently trying this:
I have no idea what to put into the while-loop, if it fails it should return NULL, that part is understandable, I need to figure out how to move around within the coverage area until I get a rectangle I can build on
Trying to find a nice function to get a square ready to build a station close to an industry. The purpose is to find a square of sufficient space within the area of coverage of so I do not need to terraform or demolish anything. I am currently trying this:
Code: Select all
function MyAI::BuildStation(near, cargoid)
{
local ind_idx = AIIndustry.GetIndustryID(near);
local ind_type = AIIndustry.GetIndustryType(ind_idx);
local town_id = AITile.GetClosestTown(near);
local station_name = AITown.GetName(town_id) + " " + AIIndustryType.GetName(ind_type) + " Cargo Station";
local tile = near;
while (!AITile.IsBuildableRectangle(tile, 3, 3)) {
}
AIRail.BuildRailStation(tile, AIRail.RAILTRACK_NW_SE, 3, 3, AIStation.STATION_JOIN_ADJACENT);
local station = AIStation.GetStationID(tile);
AIBaseStation.SetName(station, station_name);
return station;
}
Skippern
OpenTTD Mac user
OpenTTD Mac user
Re: Station location, industry location and GetCoverageRadiu
Well if you are specifying a tile to build near to, I'd say best would be to generate a TileList of all possible tiles in your chosen radius and run through each with a for loop:
Also check out the util functions in NoCAB (or Krinn's Dictator), there is a nice method of terraforming to flatten a rectange for building.
Code: Select all
local tile_list = AITileList();
tile_list.AddRectangle(tile - AIMap.GetTileIndex(radius, radius), tile + AIMap.GetTileIndex(radius, radius));
tile_list.Valuate(AIBase.RandItem); // Avoid building similar layouts all the time:)
tile_list.Sort(AIList.SORT_BY_VALUE, AIList.SORT_DESCENDING);
local current_tile = null;
for(current_tile = tile_list.Begin(); !tile_list.IsEnd(); current_tile = tile_list.Next()) {
if(AIRail.BuildRailStation(current_tile, AIRail.RAILTRACK_NW_SE, 3, 3, AIStation.STATION_NEW)); // Try build whole thing at once.
break;
}
if(!AIRail.IsRailStationTile(current_tile))
return null; //failed to build for all tiles.
Re: Station location, industry location and GetCoverageRadiu
Dictator is a messy codeR2dical wrote: Also check out the util functions in NoCAB (or Krinn's Dictator), there is a nice method of terraforming to flatten a rectange for building.

Skippern
OpenTTD Mac user
OpenTTD Mac user
Re: Station location, industry location and GetCoverageRadiu
What am I doing wrong?
No station built, and no debugging signs placed, what happens?
Code: Select all
local tile_list = AITileList();
tile_list.AddRectangle(near - AIMap.GetTileIndex(radius, radius), near + AIMap.GetTileIndex(radius, radius));
tile_list.Valuate(AIBase.RandItem);
tile_list.Sort(AIList.SORT_BY_VALUE, AIList.SORT_DESCENDING);
local i = 0; // help with debugging
local current_tile = tile_list.Begin(); // changed from null to make sure that this wasn't the problem
AILog.Info("Trying to build station ("+tile_list.Count()+")"); // tells me how many tiles is in the list, for debugging
for (current_tile = tile_list.Begin(); !tile_list.IsEnd(); current_tile = tile_list.Next()) {
if (!AIMap.IsValidTile(current_tile)) AILog.Error("Error: False current_tile"); // produce nasty error if fails <- not printed, so tile is valid
if (AIRail.BuildRailStation(current_tile, direction, platforms, length, AIStation.STATION_NEW)) break; // station is not built
i++; // for debugging
AISign.BuildSign(current_tile, station_name); // sign is not placed
}
AILog.Info("Tried "+i+" tiles, either all tiles tried or station built");
Skippern
OpenTTD Mac user
OpenTTD Mac user
Re: Station location, industry location and GetCoverageRadiu
You set a rail type before doing the loop right?
This works for my AI (not gonna bother with the screenshot
):
In practise you may want to use the Superlib version of AddRectange, which accounts for edge of map and "wrap around" avoid clamp feature. Also looping through a tile list means you don't have to bother with IsValid.
(not "messy" but non descriptive variables and comments...)
This works for my AI (not gonna bother with the screenshot

Code: Select all
local build = AIExecMode();
local near = SuperLib.Tile.GetRandomTile();
local rail_list = AIRailTypeList();
AIRail.SetCurrentRailType(rail_list.Begin());
local tile_list = AITileList();
tile_list.AddRectangle(near - AIMap.GetTileIndex(radius, radius), near + AIMap.GetTileIndex(radius, radius));
tile_list.Valuate(AIBase.RandItem);
tile_list.Sort(AIList.SORT_BY_VALUE, AIList.SORT_DESCENDING);
local current_tile = null;
for (current_tile = tile_list.Begin(); !tile_list.IsEnd(); current_tile = tile_list.Next()) {
if (AIRail.BuildRailStation(current_tile, AIRail.RAILTRACK_NW_SE, 3, 5, AIStation.STATION_NEW))
break;
}
Really? Take a look at TeshiNetskippern wrote:Dictator is a messy code

Re: Station location, industry location and GetCoverageRadiu
That was it!R2dical wrote:You set a rail type before doing the loop right?
First need to get this rolling, than I can start looking at better solutionsR2dical wrote:Really? Take a look at TeshiNetskipern wrote:Dictator is a messy code(not "messy" but non descriptive variables and comments...)
In practise you may want to use the Superlib version of AddRectange, which accounts for edge of map and "wrap around" avoid clamp feature. Also looping through a tile list means you don't have to bother with IsValid.
Skippern
OpenTTD Mac user
OpenTTD Mac user
Who is online
Users browsing this forum: No registered users and 20 guests