Codechange: introduce iterator to iterate over the Tiles of a Map

Note: this version is using TileIndex, but that changes later
This commit is contained in:
Rubidium 2023-01-21 17:07:06 +01:00 committed by rubidium42
parent 20a1b24b45
commit 0fb0469e47
2 changed files with 81 additions and 49 deletions

View File

@ -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(); }
};
/**

View File

@ -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);
}
}