Skip to content

Instantly share code, notes, and snippets.

@SamuXarick
Last active January 19, 2023 23:05
Show Gist options
  • Save SamuXarick/e566722c7fa73555c8cd84edeaca5c75 to your computer and use it in GitHub Desktop.
Save SamuXarick/e566722c7fa73555c8cd84edeaca5c75 to your computer and use it in GitHub Desktop.
/* 14 ensures rail can't be built backwards and allows 'from' and 'to'
* tiles to be invalid, as long as they're void tiles. */
AIRail._BuildRail <- AIRail.BuildRail
AIRail.BuildRail <- function(from, tile, to)
{
local map_log_x = function()
{
local x = AIMap.GetMapSizeX();
local pos = 0;
if ((x & 0xFFFFFFFF) == 0) { x = x >> 32; pos += 32; }
if ((x & 0x0000FFFF) == 0) { x = x >> 16; pos += 16; }
if ((x & 0x000000FF) == 0) { x = x >> 8; pos += 8; }
if ((x & 0x0000000F) == 0) { x = x >> 4; pos += 4; }
if ((x & 0x00000003) == 0) { x = x >> 2; pos += 2; }
if ((x & 0x00000001) == 0) { pos += 1; }
return pos;
};
/* Workaround to circumvent IsValidTile. We want to give a pass to void tiles */
local is_tile_inside_map = function(t)
{
return t >= 0 && t < AIMap.GetMapSize();
};
/* Workaround to circumvent GetTileX which tests IsValidTile */
local tile_x = function(t)
{
return t & (AIMap.GetMapSizeX() - 1);
};
/* Workaround to circumvent GetTileY which tests IsValidTile */
local tile_y = function(t, maplogx = map_log_x)
{
return t >> maplogx();
};
/* Workaround to circumvent DistanceManhattan which tests IsValidTile */
local distance_manhattan = function(t_void, t_valid, tx = tile_x, ty = tile_y)
{
return abs(tx(t_void) - AIMap.GetTileX(t_valid)) + abs(ty(t_void) - AIMap.GetTileY(t_valid));
};
local diag_offset = function(t_void, t_valid, tx = tile_x, ty = tile_y)
{
return abs(abs(tx(t_void) - AIMap.GetTileX(t_valid)) - abs(ty(t_void) - AIMap.GetTileY(t_valid)));
};
/* Run common tests to both API versions */
if (AICompany.ResolveCompanyID(AICompany.COMPANY_SELF) != AICompany.COMPANY_INVALID &&
is_tile_inside_map(from) && AIMap.IsValidTile(tile) && is_tile_inside_map(to) &&
distance_manhattan(from, tile) == 1 && distance_manhattan(to, tile) >= 1 &&
AIRail.IsRailTypeAvailable(AIRail.GetCurrentRailType()) && (diag_offset(to, tile) <= 1 ||
(tile_x(from) == AIMap.GetTileX(tile) && AIMap.GetTileX(tile) == tile_x(to)) ||
(tile_y(from) == AIMap.GetTileY(tile) && AIMap.GetTileY(tile) == tile_y(to)))) {
/* Run tests which differ from version 14 */
if (AIMap.IsValidTile(from) && AIMap.IsValidTile(to)) {
if (from == to ||
(AIMap.GetTileX(from) == AIMap.GetTileX(tile) && AIMap.GetTileX(tile) == AIMap.GetTileX(to) &&
AIMap.GetTileY(from) - AIMap.GetTileY(tile) == -(AIMap.GetTileY(tile) - AIMap.GetTileY(to)) / abs(AIMap.GetTileY(tile) - AIMap.GetTileY(to))) ||
(AIMap.GetTileY(from) == AIMap.GetTileY(tile) && AIMap.GetTileY(tile) == AIMap.GetTileY(to) &&
AIMap.GetTileX(from) - AIMap.GetTileX(tile) == -(AIMap.GetTileX(tile) - AIMap.GetTileX(to)) / abs(AIMap.GetTileX(tile) - AIMap.GetTileX(to)))) {
/* Adjust 'from' to simulate pre-14 behaviour */
from = tile + (tile - from);
}
} else {
/* Provoke a precondition fail to simulate pre-14 behaviour */
from = tile;
}
}
return AIRail._BuildRail(from, tile, to);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment