Skip to content

Instantly share code, notes, and snippets.

@SamuXarick
Last active December 17, 2023 18:31
Show Gist options
  • Save SamuXarick/182368662a8be3bc771a4bce871afd4e to your computer and use it in GitHub Desktop.
Save SamuXarick/182368662a8be3bc771a4bce871afd4e to your computer and use it in GitHub Desktop.
How do I create a list for each noise amount and sort it by distance and for tiles with the same distance, also sort it by the order they were added?
_tile_queue = null; // Not constant
_tile_distances = null; // Not constant
_tile_noises = null; // Not constant
_tile_priorities = null; // Not constant
function MainClass::InitializeTileVariables()
{
_map_size = GSMap.GetMapSize();
_tile_N = null; // Initialize as null
_tile_W = null; // Initialize as null
_tile_S = null; // Initialize as null
_tile_E = null; // Initialize as null
_tile = _tile_N;
_tile_num = 0; // Reset counter
if (_tile_queue != null) {
_tile_queue.Clear();
} else {
_tile_queue = GSList();
_tile_queue.Sort(GSList.SORT_BY_VALUE, GSList.SORT_ASCENDING);
}
if (_tile_distances != null) {
_tile_distances.Clear();
} else {
_tile_distances = GSList();
_tile_distances.Sort(GSList.SORT_BY_VALUE, GSList.SORT_DESCENDING);
}
if (_tile_noises != null) {
_tile_noises.Clear();
} else {
_tile_noises = GSList();
_tile_noises.Sort(GSList.SORT_BY_VALUE, GSList.SORT_ASCENDING);
}
_tile_priorities = { }; // Initialize all of them as null
for (local noise = 1; noise <= _noisiest_airport_noise; noise++) {
_tile_priorities[noise] <- null;
}
}
local proc = function(tile)
{
/* The tile to check should not be a repeat */
assert(!_tile_queue.HasItem(tile));
_tile_queue.AddItem(tile, _tile_num++);
/* We're only interested in one specific town */
local nearest_town = GSAirport.GetNearestTown(tile, _noisiest_airport_type);
if (nearest_town != _town) return false;
/* We're only interested in distances that fit in the map */
local airport_distance_to_town = GetAirportMinDistanceToTown(tile, _noisiest_airport_width, _noisiest_airport_height, _town);
if (airport_distance_to_town < _max_dist) _tile_distances.AddItem(tile, airport_distance_to_town);
/* At this point, all results for noise values should be valid */
local noise = GSAirport.GetNoiseLevelIncrease(tile, _noisiest_airport_type);
assert(noise > 0);
_tile_noises.AddItem(tile, noise);
/* Add the tiles in the order they first appeared */
if (_tile_priorities[noise] != null) {
_tile_priorities[noise].AddItem(tile, _tile_priorities[noise].GetValue(_tile_priorities[noise].Begin()) + 1);
} else {
_tile_priorities[noise] = GSList();
_tile_priorities[noise].AddItem(tile, 0);
}
// PlaceSign(tile, /*noise + "/" + */airport_distance_to_town + "/" + _tile_num);
/* Always return false */
return false;
};
function MainClass::CircularTileQueue(min_noise_level_increase = null)
{
if (min_noise_level_increase == null) min_noise_level_increase = GSController.GetSetting("min_noise_level_increase");
local distance = min_noise_level_increase == 1 ? _max_dist : min(_max_dist, GetMaxNoiseToleranceLevelDistance(min_noise_level_increase));
if (!AreTileVariablesInitialized()) {
_tile_N = GSMap.GetTileIndex(_min_x, _min_y);
_tile_S = GSMap.GetTileIndex(_max_x, _max_y);
local tile_Nx = GetTileX(_tile_N);
local tile_Ny = GetTileY(_tile_N);
local tile_Sx = GetTileX(_tile_S);
local tile_Sy = GetTileY(_tile_S);
local town_location_x = GetTileX(_town_location);
local town_location_y = GetTileY(_town_location);
_tile = GSMap.GetTileIndex(max(tile_Nx, town_location_x - (_noisiest_airport_width - 1)), max(tile_Ny, town_location_y - (_noisiest_airport_height - 1)));
_tile_N = GSMap.GetTileIndex(max(tile_Nx, town_location_x - distance - (_noisiest_airport_width - 1)), max(tile_Ny, town_location_y - distance - (_noisiest_airport_height - 1)));
_tile_S = GSMap.GetTileIndex(min(tile_Sx, town_location_x + distance), min(tile_Sy, town_location_y + distance));
// GSLog.Info("_tile: " + _tile + "; _tile_N: " + _tile_N + "; _tile_S: " + _tile_S);
// PlaceSign(_tile, "_tile");
// PlaceSign(_tile_N, "_tile_N");
// PlaceSign(_tile_S, "_Tile_S");
}
local proc = function(tile)
{
/* The tile to check should not be a repeat */
assert(!_tile_queue.HasItem(tile));
_tile_queue.AddItem(tile, _tile_num++);
/* We're only interested in one specific town */
local nearest_town = GSAirport.GetNearestTown(tile, _noisiest_airport_type);
if (nearest_town != _town) return false;
/* We're only interested in distances that fit in the map */
local airport_distance_to_town = GetAirportMinDistanceToTown(tile, _noisiest_airport_width, _noisiest_airport_height, _town);
if (airport_distance_to_town < _max_dist) _tile_distances.AddItem(tile, airport_distance_to_town);
/* At this point, all results for noise values should be valid */
local noise = GSAirport.GetNoiseLevelIncrease(tile, _noisiest_airport_type);
assert(noise > 0);
_tile_noises.AddItem(tile, noise);
/* Add the tiles in the order they first appeared */
if (_tile_priorities[noise] != null) {
_tile_priorities[noise].AddItem(tile, _tile_priorities[noise].GetValue(_tile_priorities[noise].Begin()) + 1);
} else {
_tile_priorities[noise] = GSList();
_tile_priorities[noise].AddItem(tile, 0);
}
// PlaceSign(tile, /*noise + "/" + */airport_distance_to_town + "/" + _tile_num);
/* Always return false */
return false;
};
if (_tile_distances.IsEmpty()) {
// GSLog.Info("distance: " + distance);
local search = CircularTileSearch(_tile, _tile_N, _tile_S, distance, _noisiest_airport_width, _noisiest_airport_height, proc);
}
return true;
}
function MainClass::CircularTileSearch(tile, tile_N, tile_S, distance, width, height, proc)
{
assert(proc != null);
assert(distance > 0);
local d = abs(width - height);
local w = 0;
local h = 0;
if (d) {
if (width > height) {
w = d;
} else {
h = d;
}
}
local tile_x = GetTileX(tile);
local tile_y = GetTileY(tile);
local x = tile_x + w + 1;
local y = tile_y;
local min_x = max(0, GetTileX(tile_N));
local max_x = min(GetTileX(tile_S), _map_size_x - 1);
local min_y = max(0, GetTileY(tile_N));
local max_y = min(GetTileY(tile_S), _map_size_y - 1);
local extent = [ w, h, w, h ];
distance += min(width, height);
for (local n = 0; n < distance; n++) {
for (local dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
/* Is the tile within the map? */
for (local j = extent[dir] + n * 2 + 1; j != 0; j--) {
if (x >= min_x && x <= max_x && y >= min_y && y <= max_y) {
local t = GSMap.GetTileIndex(x, y);
/* Is the callback successful? */
if (proc(t)) {
/* Stop the search */
return true;
}
}
/* Step to the next 'neighbour' in the circular line */
x += _tileoffs_by_diagdir[dir].x;
y += _tileoffs_by_diagdir[dir].y;
}
}
/* Jump to next circle to test */
x += 1;
y -= 1;
}
return false;
}
/* I did it! It's some sort of ring sort priority. */
if (_tile_priorities[noise] != null) {
/* Keep only a list of tiles for the current noise level */
local tile_noises = GSList();
tile_noises.AddList(_tile_noises);
tile_noises.KeepValue(noise);
/* Get the distances of the tiles kept */
local tile_distances = GSList();
tile_distances.AddList(_tile_distances);
tile_distances.KeepList(tile_noises);
assert(tile_noises.Count() == tile_distances.Count());
/* Create lists of tiles for each distance and store each tile priority in them
* Also create a list of distances */
local distances_table = { };
local distances_list = GSList();
foreach (tile, distance in tile_distances) {
if (!distances_table.rawin(distance)) {
distances_table[distance] <- null;
distances_table[distance] = GSList();
}
assert(_tile_priorities[noise].HasItem(tile));
distances_table[distance].AddItem(tile, _tile_priorities[noise].GetValue(tile));
if (!distances_list.HasItem(distance)) {
distances_list.AddItem(distance, 0);
} else {
distances_list.AddItem(distance, distances_list.GetValue(distance) + 1);
}
}
/* Finally place signs */
foreach (distance, _ in distances_list) {
foreach (tile, priority in distances_table[distance]) {
PlaceSign(tile, noise + "/" + distance + "/" + priority);
}
GSController.Sleep(10);
MassRemoveSigns();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment