From f98b90ac2edc3da861bf5c60dd90015933f0a38f Mon Sep 17 00:00:00 2001 From: dP Date: Tue, 2 Jul 2024 00:39:25 +0500 Subject: [PATCH] Codechange: Use constants for tree growth stages and tile update frequency (#12833) --- src/industry_cmd.cpp | 2 +- src/landscape.cpp | 20 ++++++++++-------- src/tree_cmd.cpp | 45 +++++++++++++++++++++-------------------- src/tree_map.h | 48 ++++++++++++++++++++++++++++---------------- 4 files changed, 67 insertions(+), 48 deletions(-) diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 8596b6e658cce..a36676245e4d4 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -1102,7 +1102,7 @@ void PlantRandomFarmField(const Industry *i) */ static bool SearchLumberMillTrees(TileIndex tile, void *) { - if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees + if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) >= TreeGrowthStage::Grown) { /* found a tree */ Backup cur_company(_current_company, OWNER_NONE); diff --git a/src/landscape.cpp b/src/landscape.cpp index 121c6035698e8..7964e3ba02b5a 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -82,6 +82,9 @@ extern const uint8_t _slope_to_sprite_offset[32] = { 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 15, 18, 0, }; +static const uint TILE_UPDATE_FREQUENCY_LOG = 8; ///< The logarithm of how many ticks it takes between tile updates (log base 2). +static const uint TILE_UPDATE_FREQUENCY = 1 << TILE_UPDATE_FREQUENCY_LOG; ///< How many ticks it takes between tile updates (has to be a power of 2). + /** * Description of the snow line throughout the year. * @@ -759,7 +762,7 @@ std::tuple CmdClearArea(DoCommandFlag flags, TileIndex tile, TileIndex _cur_tileloop_tile; /** - * Gradually iterate over all tiles on the map, calling their TileLoopProcs once every 256 ticks. + * Gradually iterate over all tiles on the map, calling their TileLoopProcs once every TILE_UPDATE_FREQUENCY ticks. */ void RunTileLoop() { @@ -777,15 +780,16 @@ void RunTileLoop() static_assert(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1); const uint32_t feedback = feedbacks[Map::LogX() + Map::LogY() - 2 * MIN_MAP_SIZE_BITS]; - /* We update every tile every 256 ticks, so divide the map size by 2^8 = 256 */ - uint count = 1 << (Map::LogX() + Map::LogY() - 8); + /* We update every tile every TILE_UPDATE_FREQUENCY ticks, so divide the map size by 2^TILE_UPDATE_FREQUENCY_LOG = TILE_UPDATE_FREQUENCY */ + static_assert(2 * MIN_MAP_SIZE_BITS >= TILE_UPDATE_FREQUENCY_LOG); + uint count = 1 << (Map::LogX() + Map::LogY() - TILE_UPDATE_FREQUENCY_LOG); TileIndex tile = _cur_tileloop_tile; /* The LFSR cannot have a zeroed state. */ assert(tile != 0); - /* Manually update tile 0 every 256 ticks - the LFSR never iterates over it itself. */ - if (TimerGameTick::counter % 256 == 0) { + /* Manually update tile 0 every TILE_UPDATE_FREQUENCY ticks - the LFSR never iterates over it itself. */ + if (TimerGameTick::counter % TILE_UPDATE_FREQUENCY == 0) { _tile_type_procs[GetTileType(0)]->tile_loop_proc(0); count--; } @@ -958,7 +962,7 @@ static void CreateDesertOrRainForest(uint desert_tropic_line) } } - for (uint i = 0; i != 256; i++) { + for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) { if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); RunTileLoop(); @@ -1401,7 +1405,7 @@ static void CreateRivers() uint wells = Map::ScaleBySize(4 << _settings_game.game_creation.amount_of_rivers); const uint num_short_rivers = wells - std::max(1u, wells / 10); - SetGeneratingWorldProgress(GWP_RIVER, wells + 256 / 64); // Include the tile loop calls below. + SetGeneratingWorldProgress(GWP_RIVER, wells + TILE_UPDATE_FREQUENCY / 64); // Include the tile loop calls below. /* Try to create long rivers. */ for (; wells > num_short_rivers; wells--) { @@ -1427,7 +1431,7 @@ static void CreateRivers() ConvertGroundTilesIntoWaterTiles(); /* Run tile loop to update the ground density. */ - for (uint i = 0; i != 256; i++) { + for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) { if (i % 64 == 0) IncreaseGeneratingWorldProgress(GWP_RIVER); RunTileLoop(); } diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 1a58c6c2e1a9e..1cf11de25d970 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -91,7 +91,7 @@ static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert) * @param count the number of trees (minus 1) * @param growth the growth status */ -static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, uint growth) +static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, TreeGrowthStage growth) { assert(treetype != TREE_INVALID); assert(CanPlantTreesOnTile(tile, true)); @@ -135,20 +135,20 @@ static TreeType GetRandomTreeType(TileIndex tile, uint seed) { switch (_settings_game.game_creation.landscape) { case LT_TEMPERATE: - return (TreeType)(seed * TREE_COUNT_TEMPERATE / 256 + TREE_TEMPERATE); + return static_cast(seed * TREE_COUNT_TEMPERATE / 256 + TREE_TEMPERATE); case LT_ARCTIC: - return (TreeType)(seed * TREE_COUNT_SUB_ARCTIC / 256 + TREE_SUB_ARCTIC); + return static_cast(seed * TREE_COUNT_SUB_ARCTIC / 256 + TREE_SUB_ARCTIC); case LT_TROPIC: switch (GetTropicZone(tile)) { - case TROPICZONE_NORMAL: return (TreeType)(seed * TREE_COUNT_SUB_TROPICAL / 256 + TREE_SUB_TROPICAL); - case TROPICZONE_DESERT: return (TreeType)((seed > 12) ? TREE_INVALID : TREE_CACTUS); - default: return (TreeType)(seed * TREE_COUNT_RAINFOREST / 256 + TREE_RAINFOREST); + case TROPICZONE_NORMAL: return static_cast(seed * TREE_COUNT_SUB_TROPICAL / 256 + TREE_SUB_TROPICAL); + case TROPICZONE_DESERT: return static_cast((seed > 12) ? TREE_INVALID : TREE_CACTUS); + default: return static_cast(seed * TREE_COUNT_RAINFOREST / 256 + TREE_RAINFOREST); } default: - return (TreeType)(seed * TREE_COUNT_TOYLAND / 256 + TREE_TOYLAND); + return static_cast(seed * TREE_COUNT_TOYLAND / 256 + TREE_TOYLAND); } } @@ -166,7 +166,7 @@ static void PlaceTree(TileIndex tile, uint32_t r) TreeType tree = GetRandomTreeType(tile, GB(r, 24, 8)); if (tree != TREE_INVALID) { - PlantTreesOnTile(tile, tree, GB(r, 22, 2), std::min(GB(r, 16, 3), 6)); + PlantTreesOnTile(tile, tree, GB(r, 22, 2), static_cast(std::min(GB(r, 16, 3), 6))); MarkTileDirtyByTile(tile); /* Rerandomize ground, if neither snow nor shore */ @@ -324,11 +324,11 @@ uint PlaceTreeGroupAroundTile(TileIndex tile, TreeType treetype, uint radius, ui if (tile_to_plant != INVALID_TILE) { if (IsTileType(tile_to_plant, MP_TREES) && GetTreeCount(tile_to_plant) < 4) { AddTreeCount(tile_to_plant, 1); - SetTreeGrowth(tile_to_plant, 0); + SetTreeGrowth(tile_to_plant, TreeGrowthStage::Growing1); MarkTileDirtyByTile(tile_to_plant, 0); planted++; } else if (CanPlantTreesOnTile(tile_to_plant, allow_desert)) { - PlantTreesOnTile(tile_to_plant, treetype, 0, 3); + PlantTreesOnTile(tile_to_plant, treetype, 0, TreeGrowthStage::Grown); MarkTileDirtyByTile(tile_to_plant, 0); planted++; } @@ -482,7 +482,7 @@ CommandCost CmdPlantTree(DoCommandFlag flags, TileIndex tile, TileIndex start_ti } /* Plant full grown trees in scenario editor */ - PlantTreesOnTile(current_tile, treetype, 0, _game_mode == GM_EDITOR ? 3 : 0); + PlantTreesOnTile(current_tile, treetype, 0, _game_mode == GM_EDITOR ? TreeGrowthStage::Grown : TreeGrowthStage::Growing1); MarkTileDirtyByTile(current_tile); if (c != nullptr) c->tree_limit -= 1 << 16; @@ -551,7 +551,7 @@ static void DrawTile_Trees(TileInfo *ti) uint trees = GetTreeCount(ti->tile); for (uint i = 0; i < trees; i++) { - SpriteID sprite = s[0].sprite + (i == trees - 1 ? GetTreeGrowth(ti->tile) : 3); + SpriteID sprite = s[0].sprite + (i == trees - 1 ? static_cast(GetTreeGrowth(ti->tile)) : 3); PaletteID pal = s[0].pal; te[i].sprite = sprite; @@ -723,10 +723,11 @@ static void TileLoop_Trees(TileIndex tile) if (_settings_game.construction.extra_tree_placement == ETP_NO_GROWTH_NO_SPREAD) return; - if ((cycle & 15) != 15) return; + static const uint32_t TREE_UPDATE_FREQUENCY = 16; // How many tile updates happen for one tree update + if (cycle % TREE_UPDATE_FREQUENCY != TREE_UPDATE_FREQUENCY - 1) return; switch (GetTreeGrowth(tile)) { - case 3: // regular sized tree + case TreeGrowthStage::Grown: // regular sized tree if (_settings_game.game_creation.landscape == LT_TROPIC && GetTreeType(tile) != TREE_CACTUS && GetTropicZone(tile) == TROPICZONE_DESERT) { @@ -740,7 +741,7 @@ static void TileLoop_Trees(TileIndex tile) case 1: // add a tree if (GetTreeCount(tile) < 4 && CanPlantExtraTrees(tile)) { AddTreeCount(tile, 1); - SetTreeGrowth(tile, 0); + SetTreeGrowth(tile, TreeGrowthStage::Growing1); break; } [[fallthrough]]; @@ -750,7 +751,7 @@ static void TileLoop_Trees(TileIndex tile) TreeType treetype = GetTreeType(tile); - tile += TileOffsByDir((Direction)(Random() & 7)); + tile += TileOffsByDir(static_cast(Random() % DIR_END)); /* Cacti don't spread */ if (!CanPlantTreesOnTile(tile, false)) return; @@ -758,7 +759,7 @@ static void TileLoop_Trees(TileIndex tile) /* Don't plant trees, if ground was freshly cleared */ if (IsTileType(tile, MP_CLEAR) && GetClearGround(tile) == CLEAR_GRASS && GetClearDensity(tile) != 3) return; - PlantTreesOnTile(tile, treetype, 0, 0); + PlantTreesOnTile(tile, treetype, 0, TreeGrowthStage::Growing1); break; } @@ -769,14 +770,14 @@ static void TileLoop_Trees(TileIndex tile) } break; - case 6: // final stage of tree destruction + case TreeGrowthStage::Dead: // final stage of tree destruction if (!CanPlantExtraTrees(tile)) { /* if trees can't spread just plant a new one to prevent deforestation */ - SetTreeGrowth(tile, 0); + SetTreeGrowth(tile, TreeGrowthStage::Growing1); } else if (GetTreeCount(tile) > 1) { /* more than one tree, delete it */ AddTreeCount(tile, -1); - SetTreeGrowth(tile, 3); + SetTreeGrowth(tile, TreeGrowthStage::Grown); } else { /* just one tree, change type into MP_CLEAR */ switch (GetTreeGround(tile)) { @@ -848,7 +849,7 @@ void OnTick_Trees() if ((r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) && CanPlantTreesOnTile(tile, false) && (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { - PlantTreesOnTile(tile, tree, 0, 0); + PlantTreesOnTile(tile, tree, 0, TreeGrowthStage::Growing1); } } } @@ -859,7 +860,7 @@ void OnTick_Trees() r = Random(); tile = RandomTileSeed(r); if (CanPlantTreesOnTile(tile, false) && (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { - PlantTreesOnTile(tile, tree, 0, 0); + PlantTreesOnTile(tile, tree, 0, TreeGrowthStage::Growing1); } } diff --git a/src/tree_map.h b/src/tree_map.h index 3992b47a751fe..25a2e71a0bca4 100644 --- a/src/tree_map.h +++ b/src/tree_map.h @@ -57,6 +57,20 @@ enum TreeGround { TREE_GROUND_ROUGH_SNOW = 4, ///< A snow tile that is rough underneath. }; +/** + * Enumeration for tree growth stages. + * + * This enumeration defines the stages of tree growth for tiles with trees on it. + */ +enum class TreeGrowthStage : uint { + Growing1 = 0, ///< First stage of growth + Growing2 = 1, ///< Second stage of growth + Growing3 = 2, ///< Third stage of growth + Grown = 3, ///< Fully grown tree + Dying1 = 4, ///< First stage of dying + Dying2 = 5, ///< Second stage of dying + Dead = 6, ///< Dead tree +}; /** * Returns the treetype of a tile. @@ -170,27 +184,27 @@ inline void AddTreeCount(Tile t, int c) } /** - * Returns the tree growth status. + * Returns the tree growth stage. * - * This function returns the tree growth status of a tile with trees. + * This function returns the tree growth stage of a tile with trees. * - * @param t The tile to get the tree growth status - * @return The tree growth status + * @param t The tile to get the tree growth stage + * @return The tree growth stage * @pre Tile must be of type MP_TREES */ -inline uint GetTreeGrowth(Tile t) +inline TreeGrowthStage GetTreeGrowth(Tile t) { assert(IsTileType(t, MP_TREES)); - return GB(t.m5(), 0, 3); + return static_cast(GB(t.m5(), 0, 3)); } /** - * Add a value to the tree growth status. + * Add a value to the tree growth stage. * - * This function adds a value to the tree grow status of a tile. + * This function adds a value to the tree grow stage of a tile. * * @param t The tile to add the value on - * @param a The value to add on the tree growth status + * @param a The value to add on the tree growth stage * @pre Tile must be of type MP_TREES */ inline void AddTreeGrowth(Tile t, int a) @@ -200,19 +214,19 @@ inline void AddTreeGrowth(Tile t, int a) } /** - * Sets the tree growth status of a tile. + * Sets the tree growth stage of a tile. * - * This function sets the tree growth status of a tile directly with + * This function sets the tree growth stage of a tile directly with * the given value. * - * @param t The tile to change the tree growth status + * @param t The tile to change the tree growth stage * @param g The new value * @pre Tile must be of type MP_TREES */ -inline void SetTreeGrowth(Tile t, uint g) +inline void SetTreeGrowth(Tile t, TreeGrowthStage g) { assert(IsTileType(t, MP_TREES)); // XXX incomplete - SB(t.m5(), 0, 3, g); + SB(t.m5(), 0, 3, static_cast(g)); } /** @@ -223,11 +237,11 @@ inline void SetTreeGrowth(Tile t, uint g) * @param t The tile to make a tree-tile from * @param type The type of the tree * @param count the number of trees - * @param growth the growth status + * @param growth the growth stage * @param ground the ground type * @param density the density (not the number of trees) */ -inline void MakeTree(Tile t, TreeType type, uint count, uint growth, TreeGround ground, uint density) +inline void MakeTree(Tile t, TreeType type, uint count, TreeGrowthStage growth, TreeGround ground, uint density) { SetTileType(t, MP_TREES); SetTileOwner(t, OWNER_NONE); @@ -235,7 +249,7 @@ inline void MakeTree(Tile t, TreeType type, uint count, uint growth, TreeGround t.m2() = ground << 6 | density << 4 | 0; t.m3() = type; t.m4() = 0 << 5 | 0 << 2; - t.m5() = count << 6 | growth; + t.m5() = count << 6 | static_cast(growth); SB(t.m6(), 2, 4, 0); t.m7() = 0; }