mirror of https://github.com/OpenTTD/OpenTTD
Merge 9f9a074d27
into 3eba97f67c
commit
2f224f6922
|
@ -139,11 +139,13 @@ static void _GenerateWorld()
|
||||||
if (_game_mode != GM_MENU) FlatEmptyWorld(_settings_game.game_creation.se_flat_world_height);
|
if (_game_mode != GM_MENU) FlatEmptyWorld(_settings_game.game_creation.se_flat_world_height);
|
||||||
|
|
||||||
ConvertGroundTilesIntoWaterTiles();
|
ConvertGroundTilesIntoWaterTiles();
|
||||||
|
Map::CountLandTiles();
|
||||||
IncreaseGeneratingWorldProgress(GWP_OBJECT);
|
IncreaseGeneratingWorldProgress(GWP_OBJECT);
|
||||||
|
|
||||||
_settings_game.game_creation.snow_line_height = DEF_SNOWLINE_HEIGHT;
|
_settings_game.game_creation.snow_line_height = DEF_SNOWLINE_HEIGHT;
|
||||||
} else {
|
} else {
|
||||||
GenerateClearTile();
|
GenerateClearTile();
|
||||||
|
Map::CountLandTiles();
|
||||||
|
|
||||||
/* Only generate towns, tree and industries in newgame mode. */
|
/* Only generate towns, tree and industries in newgame mode. */
|
||||||
if (_game_mode != GM_EDITOR) {
|
if (_game_mode != GM_EDITOR) {
|
||||||
|
|
|
@ -64,7 +64,8 @@ enum GenWorldProgress : uint8_t {
|
||||||
GWP_RIVER, ///< Create the rivers
|
GWP_RIVER, ///< Create the rivers
|
||||||
GWP_ROUGH_ROCKY, ///< Make rough and rocky areas
|
GWP_ROUGH_ROCKY, ///< Make rough and rocky areas
|
||||||
GWP_TOWN, ///< Generate towns
|
GWP_TOWN, ///< Generate towns
|
||||||
GWP_INDUSTRY, ///< Generate industries
|
GWP_LAND_INDUSTRY, ///< Generate industries
|
||||||
|
GWP_WATER_INDUSTRY, ///< Generate industries
|
||||||
GWP_OBJECT, ///< Generate objects (radio tower, light houses)
|
GWP_OBJECT, ///< Generate objects (radio tower, light houses)
|
||||||
GWP_TREE, ///< Generate trees
|
GWP_TREE, ///< Generate trees
|
||||||
GWP_GAME_INIT, ///< Initialize the game
|
GWP_GAME_INIT, ///< Initialize the game
|
||||||
|
|
|
@ -1327,7 +1327,8 @@ static const StringID _generation_class_table[] = {
|
||||||
STR_GENERATION_RIVER_GENERATION,
|
STR_GENERATION_RIVER_GENERATION,
|
||||||
STR_GENERATION_CLEARING_TILES,
|
STR_GENERATION_CLEARING_TILES,
|
||||||
STR_GENERATION_TOWN_GENERATION,
|
STR_GENERATION_TOWN_GENERATION,
|
||||||
STR_GENERATION_INDUSTRY_GENERATION,
|
STR_GENERATION_LAND_INDUSTRY_GENERATION,
|
||||||
|
STR_GENERATION_WATER_INDUSTRY_GENERATION,
|
||||||
STR_GENERATION_OBJECT_GENERATION,
|
STR_GENERATION_OBJECT_GENERATION,
|
||||||
STR_GENERATION_TREE_GENERATION,
|
STR_GENERATION_TREE_GENERATION,
|
||||||
STR_GENERATION_SETTINGUP_GAME,
|
STR_GENERATION_SETTINGUP_GAME,
|
||||||
|
@ -1435,7 +1436,7 @@ void ShowGenerateWorldProgress()
|
||||||
|
|
||||||
static void _SetGeneratingWorldProgress(GenWorldProgress cls, uint progress, uint total)
|
static void _SetGeneratingWorldProgress(GenWorldProgress cls, uint progress, uint total)
|
||||||
{
|
{
|
||||||
static const int percent_table[] = {0, 5, 14, 17, 20, 40, 60, 65, 80, 85, 95, 99, 100 };
|
static const int percent_table[] = {0, 5, 14, 17, 20, 40, 55, 60, 65, 80, 85, 95, 99, 100 };
|
||||||
static_assert(lengthof(percent_table) == GWP_CLASS_COUNT + 1);
|
static_assert(lengthof(percent_table) == GWP_CLASS_COUNT + 1);
|
||||||
assert(cls < GWP_CLASS_COUNT);
|
assert(cls < GWP_CLASS_COUNT);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "industry_cmd.h"
|
#include "industry_cmd.h"
|
||||||
#include "landscape_cmd.h"
|
#include "landscape_cmd.h"
|
||||||
#include "terraform_cmd.h"
|
#include "terraform_cmd.h"
|
||||||
|
#include "map_func.h"
|
||||||
#include "timer/timer.h"
|
#include "timer/timer.h"
|
||||||
#include "timer/timer_game_calendar.h"
|
#include "timer/timer_game_calendar.h"
|
||||||
#include "timer/timer_game_economy.h"
|
#include "timer/timer_game_economy.h"
|
||||||
|
@ -2284,9 +2285,11 @@ static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAv
|
||||||
* @param[out] force_at_least_one Returns whether at least one instance should be forced on map creation.
|
* @param[out] force_at_least_one Returns whether at least one instance should be forced on map creation.
|
||||||
* @return Relative probability for the industry to appear.
|
* @return Relative probability for the industry to appear.
|
||||||
*/
|
*/
|
||||||
static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
|
static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, std::optional<bool> water, bool *force_at_least_one)
|
||||||
{
|
{
|
||||||
const IndustrySpec *ind_spc = GetIndustrySpec(it);
|
const IndustrySpec *ind_spc = GetIndustrySpec(it);
|
||||||
|
if (water.has_value() && ind_spc->behaviour.Test(IndustryBehaviour::BuiltOnWater) != *water) return 0;
|
||||||
|
|
||||||
uint32_t chance = ind_spc->appear_creation[to_underlying(_settings_game.game_creation.landscape)];
|
uint32_t chance = ind_spc->appear_creation[to_underlying(_settings_game.game_creation.landscape)];
|
||||||
if (!ind_spc->enabled || ind_spc->layouts.empty() ||
|
if (!ind_spc->enabled || ind_spc->layouts.empty() ||
|
||||||
(_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
|
(_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
|
||||||
|
@ -2378,11 +2381,11 @@ static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType c
|
||||||
* @param type IndustryType of the desired industry
|
* @param type IndustryType of the desired industry
|
||||||
* @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
|
* @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
|
||||||
*/
|
*/
|
||||||
static void PlaceInitialIndustry(IndustryType type, bool try_hard)
|
static void PlaceInitialIndustry(IndustryType type, bool water, bool try_hard)
|
||||||
{
|
{
|
||||||
Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
|
Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
|
||||||
|
|
||||||
IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
|
IncreaseGeneratingWorldProgress(water ? GWP_WATER_INDUSTRY : GWP_LAND_INDUSTRY);
|
||||||
PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
|
PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
|
||||||
|
|
||||||
cur_company.Restore();
|
cur_company.Restore();
|
||||||
|
@ -2436,6 +2439,31 @@ void IndustryBuildData::EconomyMonthlyLoop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IndustryGenerationProbabilities {
|
||||||
|
std::array<uint32_t, NUM_INDUSTRYTYPES> probs{};
|
||||||
|
std::array<bool, NUM_INDUSTRYTYPES> force_one{};
|
||||||
|
uint64_t total = 0;
|
||||||
|
uint num_forced = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get scaled industry generation probabilities.
|
||||||
|
* @param water Whether to get land or water industry probabilities.
|
||||||
|
* @returns Probability information.
|
||||||
|
*/
|
||||||
|
static IndustryGenerationProbabilities GetScaledProbabilities(bool water)
|
||||||
|
{
|
||||||
|
IndustryGenerationProbabilities p{};
|
||||||
|
|
||||||
|
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
||||||
|
p.probs[it] = GetScaledIndustryGenerationProbability(it, water, &p.force_one[it]);
|
||||||
|
p.total += p.probs[it];;
|
||||||
|
if (p.force_one[it]) p.num_forced++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function will create random industries during game creation.
|
* This function will create random industries during game creation.
|
||||||
* It will scale the amount of industries by mapsize and difficulty level.
|
* It will scale the amount of industries by mapsize and difficulty level.
|
||||||
|
@ -2444,46 +2472,54 @@ void GenerateIndustries()
|
||||||
{
|
{
|
||||||
if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
|
if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
|
||||||
|
|
||||||
uint32_t industry_probs[NUM_INDUSTRYTYPES];
|
/* Get the probabilities for all industries. This is done first as we need the total of
|
||||||
bool force_at_least_one[NUM_INDUSTRYTYPES];
|
* both land and water for scaling later. */
|
||||||
uint32_t total_prob = 0;
|
IndustryGenerationProbabilities lprob = GetScaledProbabilities(false);
|
||||||
uint num_forced = 0;
|
IndustryGenerationProbabilities wprob = GetScaledProbabilities(true);
|
||||||
|
|
||||||
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
/* Run generation twice, for land and water industries in turn. */
|
||||||
industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
|
for (bool water = false;; water = true) {
|
||||||
total_prob += industry_probs[it];
|
auto &p = water ? wprob : lprob;
|
||||||
if (force_at_least_one[it]) num_forced++;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint total_amount = GetNumberOfIndustries();
|
/* Total number of industries scaled by land/water proportion. */
|
||||||
if (total_prob == 0 || total_amount < num_forced) {
|
uint total_amount = p.total * GetNumberOfIndustries() / (lprob.total + wprob.total);
|
||||||
/* Only place the forced ones */
|
|
||||||
total_amount = num_forced;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
|
/* Scale land-based industries to the land proportion. */
|
||||||
|
if (!water) total_amount = Map::ScaleByLandProportion(total_amount);
|
||||||
|
|
||||||
/* Try to build one industry per type independent of any probabilities */
|
/* Ensure that forced industries are generated even if the scaled amounts are too low. */
|
||||||
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
if (p.total == 0 || total_amount < p.num_forced) {
|
||||||
if (force_at_least_one[it]) {
|
/* Only place the forced ones */
|
||||||
assert(total_amount > 0);
|
total_amount = p.num_forced;
|
||||||
total_amount--;
|
|
||||||
PlaceInitialIndustry(it, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetGeneratingWorldProgress(water ? GWP_WATER_INDUSTRY : GWP_LAND_INDUSTRY, total_amount);
|
||||||
|
|
||||||
|
/* Try to build one industry per type independent of any probabilities */
|
||||||
|
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
||||||
|
if (p.force_one[it]) {
|
||||||
|
assert(total_amount > 0);
|
||||||
|
total_amount--;
|
||||||
|
PlaceInitialIndustry(it, water, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the remaining industries according to their probabilities */
|
||||||
|
for (uint i = 0; i < total_amount; i++) {
|
||||||
|
uint32_t r = RandomRange(p.total);
|
||||||
|
IndustryType it = 0;
|
||||||
|
while (r >= p.probs[it]) {
|
||||||
|
r -= p.probs[it];
|
||||||
|
it++;
|
||||||
|
assert(it < NUM_INDUSTRYTYPES);
|
||||||
|
}
|
||||||
|
assert(p.probs[it] > 0);
|
||||||
|
PlaceInitialIndustry(it, water, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (water) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the remaining industries according to their probabilities */
|
|
||||||
for (uint i = 0; i < total_amount; i++) {
|
|
||||||
uint32_t r = RandomRange(total_prob);
|
|
||||||
IndustryType it = 0;
|
|
||||||
while (r >= industry_probs[it]) {
|
|
||||||
r -= industry_probs[it];
|
|
||||||
it++;
|
|
||||||
assert(it < NUM_INDUSTRYTYPES);
|
|
||||||
}
|
|
||||||
assert(industry_probs[it] > 0);
|
|
||||||
PlaceInitialIndustry(it, false);
|
|
||||||
}
|
|
||||||
_industry_builder.Reset();
|
_industry_builder.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3083,7 +3119,7 @@ void CheckIndustries()
|
||||||
if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
|
if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
|
||||||
|
|
||||||
bool force_at_least_one;
|
bool force_at_least_one;
|
||||||
uint32_t chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
|
uint32_t chance = GetScaledIndustryGenerationProbability(it, std::nullopt, &force_at_least_one);
|
||||||
if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
|
if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
|
||||||
|
|
||||||
const IndustrySpec *is = GetIndustrySpec(it);
|
const IndustrySpec *is = GetIndustrySpec(it);
|
||||||
|
|
|
@ -3454,7 +3454,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landscap
|
||||||
STR_GENERATION_RIVER_GENERATION :{BLACK}River generation
|
STR_GENERATION_RIVER_GENERATION :{BLACK}River generation
|
||||||
STR_GENERATION_CLEARING_TILES :{BLACK}Rough and rocky area generation
|
STR_GENERATION_CLEARING_TILES :{BLACK}Rough and rocky area generation
|
||||||
STR_GENERATION_TOWN_GENERATION :{BLACK}Town generation
|
STR_GENERATION_TOWN_GENERATION :{BLACK}Town generation
|
||||||
STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industry generation
|
STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Land industry generation
|
||||||
|
STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Water industry generation
|
||||||
STR_GENERATION_OBJECT_GENERATION :{BLACK}Object generation
|
STR_GENERATION_OBJECT_GENERATION :{BLACK}Object generation
|
||||||
STR_GENERATION_TREE_GENERATION :{BLACK}Tree generation
|
STR_GENERATION_TREE_GENERATION :{BLACK}Tree generation
|
||||||
STR_GENERATION_SETTINGUP_GAME :{BLACK}Setting up game
|
STR_GENERATION_SETTINGUP_GAME :{BLACK}Setting up game
|
||||||
|
|
11
src/map.cpp
11
src/map.cpp
|
@ -23,6 +23,8 @@
|
||||||
/* static */ uint Map::size; ///< The number of tiles on the map
|
/* static */ uint Map::size; ///< The number of tiles on the map
|
||||||
/* static */ uint Map::tile_mask; ///< _map_size - 1 (to mask the mapsize)
|
/* static */ uint Map::tile_mask; ///< _map_size - 1 (to mask the mapsize)
|
||||||
|
|
||||||
|
/* static */ uint Map::initial_land_count; ///< Initial number of land tiles on the map.
|
||||||
|
|
||||||
/* static */ std::unique_ptr<Tile::TileBase[]> Tile::base_tiles; ///< Base tiles of the map
|
/* static */ std::unique_ptr<Tile::TileBase[]> Tile::base_tiles; ///< Base tiles of the map
|
||||||
/* static */ std::unique_ptr<Tile::TileExtended[]> Tile::extended_tiles; ///< Extended tiles of the map
|
/* static */ std::unique_ptr<Tile::TileExtended[]> Tile::extended_tiles; ///< Extended tiles of the map
|
||||||
|
|
||||||
|
@ -58,6 +60,15 @@
|
||||||
AllocateWaterRegions();
|
AllocateWaterRegions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void Map::CountLandTiles()
|
||||||
|
{
|
||||||
|
/* Count number of tiles that are land. */
|
||||||
|
Map::initial_land_count = 0;
|
||||||
|
for (const auto tile : Map::Iterate()) {
|
||||||
|
Map::initial_land_count += IsWaterTile(tile) ? 0 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
|
TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
|
||||||
|
|
|
@ -239,8 +239,11 @@ private:
|
||||||
static uint size; ///< The number of tiles on the map
|
static uint size; ///< The number of tiles on the map
|
||||||
static uint tile_mask; ///< _map_size - 1 (to mask the mapsize)
|
static uint tile_mask; ///< _map_size - 1 (to mask the mapsize)
|
||||||
|
|
||||||
|
static uint initial_land_count; ///< Initial number of land tiles on the map.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Allocate(uint size_x, uint size_y);
|
static void Allocate(uint size_x, uint size_y);
|
||||||
|
static void CountLandTiles();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logarithm of the map size along the X side.
|
* Logarithm of the map size along the X side.
|
||||||
|
@ -307,6 +310,16 @@ public:
|
||||||
return Map::SizeY() - 1;
|
return Map::SizeY() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales the given value by the number of water tiles.
|
||||||
|
* @param n the value to scale
|
||||||
|
* @return the scaled size
|
||||||
|
*/
|
||||||
|
static inline uint ScaleByLandProportion(uint n)
|
||||||
|
{
|
||||||
|
/* Use 64-bit arithmetic to avoid overflow. */
|
||||||
|
return static_cast<uint>(static_cast<uint64_t>(n) * Map::initial_land_count / Map::size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'Wraps' the given "tile" so it is within the map.
|
* 'Wraps' the given "tile" so it is within the map.
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "road_cmd.h"
|
#include "road_cmd.h"
|
||||||
#include "terraform_cmd.h"
|
#include "terraform_cmd.h"
|
||||||
#include "tunnelbridge_cmd.h"
|
#include "tunnelbridge_cmd.h"
|
||||||
|
#include "map_func.h"
|
||||||
#include "timer/timer.h"
|
#include "timer/timer.h"
|
||||||
#include "timer/timer_game_calendar.h"
|
#include "timer/timer_game_calendar.h"
|
||||||
#include "timer/timer_game_economy.h"
|
#include "timer/timer_game_economy.h"
|
||||||
|
@ -2384,7 +2385,7 @@ bool GenerateTowns(TownLayout layout)
|
||||||
{
|
{
|
||||||
uint current_number = 0;
|
uint current_number = 0;
|
||||||
uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.number_towns : 0;
|
uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.number_towns : 0;
|
||||||
uint total = (difficulty == (uint)CUSTOM_TOWN_NUMBER_DIFFICULTY) ? _settings_game.game_creation.custom_town_number : Map::ScaleBySize(_num_initial_towns[difficulty] + (Random() & 7));
|
uint total = (difficulty == (uint)CUSTOM_TOWN_NUMBER_DIFFICULTY) ? _settings_game.game_creation.custom_town_number : Map::ScaleByLandProportion(Map::ScaleBySize(_num_initial_towns[difficulty] + (Random() & 7)));
|
||||||
total = std::min<uint>(TownPool::MAX_SIZE, total);
|
total = std::min<uint>(TownPool::MAX_SIZE, total);
|
||||||
uint32_t townnameparts;
|
uint32_t townnameparts;
|
||||||
TownNames town_names;
|
TownNames town_names;
|
||||||
|
|
Loading…
Reference in New Issue