/** * Finds the distance for the closest tile with water/land given a tile * @param tile the tile to find the distance too * @param water whether to find water or land * @return distance to nearest water (max 0x7F) / land (max 0x1FF; 0x200 if there is no land) */ uint GetClosestWaterDistance(TileIndex tile, bool water) { if (WaterMap.HasTileWaterGround(tile) == water) { return(0); } uint max_dist = (uint)(water ? 0x7F : 0x200); int x = (int)TileX(tile); int y = (int)TileY(tile); uint max_x = MapMaxX(); uint max_y = MapMaxY(); uint min_xy = (uint)(_settings_game.construction.freeform_edges ? 1 : 0); /* go in a 'spiral' with increasing manhattan distance in each iteration */ for (uint dist = 1; dist < max_dist; dist++) { /* next 'diameter' */ y--; /* going counter-clockwise around this square */ for (var dir = (int)DiagDirection.DIAGDIR_BEGIN; dir < (int)DiagDirection.DIAGDIR_END; dir++) { int dx = ddx[dir]; int dy = ddy[dir]; /* each side of this square has length 'dist' */ for (uint a = 0; a < dist; a++) { /* MP_VOID tiles are not checked (interval is [min; max) for IsInsideMM())*/ if (MathFuncs.IsInsideMM(x, min_xy, max_x) && MathFuncs.IsInsideMM(y, min_xy, max_y)) { TileIndex t = TileXY((uint)x, (uint)y); if (WaterMap.HasTileWaterGround(t) == water) { return(dist); } } x += dx; y += dy; } } } if (!water) { /* no land found - is this a water-only map? */ for (TileIndex t = 0; t < MapSize(); t++) { if (!TileMap.IsTileType(t, TileType.MP_VOID) && !TileMap.IsTileType(t, TileType.MP_WATER)) { return(0x1FF); } } } return(max_dist); }
/** * Find file information of a file by its name from the file list. * @param file The filename to return information about. Can be the actual name * or a numbered entry into the filename list. * @return The information on the file, or \c NULL if the file is not available. */ public FiosItem FindItem(string file) { foreach (var item in files) { if (file == item.name || file == item.title) { return(item); } } /* If no name matches, try to parse it as number */ if (int.TryParse(file, out var i) && MathFuncs.IsInsideMM(i, 0, (uint)this.files.Count)) { return(this[i]); } /* As a last effort assume it is an OpenTTD savegame and * that the ".sav" part was not given. */ var long_file = file + ".sav"; foreach (var item in files) { if (long_file == item.name || long_file == item.title) { return(item); } } return(null); }
/** * Add the rail types that are to be introduced at the given date. * @param current The currently available railtypes. * @param date The date for the introduction comparisons. * @return The rail types that should be available when date * introduced rail types are taken into account as well. */ public RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date) { RailTypes rts = current; for (RailType rt = RailType.RAILTYPE_BEGIN; rt != RailType.RAILTYPE_END; rt++) { RailtypeInfo rti = GetRailTypeInfo(rt); /* Unused rail type. */ if (rti.label == 0) { continue; } /* Not date introduced. */ if (!MathFuncs.IsInsideMM(rti.introduction_date, 0, MAX_DAY)) { continue; } /* Not yet introduced at this date. */ if (rti.introduction_date > date) { continue; } /* Have we introduced all required railtypes? */ RailTypes required = rti.introduction_required_railtypes; if ((rts & required) != required) { continue; } rts |= rti.introduces_railtypes; } /* When we added railtypes we need to run this method again; the added * railtypes might enable more rail types to become introduced. */ return(rts == current ? rts : AddDateIntroducedRailTypes(rts, date)); }
/** * (Re)allocates a map with the given dimension * @param size_x the width of the map along the NE/SW edge * @param size_y the 'height' of the map along the SE/NW edge */ public static void AllocateMap(uint size_x, uint size_y) { /* Make sure that the map size is within the limits and that * size of both axes is a power of 2. */ if (!MathFuncs.IsInsideMM((int)size_x, TileConstants.MIN_MAP_SIZE, TileConstants.MAX_MAP_SIZE + 1) || !MathFuncs.IsInsideMM((int)size_y, TileConstants.MIN_MAP_SIZE, TileConstants.MAX_MAP_SIZE + 1) || (size_x & (size_x - 1)) != 0 || (size_y & (size_y - 1)) != 0) { throw new Exception("Invalid map size"); } Log.Error($"Allocating map of size {size_x}x{size_y}"); _map_log_x = BitMath.FindFirstBit(size_x); _map_log_y = BitMath.FindFirstBit(size_y); _map_size_x = size_x; _map_size_y = size_y; _map_size = size_x * size_y; _map_tile_mask = _map_size - 1; _m = new Tile[_map_size]; _me = new TileExtended[_map_size]; }