Fix #9242: Tree tick handler did not scale by map size. (#9246)

This means that random tree generation density is higher on small maps and lower on large maps. This difference is enough to make the Lumber Mill impractical to use on large maps.

This change skips ticks on maps smaller than 256x256 and increases iterations or shortens the interval on maps larger than 256x256.
This commit is contained in:
PeterN 2021-05-12 18:17:57 +01:00 committed by GitHub
parent 7b7dbbc935
commit b972ed8604
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 33 additions and 7 deletions

View File

@ -22,6 +22,7 @@
#include "company_base.h"
#include "core/random_func.hpp"
#include "newgrf_generic.h"
#include "date_func.h"
#include "table/strings.h"
#include "table/tree_land.h"
@ -803,6 +804,23 @@ static void TileLoop_Trees(TileIndex tile)
MarkTileDirtyByTile(tile);
}
/**
* Decrement the tree tick counter.
* The interval is scaled by map size to allow for the same density regardless of size.
* Adjustment for map sizes below the standard 256 * 256 are handled earlier.
* @return true if the counter was decremented past zero
*/
bool DecrementTreeCounter()
{
/* Ensure _trees_tick_ctr can be decremented past zero only once for the largest map size. */
static_assert(2 * (MAX_MAP_SIZE_BITS - MIN_MAP_SIZE_BITS) - 4 <= std::numeric_limits<byte>::digits);
/* byte underflow */
byte old_trees_tick_ctr = _trees_tick_ctr;
_trees_tick_ctr -= ScaleByMapSize(1);
return old_trees_tick_ctr <= _trees_tick_ctr;
}
void OnTick_Trees()
{
/* Don't spread trees if that's not allowed */
@ -812,16 +830,24 @@ void OnTick_Trees()
TileIndex tile;
TreeType tree;
/* Skip some tree ticks for map sizes below 256 * 256. 64 * 64 is 16 times smaller, so
* this is the maximum number of ticks that are skipped. Number of ticks to skip is
* inversely proportional to map size, so that is handled to create a mask. */
int skip = ScaleByMapSize(16);
if (skip < 16 && (_tick_counter & (16 / skip - 1)) != 0) return;
/* place a tree at a random rainforest spot */
if (_settings_game.game_creation.landscape == LT_TROPIC &&
(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);
if (_settings_game.game_creation.landscape == LT_TROPIC) {
for (uint c = ScaleByMapSize(1); c > 0; c--) {
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);
}
}
}
/* byte underflow */
if (--_trees_tick_ctr != 0 || _settings_game.construction.extra_tree_placement == ETP_SPREAD_RAINFOREST) return;
if (!DecrementTreeCounter() || _settings_game.construction.extra_tree_placement == ETP_SPREAD_RAINFOREST) return;
/* place a tree at a random spot */
r = Random();