OpenTTD Source 20260731-master-g77ba2b244a
landscape.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
11
12#include "stdafx.h"
13#include "heightmap.h"
14#include "clear_map.h"
15#include "spritecache.h"
16#include "station_map.h"
17#include "viewport_func.h"
18#include "command_func.h"
19#include "landscape.h"
20#include "void_map.h"
21#include "tgp.h"
22#include "genworld.h"
23#include "fios.h"
24#include "error_func.h"
27#include "water.h"
28#include "effectvehicle_func.h"
29#include "landscape_type.h"
30#include "animated_tile_func.h"
31#include "core/random_func.hpp"
32#include "object_base.h"
33#include "tree_cmd.h"
34#include "company_func.h"
35#include "company_gui.h"
37#include "framerate_type.h"
38#include "landscape_cmd.h"
39#include "terraform_cmd.h"
40#include "station_func.h"
43
44#include "table/strings.h"
45#include "table/sprites.h"
46
47#include <unordered_set>
48
49#include "safeguards.h"
50
51extern const TileTypeProcs
63
70 &_tile_type_clear_procs, // Callback functions for TileType::Clear tiles
71 &_tile_type_rail_procs, // Callback functions for TileType::Railway tiles
72 &_tile_type_road_procs, // Callback functions for TileType::Road tiles
73 &_tile_type_town_procs, // Callback functions for TileType::House tiles
74 &_tile_type_trees_procs, // Callback functions for TileType::Trees tiles
75 &_tile_type_station_procs, // Callback functions for TileType::Station tiles
76 &_tile_type_water_procs, // Callback functions for TileType::Water tiles
77 &_tile_type_void_procs, // Callback functions for TileType::Void tiles
78 &_tile_type_industry_procs, // Callback functions for TileType::Industry tiles
79 &_tile_type_tunnelbridge_procs, // Callback functions for TileType::TunnelBridge tiles
80 &_tile_type_object_procs, // Callback functions for TileType::Object tiles
81 /* Explicitly initialize invalid elements to make sure that they are nullptr. */
82 nullptr,
83 nullptr,
84 nullptr,
85 nullptr,
86 nullptr,
87};
88
91 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0,
92 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 15, 18,
93};
94
95static const uint TILE_UPDATE_FREQUENCY_LOG = 8;
97
106static std::unique_ptr<SnowLine> _snow_line;
107
121Point InverseRemapCoords2(int x, int y, bool clamp_to_map, bool *clamped)
122{
123 if (clamped != nullptr) *clamped = false; // Not clamping yet.
124
125 /* Initial x/y world coordinate is like if the landscape
126 * was completely flat on height 0. */
127 Point pt = InverseRemapCoords(x, y);
128
129 const uint min_coord = _settings_game.construction.freeform_edges ? TILE_SIZE : 0;
130 const uint max_x = Map::MaxX() * TILE_SIZE - 1;
131 const uint max_y = Map::MaxY() * TILE_SIZE - 1;
132
133 if (clamp_to_map) {
134 /* Bring the coordinates near to a valid range. At the top we allow a number
135 * of extra tiles. This is mostly due to the tiles on the north side of
136 * the map possibly being drawn higher due to the extra height levels. */
137 int extra_tiles = CeilDiv(_settings_game.construction.map_height_limit * TILE_HEIGHT, TILE_PIXELS);
138 Point old_pt = pt;
139 pt.x = Clamp(pt.x, -extra_tiles * TILE_SIZE, max_x);
140 pt.y = Clamp(pt.y, -extra_tiles * TILE_SIZE, max_y);
141 if (clamped != nullptr) *clamped = (pt.x != old_pt.x) || (pt.y != old_pt.y);
142 }
143
144 /* Now find the Z-world coordinate by fix point iteration.
145 * This is a bit tricky because the tile height is non-continuous at foundations.
146 * The clicked point should be approached from the back, otherwise there are regions that are not clickable.
147 * (FOUNDATION_HALFTILE_LOWER on SLOPE_STEEP_S hides north halftile completely)
148 * So give it a z-malus of 4 in the first iterations. */
149 int z = 0;
150 if (clamp_to_map) {
151 for (int i = 0; i < 5; i++) z = GetSlopePixelZ(Clamp(pt.x + std::max(z, 4) - 4, min_coord, max_x), Clamp(pt.y + std::max(z, 4) - 4, min_coord, max_y)) / 2;
152 for (int m = 3; m > 0; m--) z = GetSlopePixelZ(Clamp(pt.x + std::max(z, m) - m, min_coord, max_x), Clamp(pt.y + std::max(z, m) - m, min_coord, max_y)) / 2;
153 for (int i = 0; i < 5; i++) z = GetSlopePixelZ(Clamp(pt.x + z, min_coord, max_x), Clamp(pt.y + z, min_coord, max_y)) / 2;
154 } else {
155 for (int i = 0; i < 5; i++) z = GetSlopePixelZOutsideMap(pt.x + std::max(z, 4) - 4, pt.y + std::max(z, 4) - 4) / 2;
156 for (int m = 3; m > 0; m--) z = GetSlopePixelZOutsideMap(pt.x + std::max(z, m) - m, pt.y + std::max(z, m) - m) / 2;
157 for (int i = 0; i < 5; i++) z = GetSlopePixelZOutsideMap(pt.x + z, pt.y + z ) / 2;
158 }
159
160 pt.x += z;
161 pt.y += z;
162 if (clamp_to_map) {
163 Point old_pt = pt;
164 pt.x = Clamp(pt.x, min_coord, max_x);
165 pt.y = Clamp(pt.y, min_coord, max_y);
166 if (clamped != nullptr) *clamped = *clamped || (pt.x != old_pt.x) || (pt.y != old_pt.y);
167 }
168
169 return pt;
170}
171
181{
182 if (!IsFoundation(f)) return 0;
183
184 if (IsLeveledFoundation(f)) {
185 uint dz = 1 + (IsSteepSlope(s) ? 1 : 0);
186 s = SLOPE_FLAT;
187 return dz;
188 }
189
192 return 0;
193 }
194
197 return 0;
198 }
199
200 uint dz = IsSteepSlope(s) ? 1 : 0;
201 Corner highest_corner = GetHighestSlopeCorner(s);
202
203 switch (f) {
205 s = (((highest_corner == Corner::W) || (highest_corner == Corner::S)) ? SLOPE_SW : SLOPE_NE);
206 break;
207
209 s = (((highest_corner == Corner::S) || (highest_corner == Corner::E)) ? SLOPE_SE : SLOPE_NW);
210 break;
211
213 s = SlopeWithOneCornerRaised(highest_corner);
214 break;
215
217 s = HalftileSlope(SlopeWithOneCornerRaised(highest_corner), highest_corner);
218 break;
219
220 default: NOT_REACHED();
221 }
222 return dz;
223}
224
225
238uint GetPartialPixelZ(int x, int y, Slope corners)
239{
240 if (IsHalftileSlope(corners)) {
241 /* A foundation is placed on half the tile at a specific corner. This means that,
242 * depending on the corner, that one half of the tile is at the maximum height. */
243 switch (GetHalftileSlopeCorner(corners)) {
244 case Corner::W:
245 if (x > y) return GetSlopeMaxPixelZ(corners);
246 break;
247
248 case Corner::S:
249 if (x + y >= (int)TILE_SIZE) return GetSlopeMaxPixelZ(corners);
250 break;
251
252 case Corner::E:
253 if (x <= y) return GetSlopeMaxPixelZ(corners);
254 break;
255
256 case Corner::N:
257 if (x + y < (int)TILE_SIZE) return GetSlopeMaxPixelZ(corners);
258 break;
259
260 default: NOT_REACHED();
261 }
262 }
263
264 switch (RemoveHalftileSlope(corners)) {
265 case SLOPE_FLAT: return 0;
266
267 /* One corner is up.*/
268 case SLOPE_N: return x + y <= (int)TILE_SIZE ? (TILE_SIZE - x - y) >> 1 : 0;
269 case SLOPE_E: return y >= x ? (1 + y - x) >> 1 : 0;
270 case SLOPE_S: return x + y >= (int)TILE_SIZE ? (1 + x + y - TILE_SIZE) >> 1 : 0;
271 case SLOPE_W: return x >= y ? (x - y) >> 1 : 0;
272
273 /* Two corners next to each other are up. */
274 case SLOPE_NE: return (TILE_SIZE - x) >> 1;
275 case SLOPE_SE: return (y + 1) >> 1;
276 case SLOPE_SW: return (x + 1) >> 1;
277 case SLOPE_NW: return (TILE_SIZE - y) >> 1;
278
279 /* Three corners are up on the same level. */
280 case SLOPE_ENW: return x + y >= (int)TILE_SIZE ? TILE_HEIGHT - ((1 + x + y - TILE_SIZE) >> 1) : TILE_HEIGHT;
281 case SLOPE_SEN: return y < x ? TILE_HEIGHT - ((x - y) >> 1) : TILE_HEIGHT;
282 case SLOPE_WSE: return x + y <= (int)TILE_SIZE ? TILE_HEIGHT - ((TILE_SIZE - x - y) >> 1) : TILE_HEIGHT;
283 case SLOPE_NWS: return x < y ? TILE_HEIGHT - ((1 + y - x) >> 1) : TILE_HEIGHT;
284
285 /* Two corners at opposite sides are up. */
286 case SLOPE_NS: return x + y < (int)TILE_SIZE ? (TILE_SIZE - x - y) >> 1 : (1 + x + y - TILE_SIZE) >> 1;
287 case SLOPE_EW: return x >= y ? (x - y) >> 1 : (1 + y - x) >> 1;
288
289 /* Very special cases. */
290 case SLOPE_ELEVATED: return TILE_HEIGHT;
291
292 /* Steep slopes. The top is at 2 * TILE_HEIGHT. */
293 case SLOPE_STEEP_N: return (TILE_SIZE - x + TILE_SIZE - y) >> 1;
294 case SLOPE_STEEP_E: return (TILE_SIZE + 1 + y - x) >> 1;
295 case SLOPE_STEEP_S: return (1 + x + y) >> 1;
296 case SLOPE_STEEP_W: return (TILE_SIZE + x - y) >> 1;
297
298 default: NOT_REACHED();
299 }
300}
301
313int GetSlopePixelZ(int x, int y, bool ground_vehicle)
314{
315 TileIndex tile = TileVirtXY(x, y);
316
317 return _tile_type_procs[GetTileType(tile)]->get_slope_pixel_z_proc(tile, x, y, ground_vehicle);
318}
319
329{
330 if (IsInsideBS(x, 0, Map::SizeX() * TILE_SIZE) && IsInsideBS(y, 0, Map::SizeY() * TILE_SIZE)) {
331 return GetSlopePixelZ(x, y, false);
332 } else {
333 return _tile_type_procs[TileType::Void]->get_slope_pixel_z_proc(INVALID_TILE, x, y, false);
334 }
335}
336
347{
348 assert(!IsHalftileSlope(tileh));
349 return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? 1 : 0) + (tileh == SteepSlope(corner) ? 1 : 0);
350}
351
364std::tuple<int, int> GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int z)
365{
366 static const DiagDirectionIndexArray<std::array<Slope, 4>> corners{{{
367 /* corner | steep slope
368 * z1 z2 | z1 z2 */
369 {SLOPE_E, SLOPE_N, SLOPE_STEEP_E, SLOPE_STEEP_N}, // DiagDirection::NE, z1 = E, z2 = N
370 {SLOPE_S, SLOPE_E, SLOPE_STEEP_S, SLOPE_STEEP_E}, // DiagDirection::SE, z1 = S, z2 = E
371 {SLOPE_S, SLOPE_W, SLOPE_STEEP_S, SLOPE_STEEP_W}, // DiagDirection::SW, z1 = S, z2 = W
372 {SLOPE_W, SLOPE_N, SLOPE_STEEP_W, SLOPE_STEEP_N}, // DiagDirection::NW, z1 = W, z2 = N
373 }}};
374
375 int z1 = z;
376 int z2 = z;
377
379 if (halftile_test == corners[edge][0]) z2 += TILE_HEIGHT; // The slope is non-continuous in z2. z2 is on the upper side.
380 if (halftile_test == corners[edge][1]) z1 += TILE_HEIGHT; // The slope is non-continuous in z1. z1 is on the upper side.
381
382 if ((tileh & corners[edge][0]) != 0) z1 += TILE_HEIGHT; // z1 is raised
383 if ((tileh & corners[edge][1]) != 0) z2 += TILE_HEIGHT; // z2 is raised
384 if (RemoveHalftileSlope(tileh) == corners[edge][2]) z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
385 if (RemoveHalftileSlope(tileh) == corners[edge][3]) z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
386
387 return {z1, z2};
388}
389
397std::tuple<Slope, int> GetFoundationSlope(TileIndex tile)
398{
399 auto [tileh, z] = GetTileSlopeZ(tile);
400 Foundation f = _tile_type_procs[GetTileType(tile)]->get_foundation_proc(tile, tileh);
401 z += ApplyFoundationToSlope(f, tileh);
402 return {tileh, z};
403}
404
413static bool HasFoundation(TileIndex tile, Slope slope_here, uint z_here, DiagDirection edge)
414{
415 auto [z1_here, z2_here] = GetSlopePixelZOnEdge(slope_here, edge, z_here);
416
417 auto [slope, z] = GetFoundationPixelSlope(TileAddByDiagDir(tile, edge));
418 auto [z1, z2] = GetSlopePixelZOnEdge(slope, ChangeDiagDir(edge, DiagDirDiff::Reverse), z);
419
420 return (z1_here > z1) || (z2_here > z2);
421}
422
433{
434 auto [slope, z] = GetFoundationPixelSlope(tile);
435 uint block = 0;
436 if (!HasFoundation(tile, slope, z, DiagDirection::NW)) block += 1;
437 if (!HasFoundation(tile, slope, z, DiagDirection::NE)) block += 2;
438 return block;
439}
440
447{
448 if (!IsFoundation(f)) return;
449
450 /* Two part foundations must be drawn separately */
451 assert(f != Foundation::SteepBoth);
452
453 uint sprite_block = GetFoundationSpriteBlock(ti->tile);
454
455 /* Use the original slope sprites if NW and NE borders should be visible */
456 SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * TRKFOUND_BLOCK_SIZE));
457 SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SLOPES_INCLINED_OFFSET + sprite_block * TRKFOUND_BLOCK_SIZE;
458 SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * HALFTILE_BLOCK_SIZE;
459
460 if (IsSteepSlope(ti->tileh)) {
462 /* Lower part of foundation */
463 static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
464 AddSortableSpriteToDraw(leveled_base + RemoveSteepSlope(ti->tileh), PAL_NONE, *ti, bounds);
465 }
466
467 Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
468 ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
469
470 if (IsInclinedFoundation(f)) {
471 /* inclined foundation */
472 uint8_t inclined = to_underlying(highest_corner) * 2 + (f == Foundation::InclinedY ? 1 : 0);
473
474 SpriteBounds bounds{{}, {1, 1, TILE_HEIGHT}, {}};
475 if (f == Foundation::InclinedX) bounds.extent.x = TILE_SIZE;
476 if (f == Foundation::InclinedY) bounds.extent.y = TILE_SIZE;
477 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, *ti, bounds);
478 OffsetGroundSprite(0, 0);
479 } else if (IsLeveledFoundation(f)) {
480 static constexpr SpriteBounds bounds{{0, 0, -(int)TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
481 AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, *ti, bounds);
483 } else if (f == Foundation::SteepLower) {
484 /* one corner raised */
486 } else {
487 /* halftile foundation */
488 int8_t x_bb = (((highest_corner == Corner::W) || (highest_corner == Corner::S)) ? TILE_SIZE / 2 : 0);
489 int8_t y_bb = (((highest_corner == Corner::S) || (highest_corner == Corner::E)) ? TILE_SIZE / 2 : 0);
490
491 SpriteBounds bounds{{x_bb, y_bb, TILE_HEIGHT}, {TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1}, {}};
492 AddSortableSpriteToDraw(halftile_base + to_underlying(highest_corner), PAL_NONE, *ti, bounds);
493 /* Reposition ground sprite back to original position after bounding box change above. This is similar to
494 * RemapCoords() but without zoom scaling. */
495 Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
496 OffsetGroundSprite(-pt.x, -pt.y);
497 }
498 } else {
499 if (IsLeveledFoundation(f)) {
500 /* leveled foundation */
501 static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
502 AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, *ti, bounds);
504 } else if (IsNonContinuousFoundation(f)) {
505 /* halftile foundation */
506 Corner halftile_corner = GetHalftileFoundationCorner(f);
507 int8_t x_bb = (((halftile_corner == Corner::W) || (halftile_corner == Corner::S)) ? TILE_SIZE / 2 : 0);
508 int8_t y_bb = (((halftile_corner == Corner::S) || (halftile_corner == Corner::E)) ? TILE_SIZE / 2 : 0);
509
510 SpriteBounds bounds{{x_bb, y_bb, 0}, {TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1}, {}};
511 AddSortableSpriteToDraw(halftile_base + to_underlying(halftile_corner), PAL_NONE, *ti, bounds);
512 /* Reposition ground sprite back to original position after bounding box change above. This is similar to
513 * RemapCoords() but without zoom scaling. */
514 Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
515 OffsetGroundSprite(-pt.x, -pt.y);
516 } else if (IsSpecialRailFoundation(f)) {
517 /* anti-zig-zag foundation */
518 SpriteID spr;
519 if (ti->tileh == SLOPE_NS || ti->tileh == SLOPE_EW) {
520 /* half of leveled foundation under track corner */
522 } else {
523 /* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
524 spr = inclined_base + 2 * to_underlying(GetRailFoundationCorner(f)) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
525 }
526 static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
527 AddSortableSpriteToDraw(spr, PAL_NONE, *ti, bounds);
528 OffsetGroundSprite(0, 0);
529 } else {
530 /* inclined foundation */
531 uint8_t inclined = to_underlying(GetHighestSlopeCorner(ti->tileh)) * 2 + (f == Foundation::InclinedY ? 1 : 0);
532
533 SpriteBounds bounds{{}, {1, 1, TILE_HEIGHT}, {}};
534 if (f == Foundation::InclinedX) bounds.extent.x = TILE_SIZE;
535 if (f == Foundation::InclinedY) bounds.extent.y = TILE_SIZE;
536 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, *ti, bounds);
537 OffsetGroundSprite(0, 0);
538 }
539 ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
540 }
541}
542
543void DoClearSquare(TileIndex tile)
544{
545 /* If the tile can have animation and we clear it, delete it from the animated tile list. */
546 if (MayAnimateTile(tile)) DeleteAnimatedTile(tile, true);
547
548 bool remove = IsDockingTile(tile);
551 if (remove) RemoveDockingTile(tile);
552
555}
556
568{
569 return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode, sub_mode, side);
570}
571
578void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
579{
580 _tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_owner, new_owner);
581}
582
583void GetTileDesc(TileIndex tile, TileDesc &td)
584{
585 _tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
586}
587
594{
595 return _snow_line != nullptr;
596}
597
603void SetSnowLine(std::unique_ptr<SnowLine> &&snow_line)
604{
605 _snow_line = std::move(snow_line);
606}
607
613uint8_t GetSnowLine()
614{
615 if (_snow_line == nullptr) return _settings_game.game_creation.snow_line_height;
616
617 TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
618 return _snow_line->table[ymd.month][ymd.day];
619}
620
627{
628 return _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->highest_value;
629}
630
637{
638 return _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->lowest_value;
639}
640
646{
647 _snow_line = nullptr;
648}
649
655{
656 auto check_tile = [](uint x, uint y) -> bool {
657 auto [slope, h] = GetTilePixelSlopeOutsideMap(x, y);
658 return ((slope == SLOPE_FLAT) && (h == 0));
659 };
660
661 /* Check the map corners. */
662 if (!check_tile(0, 0)) return false;
663 if (!check_tile(0, Map::SizeY())) return false;
664 if (!check_tile(Map::SizeX(), 0)) return false;
665 if (!check_tile(Map::SizeX(), Map::SizeY())) return false;
666
667 /* Check the map edges.*/
668 for (uint x = 0; x <= Map::SizeX(); x++) {
669 if (!check_tile(x, 0)) return false;
670 if (!check_tile(x, Map::SizeY())) return false;
671 }
672 for (uint y = 1; y < Map::SizeY(); y++) {
673 if (!check_tile(0, y)) return false;
674 if (!check_tile(Map::SizeX(), y)) return false;
675 }
676
677 return true;
678}
679
687{
689 bool do_clear = false;
690 /* Test for stuff which results in water when cleared. Then add the cost to also clear the water. */
691 if (flags.Test(DoCommandFlag::ForceClearTile) && HasTileWaterClass(tile) && IsTileOnWater(tile) && !IsWaterTile(tile) && !IsCoastTile(tile)) {
692 if (flags.Test(DoCommandFlag::Auto) && GetWaterClass(tile) == WaterClass::Canal) return CommandCost(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
693 /* Buoy tiles are special as they can be cleared by anyone, but the underlying tile shouldn't be cleared if it has a different owner. */
694 if (!IsBuoyTile(tile) || GetTileOwner(tile) == _current_company) {
695 do_clear = true;
697 }
698 }
699
701 if (c != nullptr && (int)GB(c->clear_limit, 16, 16) < 1) {
702 return CommandCost(STR_ERROR_CLEARING_LIMIT_REACHED);
703 }
704
705 const ClearedObjectArea *coa = FindClearedObject(tile);
706
707 /* If this tile was the first tile which caused object destruction, always
708 * pass it on to the tile_type_proc. That way multiple test runs and the exec run stay consistent. */
709 if (coa != nullptr && coa->first_tile != tile) {
710 /* If this tile belongs to an object which was already cleared via another tile, pretend it has been
711 * already removed.
712 * However, we need to check stuff, which is not the same for all object tiles. (e.g. being on water or not) */
713
714 /* If a object is removed, it leaves either bare land or water. */
715 if (flags.Test(DoCommandFlag::NoWater) && HasTileWaterClass(tile) && IsTileOnWater(tile)) {
716 return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
717 }
718 } else {
719 cost.AddCost(_tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags));
720 }
721
722 if (flags.Test(DoCommandFlag::Execute)) {
723 if (c != nullptr) c->clear_limit -= 1 << 16;
724 if (do_clear) {
725 if (IsWaterTile(tile) && IsCanal(tile)) {
726 Owner owner = GetTileOwner(tile);
727 if (Company::IsValidID(owner)) {
728 Company::Get(owner)->infrastructure.water--;
730 }
731 }
732 DoClearSquare(tile);
734 }
735 }
736 return cost;
737}
738
747std::tuple<CommandCost, Money> CmdClearArea(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, bool diagonal)
748{
749 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
750
751 Money money = GetAvailableMoneyForCommand();
753 CommandCost last_error = CMD_ERROR;
754 bool had_success = false;
755
757 int limit = (c == nullptr ? INT32_MAX : GB(c->clear_limit, 16, 16));
758
759 if (tile != start_tile) flags.Set(DoCommandFlag::ForceClearTile);
760
761 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
762 for (; *iter != INVALID_TILE; ++(*iter)) {
763 TileIndex t = *iter;
764 CommandCost ret = Command<Commands::LandscapeClear>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), t);
765 if (ret.Failed()) {
766 last_error = std::move(ret);
767
768 /* We may not clear more tiles. */
769 if (c != nullptr && GB(c->clear_limit, 16, 16) < 1) break;
770 continue;
771 }
772
773 had_success = true;
774 if (flags.Test(DoCommandFlag::Execute)) {
775 money -= ret.GetCost();
776 if (ret.GetCost() > 0 && money < 0) {
777 return { cost, ret.GetCost() };
778 }
779 Command<Commands::LandscapeClear>::Do(flags, t);
780
781 /* draw explosion animation...
782 * Disable explosions when game is paused. Looks silly and blocks the view. */
783 if ((t == tile || t == start_tile) && _pause_mode.None()) {
784 /* big explosion in two corners, or small explosion for single tiles */
786 TileX(tile) == TileX(start_tile) && TileY(tile) == TileY(start_tile) ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
787 );
788 }
789 } else {
790 /* When we're at the clearing limit we better bail (unneed) testing as well. */
791 if (ret.GetCost() != 0 && --limit <= 0) break;
792 }
793 cost.AddCost(ret.GetCost());
794 }
795
796 return { had_success ? cost : last_error, 0 };
797}
798
799
800TileIndex _cur_tileloop_tile;
801
806{
808
809 /* The pseudorandom sequence of tiles is generated using a Galois linear feedback
810 * shift register (LFSR). This allows a deterministic pseudorandom ordering, but
811 * still with minimal state and fast iteration. */
812
813 /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 24-bit (for 4096x4096 maps).
814 * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */
815 static const uint32_t feedbacks[] = {
816 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87
817 };
818 static_assert(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1);
819 const uint32_t feedback = feedbacks[Map::LogX() + Map::LogY() - 2 * MIN_MAP_SIZE_BITS];
820
821 /* We update every tile every TILE_UPDATE_FREQUENCY ticks, so divide the map size by 2^TILE_UPDATE_FREQUENCY_LOG = TILE_UPDATE_FREQUENCY */
822 static_assert(2 * MIN_MAP_SIZE_BITS >= TILE_UPDATE_FREQUENCY_LOG);
823 uint count = 1 << (Map::LogX() + Map::LogY() - TILE_UPDATE_FREQUENCY_LOG);
824
825 TileIndex tile = _cur_tileloop_tile;
826 /* The LFSR cannot have a zeroed state. */
827 assert(tile != 0);
828
829 /* Manually update tile 0 every TILE_UPDATE_FREQUENCY ticks - the LFSR never iterates over it itself. */
831 _tile_type_procs[GetTileType(0)]->tile_loop_proc(TileIndex{});
832 count--;
833 }
834
835 while (count--) {
836 _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
837
838 /* Get the next tile in sequence using a Galois LFSR. */
839 tile = TileIndex{(tile.base() >> 1) ^ (-(int32_t)(tile.base() & 1) & feedback)};
840 }
841
842 _cur_tileloop_tile = tile;
843}
844
845void InitializeLandscape()
846{
847 for (uint y = _settings_game.construction.freeform_edges ? 1 : 0; y < Map::MaxY(); y++) {
848 for (uint x = _settings_game.construction.freeform_edges ? 1 : 0; x < Map::MaxX(); x++) {
850 SetTileHeight(TileXY(x, y), 0);
853 }
854 }
855
856 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, Map::MaxY()));
857 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(Map::MaxX(), y));
858}
859
860static const uint8_t _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 };
861static const uint8_t _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
862
863static void GenerateTerrain(int type, uint flag)
864{
865 uint32_t r = Random();
866
867 /* Choose one of the templates from the graphics file. */
868 const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + SPR_MAPGEN_BEGIN, SpriteType::MapGen);
869 if (templ == nullptr) UserError("Map generator sprites could not be loaded");
870
871 /* Chose a random location to apply the template to. */
872 uint x = r & Map::MaxX();
873 uint y = (r >> Map::LogX()) & Map::MaxY();
874
875 /* Make sure the template is not too close to the upper edges; bottom edges are checked later. */
876 uint edge_distance = 1 + (_settings_game.construction.freeform_edges ? 1 : 0);
877 if (x <= edge_distance || y <= edge_distance) return;
878
879 DiagDirection direction = (DiagDirection)GB(r, 22, 2);
880 uint w = templ->width;
881 uint h = templ->height;
882
883 if (DiagDirToAxis(direction) == Axis::Y) std::swap(w, h);
884
885 const uint8_t *p = reinterpret_cast<const uint8_t *>(templ->data);
886
887 if ((flag & 4) != 0) {
888 /* This is only executed in secondary/tertiary loops to generate the terrain for arctic and tropic.
889 * It prevents the templates to be applied to certain parts of the map based on the flags, thus
890 * creating regions with different elevations/topography. */
891 uint xw = x * Map::SizeY();
892 uint yw = y * Map::SizeX();
893 uint bias = (Map::SizeX() + Map::SizeY()) * 16;
894
895 switch (flag & 3) {
896 default: NOT_REACHED();
897 case 0:
898 if (xw + yw > Map::Size() - bias) return;
899 break;
900
901 case 1:
902 if (yw < xw + bias) return;
903 break;
904
905 case 2:
906 if (xw + yw < Map::Size() + bias) return;
907 break;
908
909 case 3:
910 if (xw < yw + bias) return;
911 break;
912 }
913 }
914
915 /* Ensure the template does not overflow at the bottom edges of the map; upper edges were checked before. */
916 if (x + w >= Map::MaxX()) return;
917 if (y + h >= Map::MaxY()) return;
918
919 TileIndex tile = TileXY(x, y);
920
921 /* Get the template and overlay in a particular direction over the map's height from the given
922 * origin point (tile), and update the map's height everywhere where the height from the template
923 * is higher than the height of the map. In other words, this only raises the tile heights. */
924 switch (direction) {
925 default: NOT_REACHED();
927 do {
928 TileIndex tile_cur = tile;
929
930 for (uint w_cur = w; w_cur != 0; --w_cur) {
931 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
932 p++;
933 tile_cur += TileDiffXY(1, 0);
934 }
935 tile += TileDiffXY(0, 1);
936 } while (--h != 0);
937 break;
938
940 do {
941 TileIndex tile_cur = tile;
942
943 for (uint h_cur = h; h_cur != 0; --h_cur) {
944 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
945 p++;
946 tile_cur += TileDiffXY(0, 1);
947 }
948 tile += TileDiffXY(1, 0);
949 } while (--w != 0);
950 break;
951
953 tile += TileDiffXY(w - 1, 0);
954 do {
955 TileIndex tile_cur = tile;
956
957 for (uint w_cur = w; w_cur != 0; --w_cur) {
958 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
959 p++;
960 tile_cur -= TileDiffXY(1, 0);
961 }
962 tile += TileDiffXY(0, 1);
963 } while (--h != 0);
964 break;
965
967 tile += TileDiffXY(0, h - 1);
968 do {
969 TileIndex tile_cur = tile;
970
971 for (uint h_cur = h; h_cur != 0; --h_cur) {
972 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
973 p++;
974 tile_cur -= TileDiffXY(0, 1);
975 }
976 tile += TileDiffXY(1, 0);
977 } while (--w != 0);
978 break;
979 }
980}
981
982
983#include "table/genland.h"
984
985static void CreateDesertOrRainForest(uint desert_tropic_line)
986{
987 uint update_freq = Map::Size() / 4;
988
989 for (const auto tile : Map::Iterate()) {
990 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GenWorldProgress::Landscape);
991
992 if (!IsValidTile(tile)) continue;
993
994 auto allows_desert = [tile, desert_tropic_line](auto &offset) {
995 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
996 return t == INVALID_TILE || (TileHeight(t) < desert_tropic_line && !IsTileType(t, TileType::Water));
997 };
998 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_desert)) {
1000 }
1001 }
1002
1003 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
1005
1006 RunTileLoop();
1007 }
1008
1009 for (const auto tile : Map::Iterate()) {
1010 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GenWorldProgress::Landscape);
1011
1012 if (!IsValidTile(tile)) continue;
1013
1014 auto allows_rainforest = [tile](auto &offset) {
1015 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
1017 };
1018 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_rainforest)) {
1020 }
1021 }
1022}
1023
1029static bool FindSpring(TileIndex tile)
1030{
1031 if (!IsValidTile(tile)) return false;
1032
1033 int reference_height;
1034 if (!IsTileFlat(tile, &reference_height) || IsWaterTile(tile)) return false;
1035
1036 /* In the tropics rivers start in the rainforest. */
1037 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) != TropicZone::Rainforest) return false;
1038
1039 /* Rivers begin where water flows off hillsides and collects at the bottom. */
1040 uint max_hill_distance = 1;
1041 uint required_num_hills = 3;
1042
1043 /* If we don't have many hills, loosen the standards so we still get rivers. */
1044 if (_settings_game.difficulty.terrain_type < GenworldMaxHeight::Hilly) {
1045 max_hill_distance = 3;
1046 required_num_hills = 1;
1047 };
1048
1049 uint num_hills = 0;
1051 TileIndex check_tile = tile;
1052 for (uint i = 0; i < max_hill_distance; i++) {
1053 check_tile = TileAddByDiagDir(check_tile, d);
1054 if (!IsValidTile(check_tile)) break;
1055 if (GetTileMaxZ(check_tile) > reference_height) {
1056 num_hills++;
1057 break;
1058 }
1059 }
1060 }
1061
1062 return num_hills >= required_num_hills;
1063}
1064
1071static bool IsValidRiverTerminusTile(TileIndex tile, uint height)
1072{
1073 if (!IsValidTile(tile) || TileHeight(tile) != height || !IsTileFlat(tile)) return false;
1074 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) == TropicZone::Desert) return false;
1075
1076 return true;
1077}
1078
1084static void MakeLake(TileIndex lake_centre, uint height_lake)
1085{
1087 uint diameter = RandomRange(8) + 3;
1088
1089 /* Run the loop twice, so artefacts from going circular in one direction get (mostly) hidden. */
1090 for (uint loops = 0; loops < 2; ++loops) {
1091 for (TileIndex tile : SpiralTileSequence(lake_centre, diameter)) {
1092 if (!IsValidRiverTerminusTile(tile, height_lake)) continue;
1094 TileIndex t = tile + TileOffsByDiagDir(d);
1095 if (IsWaterTile(t)) {
1097 break;
1098 }
1099 }
1100 }
1101 }
1102}
1103
1110static void MakeWetlands(TileIndex centre, uint height, uint river_length)
1111{
1113
1114 uint diameter = std::max((river_length), 16u);
1115
1116 /* Some wetlands have trees planted among the water tiles. */
1117 bool has_trees = Chance16(1, 2);
1118
1119 /* Create the main wetland area. */
1120 for (TileIndex tile : SpiralTileSequence(centre, diameter)) {
1121 if (!IsValidRiverTerminusTile(tile, height)) continue;
1122
1123 /* Don't make a perfect square, but a circle with a noisy border. */
1124 uint radius = diameter / 2;
1125 if ((DistanceSquare(tile, centre) > radius * radius) && Chance16(3, 4)) continue;
1126
1127 if (Chance16(1, 3)) {
1128 /* This tile is water. */
1130 } else if (IsTileType(tile, TileType::Clear)) {
1131 /* This tile is ground, which we always make rough. */
1133 /* Maybe place trees? */
1134 if (has_trees && _settings_game.game_creation.tree_placer != TreePlacer::None) {
1135 PlaceTree(tile, Random(), true);
1136 }
1137 }
1138 }
1139}
1140
1148{
1149 if (!IsValidTile(tile)) return false;
1150
1151 /* We don't want to end the river at the entry of the valley. */
1152 if (tile == begin) return false;
1153
1154 /* We don't want the river to end in the desert. */
1155 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) == TropicZone::Desert) return false;
1156
1157 /* Only end on flat slopes. */
1158 int height_lake;
1159 if (!IsTileFlat(tile, &height_lake)) return false;
1160
1161 /* Only build at the height of the river. */
1162 int height_begin = TileHeight(begin);
1163 if (height_lake != height_begin) return false;
1164
1165 /* Checks successful, time to build.
1166 * Chance of water feature is split evenly between a lake, a wetland with trees, and a wetland with grass. */
1167 if (Chance16(1, 3)) {
1168 MakeLake(tile, height_lake);
1169 } else {
1170 MakeWetlands(tile, height_lake, DistanceManhattan(tile, begin));
1171 }
1172
1173 /* This is the new end of the river. */
1174 return true;
1175}
1176
1182void RiverMakeWider(TileIndex tile, TileIndex origin_tile)
1183{
1184 /* Don't expand into void tiles. */
1185 if (!IsValidTile(tile)) return;
1186
1187 /* If the tile is already sea or river, don't expand. */
1188 if (IsWaterTile(tile)) return;
1189
1190 /* If the tile is at height 0 after terraforming but the ocean hasn't flooded yet, don't build river. */
1191 if (GetTileMaxZ(tile) == 0) return;
1192
1193 Slope cur_slope = GetTileSlope(tile);
1194 Slope desired_slope = GetTileSlope(origin_tile); // Initialize matching the origin tile as a shortcut if no terraforming is needed.
1195
1196 /* Never flow uphill. */
1197 if (GetTileMaxZ(tile) > GetTileMaxZ(origin_tile)) return;
1198
1199 /* If the new tile can't hold a river tile, try terraforming. */
1200 if (!IsTileFlat(tile) && !IsInclinedSlope(cur_slope)) {
1201 /* Don't try to terraform steep slopes. */
1202 if (IsSteepSlope(cur_slope)) return;
1203
1204 bool flat_river_found = false;
1205 bool sloped_river_found = false;
1206
1207 /* There are two common possibilities:
1208 * 1. River flat, adjacent tile has one corner lowered.
1209 * 2. River descending, adjacent tile has either one or three corners raised.
1210 */
1211
1212 /* First, determine the desired slope based on adjacent river tiles. This doesn't necessarily match the origin tile for the SpiralTileSequence. */
1214 TileIndex other_tile = TileAddByDiagDir(tile, d);
1215 Slope other_slope = GetTileSlope(other_tile);
1216
1217 /* Only consider river tiles. */
1218 if (IsWaterTile(other_tile) && IsRiver(other_tile)) {
1219 /* If the adjacent river tile flows downhill, we need to check where we are relative to the slope. */
1220 if (IsInclinedSlope(other_slope) && GetTileMaxZ(tile) == GetTileMaxZ(other_tile)) {
1221 /* Check for a parallel slope. If we don't find one, we're above or below the slope instead. */
1224 desired_slope = other_slope;
1225 sloped_river_found = true;
1226 break;
1227 }
1228 }
1229 /* If we find an adjacent river tile, remember it. We'll terraform to match it later if we don't find a slope. */
1230 if (IsTileFlat(other_tile)) flat_river_found = true;
1231 }
1232 }
1233 /* We didn't find either an inclined or flat river, so we're climbing the wrong slope. Bail out. */
1234 if (!sloped_river_found && !flat_river_found) return;
1235
1236 /* We didn't find an inclined river, but there is a flat river. */
1237 if (!sloped_river_found && flat_river_found) desired_slope = SLOPE_FLAT;
1238
1239 /* Now that we know the desired slope, it's time to terraform! */
1240
1241 /* If the river is flat and the adjacent tile has one corner lowered, we want to raise it. */
1242 if (desired_slope == SLOPE_FLAT && IsSlopeWithThreeCornersRaised(cur_slope)) {
1243 /* Make sure we're not affecting an existing river slope tile. */
1245 TileIndex other_tile = TileAddByDiagDir(tile, d);
1246 if (IsInclinedSlope(GetTileSlope(other_tile)) && IsWaterTile(other_tile)) return;
1247 }
1248 Command<Commands::TerraformLand>::Do({DoCommandFlag::Execute, DoCommandFlag::Auto}, tile, ComplementSlope(cur_slope), true);
1249
1250 /* If the river is descending and the adjacent tile has either one or three corners raised, we want to make it match the slope. */
1251 } else if (IsInclinedSlope(desired_slope)) {
1252 /* Don't break existing flat river tiles by terraforming under them. */
1253 DiagDirection river_direction = ReverseDiagDir(GetInclinedSlopeDirection(desired_slope));
1254
1256 /* We don't care about downstream or upstream tiles, just the riverbanks. */
1257 TileIndex other_tile = (TileAddByDiagDir(tile, ChangeDiagDir(river_direction, d)));
1258 if (IsWaterTile(other_tile) && IsRiver(other_tile) && IsTileFlat(other_tile)) return;
1259 }
1260
1261 /* Get the corners which are different between the current and desired slope. */
1262 Slope to_change = cur_slope ^ desired_slope;
1263
1264 /* Lower unwanted corners first. If only one corner is raised, no corners need lowering. */
1265 if (!IsSlopeWithOneCornerRaised(cur_slope)) {
1266 to_change = to_change & ComplementSlope(desired_slope);
1267 Command<Commands::TerraformLand>::Do({DoCommandFlag::Execute, DoCommandFlag::Auto}, tile, to_change, false);
1268 }
1269
1270 /* Now check the match and raise any corners needed. */
1271 cur_slope = GetTileSlope(tile);
1272 if (cur_slope != desired_slope && IsSlopeWithOneCornerRaised(cur_slope)) {
1273 to_change = cur_slope ^ desired_slope;
1274 Command<Commands::TerraformLand>::Do({DoCommandFlag::Execute, DoCommandFlag::Auto}, tile, to_change, true);
1275 }
1276 }
1277 /* Update cur_slope after possibly terraforming. */
1278 cur_slope = GetTileSlope(tile);
1279 }
1280
1281 /* Sloped rivers need water both upstream and downstream. */
1282 if (IsInclinedSlope(cur_slope)) {
1283 DiagDirection slope_direction = GetInclinedSlopeDirection(cur_slope);
1284
1285 TileIndex upstream_tile = TileAddByDiagDir(tile, slope_direction);
1286 TileIndex downstream_tile = TileAddByDiagDir(tile, ReverseDiagDir(slope_direction));
1287
1288 /* Don't look outside the map. */
1289 if (!IsValidTile(upstream_tile) || !IsValidTile(downstream_tile)) return;
1290
1291 /* Downstream might be new ocean created by our terraforming, and it hasn't flooded yet. */
1292 bool downstream_is_ocean = GetTileZ(downstream_tile) == 0 && (GetTileSlope(downstream_tile) == SLOPE_FLAT || IsSlopeWithOneCornerRaised(GetTileSlope(downstream_tile)));
1293
1294 /* If downstream is dry, flat, and not ocean, try making it a river tile. */
1295 if (!IsWaterTile(downstream_tile) && !downstream_is_ocean) {
1296 /* If the tile upstream isn't flat, don't bother. */
1297 if (GetTileSlope(downstream_tile) != SLOPE_FLAT) return;
1298
1299 MakeRiverAndModifyDesertZoneAround(downstream_tile);
1300 }
1301
1302 /* If upstream is dry and flat, try making it a river tile. */
1303 if (!IsWaterTile(upstream_tile)) {
1304 /* If the tile upstream isn't flat, don't bother. */
1305 if (GetTileSlope(upstream_tile) != SLOPE_FLAT) return;
1306
1308 }
1309 }
1310
1311 /* If the tile slope matches the desired slope, add a river tile. */
1312 if (cur_slope == desired_slope) {
1314 }
1315}
1316
1324{
1325 assert(DistanceManhattan(begin, end) == 1);
1326
1327 auto [slope_end, height_end] = GetTileSlopeZ(end);
1328
1329 /* Slope either is inclined or flat; rivers don't support other slopes. */
1330 if (slope_end != SLOPE_FLAT && !IsInclinedSlope(slope_end)) return false;
1331
1332 auto [slope_begin, height_begin] = GetTileSlopeZ(begin);
1333
1334 /* It can't flow uphill. */
1335 if (height_end > height_begin) return false;
1336
1337 /* Slope continues, then it must be lower... */
1338 if (slope_end == slope_begin && height_end < height_begin) return true;
1339
1340 /* ... or either end must be flat. */
1341 return slope_end == SLOPE_FLAT || slope_begin == SLOPE_FLAT;
1342}
1343
1351static bool CountConnectedSeaTiles(TileIndex tile, std::unordered_set<TileIndex> &sea, const uint limit)
1352{
1353 /* This tile might not be sea. */
1354 if (!IsWaterTile(tile) || GetWaterClass(tile) != WaterClass::Sea || !IsTileFlat(tile)) return false;
1355
1356 /* If we've found an edge tile, we are "connected to the sea outside the map." */
1357 if (DistanceFromEdge(tile) <= 1) return true;
1358
1359 /* We have now evaluated this tile and don't want to check it again. */
1360 sea.insert(tile);
1361
1362 /* We might want to cut our search short if the size of the sea is "big enough".
1363 * Count this tile but don't check its neighbors. */
1364 if (sea.size() > limit) return false;
1365
1366 /* Count adjacent tiles using recursion. */
1368 TileIndex t = tile + TileOffsByDiagDir(d);
1369 if (IsValidTile(t) && !sea.contains(t)) {
1370 if (CountConnectedSeaTiles(t, sea, limit)) return true;
1371 }
1372 }
1373
1374 return false;
1375}
1376
1384static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
1385{
1386 if (IsWaterTile(begin)) {
1387 return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 };
1388 }
1389
1390 int height_begin = TileHeight(begin);
1391
1392 std::unordered_set<TileIndex> marks;
1393 marks.insert(begin);
1394
1395 std::vector<TileIndex> queue;
1396 queue.push_back(begin);
1397
1398 /* Breadth first search for the closest tile we can flow down to.
1399 * We keep the queue to find the Nth tile for lake guessing. The tiles
1400 * in the queue are neatly ordered by insertion.
1401 */
1402 bool found = false;
1403 TileIndex end;
1404 for (size_t i = 0; i != queue.size(); i++) {
1405 end = queue[i];
1406
1407 int height_end;
1408 if (IsTileFlat(end, &height_end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) {
1409 /* We don't want rivers to flow into tiny bits of sea, so we fill them, unless using the original land generator. */
1410 if (_settings_game.game_creation.land_generator != LG_ORIGINAL && IsWaterTile(end) && GetWaterClass(end) == WaterClass::Sea) {
1411 /* If we've found the sea, make sure it's large enough. Scale by the map size but set a cap to avoid performance issues on large maps. */
1412 const uint MAX_SEA_SIZE_THRESHOLD = 1024;
1413 const uint SEA_SIZE_THRESHOLD = std::min(static_cast<uint>(2 * std::sqrt(Map::SizeX() * Map::SizeY())), MAX_SEA_SIZE_THRESHOLD);
1414 std::unordered_set<TileIndex> sea;
1415 /* Count the connected tiles, if the sea is large we can end the river here. */
1416 bool found_edge = CountConnectedSeaTiles(end, sea, SEA_SIZE_THRESHOLD);
1417 if (found_edge || sea.size() > SEA_SIZE_THRESHOLD) {
1418 found = true;
1419 break;
1420 } else {
1421 /* Sea is too small, flatten it so the river keeps looking or forms a lake / wetland. */
1422 for (TileIndex sea_tile : sea) {
1423 Command<Commands::TerraformLand>::Do(DoCommandFlag::Execute, sea_tile, SLOPE_ELEVATED, false);
1424 Slope slope = ComplementSlope(GetTileSlope(sea_tile));
1425 Command<Commands::TerraformLand>::Do(DoCommandFlag::Execute, sea_tile, slope, true);
1426 }
1427 }
1428 } else {
1429 /* We've found a river, or a sea if using the original land generator. */
1430 found = true;
1431 break;
1432 }
1433 }
1434
1436 TileIndex t = end + TileOffsByDiagDir(d);
1437 if (IsValidTile(t) && !marks.contains(t) && RiverFlowsDown(end, t)) {
1438 marks.insert(t);
1439 queue.push_back(t);
1440 }
1441 }
1442 }
1443
1444 bool main_river = false;
1445 if (found) {
1446 /* Flow further down hill. */
1447 std::tie(found, main_river) = FlowRiver(spring, end, min_river_length);
1448 } else if (queue.size() > 32) {
1449 /* Maybe we can make a lake. Find the Nth of the considered tiles. */
1450 TileIndex lake_centre = queue[RandomRange(static_cast<uint32_t>(queue.size()))];
1451 if (DistanceManhattan(spring, lake_centre) > min_river_length) {
1452 if (TryMakeRiverTerminus(lake_centre, begin)) {
1453 /* If successful, this becomes the new end of the river. */
1454 end = lake_centre;
1455 found = true;
1456 }
1457 }
1458 }
1459
1460 if (found) YapfBuildRiver(begin, end, spring, main_river);
1461 return { found, main_river };
1462}
1463
1467static void CreateRivers()
1468{
1469 int amount = _settings_game.game_creation.amount_of_rivers;
1470 if (amount == 0) return;
1471
1472 uint wells = Map::ScaleBySize(4 << _settings_game.game_creation.amount_of_rivers);
1473 const uint num_short_rivers = wells - std::max(1u, wells / 10);
1474 SetGeneratingWorldProgress(GenWorldProgress::Rivers, wells + TILE_UPDATE_FREQUENCY / 64); // Include the tile loop calls below.
1475
1476 /* Try to create long rivers. */
1477 for (; wells > num_short_rivers; wells--) {
1479 bool done = false;
1480 for (int tries = 0; tries < 512; tries++) {
1481 for (auto t : SpiralTileSequence(RandomTile(), 8)) {
1482 if (FindSpring(t)) {
1483 done = std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length * 4));
1484 break;
1485 }
1486 }
1487 if (done) break;
1488 }
1489 }
1490
1491 /* Try to create short rivers. */
1492 for (; wells != 0; wells--) {
1494 bool done = false;
1495 for (int tries = 0; tries < 128; tries++) {
1496 for (auto t : SpiralTileSequence(RandomTile(), 8)) {
1497 if (FindSpring(t)) {
1498 done = std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length));
1499 break;
1500 }
1501 }
1502 if (done) break;
1503 }
1504 }
1505
1506 /* Widening rivers may have left some tiles requiring to be watered. */
1507 ConvertGroundTilesIntoWaterTiles();
1508
1509 /* Run tile loop to update the ground density. */
1510 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
1512 RunTileLoop();
1513 }
1514}
1515
1533static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
1534{
1535 /* Histogram of how many tiles per height level exist. */
1536 std::array<int, MAX_TILE_HEIGHT + 1> histogram = {};
1537 /* Histogram of how many neighbour tiles are lower than the tiles of the height level. */
1538 std::array<int, MAX_TILE_HEIGHT + 1> edge_histogram = {};
1539
1540 /* Build a histogram of the map height. */
1541 for (const auto tile : Map::Iterate()) {
1542 uint h = TileHeight(tile);
1543 histogram[h]++;
1544
1545 if (edge_multiplier != 0) {
1546 /* Check if any of our neighbours is below us. */
1548 TileIndex neighbour_tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(dir));
1549 if (IsValidTile(neighbour_tile) && TileHeight(neighbour_tile) < h) {
1550 edge_histogram[h]++;
1551 }
1552 }
1553 }
1554 }
1555
1556 /* The amount of land we have is the map size minus the first (sea) layer. */
1557 uint land_tiles = Map::Size() - histogram[0];
1558 int best_score = land_tiles;
1559
1560 /* Our goal is the coverage amount of the land-mass. */
1561 int goal_tiles = land_tiles * coverage / 100;
1562
1563 /* We scan from top to bottom. */
1564 uint h = MAX_TILE_HEIGHT;
1565 uint best_h = h;
1566
1567 int current_tiles = 0;
1568 for (; h > 0; h--) {
1569 current_tiles += histogram[h];
1570 int current_score = goal_tiles - current_tiles;
1571
1572 /* Tropic grows from water and mountains into the desert. This is a
1573 * great visual, but it also means we* need to take into account how
1574 * much less desert tiles are being created if we are on this
1575 * height-level. We estimate this based on how many neighbouring
1576 * tiles are below us for a given length, assuming that is where
1577 * tropic is growing from.
1578 */
1579 if (edge_multiplier != 0 && h > 1) {
1580 /* From water tropic tiles grow for a few tiles land inward. */
1581 current_score -= edge_histogram[1] * edge_multiplier;
1582 /* Tropic tiles grow into the desert for a few tiles. */
1583 current_score -= edge_histogram[h] * edge_multiplier;
1584 }
1585
1586 if (std::abs(current_score) < std::abs(best_score)) {
1587 best_score = current_score;
1588 best_h = h;
1589 }
1590
1591 /* Always scan all height-levels, as h == 1 might give a better
1592 * score than any before. This is true for example with 0% desert
1593 * coverage. */
1594 }
1595
1596 return best_h;
1597}
1598
1603{
1604 /* We do not have snow sprites on coastal tiles, so never allow "1" as height. */
1605 _settings_game.game_creation.snow_line_height = std::max<uint8_t>(CalculateCoverageLine(_settings_game.game_creation.snow_coverage, 0), 2u);
1606}
1607
1612static uint8_t CalculateDesertLine()
1613{
1614 /* CalculateCoverageLine() runs from top to bottom, so we need to invert the coverage. */
1615 return CalculateCoverageLine(100 - _settings_game.game_creation.desert_coverage, 4);
1616}
1617
1618bool GenerateLandscape(uint8_t mode)
1619{
1620 /* Number of steps of landscape generation */
1621 static constexpr uint GLS_HEIGHTMAP = 3;
1622 static constexpr uint GLS_TERRAGENESIS = 4;
1623 static constexpr uint GLS_ORIGINAL = 2;
1624 static constexpr uint GLS_TROPIC = 12;
1625 static constexpr uint GLS_OTHER = 0;
1626 uint steps = (_settings_game.game_creation.landscape == LandscapeType::Tropic) ? GLS_TROPIC : GLS_OTHER;
1627
1628 if (mode == GWM_HEIGHTMAP) {
1630 if (!LoadHeightmap(_file_to_saveload.ftype.detailed, _file_to_saveload.name)) {
1631 return false;
1632 }
1634 } else if (_settings_game.game_creation.land_generator == LG_TERRAGENESIS) {
1637 } else {
1639 if (_settings_game.construction.freeform_edges) {
1640 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, 0));
1641 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(0, y));
1642 }
1643 switch (_settings_game.game_creation.landscape) {
1644 case LandscapeType::Arctic: {
1645 uint32_t r = Random();
1646
1647 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 950); i != 0; --i) {
1648 GenerateTerrain(2, 0);
1649 }
1650
1651 uint flag = GB(r, 7, 2) | 4;
1652 for (uint i = Map::ScaleBySize(GB(r, 9, 7) + 450); i != 0; --i) {
1653 GenerateTerrain(4, flag);
1654 }
1655 break;
1656 }
1657
1658 case LandscapeType::Tropic: {
1659 uint32_t r = Random();
1660
1661 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 170); i != 0; --i) {
1662 GenerateTerrain(0, 0);
1663 }
1664
1665 uint flag = GB(r, 7, 2) | 4;
1666 for (uint i = Map::ScaleBySize(GB(r, 9, 8) + 1700); i != 0; --i) {
1667 GenerateTerrain(0, flag);
1668 }
1669
1670 flag ^= 2;
1671
1672 for (uint i = Map::ScaleBySize(GB(r, 17, 7) + 410); i != 0; --i) {
1673 GenerateTerrain(3, flag);
1674 }
1675 break;
1676 }
1677
1678 default: {
1679 uint32_t r = Random();
1680
1681 assert(_settings_game.difficulty.quantity_sea_lakes != CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY);
1682 uint i = Map::ScaleBySize(GB(r, 0, 7) + (3 - _settings_game.difficulty.quantity_sea_lakes) * 256 + 100);
1683 for (; i != 0; --i) {
1684 /* Make sure we do not overflow. */
1685 GenerateTerrain(static_cast<int>(Clamp(_settings_game.difficulty.terrain_type, GenworldMaxHeight::VeryFlat, GenworldMaxHeight::Mountainous)), 0);
1686 }
1687 break;
1688 }
1689 }
1690 }
1691
1692 /* Do not call IncreaseGeneratingWorldProgress() before FixSlopes(),
1693 * it allows screen redraw. Drawing of broken slopes crashes the game */
1694 FixSlopes();
1697
1698 ConvertGroundTilesIntoWaterTiles();
1701
1702 switch (_settings_game.game_creation.landscape) {
1705 break;
1706
1707 case LandscapeType::Tropic: {
1708 uint desert_tropic_line = CalculateDesertLine();
1709 CreateDesertOrRainForest(desert_tropic_line);
1710 break;
1711 }
1712
1713 default:
1714 break;
1715 }
1716
1717 CreateRivers();
1718 return true;
1719}
1720
1721void OnTick_Town();
1722void OnTick_Trees();
1723void OnTick_Station();
1724void OnTick_Industry();
1725
1726void OnTick_Companies();
1727void OnTick_LinkGraph();
1728
1729void CallLandscapeTick()
1730{
1731 {
1733
1734 OnTick_Town();
1735 OnTick_Trees();
1736 OnTick_Station();
1737 OnTick_Industry();
1738 }
1739
1742}
void DeleteAnimatedTile(TileIndex tile, bool immediate)
Stops animation on the given tile.
Tile animation!
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
void ClearBridgeMiddle(Tile t)
Removes bridges from the given, that is bridges along the X and Y axis.
Definition bridge_map.h:103
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Common return value for all commands.
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Money GetCost() const
The costs as made up to this moment.
bool Failed() const
Did this command fail?
Iterate a range of enum values.
RAII class for measuring multi-step elements of performance.
Generate TileIndices around a center tile or tile area, with increasing distance.
static std::unique_ptr< TileIterator > Create(TileIndex corner1, TileIndex corner2, bool diagonal)
Create either an OrthogonalTileIterator or DiagonalTileIterator given the diagonal parameter.
Definition tilearea.cpp:292
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static Date date
Current date in days (day counter).
static TickCounter counter
Monotonic counter, in ticks, since start of game.
const TileTypeProcs _tile_type_clear_procs
TileTypeProcs definitions for TileType::Clear tiles.
Map accessors for 'clear' tiles.
bool IsClearGround(Tile t, ClearGround ct)
Set the type of clear tile.
Definition clear_map.h:65
@ Desert
Desert with transition (1,3).
Definition clear_map.h:26
@ Grass
Plain grass with dirt transition (0-3).
Definition clear_map.h:22
@ Rough
Rough mounds (3).
Definition clear_map.h:23
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition clear_map.h:253
void SetClearGroundDensity(Tile t, ClearGround type, uint density)
Sets ground type and density in one go, also sets the counter to 0.
Definition clear_map.h:152
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Auto
don't allow building on structures
@ NoWater
don't allow building on water
@ Execute
execute the given command
@ Bankrupt
company bankrupts, skip money check, skip vehicle on tile check in some cases
@ ForceClearTile
do not only remove the object on the tile, but also clear any water left on it
EnumBitSet< DoCommandFlag, uint16_t > DoCommandFlags
Bitset of DoCommandFlag elements.
Money GetAvailableMoneyForCommand()
This functions returns the money which can be used to execute a command.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
Applies a difference on a DiagDirection.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
EnumIndexArray< T, DiagDirection, DiagDirection::End > DiagDirectionIndexArray
Array with DiagDirection as index.
DiagDirDiff
Enumeration for the difference between to DiagDirection.
@ Reverse
Reverse directions.
@ Left90
90 degrees left
@ Right90
90 degrees right
@ Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
@ SW
Southwest.
@ NW
Northwest.
@ End
Used for iterations.
@ NE
Northeast, upper right on your monitor.
@ SE
Southeast.
Prices _price
Prices and also the fractional part.
Definition economy.cpp:107
@ Construction
Construction costs.
@ ClearCanal
Price for destroying canals.
@ ClearWater
Price for destroying water e.g. see, rives.
EffectVehicle * CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular location.
Functions related to effect vehicles.
@ EV_EXPLOSION_SMALL
Various explosions.
@ EV_EXPLOSION_LARGE
Various explosions.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
Error reporting related functions.
Declarations for savegames operations.
Types for recording game performance data.
@ GameLoopLandscape
Time spent processing other world features.
Table used to generate deserts and/or rainforests.
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:74
Functions related to world/map generation.
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
@ LG_ORIGINAL
The original landscape generator.
Definition genworld.h:21
@ LG_TERRAGENESIS
TerraGenesis Perlin landscape generator.
Definition genworld.h:22
static const uint CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
Value for custom sea level in difficulty settings.
Definition genworld.h:46
@ Rivers
Create the rivers.
Definition genworld.h:62
@ Landscape
Create the landscape.
Definition genworld.h:61
void SetGeneratingWorldProgress(GenWorldProgress cls, uint total)
Set the total of a stage of the world generation.
@ GWM_HEIGHTMAP
Generate a newgame from a heightmap.
Definition genworld.h:32
PauseModes _pause_mode
The current pause mode.
Definition gfx.cpp:51
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ MapGen
Special sprite for the map generator.
Definition gfx_type.h:406
uint8_t LowestSnowLine()
Get the lowest possible snow line height, either variable or static.
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
bool IsSnowLineSet()
Has a snow line table already been loaded.
void ClearSnowLine()
Clear the variable snow line table and free the memory.
static std::unique_ptr< SnowLine > _snow_line
Description of the snow line throughout the year.
void SetSnowLine(std::unique_ptr< SnowLine > &&snow_line)
Set a variable snow line, as loaded from a newgrf file.
uint8_t HighestSnowLine()
Get the highest possible snow line height, either variable or static.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1553
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
bool LoadHeightmap(DetailedFileType dft, std::string_view filename)
Load a heightmap from file and change the map in its current dimensions to a landscape representing t...
void FixSlopes()
This function takes care of the fact that land in OpenTTD can never differ more than 1 in height.
Functions related to creating heightmaps from files.
const TileTypeProcs _tile_type_industry_procs
TileTypeProcs definitions for TileType::Industry tiles.
Definition landscape.cpp:60
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
std::tuple< int, int > GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int z)
Determine the Z height of the corners of a specific tile edge.
static std::tuple< bool, bool > FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
Try to flow the river down from a given begin.
int GetSlopePixelZOutsideMap(int x, int y)
Return world z coordinate of a given point of a tile, also for tiles outside the map (virtual "black"...
const SlopeIndexArray< uint8_t > _slope_to_sprite_offset
landscape slope => sprite
void OnTick_Companies()
Called every tick for updating some company info.
static bool TryMakeRiverTerminus(TileIndex tile, TileIndex begin)
Try to end a river at a tile which is not the sea.
const TileTypeProcs _tile_type_trees_procs
TileTypeProcs definitions for TileType::Trees tiles.
Definition landscape.cpp:56
static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
Calculate what height would be needed to cover N% of the landmass.
const TileTypeProcs _tile_type_station_procs
TileTypeProcs definitions for TileType::Station tiles.
Definition landscape.cpp:57
static bool IsValidRiverTerminusTile(TileIndex tile, uint height)
Is this a valid tile for the water feature at the end of a river?
static void CalculateSnowLine()
Calculate the line from which snow begins.
static const uint TILE_UPDATE_FREQUENCY_LOG
The logarithm of how many ticks it takes between tile updates (log base 2).
Definition landscape.cpp:95
void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
Change the owner of a tile.
const TileTypeProcs _tile_type_void_procs
TileTypeProcs definitions for TileType::Void tiles.
Definition landscape.cpp:59
void RunTileLoop()
Gradually iterate over all tiles on the map, calling their TileLoopProcs once every TILE_UPDATE_FREQU...
static bool FindSpring(TileIndex tile)
Find the spring of a river.
bool RiverFlowsDown(TileIndex begin, TileIndex end)
Check whether a river at begin could (logically) flow down to end.
static void CreateRivers()
Actually (try to) create some rivers.
static bool HasFoundation(TileIndex tile, Slope slope_here, uint z_here, DiagDirection edge)
Check if the tile has foundation on given edge.
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
int GetSlopeZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
const TileTypeProcs _tile_type_tunnelbridge_procs
TileTypeProcs definitions for TileType::TunnelBridge tiles.
Definition landscape.cpp:61
std::tuple< Slope, int > GetFoundationSlope(TileIndex tile)
Get slope of a tile on top of a (possible) foundation If a tile does not have a foundation,...
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
const TileTypeProcs _tile_type_object_procs
TileTypeProcs definitions for TileType::Object tiles.
Definition landscape.cpp:62
static void MakeWetlands(TileIndex centre, uint height, uint river_length)
Make wetlands around the given tile.
void OnTick_LinkGraph()
Spawn or join a link graph job or compress a link graph if any link graph is due to do so.
Point InverseRemapCoords2(int x, int y, bool clamp_to_map, bool *clamped)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
const TileTypeProcs _tile_type_town_procs
TileTypeProcs definitions for TileType::Town tiles.
Definition landscape.cpp:55
const TileTypeProcs _tile_type_water_procs
TileTypeProcs definitions for TileType::Water tiles.
Definition landscape.cpp:58
static void MakeLake(TileIndex lake_centre, uint height_lake)
Make a lake centred on the given tile, of a random diameter.
void OnTick_Town()
Iterate through all towns and call their tick handler.
Definition town_cmd.cpp:914
static uint8_t CalculateDesertLine()
Calculate the line (in height) between desert and tropic.
const TileTypeProcs _tile_type_rail_procs
TileTypeProcs definitions for TileType::Rail tiles.
Definition landscape.cpp:53
std::tuple< CommandCost, Money > CmdClearArea(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, bool diagonal)
Clear a big piece of landscape.
const TileTypeProcs _tile_type_road_procs
TileTypeProcs definitions for TileType::Road tiles.
Definition landscape.cpp:54
uint ApplyFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
bool IsMapSurroundedByWater()
Check if all tiles on the map edge should be considered water borders.
const EnumIndexArray< const TileTypeProcs *, TileType, TileType::MaxSize > _tile_type_procs
Tile callback functions for each type of tile.
Definition landscape.cpp:69
static bool CountConnectedSeaTiles(TileIndex tile, std::unordered_set< TileIndex > &sea, const uint limit)
Find the size of a patch of connected sea tiles.
bool GenerateLandscape(uint8_t mode)
CommandCost CmdLandscapeClear(DoCommandFlags flags, TileIndex tile)
Clear a piece of landscape.
uint GetFoundationSpriteBlock(TileIndex tile)
Get the sprite block to use for a foundation.
void RiverMakeWider(TileIndex tile, TileIndex origin_tile)
Widen a river by expanding into adjacent tiles via circular tile search.
static const uint TILE_UPDATE_FREQUENCY
How many ticks it takes between tile updates (has to be a power of 2).
Definition landscape.cpp:96
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Functions related to OTTD's landscape.
std::tuple< Slope, int > GetFoundationPixelSlope(TileIndex tile)
Get slope of a tile on top of a (possible) foundation If a tile does not have a foundation,...
Definition landscape.h:67
uint ApplyPixelFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition landscape.h:128
Point InverseRemapCoords(int x, int y)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
Definition landscape.h:111
Command definitions related to landscape (slopes etc.).
Types related to the landscape.
@ Arctic
Landscape with snow levels.
@ Tropic
Landscape with distinct rainforests and deserts,.
#define Point
Macro that prevents name conflicts between included headers.
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:186
uint DistanceFromEdge(TileIndex tile)
Param the minimum distance to an edge.
Definition map.cpp:229
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:169
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:407
TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
Add a TileIndexDiffC to a TileIndex and returns the new one.
Definition map_func.h:519
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:615
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:392
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition map_func.h:376
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:429
TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
Returns the TileIndexDiffC offset from a DiagDirection.
Definition map_func.h:487
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:419
#define RandomTile()
Get a valid random tile.
Definition map_func.h:656
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:574
static const uint MIN_MAP_SIZE_BITS
Minimal and maximal map width and height.
Definition map_type.h:37
static const uint MAX_MAP_SIZE_BITS
Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS.
Definition map_type.h:38
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
Base for all objects.
ClearedObjectArea * FindClearedObject(TileIndex tile)
Find the entry in _cleared_object_areas which occupies a certain tile.
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
RoadTramType
The different types of road type.
Definition road_type.h:38
A number of safeguards to prevent using unsafe methods.
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition saveload.cpp:78
Functions related to saving and loading games.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
@ None
No tree placer algorithm.
bool IsSpecialRailFoundation(Foundation f)
Tests if a foundation is a special rail foundation for single horizontal/vertical track.
Definition slope_func.h:355
Slope SlopeWithThreeCornersRaised(Corner corner)
Returns the slope with all except one corner raised.
Definition slope_func.h:216
Corner OppositeCorner(Corner corner)
Returns the opposite corner.
Definition slope_func.h:194
static constexpr Corner GetHalftileSlopeCorner(Slope s)
Returns the leveled halftile of a halftile slope.
Definition slope_func.h:158
static constexpr Slope RemoveHalftileSlope(Slope s)
Removes a halftile slope from a slope.
Definition slope_func.h:70
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:98
bool IsNonContinuousFoundation(Foundation f)
Tests if a foundation is a non-continuous foundation, i.e.
Definition slope_func.h:330
Corner GetHighestSlopeCorner(Slope s)
Returns the highest corner of a slope (one corner raised or a steep slope).
Definition slope_func.h:136
Corner GetHalftileFoundationCorner(Foundation f)
Returns the halftile corner of a halftile-foundation.
Definition slope_func.h:343
bool IsLeveledFoundation(Foundation f)
Tests if the foundation is a leveled foundation.
Definition slope_func.h:308
bool IsFoundation(Foundation f)
Tests whether the given foundation is a foundation.
Definition slope_func.h:297
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
bool IsSlopeWithThreeCornersRaised(Slope s)
Tests if a specific slope has exactly three corners raised.
Definition slope_func.h:205
static constexpr Slope RemoveSteepSlope(Slope s)
Removes a steep flag from a slope.
Definition slope_func.h:46
bool IsInclinedSlope(Slope s)
Tests if a specific slope is an inclined slope.
Definition slope_func.h:238
Slope SteepSlope(Corner corner)
Returns a specific steep slope.
Definition slope_func.h:227
Corner GetRailFoundationCorner(Foundation f)
Returns the track corner of a special rail foundation.
Definition slope_func.h:366
static constexpr bool IsHalftileSlope(Slope s)
Checks for non-continuous slope on halftile foundations.
Definition slope_func.h:57
static constexpr int GetSlopeMaxPixelZ(Slope s)
Returns the height of the highest corner of a slope relative to TileZ (= minimal height).
Definition slope_func.h:183
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition slope_func.h:249
static constexpr Slope HalftileSlope(Slope s, Corner corner)
Adds a halftile slope to a slope.
Definition slope_func.h:284
Slope ComplementSlope(Slope s)
Return the complement of a slope.
Definition slope_func.h:86
Slope SlopeWithOneCornerRaised(Corner corner)
Returns the slope with a specific corner raised.
Definition slope_func.h:109
bool IsInclinedFoundation(Foundation f)
Tests if the foundation is an inclined foundation.
Definition slope_func.h:319
Corner
Enumeration of tile corners.
Definition slope_type.h:21
@ E
East tile corner.
Definition slope_type.h:24
@ S
South tile corner.
Definition slope_type.h:23
@ W
West tile corner.
Definition slope_type.h:22
@ N
North tile corner.
Definition slope_type.h:25
Slope
Enumeration for the slope-type.
Definition slope_type.h:53
@ SLOPE_W
the west corner of the tile is raised
Definition slope_type.h:55
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:66
@ SLOPE_NS
north and south corner are raised
Definition slope_type.h:65
@ SLOPE_E
the east corner of the tile is raised
Definition slope_type.h:57
@ SLOPE_WSE
west, south and east corner are raised
Definition slope_type.h:68
@ SLOPE_S
the south corner of the tile is raised
Definition slope_type.h:56
@ SLOPE_N
the north corner of the tile is raised
Definition slope_type.h:58
@ SLOPE_SEN
south, east and north corner are raised
Definition slope_type.h:69
@ SLOPE_ENW
east, north and west corner are raised
Definition slope_type.h:70
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:61
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:54
@ SLOPE_STEEP_W
a steep slope falling to east (from west)
Definition slope_type.h:71
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:63
@ SLOPE_STEEP_E
a steep slope falling to west (from east)
Definition slope_type.h:73
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:62
@ SLOPE_NWS
north, west and south corner are raised
Definition slope_type.h:67
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:60
@ SLOPE_STEEP_N
a steep slope falling to south (from north)
Definition slope_type.h:74
@ SLOPE_STEEP_S
a steep slope falling to north (from south)
Definition slope_type.h:72
@ SLOPE_EW
east and west corner are raised
Definition slope_type.h:64
Foundation
Enumeration for Foundations.
Definition slope_type.h:119
@ SteepLower
The tile has a steep slope. The lowest corner is raised by a foundation to allow building railroad on...
Definition slope_type.h:124
@ InclinedY
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:123
@ SteepBoth
The tile has a steep slope. The lowest corner is raised by a foundation and the upper halftile is lev...
Definition slope_type.h:127
@ InclinedX
The tile has an along X-axis inclined foundation.
Definition slope_type.h:122
EnumClassIndexContainer< std::array< T, SLOPE_STEEP|SLOPE_ELEVATED >, Slope > SlopeIndexArray
Array with Slope as index.
Definition slope_type.h:95
Functions to cache sprites in memory.
This file contains all sprite-related enums and defines.
static const uint16_t HALFTILE_BLOCK_SIZE
The half tile foundation sprites are organized in blocks of 4.
Definition sprites.h:230
static const SpriteID SPR_HALFTILE_FOUNDATION_BASE
Halftile foundations.
Definition sprites.h:229
static const SpriteID SPR_MAPGEN_BEGIN
Definition sprites.h:1293
static const SpriteID SPR_SLOPES_VIRTUAL_BASE
The original foundations (see SPR_FOUNDATION_BASE below) are mapped before the additional foundations...
Definition sprites.h:225
static const SpriteID SPR_FOUNDATION_BASE
Sprite number one before first foundation sprite, because tileh 0 has no foundation.
Definition sprites.h:389
static const uint16_t TRKFOUND_BLOCK_SIZE
The normal track foundation sprites are organized in blocks of 22.
Definition sprites.h:226
Functions related to stations.
Maps accessors for stations.
bool IsBuoyTile(Tile t)
Is tile t a buoy tile?
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:261
Keeps track of removed objects during execution/testruns of commands.
Definition object_base.h:87
TileIndex first_tile
The first tile being cleared, which then causes the whole object to be cleared.
Definition object_base.h:88
uint32_t clear_limit
Amount of tiles we can (still) clear (times 65536).
T y
Y coordinate.
T x
X coordinate.
T x
X coordinate.
T y
Y coordinate.
T z
Z coordinate.
static uint SizeX()
Get the size of the map along the X.
Definition map_func.h:262
static uint ScaleBySize(uint n)
Scales the given value by the map size, where the given value is for a 256 by 256 map.
Definition map_func.h:331
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:271
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:366
static uint LogX()
Logarithm of the map size along the X side.
Definition map_func.h:243
static uint LogY()
Logarithm of the map size along the y side.
Definition map_func.h:253
static uint MaxY()
Gets the maximum Y coordinate within the map, including TileType::Void.
Definition map_func.h:298
static uint MaxX()
Gets the maximum X coordinate within the map, including TileType::Void.
Definition map_func.h:289
static uint Size()
Get the size of the map.
Definition map_func.h:280
static Company * Get(auto index)
static Company * GetIfValid(auto index)
Coord3D< uint8_t > extent
Size of bounding box.
Definition sprite.h:20
Data structure describing a sprite.
uint16_t width
Width of the sprite.
uint16_t height
Height of the sprite.
std::byte data[]
Sprite data.
Tile description for the 'land area information' tool.
Definition tile_cmd.h:40
Tile information, used while rendering the tile.
Definition tile_cmd.h:34
Slope tileh
Slope of the tile.
Definition tile_cmd.h:35
TileIndex tile
Tile index.
Definition tile_cmd.h:36
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:214
Track status of a tile.
Definition track_type.h:105
Command definitions related to terraforming.
void GenerateTerrainPerlin()
The main new land generator using Perlin noise.
Definition tgp.cpp:1057
Functions for the Perlin noise enhanced map generator.
bool MayAnimateTile(TileIndex tile)
Test if a tile may be animated.
Definition tile_cmd.h:269
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition tile_map.cpp:94
std::tuple< Slope, int > GetTilePixelSlopeOutsideMap(int x, int y)
Return the slope of a given tile, also for tiles outside the map (virtual "black" tiles).
Definition tile_map.cpp:77
std::tuple< Slope, int > GetTileSlopeZ(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.cpp:55
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:135
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:115
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
static uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
void SetTileHeight(Tile tile, uint height)
Sets the height of a tile.
Definition tile_map.h:57
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
void SetTropicZone(Tile tile, TropicZone type)
Set the tropic zone.
Definition tile_map.h:225
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
static constexpr uint MAX_TILE_HEIGHT
Maximum allowed tile height.
Definition tile_type.h:24
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
@ Desert
Tile is desert.
Definition tile_type.h:83
@ Rainforest
Rainforest tile.
Definition tile_type.h:84
@ Normal
Normal tropiczone.
Definition tile_type.h:82
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
static constexpr uint TILE_PIXELS
Pixel distance between tile columns/rows in ZOOM_BASE.
Definition tile_type.h:17
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
@ Water
Water tile.
Definition tile_type.h:55
@ Void
Invisible tiles at the SW and SE border.
Definition tile_type.h:56
@ Clear
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:49
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.
TransportType
Available types of transport.
void PlaceTree(TileIndex tile, uint32_t r, bool keep_density)
Make a random tree tile of the given tile.
Definition tree_cmd.cpp:171
Command definitions related to tree tiles.
void OffsetGroundSprite(int x, int y)
Called when a foundation has been drawn for the current tile.
Definition viewport.cpp:605
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:664
Functions related to (drawing on) viewports.
Map accessors for void tiles.
void MakeVoid(Tile t)
Make a nice void tile ;).
Definition void_map.h:19
Functions related to water management.
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:99
void MakeRiverAndModifyDesertZoneAround(TileIndex tile)
Make a river tile and remove desert directly around it.
bool IsTileOnWater(Tile t)
Tests if the tile was built on water.
Definition water_map.h:138
bool IsRiver(Tile t)
Is it a river water tile?
Definition water_map.h:182
@ Canal
Canal.
Definition water_map.h:41
@ Sea
Sea.
Definition water_map.h:40
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:103
bool IsCanal(Tile t)
Is it a canal tile?
Definition water_map.h:171
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:114
bool IsCoastTile(Tile t)
Is it a coast tile.
Definition water_map.h:213
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:375
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition water_map.h:192
void InvalidateWaterRegion(TileIndex tile)
Marks the water region that tile is part of as invalid.
Handles dividing the water in the map into regions to assist pathfinding.
void YapfBuildRiver(TileIndex start_tile, TileIndex end_tile, TileIndex spring_tile, bool main_river)
Builds a river from the start tile to the end tile.
Pathfinder for river building.