diff --git a/src/map_func.h b/src/map_func.h index 3ebfb349c6..399f84a943 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -36,6 +36,34 @@ extern TileExtended *_me; */ struct Map { private: + /** + * Iterator to iterate all Tiles + */ + struct Iterator { + typedef TileIndex value_type; + typedef TileIndex *pointer; + typedef TileIndex &reference; + typedef size_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + explicit Iterator(TileIndex index) : index(index) {} + bool operator==(const Iterator &other) const { return this->index == other.index; } + bool operator!=(const Iterator &other) const { return !(*this == other); } + TileIndex operator*() const { return this->index; } + Iterator & operator++() { this->index++; return *this; } + private: + TileIndex index; + }; + + /* + * Iterable ensemble of all Tiles + */ + struct IterateWrapper { + Iterator begin() { return Iterator(0); } + Iterator end() { return Iterator(Map::Size()); } + bool empty() { return false; } + }; + static uint log_x; ///< 2^_map_log_x == _map_size_x static uint log_y; ///< 2^_map_log_y == _map_size_y static uint size_x; ///< Size of the map along the X @@ -158,6 +186,12 @@ public: { return _m != nullptr; } + + /** + * Returns an iterable ensemble of all Tiles + * @return an iterable ensemble of all Tiles + */ + static IterateWrapper Iterate() { return IterateWrapper(); } }; /** diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 4c3e942255..28dad77a29 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -150,7 +150,7 @@ void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_wate static void ConvertTownOwner() { - for (TileIndex tile = 0; tile != Map::Size(); tile++) { + for (auto tile : Map::Iterate()) { switch (GetTileType(tile)) { case MP_ROAD: if (GB(_m[tile].m5, 4, 2) == ROAD_TILE_CROSSING && HasBit(_m[tile].m3, 7)) { @@ -566,8 +566,6 @@ bool AfterLoadGame() { SetSignalHandlers(); - TileIndex map_size = Map::Size(); - extern TileIndex _cur_tileloop_tile; // From landscape.cpp. /* The LFSR used in RunTileLoop iteration cannot have a zeroed state, make it non-zeroed. */ if (_cur_tileloop_tile == 0) _cur_tileloop_tile = 1; @@ -614,7 +612,7 @@ bool AfterLoadGame() for (Station *st : Station::Iterate()) { st->train_station.w = st->train_station.h = 0; } - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (!IsTileType(t, MP_STATION)) continue; if (_m[t].m5 > 7) continue; // is it a rail station tile? Station *st = Station::Get(_m[t].m2); @@ -631,7 +629,7 @@ bool AfterLoadGame() _settings_game.construction.map_height_limit = 15; /* In old savegame versions, the heightlevel was coded in bits 0..3 of the type field */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { _m[t].height = GB(_m[t].type, 0, 4); SB(_m[t].type, 0, 2, GB(_me[t].m6, 0, 2)); SB(_me[t].m6, 0, 2, 0); @@ -658,7 +656,7 @@ bool AfterLoadGame() * (4.3) version, so I just check when versions are older, and then * walk through the whole map.. */ if (IsSavegameVersionBefore(SLV_4, 3)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_WATER) && GetTileOwner(t) >= MAX_COMPANIES) { SetTileOwner(t, OWNER_WATER); } @@ -840,7 +838,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_72)) { /* Locks in very old savegames had OWNER_WATER as owner */ - for (TileIndex t = 0; t < Map::Size(); t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { default: break; @@ -894,7 +892,7 @@ bool AfterLoadGame() } } - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_STATION: { BaseStation *bst = BaseStation::GetByTile(t); @@ -964,7 +962,7 @@ bool AfterLoadGame() * to use m2 (16bit big), so we need to clean m2, and that is where this is * all about ;) */ if (IsSavegameVersionBefore(SLV_6, 1)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_HOUSE: _m[t].m4 = _m[t].m2; @@ -1019,7 +1017,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_48)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: if (IsPlainRail(t)) { @@ -1049,7 +1047,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_61)) { /* Added the RoadType */ bool old_bridge = IsSavegameVersionBefore(SLV_42); - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_ROAD: SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2)); @@ -1089,7 +1087,7 @@ bool AfterLoadGame() bool fix_roadtypes = !IsSavegameVersionBefore(SLV_61); bool old_bridge = IsSavegameVersionBefore(SLV_42); - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_ROAD: if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_me[t].m7, 5, 3)); @@ -1154,7 +1152,7 @@ bool AfterLoadGame() /* Railtype moved from m3 to m8 in version SLV_EXTEND_RAILTYPES. */ if (IsSavegameVersionBefore(SLV_EXTEND_RAILTYPES)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: SetRailType(t, (RailType)GB(_m[t].m3, 0, 4)); @@ -1185,7 +1183,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_42)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (MayHaveBridgeAbove(t)) ClearBridgeMiddle(t); if (IsBridgeTile(t)) { if (HasBit(_m[t].m5, 6)) { // middle part @@ -1267,7 +1265,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_ROAD_TYPES)) { /* Add road subtypes */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { bool has_road = false; switch (GetTileType(t)) { case MP_ROAD: @@ -1306,7 +1304,7 @@ bool AfterLoadGame() } /* .. so we convert the entire map from normal to elrail (so maintain "fairness") */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: SetRailType(t, UpdateRailType(GetRailType(t), min_rail)); @@ -1358,7 +1356,7 @@ bool AfterLoadGame() /* From version 15, we moved a semaphore bit from bit 2 to bit 3 in m4, making * room for PBS. Now in version 21 move it back :P. */ if (IsSavegameVersionBefore(SLV_21) && !IsSavegameVersionBefore(SLV_15)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: if (HasSignals(t)) { @@ -1438,7 +1436,7 @@ bool AfterLoadGame() * To give this prettiness to old savegames, we remove all farmfields and * plant new ones. */ if (IsSavegameVersionBefore(SLV_32)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) { /* remove fields */ MakeClear(t, CLEAR_GRASS, 3); @@ -1475,7 +1473,7 @@ bool AfterLoadGame() /* From version 53, the map array was changed for house tiles to allow * space for newhouses grf features. A new byte, m7, was also added. */ if (IsSavegameVersionBefore(SLV_53)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_HOUSE)) { if (GB(_m[t].m3, 6, 2) != TOWN_HOUSE_COMPLETED) { /* Move the construction stage from m3[7..6] to m5[5..4]. @@ -1512,7 +1510,7 @@ bool AfterLoadGame() UpdateHousesAndTowns(); if (IsSavegameVersionBefore(SLV_43)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_INDUSTRY)) { switch (GetIndustryGfx(t)) { case GFX_POWERPLANT_SPARKS: @@ -1572,7 +1570,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_49)) for (Company *c : Company::Iterate()) c->face = ConvertFromOldCompanyManagerFace(c->face); if (IsSavegameVersionBefore(SLV_52)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_OBJECT) && _m[t].m5 == OBJECT_STATUE) { _m[t].m2 = CalcClosestTownFromTile(t)->index; } @@ -1630,7 +1628,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_64)) { /* Since now we allow different signal types and variants on a single tile. * Move signal states to m4 to make room and clone the signal type/variant. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_RAILWAY) && HasSignals(t)) { /* move signal states */ SetSignalStates(t, GB(_m[t].m2, 4, 4)); @@ -1658,7 +1656,7 @@ bool AfterLoadGame() /* From version 82, old style canals (above sealevel (0), WATER owner) are no longer supported. Replace the owner for those by OWNER_NONE. */ if (IsSavegameVersionBefore(SLV_82)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_WATER) && GetWaterTileType(t) == WATER_TILE_CLEAR && GetTileOwner(t) == OWNER_WATER && @@ -1675,7 +1673,7 @@ bool AfterLoadGame() * making floods using the removal of ship depots. */ if (IsSavegameVersionBefore(SLV_83)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsShipDepotTile(t)) { _m[t].m4 = (TileHeight(t) == 0) ? OWNER_WATER : OWNER_NONE; } @@ -1709,7 +1707,7 @@ bool AfterLoadGame() * land used to have zero density, now they have full density. Therefore, * make all grassy/rough land trees have a density of 3. */ if (IsSavegameVersionBefore(SLV_81)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (GetTileType(t) == MP_TREES) { TreeGround groundType = (TreeGround)GB(_m[t].m2, 4, 2); if (groundType != TREE_GROUND_SNOW_DESERT) SB(_m[t].m2, 6, 2, 3); @@ -1767,7 +1765,7 @@ bool AfterLoadGame() /* The water class was moved/unified. */ if (IsSavegameVersionBefore(SLV_146)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_STATION: switch (GetStationType(t)) { @@ -1801,7 +1799,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_86)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { /* Move river flag and update canals to use water class */ if (IsTileType(t, MP_WATER)) { if (GetWaterClass(t) != WATER_CLASS_RIVER) { @@ -1823,7 +1821,7 @@ bool AfterLoadGame() /* Update locks, depots, docks and buoys to have a water class based * on its neighbouring tiles. Done after river and canal updates to * ensure neighbours are correct. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (!IsTileFlat(t)) continue; if (IsTileType(t, MP_WATER) && IsLock(t)) SetWaterClassDependingOnSurroundings(t, false); @@ -1832,7 +1830,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_87)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { /* skip oil rigs at borders! */ if ((IsTileType(t, MP_WATER) || IsBuoyTile(t)) && (TileX(t) == 0 || TileY(t) == 0 || TileX(t) == Map::MaxX() - 1 || TileY(t) == Map::MaxY() - 1)) { @@ -1899,7 +1897,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_91)) { /* Increase HouseAnimationFrame from 5 to 7 bits */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_HOUSE) && GetHouseType(t) >= NEW_HOUSE_OFFSET) { SB(_me[t].m6, 2, 6, GB(_me[t].m6, 3, 5)); SB(_m[t].m3, 5, 1, 0); @@ -1920,7 +1918,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_99)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { /* Set newly introduced WaterClass of industry tiles */ if (IsTileType(t, MP_STATION) && IsOilRig(t)) { SetWaterClassDependingOnSurroundings(t, true); @@ -1944,7 +1942,7 @@ bool AfterLoadGame() * format here, as an old layout wouldn't work properly anyway. To be safe, we * clear any possible PBS reservations as well. */ if (IsSavegameVersionBefore(SLV_100)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: if (HasSignals(t)) { @@ -2027,7 +2025,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_112)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { /* Check for HQ bit being set, instead of using map accessor, * since we've already changed it code-wise */ if (IsTileType(t, MP_OBJECT) && HasBit(_m[t].m5, 7)) { @@ -2039,7 +2037,7 @@ bool AfterLoadGame() } } if (IsSavegameVersionBefore(SLV_144)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (!IsTileType(t, MP_OBJECT)) continue; /* Reordering/generalisation of the object bits. */ @@ -2055,7 +2053,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_147) && Object::GetNumItems() == 0) { /* Make real objects for object tiles. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (!IsTileType(t, MP_OBJECT)) continue; if (Town::GetNumItems() == 0) { @@ -2322,7 +2320,7 @@ bool AfterLoadGame() /* The bits for the tree ground and tree density have * been swapped (m2 bits 7..6 and 5..4. */ if (IsSavegameVersionBefore(SLV_135)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_CLEAR)) { if (GetRawClearGround(t) == CLEAR_SNOW) { SetClearGroundDensity(t, CLEAR_GRASS, GetClearDensity(t)); @@ -2367,7 +2365,7 @@ bool AfterLoadGame() {119, 15}, // 14 unused tiles (radar) {140, 4}, // APT_GRASS_FENCE_NE_FLAG_2 }; - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsAirportTile(t)) { StationGfx old_gfx = GetStationGfx(t); byte offset = 0; @@ -2397,7 +2395,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_141)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { /* Reset tropic zone for VOID tiles, they shall not have any. */ if (IsTileType(t, MP_VOID)) SetTropicZone(t, TROPICZONE_NORMAL); } @@ -2438,7 +2436,7 @@ bool AfterLoadGame() /* Move the animation frame to the same location (m7) for all objects. */ if (IsSavegameVersionBefore(SLV_147)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_HOUSE: if (GetHouseType(t) >= NEW_HOUSE_OFFSET) { @@ -2477,7 +2475,7 @@ bool AfterLoadGame() } if (IsSavegameVersionBefore(SLV_149)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (!IsTileType(t, MP_STATION)) continue; if (!IsBuoy(t) && !IsOilRig(t) && !(IsDock(t) && IsTileFlat(t))) { SetWaterClass(t, WATER_CLASS_INVALID); @@ -2770,7 +2768,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_164) && !IsSavegameVersionBefore(SLV_32)) { /* We store 4 fences in the field tiles instead of only SE and SW. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (!IsTileType(t, MP_CLEAR) && !IsTileType(t, MP_TREES)) continue; if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) continue; uint fence = GB(_m[t].m4, 5, 3); @@ -2819,7 +2817,7 @@ bool AfterLoadGame() /* The road owner of standard road stops was not properly accounted for. */ if (IsSavegameVersionBefore(SLV_172)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (!IsStandardRoadStopTile(t)) continue; Owner o = GetTileOwner(t); SetRoadOwner(t, RTT_ROAD, o); @@ -2860,7 +2858,7 @@ bool AfterLoadGame() /* Blocked tiles could be reserved due to a bug, which causes * other places to assert upon e.g. station reconstruction. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (HasStationTileRail(t) && IsStationTileBlocked(t)) { SetRailStationReservation(t, false); } @@ -2880,7 +2878,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_186)) { /* Move ObjectType from map to pool */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_OBJECT)) { Object *o = Object::Get(_m[t].m2); o->type = _m[t].m5; @@ -3079,14 +3077,14 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_TREES_WATER_CLASS)) { /* Update water class for trees. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_TREES)) SetWaterClass(t, GetTreeGround(t) == TREE_GROUND_SHORE ? WATER_CLASS_SEA : WATER_CLASS_INVALID); } } /* Update structures for multitile docks */ if (IsSavegameVersionBefore(SLV_MULTITILE_DOCKS)) { - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { /* Clear docking tile flag from relevant tiles as it * was not previously cleared. */ if (IsTileType(t, MP_WATER) || IsTileType(t, MP_RAILWAY) || IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE)) { @@ -3108,7 +3106,7 @@ bool AfterLoadGame() if (IsSavegameVersionBeforeOrAt(SLV_ENDING_YEAR)) { /* Reset roadtype/streetcartype info for non-road bridges. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) != TRANSPORT_ROAD) { SetRoadTypes(t, INVALID_ROADTYPE, INVALID_ROADTYPE); } @@ -3191,7 +3189,7 @@ bool AfterLoadGame() if (IsSavegameVersionBeforeOrAt(SLV_MULTITRACK_LEVEL_CROSSINGS)) { /* Reset unused tree counters to reduce the savegame size. */ - for (TileIndex t = 0; t < map_size; t++) { + for (auto t : Map::Iterate()) { if (IsTileType(t, MP_TREES)) { SB(_m[t].m2, 0, 4, 0); } @@ -3199,7 +3197,7 @@ bool AfterLoadGame() } /* Refresh all level crossings to bar adjacent crossing tiles, if needed. */ - for (TileIndex tile = 0; tile < Map::Size(); tile++) { + for (auto tile : Map::Iterate()) { if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile, false); } }