OpenTTD Source: src/landscape.cpp Source File

OpenTTD Source 15.3

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
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"
25#include "timer/timer_game_calendar.h"
26#include "timer/timer_game_tick.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"
36#include "saveload/saveload.h"
37#include "framerate_type.h"
38#include "landscape_cmd.h"
39#include "terraform_cmd.h"
40#include "station_func.h"
41#include "pathfinder/water_regions.h"
42#include "pathfinder/yapf/yapf_river_builder.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
52 _tile_type_clear_procs,
53 _tile_type_rail_procs,
54 _tile_type_road_procs,
55 _tile_type_town_procs,
56 _tile_type_trees_procs,
57 _tile_type_station_procs,
58 _tile_type_water_procs,
59 _tile_type_void_procs,
60 _tile_type_industry_procs,
61 _tile_type_tunnelbridge_procs,
62 _tile_type_object_procs;
63
69 const TileTypeProcs * const _tile_type_procs[16] = {
70 &_tile_type_clear_procs,
71 &_tile_type_rail_procs,
72 &_tile_type_road_procs,
73 &_tile_type_town_procs,
74 &_tile_type_trees_procs,
75 &_tile_type_station_procs,
76 &_tile_type_water_procs,
77 &_tile_type_void_procs,
78 &_tile_type_industry_procs,
79 &_tile_type_tunnelbridge_procs,
80 &_tile_type_object_procs,
81};
82
84extern const uint8_t _slope_to_sprite_offset[32] = {
85 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0,
86 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 15, 18, 0,
87};
88
89 static const uint TILE_UPDATE_FREQUENCY_LOG = 8;
90 static const uint TILE_UPDATE_FREQUENCY = 1 << TILE_UPDATE_FREQUENCY_LOG;
91
100 static std::unique_ptr<SnowLine> _snow_line;
101
115 Point InverseRemapCoords2(int x, int y, bool clamp_to_map, bool *clamped)
116{
117 if (clamped != nullptr) *clamped = false; // Not clamping yet.
118
119 /* Initial x/y world coordinate is like if the landscape
120 * was completely flat on height 0. */
121 Point pt = InverseRemapCoords(x, y);
122
123 const uint min_coord = _settings_game.construction.freeform_edges ? TILE_SIZE : 0;
124 const uint max_x = Map::MaxX() * TILE_SIZE - 1;
125 const uint max_y = Map::MaxY() * TILE_SIZE - 1;
126
127 if (clamp_to_map) {
128 /* Bring the coordinates near to a valid range. At the top we allow a number
129 * of extra tiles. This is mostly due to the tiles on the north side of
130 * the map possibly being drawn higher due to the extra height levels. */
131 int extra_tiles = CeilDiv(_settings_game.construction.map_height_limit * TILE_HEIGHT, TILE_PIXELS);
132 Point old_pt = pt;
133 pt.x = Clamp(pt.x, -extra_tiles * TILE_SIZE, max_x);
134 pt.y = Clamp(pt.y, -extra_tiles * TILE_SIZE, max_y);
135 if (clamped != nullptr) *clamped = (pt.x != old_pt.x) || (pt.y != old_pt.y);
136 }
137
138 /* Now find the Z-world coordinate by fix point iteration.
139 * This is a bit tricky because the tile height is non-continuous at foundations.
140 * The clicked point should be approached from the back, otherwise there are regions that are not clickable.
141 * (FOUNDATION_HALFTILE_LOWER on SLOPE_STEEP_S hides north halftile completely)
142 * So give it a z-malus of 4 in the first iterations. */
143 int z = 0;
144 if (clamp_to_map) {
145 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;
146 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;
147 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;
148 } else {
149 for (int i = 0; i < 5; i++) z = GetSlopePixelZOutsideMap(pt.x + std::max(z, 4) - 4, pt.y + std::max(z, 4) - 4) / 2;
150 for (int m = 3; m > 0; m--) z = GetSlopePixelZOutsideMap(pt.x + std::max(z, m) - m, pt.y + std::max(z, m) - m) / 2;
151 for (int i = 0; i < 5; i++) z = GetSlopePixelZOutsideMap(pt.x + z, pt.y + z ) / 2;
152 }
153
154 pt.x += z;
155 pt.y += z;
156 if (clamp_to_map) {
157 Point old_pt = pt;
158 pt.x = Clamp(pt.x, min_coord, max_x);
159 pt.y = Clamp(pt.y, min_coord, max_y);
160 if (clamped != nullptr) *clamped = *clamped || (pt.x != old_pt.x) || (pt.y != old_pt.y);
161 }
162
163 return pt;
164}
165
174uint ApplyFoundationToSlope(Foundation f, Slope &s)
175{
176 if (!IsFoundation(f)) return 0;
177
178 if (IsLeveledFoundation(f)) {
179 uint dz = 1 + (IsSteepSlope(s) ? 1 : 0);
180 s = SLOPE_FLAT;
181 return dz;
182 }
183
184 if (f != FOUNDATION_STEEP_BOTH && IsNonContinuousFoundation(f)) {
185 s = HalftileSlope(s, GetHalftileFoundationCorner(f));
186 return 0;
187 }
188
189 if (IsSpecialRailFoundation(f)) {
190 s = SlopeWithThreeCornersRaised(OppositeCorner(GetRailFoundationCorner(f)));
191 return 0;
192 }
193
194 uint dz = IsSteepSlope(s) ? 1 : 0;
195 Corner highest_corner = GetHighestSlopeCorner(s);
196
197 switch (f) {
198 case FOUNDATION_INCLINED_X:
199 s = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? SLOPE_SW : SLOPE_NE);
200 break;
201
202 case FOUNDATION_INCLINED_Y:
203 s = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? SLOPE_SE : SLOPE_NW);
204 break;
205
206 case FOUNDATION_STEEP_LOWER:
207 s = SlopeWithOneCornerRaised(highest_corner);
208 break;
209
210 case FOUNDATION_STEEP_BOTH:
211 s = HalftileSlope(SlopeWithOneCornerRaised(highest_corner), highest_corner);
212 break;
213
214 default: NOT_REACHED();
215 }
216 return dz;
217}
218
219
232uint GetPartialPixelZ(int x, int y, Slope corners)
233{
234 if (IsHalftileSlope(corners)) {
235 /* A foundation is placed on half the tile at a specific corner. This means that,
236 * depending on the corner, that one half of the tile is at the maximum height. */
237 switch (GetHalftileSlopeCorner(corners)) {
238 case CORNER_W:
239 if (x > y) return GetSlopeMaxPixelZ(corners);
240 break;
241
242 case CORNER_S:
243 if (x + y >= (int)TILE_SIZE) return GetSlopeMaxPixelZ(corners);
244 break;
245
246 case CORNER_E:
247 if (x <= y) return GetSlopeMaxPixelZ(corners);
248 break;
249
250 case CORNER_N:
251 if (x + y < (int)TILE_SIZE) return GetSlopeMaxPixelZ(corners);
252 break;
253
254 default: NOT_REACHED();
255 }
256 }
257
258 switch (RemoveHalftileSlope(corners)) {
259 case SLOPE_FLAT: return 0;
260
261 /* One corner is up.*/
262 case SLOPE_N: return x + y <= (int)TILE_SIZE ? (TILE_SIZE - x - y) >> 1 : 0;
263 case SLOPE_E: return y >= x ? (1 + y - x) >> 1 : 0;
264 case SLOPE_S: return x + y >= (int)TILE_SIZE ? (1 + x + y - TILE_SIZE) >> 1 : 0;
265 case SLOPE_W: return x >= y ? (x - y) >> 1 : 0;
266
267 /* Two corners next to each other are up. */
268 case SLOPE_NE: return (TILE_SIZE - x) >> 1;
269 case SLOPE_SE: return (y + 1) >> 1;
270 case SLOPE_SW: return (x + 1) >> 1;
271 case SLOPE_NW: return (TILE_SIZE - y) >> 1;
272
273 /* Three corners are up on the same level. */
274 case SLOPE_ENW: return x + y >= (int)TILE_SIZE ? TILE_HEIGHT - ((1 + x + y - TILE_SIZE) >> 1) : TILE_HEIGHT;
275 case SLOPE_SEN: return y < x ? TILE_HEIGHT - ((x - y) >> 1) : TILE_HEIGHT;
276 case SLOPE_WSE: return x + y <= (int)TILE_SIZE ? TILE_HEIGHT - ((TILE_SIZE - x - y) >> 1) : TILE_HEIGHT;
277 case SLOPE_NWS: return x < y ? TILE_HEIGHT - ((1 + y - x) >> 1) : TILE_HEIGHT;
278
279 /* Two corners at opposite sides are up. */
280 case SLOPE_NS: return x + y < (int)TILE_SIZE ? (TILE_SIZE - x - y) >> 1 : (1 + x + y - TILE_SIZE) >> 1;
281 case SLOPE_EW: return x >= y ? (x - y) >> 1 : (1 + y - x) >> 1;
282
283 /* Very special cases. */
284 case SLOPE_ELEVATED: return TILE_HEIGHT;
285
286 /* Steep slopes. The top is at 2 * TILE_HEIGHT. */
287 case SLOPE_STEEP_N: return (TILE_SIZE - x + TILE_SIZE - y) >> 1;
288 case SLOPE_STEEP_E: return (TILE_SIZE + 1 + y - x) >> 1;
289 case SLOPE_STEEP_S: return (1 + x + y) >> 1;
290 case SLOPE_STEEP_W: return (TILE_SIZE + x - y) >> 1;
291
292 default: NOT_REACHED();
293 }
294}
295
307 int GetSlopePixelZ(int x, int y, bool ground_vehicle)
308{
309 TileIndex tile = TileVirtXY(x, y);
310
311 return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y, ground_vehicle);
312}
313
322 int GetSlopePixelZOutsideMap(int x, int y)
323{
324 if (IsInsideBS(x, 0, Map::SizeX() * TILE_SIZE) && IsInsideBS(y, 0, Map::SizeY() * TILE_SIZE)) {
325 return GetSlopePixelZ(x, y, false);
326 } else {
327 return _tile_type_procs[MP_VOID]->get_slope_z_proc(INVALID_TILE, x, y, false);
328 }
329}
330
340 int GetSlopeZInCorner(Slope tileh, Corner corner)
341{
342 assert(!IsHalftileSlope(tileh));
343 return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? 1 : 0) + (tileh == SteepSlope(corner) ? 1 : 0);
344}
345
358 void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int &z1, int &z2)
359{
360 static const Slope corners[4][4] = {
361 /* corner | steep slope
362 * z1 z2 | z1 z2 */
363 {SLOPE_E, SLOPE_N, SLOPE_STEEP_E, SLOPE_STEEP_N}, // DIAGDIR_NE, z1 = E, z2 = N
364 {SLOPE_S, SLOPE_E, SLOPE_STEEP_S, SLOPE_STEEP_E}, // DIAGDIR_SE, z1 = S, z2 = E
365 {SLOPE_S, SLOPE_W, SLOPE_STEEP_S, SLOPE_STEEP_W}, // DIAGDIR_SW, z1 = S, z2 = W
366 {SLOPE_W, SLOPE_N, SLOPE_STEEP_W, SLOPE_STEEP_N}, // DIAGDIR_NW, z1 = W, z2 = N
367 };
368
369 int halftile_test = (IsHalftileSlope(tileh) ? SlopeWithOneCornerRaised(GetHalftileSlopeCorner(tileh)) : 0);
370 if (halftile_test == corners[edge][0]) z2 += TILE_HEIGHT; // The slope is non-continuous in z2. z2 is on the upper side.
371 if (halftile_test == corners[edge][1]) z1 += TILE_HEIGHT; // The slope is non-continuous in z1. z1 is on the upper side.
372
373 if ((tileh & corners[edge][0]) != 0) z1 += TILE_HEIGHT; // z1 is raised
374 if ((tileh & corners[edge][1]) != 0) z2 += TILE_HEIGHT; // z2 is raised
375 if (RemoveHalftileSlope(tileh) == corners[edge][2]) z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
376 if (RemoveHalftileSlope(tileh) == corners[edge][3]) z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
377}
378
386std::tuple<Slope, int> GetFoundationSlope(TileIndex tile)
387{
388 auto [tileh, z] = GetTileSlopeZ(tile);
389 Foundation f = _tile_type_procs[GetTileType(tile)]->get_foundation_proc(tile, tileh);
390 z += ApplyFoundationToSlope(f, tileh);
391 return {tileh, z};
392}
393
394
395bool HasFoundationNW(TileIndex tile, Slope slope_here, uint z_here)
396{
397 int z_W_here = z_here;
398 int z_N_here = z_here;
399 GetSlopePixelZOnEdge(slope_here, DIAGDIR_NW, z_W_here, z_N_here);
400
401 auto [slope, z] = GetFoundationPixelSlope(TileAddXY(tile, 0, -1));
402 int z_W = z;
403 int z_N = z;
404 GetSlopePixelZOnEdge(slope, DIAGDIR_SE, z_W, z_N);
405
406 return (z_N_here > z_N) || (z_W_here > z_W);
407}
408
409
410bool HasFoundationNE(TileIndex tile, Slope slope_here, uint z_here)
411{
412 int z_E_here = z_here;
413 int z_N_here = z_here;
414 GetSlopePixelZOnEdge(slope_here, DIAGDIR_NE, z_E_here, z_N_here);
415
416 auto [slope, z] = GetFoundationPixelSlope(TileAddXY(tile, -1, 0));
417 int z_E = z;
418 int z_N = z;
419 GetSlopePixelZOnEdge(slope, DIAGDIR_SW, z_E, z_N);
420
421 return (z_N_here > z_N) || (z_E_here > z_E);
422}
423
429 void DrawFoundation(TileInfo *ti, Foundation f)
430{
431 if (!IsFoundation(f)) return;
432
433 /* Two part foundations must be drawn separately */
434 assert(f != FOUNDATION_STEEP_BOTH);
435
436 uint sprite_block = 0;
437 auto [slope, z] = GetFoundationPixelSlope(ti->tile);
438
439 /* Select the needed block of foundations sprites
440 * Block 0: Walls at NW and NE edge
441 * Block 1: Wall at NE edge
442 * Block 2: Wall at NW edge
443 * Block 3: No walls at NW or NE edge
444 */
445 if (!HasFoundationNW(ti->tile, slope, z)) sprite_block += 1;
446 if (!HasFoundationNE(ti->tile, slope, z)) sprite_block += 2;
447
448 /* Use the original slope sprites if NW and NE borders should be visible */
449 SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * TRKFOUND_BLOCK_SIZE));
450 SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SLOPES_INCLINED_OFFSET + sprite_block * TRKFOUND_BLOCK_SIZE;
451 SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * HALFTILE_BLOCK_SIZE;
452
453 if (IsSteepSlope(ti->tileh)) {
454 if (!IsNonContinuousFoundation(f)) {
455 /* Lower part of foundation */
456 static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
457 AddSortableSpriteToDraw(leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, *ti, bounds);
458 }
459
460 Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
461 ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
462
463 if (IsInclinedFoundation(f)) {
464 /* inclined foundation */
465 uint8_t inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
466
467 SpriteBounds bounds{{}, {1, 1, TILE_HEIGHT}, {}};
468 if (f == FOUNDATION_INCLINED_X) bounds.extent.x = TILE_SIZE;
469 if (f == FOUNDATION_INCLINED_Y) bounds.extent.y = TILE_SIZE;
470 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, *ti, bounds);
471 OffsetGroundSprite(0, 0);
472 } else if (IsLeveledFoundation(f)) {
473 static constexpr SpriteBounds bounds{{0, 0, -(int)TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
474 AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, *ti, bounds);
475 OffsetGroundSprite(0, -(int)TILE_HEIGHT);
476 } else if (f == FOUNDATION_STEEP_LOWER) {
477 /* one corner raised */
478 OffsetGroundSprite(0, -(int)TILE_HEIGHT);
479 } else {
480 /* halftile foundation */
481 int8_t x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
482 int8_t y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
483
484 SpriteBounds bounds{{x_bb, y_bb, TILE_HEIGHT}, {TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1}, {}};
485 AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, *ti, bounds);
486 /* Reposition ground sprite back to original position after bounding box change above. This is similar to
487 * RemapCoords() but without zoom scaling. */
488 Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
489 OffsetGroundSprite(-pt.x, -pt.y);
490 }
491 } else {
492 if (IsLeveledFoundation(f)) {
493 /* leveled foundation */
494 static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
495 AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, *ti, bounds);
496 OffsetGroundSprite(0, -(int)TILE_HEIGHT);
497 } else if (IsNonContinuousFoundation(f)) {
498 /* halftile foundation */
499 Corner halftile_corner = GetHalftileFoundationCorner(f);
500 int8_t x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
501 int8_t y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
502
503 SpriteBounds bounds{{x_bb, y_bb, 0}, {TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1}, {}};
504 AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, *ti, bounds);
505 /* Reposition ground sprite back to original position after bounding box change above. This is similar to
506 * RemapCoords() but without zoom scaling. */
507 Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
508 OffsetGroundSprite(-pt.x, -pt.y);
509 } else if (IsSpecialRailFoundation(f)) {
510 /* anti-zig-zag foundation */
511 SpriteID spr;
512 if (ti->tileh == SLOPE_NS || ti->tileh == SLOPE_EW) {
513 /* half of leveled foundation under track corner */
514 spr = leveled_base + SlopeWithThreeCornersRaised(GetRailFoundationCorner(f));
515 } else {
516 /* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
517 spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
518 }
519 static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
520 AddSortableSpriteToDraw(spr, PAL_NONE, *ti, bounds);
521 OffsetGroundSprite(0, 0);
522 } else {
523 /* inclined foundation */
524 uint8_t inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
525
526 SpriteBounds bounds{{}, {1, 1, TILE_HEIGHT}, {}};
527 if (f == FOUNDATION_INCLINED_X) bounds.extent.x = TILE_SIZE;
528 if (f == FOUNDATION_INCLINED_Y) bounds.extent.y = TILE_SIZE;
529 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, *ti, bounds);
530 OffsetGroundSprite(0, 0);
531 }
532 ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
533 }
534}
535
536void DoClearSquare(TileIndex tile)
537{
538 /* If the tile can have animation and we clear it, delete it from the animated tile list. */
539 if (MayAnimateTile(tile)) DeleteAnimatedTile(tile, true);
540
541 bool remove = IsDockingTile(tile);
542 MakeClear(tile, CLEAR_GRASS, _generating_world ? 3 : 0);
543 MarkTileDirtyByTile(tile);
544 if (remove) RemoveDockingTile(tile);
545
546 ClearNeighbourNonFloodingStates(tile);
547 InvalidateWaterRegion(tile);
548}
549
560TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
561{
562 return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode, sub_mode, side);
563}
564
571 void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
572{
573 _tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_owner, new_owner);
574}
575
576void GetTileDesc(TileIndex tile, TileDesc &td)
577{
578 _tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
579}
580
586 bool IsSnowLineSet()
587{
588 return _snow_line != nullptr;
589}
590
596 void SetSnowLine(std::unique_ptr<SnowLine> &&snow_line)
597{
598 _snow_line = std::move(snow_line);
599}
600
606uint8_t GetSnowLine()
607{
608 if (_snow_line == nullptr) return _settings_game.game_creation.snow_line_height;
609
610 TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
611 return _snow_line->table[ymd.month][ymd.day];
612}
613
619uint8_t HighestSnowLine()
620{
621 return _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->highest_value;
622}
623
629uint8_t LowestSnowLine()
630{
631 return _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->lowest_value;
632}
633
638 void ClearSnowLine()
639{
640 _snow_line = nullptr;
641}
642
647 bool IsMapSurroundedByWater()
648{
649 auto check_tile = [](uint x, uint y) -> bool {
650 auto [slope, h] = GetTilePixelSlopeOutsideMap(x, y);
651 return ((slope == SLOPE_FLAT) && (h == 0));
652 };
653
654 /* Check the map corners. */
655 if (!check_tile(0, 0)) return false;
656 if (!check_tile(0, Map::SizeY())) return false;
657 if (!check_tile(Map::SizeX(), 0)) return false;
658 if (!check_tile(Map::SizeX(), Map::SizeY())) return false;
659
660 /* Check the map edges.*/
661 for (uint x = 0; x <= Map::SizeX(); x++) {
662 if (!check_tile(x, 0)) return false;
663 if (!check_tile(x, Map::SizeY())) return false;
664 }
665 for (uint y = 1; y < Map::SizeY(); y++) {
666 if (!check_tile(0, y)) return false;
667 if (!check_tile(Map::SizeX(), y)) return false;
668 }
669
670 return true;
671}
672
679 CommandCost CmdLandscapeClear(DoCommandFlags flags, TileIndex tile)
680{
681 CommandCost cost(EXPENSES_CONSTRUCTION);
682 bool do_clear = false;
683 /* Test for stuff which results in water when cleared. Then add the cost to also clear the water. */
684 if (flags.Test(DoCommandFlag::ForceClearTile) && HasTileWaterClass(tile) && IsTileOnWater(tile) && !IsWaterTile(tile) && !IsCoastTile(tile)) {
685 if (flags.Test(DoCommandFlag::Auto) && GetWaterClass(tile) == WaterClass::Canal) return CommandCost(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
686 /* 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. */
687 if (!IsBuoyTile(tile) || GetTileOwner(tile) == _current_company) {
688 do_clear = true;
689 cost.AddCost(GetWaterClass(tile) == WaterClass::Canal ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER]);
690 }
691 }
692
693 Company *c = flags.Any({DoCommandFlag::Auto, DoCommandFlag::Bankrupt}) ? nullptr : Company::GetIfValid(_current_company);
694 if (c != nullptr && (int)GB(c->clear_limit, 16, 16) < 1) {
695 return CommandCost(STR_ERROR_CLEARING_LIMIT_REACHED);
696 }
697
698 const ClearedObjectArea *coa = FindClearedObject(tile);
699
700 /* If this tile was the first tile which caused object destruction, always
701 * pass it on to the tile_type_proc. That way multiple test runs and the exec run stay consistent. */
702 if (coa != nullptr && coa->first_tile != tile) {
703 /* If this tile belongs to an object which was already cleared via another tile, pretend it has been
704 * already removed.
705 * However, we need to check stuff, which is not the same for all object tiles. (e.g. being on water or not) */
706
707 /* If a object is removed, it leaves either bare land or water. */
708 if (flags.Test(DoCommandFlag::NoWater) && HasTileWaterClass(tile) && IsTileOnWater(tile)) {
709 return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
710 }
711 } else {
712 cost.AddCost(_tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags));
713 }
714
715 if (flags.Test(DoCommandFlag::Execute)) {
716 if (c != nullptr) c->clear_limit -= 1 << 16;
717 if (do_clear) {
718 if (IsWaterTile(tile) && IsCanal(tile)) {
719 Owner owner = GetTileOwner(tile);
720 if (Company::IsValidID(owner)) {
721 Company::Get(owner)->infrastructure.water--;
722 DirtyCompanyInfrastructureWindows(owner);
723 }
724 }
725 DoClearSquare(tile);
726 ClearNeighbourNonFloodingStates(tile);
727 }
728 }
729 return cost;
730}
731
740std::tuple<CommandCost, Money> CmdClearArea(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, bool diagonal)
741{
742 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
743
744 Money money = GetAvailableMoneyForCommand();
745 CommandCost cost(EXPENSES_CONSTRUCTION);
746 CommandCost last_error = CMD_ERROR;
747 bool had_success = false;
748
749 const Company *c = flags.Any({DoCommandFlag::Auto, DoCommandFlag::Bankrupt}) ? nullptr : Company::GetIfValid(_current_company);
750 int limit = (c == nullptr ? INT32_MAX : GB(c->clear_limit, 16, 16));
751
752 if (tile != start_tile) flags.Set(DoCommandFlag::ForceClearTile);
753
754 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
755 for (; *iter != INVALID_TILE; ++(*iter)) {
756 TileIndex t = *iter;
757 CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), t);
758 if (ret.Failed()) {
759 last_error = std::move(ret);
760
761 /* We may not clear more tiles. */
762 if (c != nullptr && GB(c->clear_limit, 16, 16) < 1) break;
763 continue;
764 }
765
766 had_success = true;
767 if (flags.Test(DoCommandFlag::Execute)) {
768 money -= ret.GetCost();
769 if (ret.GetCost() > 0 && money < 0) {
770 return { cost, ret.GetCost() };
771 }
772 Command<CMD_LANDSCAPE_CLEAR>::Do(flags, t);
773
774 /* draw explosion animation...
775 * Disable explosions when game is paused. Looks silly and blocks the view. */
776 if ((t == tile || t == start_tile) && _pause_mode.None()) {
777 /* big explosion in two corners, or small explosion for single tiles */
778 CreateEffectVehicleAbove(TileX(t) * TILE_SIZE + TILE_SIZE / 2, TileY(t) * TILE_SIZE + TILE_SIZE / 2, 2,
779 TileX(tile) == TileX(start_tile) && TileY(tile) == TileY(start_tile) ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
780 );
781 }
782 } else {
783 /* When we're at the clearing limit we better bail (unneed) testing as well. */
784 if (ret.GetCost() != 0 && --limit <= 0) break;
785 }
786 cost.AddCost(ret.GetCost());
787 }
788
789 return { had_success ? cost : last_error, 0 };
790}
791
792
793 TileIndex _cur_tileloop_tile;
794
798 void RunTileLoop()
799{
800 PerformanceAccumulator framerate(PFE_GL_LANDSCAPE);
801
802 /* The pseudorandom sequence of tiles is generated using a Galois linear feedback
803 * shift register (LFSR). This allows a deterministic pseudorandom ordering, but
804 * still with minimal state and fast iteration. */
805
806 /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 24-bit (for 4096x4096 maps).
807 * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */
808 static const uint32_t feedbacks[] = {
809 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87
810 };
811 static_assert(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1);
812 const uint32_t feedback = feedbacks[Map::LogX() + Map::LogY() - 2 * MIN_MAP_SIZE_BITS];
813
814 /* We update every tile every TILE_UPDATE_FREQUENCY ticks, so divide the map size by 2^TILE_UPDATE_FREQUENCY_LOG = TILE_UPDATE_FREQUENCY */
815 static_assert(2 * MIN_MAP_SIZE_BITS >= TILE_UPDATE_FREQUENCY_LOG);
816 uint count = 1 << (Map::LogX() + Map::LogY() - TILE_UPDATE_FREQUENCY_LOG);
817
818 TileIndex tile = _cur_tileloop_tile;
819 /* The LFSR cannot have a zeroed state. */
820 assert(tile != 0);
821
822 /* Manually update tile 0 every TILE_UPDATE_FREQUENCY ticks - the LFSR never iterates over it itself. */
823 if (TimerGameTick::counter % TILE_UPDATE_FREQUENCY == 0) {
824 _tile_type_procs[GetTileType(0)]->tile_loop_proc(TileIndex{});
825 count--;
826 }
827
828 while (count--) {
829 _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
830
831 /* Get the next tile in sequence using a Galois LFSR. */
832 tile = TileIndex{(tile.base() >> 1) ^ (-(int32_t)(tile.base() & 1) & feedback)};
833 }
834
835 _cur_tileloop_tile = tile;
836}
837
838void InitializeLandscape()
839{
840 for (uint y = _settings_game.construction.freeform_edges ? 1 : 0; y < Map::MaxY(); y++) {
841 for (uint x = _settings_game.construction.freeform_edges ? 1 : 0; x < Map::MaxX(); x++) {
842 MakeClear(TileXY(x, y), CLEAR_GRASS, 3);
843 SetTileHeight(TileXY(x, y), 0);
844 SetTropicZone(TileXY(x, y), TROPICZONE_NORMAL);
845 ClearBridgeMiddle(TileXY(x, y));
846 }
847 }
848
849 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, Map::MaxY()));
850 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(Map::MaxX(), y));
851}
852
853static const uint8_t _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 };
854static const uint8_t _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
855
856static void GenerateTerrain(int type, uint flag)
857{
858 uint32_t r = Random();
859
860 /* Choose one of the templates from the graphics file. */
861 const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + SPR_MAPGEN_BEGIN, SpriteType::MapGen);
862 if (templ == nullptr) UserError("Map generator sprites could not be loaded");
863
864 /* Chose a random location to apply the template to. */
865 uint x = r & Map::MaxX();
866 uint y = (r >> Map::LogX()) & Map::MaxY();
867
868 /* Make sure the template is not too close to the upper edges; bottom edges are checked later. */
869 uint edge_distance = 1 + (_settings_game.construction.freeform_edges ? 1 : 0);
870 if (x <= edge_distance || y <= edge_distance) return;
871
872 DiagDirection direction = (DiagDirection)GB(r, 22, 2);
873 uint w = templ->width;
874 uint h = templ->height;
875
876 if (DiagDirToAxis(direction) == AXIS_Y) std::swap(w, h);
877
878 const uint8_t *p = reinterpret_cast<const uint8_t *>(templ->data);
879
880 if ((flag & 4) != 0) {
881 /* This is only executed in secondary/tertiary loops to generate the terrain for arctic and tropic.
882 * It prevents the templates to be applied to certain parts of the map based on the flags, thus
883 * creating regions with different elevations/topography. */
884 uint xw = x * Map::SizeY();
885 uint yw = y * Map::SizeX();
886 uint bias = (Map::SizeX() + Map::SizeY()) * 16;
887
888 switch (flag & 3) {
889 default: NOT_REACHED();
890 case 0:
891 if (xw + yw > Map::Size() - bias) return;
892 break;
893
894 case 1:
895 if (yw < xw + bias) return;
896 break;
897
898 case 2:
899 if (xw + yw < Map::Size() + bias) return;
900 break;
901
902 case 3:
903 if (xw < yw + bias) return;
904 break;
905 }
906 }
907
908 /* Ensure the template does not overflow at the bottom edges of the map; upper edges were checked before. */
909 if (x + w >= Map::MaxX()) return;
910 if (y + h >= Map::MaxY()) return;
911
912 TileIndex tile = TileXY(x, y);
913
914 /* Get the template and overlay in a particular direction over the map's height from the given
915 * origin point (tile), and update the map's height everywhere where the height from the template
916 * is higher than the height of the map. In other words, this only raises the tile heights. */
917 switch (direction) {
918 default: NOT_REACHED();
919 case DIAGDIR_NE:
920 do {
921 TileIndex tile_cur = tile;
922
923 for (uint w_cur = w; w_cur != 0; --w_cur) {
924 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
925 p++;
926 tile_cur += TileDiffXY(1, 0);
927 }
928 tile += TileDiffXY(0, 1);
929 } while (--h != 0);
930 break;
931
932 case DIAGDIR_SE:
933 do {
934 TileIndex tile_cur = tile;
935
936 for (uint h_cur = h; h_cur != 0; --h_cur) {
937 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
938 p++;
939 tile_cur += TileDiffXY(0, 1);
940 }
941 tile += TileDiffXY(1, 0);
942 } while (--w != 0);
943 break;
944
945 case DIAGDIR_SW:
946 tile += TileDiffXY(w - 1, 0);
947 do {
948 TileIndex tile_cur = tile;
949
950 for (uint w_cur = w; w_cur != 0; --w_cur) {
951 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
952 p++;
953 tile_cur -= TileDiffXY(1, 0);
954 }
955 tile += TileDiffXY(0, 1);
956 } while (--h != 0);
957 break;
958
959 case DIAGDIR_NW:
960 tile += TileDiffXY(0, h - 1);
961 do {
962 TileIndex tile_cur = tile;
963
964 for (uint h_cur = h; h_cur != 0; --h_cur) {
965 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
966 p++;
967 tile_cur -= TileDiffXY(0, 1);
968 }
969 tile += TileDiffXY(1, 0);
970 } while (--w != 0);
971 break;
972 }
973}
974
975
976#include "table/genland.h"
977
978static void CreateDesertOrRainForest(uint desert_tropic_line)
979{
980 uint update_freq = Map::Size() / 4;
981
982 for (const auto tile : Map::Iterate()) {
983 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
984
985 if (!IsValidTile(tile)) continue;
986
987 auto allows_desert = [tile, desert_tropic_line](auto &offset) {
988 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
989 return t == INVALID_TILE || (TileHeight(t) < desert_tropic_line && !IsTileType(t, MP_WATER));
990 };
991 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_desert)) {
992 SetTropicZone(tile, TROPICZONE_DESERT);
993 }
994 }
995
996 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
997 if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
998
999 RunTileLoop();
1000 }
1001
1002 for (const auto tile : Map::Iterate()) {
1003 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
1004
1005 if (!IsValidTile(tile)) continue;
1006
1007 auto allows_rainforest = [tile](auto &offset) {
1008 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
1009 return t == INVALID_TILE || !IsTileType(t, MP_CLEAR) || !IsClearGround(t, CLEAR_DESERT);
1010 };
1011 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_rainforest)) {
1012 SetTropicZone(tile, TROPICZONE_RAINFOREST);
1013 }
1014 }
1015}
1016
1022 static bool FindSpring(TileIndex tile)
1023{
1024 int reference_height;
1025 if (!IsTileFlat(tile, &reference_height) || IsWaterTile(tile)) return false;
1026
1027 /* In the tropics rivers start in the rainforest. */
1028 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) != TROPICZONE_RAINFOREST) return false;
1029
1030 /* Are there enough higher tiles to warrant a 'spring'? */
1031 uint num = 0;
1032 for (int dx = -1; dx <= 1; dx++) {
1033 for (int dy = -1; dy <= 1; dy++) {
1034 TileIndex t = TileAddWrap(tile, dx, dy);
1035 if (t != INVALID_TILE && GetTileMaxZ(t) > reference_height) num++;
1036 }
1037 }
1038
1039 if (num < 4) return false;
1040
1041 /* Are we near the top of a hill? */
1042 for (int dx = -16; dx <= 16; dx++) {
1043 for (int dy = -16; dy <= 16; dy++) {
1044 TileIndex t = TileAddWrap(tile, dx, dy);
1045 if (t != INVALID_TILE && GetTileMaxZ(t) > reference_height + 2) return false;
1046 }
1047 }
1048
1049 return true;
1050}
1051
1058 static bool IsValidRiverTerminusTile(TileIndex tile, uint height)
1059{
1060 if (!IsValidTile(tile) || TileHeight(tile) != height || !IsTileFlat(tile)) return false;
1061 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) == TROPICZONE_DESERT) return false;
1062
1063 return true;
1064}
1065
1071 static void MakeLake(TileIndex lake_centre, uint height_lake)
1072{
1073 MakeRiverAndModifyDesertZoneAround(lake_centre);
1074 uint diameter = RandomRange(8) + 3;
1075
1076 /* Run the loop twice, so artefacts from going circular in one direction get (mostly) hidden. */
1077 for (uint loops = 0; loops < 2; ++loops) {
1078 for (TileIndex tile : SpiralTileSequence(lake_centre, diameter)) {
1079 if (!IsValidRiverTerminusTile(tile, height_lake)) continue;
1080 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1081 TileIndex t = tile + TileOffsByDiagDir(d);
1082 if (IsWaterTile(t)) {
1083 MakeRiverAndModifyDesertZoneAround(tile);
1084 break;
1085 }
1086 }
1087 }
1088 }
1089}
1090
1097 static void MakeWetlands(TileIndex centre, uint height, uint river_length)
1098{
1099 MakeRiverAndModifyDesertZoneAround(centre);
1100
1101 uint diameter = std::max((river_length), 16u);
1102
1103 /* Some wetlands have trees planted among the water tiles. */
1104 bool has_trees = Chance16(1, 2);
1105
1106 /* Create the main wetland area. */
1107 for (TileIndex tile : SpiralTileSequence(centre, diameter)) {
1108 if (!IsValidRiverTerminusTile(tile, height)) continue;
1109
1110 /* Don't make a perfect square, but a circle with a noisy border. */
1111 uint radius = diameter / 2;
1112 if ((DistanceSquare(tile, centre) > radius * radius) && Chance16(3, 4)) continue;
1113
1114 if (Chance16(1, 3)) {
1115 /* This tile is water. */
1116 MakeRiverAndModifyDesertZoneAround(tile);
1117 } else if (IsTileType(tile, MP_CLEAR)) {
1118 /* This tile is ground, which we always make rough. */
1119 SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
1120 /* Maybe place trees? */
1121 if (has_trees && _settings_game.game_creation.tree_placer != TP_NONE) {
1122 PlaceTree(tile, Random(), true);
1123 }
1124 }
1125 }
1126}
1127
1134 static bool TryMakeRiverTerminus(TileIndex tile, TileIndex begin)
1135{
1136 if (!IsValidTile(tile)) return false;
1137
1138 /* We don't want to end the river at the entry of the valley. */
1139 if (tile == begin) return false;
1140
1141 /* We don't want the river to end in the desert. */
1142 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) == TROPICZONE_DESERT) return false;
1143
1144 /* Only end on flat slopes. */
1145 int height_lake;
1146 if (!IsTileFlat(tile, &height_lake)) return false;
1147
1148 /* Only build at the height of the river. */
1149 int height_begin = TileHeight(begin);
1150 if (height_lake != height_begin) return false;
1151
1152 /* Checks successful, time to build.
1153 * Chance of water feature is split evenly between a lake, a wetland with trees, and a wetland with grass. */
1154 if (Chance16(1, 3)) {
1155 MakeLake(tile, height_lake);
1156 } else {
1157 MakeWetlands(tile, height_lake, DistanceManhattan(tile, begin));
1158 }
1159
1160 /* This is the new end of the river. */
1161 return true;
1162}
1163
1169 void RiverMakeWider(TileIndex tile, TileIndex origin_tile)
1170{
1171 /* Don't expand into void tiles. */
1172 if (!IsValidTile(tile)) return;
1173
1174 /* If the tile is already sea or river, don't expand. */
1175 if (IsWaterTile(tile)) return;
1176
1177 /* If the tile is at height 0 after terraforming but the ocean hasn't flooded yet, don't build river. */
1178 if (GetTileMaxZ(tile) == 0) return;
1179
1180 Slope cur_slope = GetTileSlope(tile);
1181 Slope desired_slope = GetTileSlope(origin_tile); // Initialize matching the origin tile as a shortcut if no terraforming is needed.
1182
1183 /* Never flow uphill. */
1184 if (GetTileMaxZ(tile) > GetTileMaxZ(origin_tile)) return;
1185
1186 /* If the new tile can't hold a river tile, try terraforming. */
1187 if (!IsTileFlat(tile) && !IsInclinedSlope(cur_slope)) {
1188 /* Don't try to terraform steep slopes. */
1189 if (IsSteepSlope(cur_slope)) return;
1190
1191 bool flat_river_found = false;
1192 bool sloped_river_found = false;
1193
1194 /* There are two common possibilities:
1195 * 1. River flat, adjacent tile has one corner lowered.
1196 * 2. River descending, adjacent tile has either one or three corners raised.
1197 */
1198
1199 /* First, determine the desired slope based on adjacent river tiles. This doesn't necessarily match the origin tile for the SpiralTileSequence. */
1200 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1201 TileIndex other_tile = TileAddByDiagDir(tile, d);
1202 Slope other_slope = GetTileSlope(other_tile);
1203
1204 /* Only consider river tiles. */
1205 if (IsWaterTile(other_tile) && IsRiver(other_tile)) {
1206 /* If the adjacent river tile flows downhill, we need to check where we are relative to the slope. */
1207 if (IsInclinedSlope(other_slope) && GetTileMaxZ(tile) == GetTileMaxZ(other_tile)) {
1208 /* Check for a parallel slope. If we don't find one, we're above or below the slope instead. */
1209 if (GetInclinedSlopeDirection(other_slope) == ChangeDiagDir(d, DIAGDIRDIFF_90RIGHT) ||
1210 GetInclinedSlopeDirection(other_slope) == ChangeDiagDir(d, DIAGDIRDIFF_90LEFT)) {
1211 desired_slope = other_slope;
1212 sloped_river_found = true;
1213 break;
1214 }
1215 }
1216 /* If we find an adjacent river tile, remember it. We'll terraform to match it later if we don't find a slope. */
1217 if (IsTileFlat(other_tile)) flat_river_found = true;
1218 }
1219 }
1220 /* We didn't find either an inclined or flat river, so we're climbing the wrong slope. Bail out. */
1221 if (!sloped_river_found && !flat_river_found) return;
1222
1223 /* We didn't find an inclined river, but there is a flat river. */
1224 if (!sloped_river_found && flat_river_found) desired_slope = SLOPE_FLAT;
1225
1226 /* Now that we know the desired slope, it's time to terraform! */
1227
1228 /* If the river is flat and the adjacent tile has one corner lowered, we want to raise it. */
1229 if (desired_slope == SLOPE_FLAT && IsSlopeWithThreeCornersRaised(cur_slope)) {
1230 /* Make sure we're not affecting an existing river slope tile. */
1231 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1232 TileIndex other_tile = TileAddByDiagDir(tile, d);
1233 if (IsInclinedSlope(GetTileSlope(other_tile)) && IsWaterTile(other_tile)) return;
1234 }
1235 Command<CMD_TERRAFORM_LAND>::Do({DoCommandFlag::Execute, DoCommandFlag::Auto}, tile, ComplementSlope(cur_slope), true);
1236
1237 /* If the river is descending and the adjacent tile has either one or three corners raised, we want to make it match the slope. */
1238 } else if (IsInclinedSlope(desired_slope)) {
1239 /* Don't break existing flat river tiles by terraforming under them. */
1240 DiagDirection river_direction = ReverseDiagDir(GetInclinedSlopeDirection(desired_slope));
1241
1242 for (DiagDirDiff d = DIAGDIRDIFF_BEGIN; d < DIAGDIRDIFF_END; d++) {
1243 /* We don't care about downstream or upstream tiles, just the riverbanks. */
1244 if (d == DIAGDIRDIFF_SAME || d == DIAGDIRDIFF_REVERSE) continue;
1245
1246 TileIndex other_tile = (TileAddByDiagDir(tile, ChangeDiagDir(river_direction, d)));
1247 if (IsWaterTile(other_tile) && IsRiver(other_tile) && IsTileFlat(other_tile)) return;
1248 }
1249
1250 /* Get the corners which are different between the current and desired slope. */
1251 Slope to_change = cur_slope ^ desired_slope;
1252
1253 /* Lower unwanted corners first. If only one corner is raised, no corners need lowering. */
1254 if (!IsSlopeWithOneCornerRaised(cur_slope)) {
1255 to_change = to_change & ComplementSlope(desired_slope);
1256 Command<CMD_TERRAFORM_LAND>::Do({DoCommandFlag::Execute, DoCommandFlag::Auto}, tile, to_change, false);
1257 }
1258
1259 /* Now check the match and raise any corners needed. */
1260 cur_slope = GetTileSlope(tile);
1261 if (cur_slope != desired_slope && IsSlopeWithOneCornerRaised(cur_slope)) {
1262 to_change = cur_slope ^ desired_slope;
1263 Command<CMD_TERRAFORM_LAND>::Do({DoCommandFlag::Execute, DoCommandFlag::Auto}, tile, to_change, true);
1264 }
1265 }
1266 /* Update cur_slope after possibly terraforming. */
1267 cur_slope = GetTileSlope(tile);
1268 }
1269
1270 /* Sloped rivers need water both upstream and downstream. */
1271 if (IsInclinedSlope(cur_slope)) {
1272 DiagDirection slope_direction = GetInclinedSlopeDirection(cur_slope);
1273
1274 TileIndex upstream_tile = TileAddByDiagDir(tile, slope_direction);
1275 TileIndex downstream_tile = TileAddByDiagDir(tile, ReverseDiagDir(slope_direction));
1276
1277 /* Don't look outside the map. */
1278 if (!IsValidTile(upstream_tile) || !IsValidTile(downstream_tile)) return;
1279
1280 /* Downstream might be new ocean created by our terraforming, and it hasn't flooded yet. */
1281 bool downstream_is_ocean = GetTileZ(downstream_tile) == 0 && (GetTileSlope(downstream_tile) == SLOPE_FLAT || IsSlopeWithOneCornerRaised(GetTileSlope(downstream_tile)));
1282
1283 /* If downstream is dry, flat, and not ocean, try making it a river tile. */
1284 if (!IsWaterTile(downstream_tile) && !downstream_is_ocean) {
1285 /* If the tile upstream isn't flat, don't bother. */
1286 if (GetTileSlope(downstream_tile) != SLOPE_FLAT) return;
1287
1288 MakeRiverAndModifyDesertZoneAround(downstream_tile);
1289 }
1290
1291 /* If upstream is dry and flat, try making it a river tile. */
1292 if (!IsWaterTile(upstream_tile)) {
1293 /* If the tile upstream isn't flat, don't bother. */
1294 if (GetTileSlope(upstream_tile) != SLOPE_FLAT) return;
1295
1296 MakeRiverAndModifyDesertZoneAround(upstream_tile);
1297 }
1298 }
1299
1300 /* If the tile slope matches the desired slope, add a river tile. */
1301 if (cur_slope == desired_slope) {
1302 MakeRiverAndModifyDesertZoneAround(tile);
1303 }
1304}
1305
1312 bool RiverFlowsDown(TileIndex begin, TileIndex end)
1313{
1314 assert(DistanceManhattan(begin, end) == 1);
1315
1316 auto [slope_end, height_end] = GetTileSlopeZ(end);
1317
1318 /* Slope either is inclined or flat; rivers don't support other slopes. */
1319 if (slope_end != SLOPE_FLAT && !IsInclinedSlope(slope_end)) return false;
1320
1321 auto [slope_begin, height_begin] = GetTileSlopeZ(begin);
1322
1323 /* It can't flow uphill. */
1324 if (height_end > height_begin) return false;
1325
1326 /* Slope continues, then it must be lower... */
1327 if (slope_end == slope_begin && height_end < height_begin) return true;
1328
1329 /* ... or either end must be flat. */
1330 return slope_end == SLOPE_FLAT || slope_begin == SLOPE_FLAT;
1331}
1332
1340 static bool CountConnectedSeaTiles(TileIndex tile, std::unordered_set<TileIndex> &sea, const uint limit)
1341{
1342 /* This tile might not be sea. */
1343 if (!IsWaterTile(tile) || GetWaterClass(tile) != WaterClass::Sea || !IsTileFlat(tile)) return false;
1344
1345 /* If we've found an edge tile, we are "connected to the sea outside the map." */
1346 if (DistanceFromEdge(tile) <= 1) return true;
1347
1348 /* We have now evaluated this tile and don't want to check it again. */
1349 sea.insert(tile);
1350
1351 /* We might want to cut our search short if the size of the sea is "big enough".
1352 * Count this tile but don't check its neighbors. */
1353 if (sea.size() > limit) return false;
1354
1355 /* Count adjacent tiles using recusion. */
1356 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1357 TileIndex t = tile + TileOffsByDiagDir(d);
1358 if (IsValidTile(t) && !sea.contains(t)) {
1359 if (CountConnectedSeaTiles(t, sea, limit)) return true;
1360 }
1361 }
1362
1363 return false;
1364}
1365
1373 static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
1374{
1375 if (IsWaterTile(begin)) {
1376 return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 };
1377 }
1378
1379 int height_begin = TileHeight(begin);
1380
1381 std::unordered_set<TileIndex> marks;
1382 marks.insert(begin);
1383
1384 std::vector<TileIndex> queue;
1385 queue.push_back(begin);
1386
1387 /* Breadth first search for the closest tile we can flow down to.
1388 * We keep the queue to find the Nth tile for lake guessing. The tiles
1389 * in the queue are neatly ordered by insertion.
1390 */
1391 bool found = false;
1392 TileIndex end;
1393 for (size_t i = 0; i != queue.size(); i++) {
1394 end = queue[i];
1395
1396 int height_end;
1397 if (IsTileFlat(end, &height_end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) {
1398 if (IsWaterTile(end) && GetWaterClass(end) == WaterClass::Sea) {
1399 /* 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. */
1400 const uint MAX_SEA_SIZE_THRESHOLD = 1024;
1401 const uint SEA_SIZE_THRESHOLD = std::min(static_cast<uint>(2 * std::sqrt(Map::SizeX() * Map::SizeY())), MAX_SEA_SIZE_THRESHOLD);
1402 std::unordered_set<TileIndex> sea;
1403 /* Count the connected tiles, if the sea is large we can end the river here. */
1404 bool found_edge = CountConnectedSeaTiles(end, sea, SEA_SIZE_THRESHOLD);
1405 if (found_edge || sea.size() > SEA_SIZE_THRESHOLD) {
1406 found = true;
1407 break;
1408 } else {
1409 /* Sea is too small, flatten it so the river keeps looking or forms a lake / wetland. */
1410 for (TileIndex sea_tile : sea) {
1411 Command<CMD_TERRAFORM_LAND>::Do(DoCommandFlag::Execute, sea_tile, SLOPE_ELEVATED, false);
1412 Slope slope = ComplementSlope(GetTileSlope(sea_tile));
1413 Command<CMD_TERRAFORM_LAND>::Do(DoCommandFlag::Execute, sea_tile, slope, true);
1414 }
1415 }
1416 } else {
1417 /* We've found a river. */
1418 found = true;
1419 break;
1420 }
1421 }
1422
1423 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1424 TileIndex t = end + TileOffsByDiagDir(d);
1425 if (IsValidTile(t) && !marks.contains(t) && RiverFlowsDown(end, t)) {
1426 marks.insert(t);
1427 queue.push_back(t);
1428 }
1429 }
1430 }
1431
1432 bool main_river = false;
1433 if (found) {
1434 /* Flow further down hill. */
1435 std::tie(found, main_river) = FlowRiver(spring, end, min_river_length);
1436 } else if (queue.size() > 32) {
1437 /* Maybe we can make a lake. Find the Nth of the considered tiles. */
1438 TileIndex lake_centre = queue[RandomRange(static_cast<uint32_t>(queue.size()))];
1439 if (DistanceManhattan(spring, lake_centre) > min_river_length) {
1440 if (TryMakeRiverTerminus(lake_centre, begin)) {
1441 /* If successful, this becomes the new end of the river. */
1442 end = lake_centre;
1443 found = true;
1444 }
1445 }
1446 }
1447
1448 if (found) YapfBuildRiver(begin, end, spring, main_river);
1449 return { found, main_river };
1450}
1451
1455 static void CreateRivers()
1456{
1457 int amount = _settings_game.game_creation.amount_of_rivers;
1458 if (amount == 0) return;
1459
1460 uint wells = Map::ScaleBySize(4 << _settings_game.game_creation.amount_of_rivers);
1461 const uint num_short_rivers = wells - std::max(1u, wells / 10);
1462 SetGeneratingWorldProgress(GWP_RIVER, wells + TILE_UPDATE_FREQUENCY / 64); // Include the tile loop calls below.
1463
1464 /* Try to create long rivers. */
1465 for (; wells > num_short_rivers; wells--) {
1466 IncreaseGeneratingWorldProgress(GWP_RIVER);
1467 bool done = false;
1468 for (int tries = 0; tries < 512; tries++) {
1469 for (auto t : SpiralTileSequence(RandomTile(), 8)) {
1470 if (FindSpring(t)) {
1471 done = std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length * 4));
1472 break;
1473 }
1474 }
1475 if (done) break;
1476 }
1477 }
1478
1479 /* Try to create short rivers. */
1480 for (; wells != 0; wells--) {
1481 IncreaseGeneratingWorldProgress(GWP_RIVER);
1482 bool done = false;
1483 for (int tries = 0; tries < 128; tries++) {
1484 for (auto t : SpiralTileSequence(RandomTile(), 8)) {
1485 if (FindSpring(t)) {
1486 done = std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length));
1487 break;
1488 }
1489 }
1490 if (done) break;
1491 }
1492 }
1493
1494 /* Widening rivers may have left some tiles requiring to be watered. */
1495 ConvertGroundTilesIntoWaterTiles();
1496
1497 /* Run tile loop to update the ground density. */
1498 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
1499 if (i % 64 == 0) IncreaseGeneratingWorldProgress(GWP_RIVER);
1500 RunTileLoop();
1501 }
1502}
1503
1521 static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
1522{
1523 /* Histogram of how many tiles per height level exist. */
1524 std::array<int, MAX_TILE_HEIGHT + 1> histogram = {};
1525 /* Histogram of how many neighbour tiles are lower than the tiles of the height level. */
1526 std::array<int, MAX_TILE_HEIGHT + 1> edge_histogram = {};
1527
1528 /* Build a histogram of the map height. */
1529 for (const auto tile : Map::Iterate()) {
1530 uint h = TileHeight(tile);
1531 histogram[h]++;
1532
1533 if (edge_multiplier != 0) {
1534 /* Check if any of our neighbours is below us. */
1535 for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) {
1536 TileIndex neighbour_tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(dir));
1537 if (IsValidTile(neighbour_tile) && TileHeight(neighbour_tile) < h) {
1538 edge_histogram[h]++;
1539 }
1540 }
1541 }
1542 }
1543
1544 /* The amount of land we have is the map size minus the first (sea) layer. */
1545 uint land_tiles = Map::Size() - histogram[0];
1546 int best_score = land_tiles;
1547
1548 /* Our goal is the coverage amount of the land-mass. */
1549 int goal_tiles = land_tiles * coverage / 100;
1550
1551 /* We scan from top to bottom. */
1552 uint h = MAX_TILE_HEIGHT;
1553 uint best_h = h;
1554
1555 int current_tiles = 0;
1556 for (; h > 0; h--) {
1557 current_tiles += histogram[h];
1558 int current_score = goal_tiles - current_tiles;
1559
1560 /* Tropic grows from water and mountains into the desert. This is a
1561 * great visual, but it also means we* need to take into account how
1562 * much less desert tiles are being created if we are on this
1563 * height-level. We estimate this based on how many neighbouring
1564 * tiles are below us for a given length, assuming that is where
1565 * tropic is growing from.
1566 */
1567 if (edge_multiplier != 0 && h > 1) {
1568 /* From water tropic tiles grow for a few tiles land inward. */
1569 current_score -= edge_histogram[1] * edge_multiplier;
1570 /* Tropic tiles grow into the desert for a few tiles. */
1571 current_score -= edge_histogram[h] * edge_multiplier;
1572 }
1573
1574 if (std::abs(current_score) < std::abs(best_score)) {
1575 best_score = current_score;
1576 best_h = h;
1577 }
1578
1579 /* Always scan all height-levels, as h == 1 might give a better
1580 * score than any before. This is true for example with 0% desert
1581 * coverage. */
1582 }
1583
1584 return best_h;
1585}
1586
1590 static void CalculateSnowLine()
1591{
1592 /* We do not have snow sprites on coastal tiles, so never allow "1" as height. */
1593 _settings_game.game_creation.snow_line_height = std::max(CalculateCoverageLine(_settings_game.game_creation.snow_coverage, 0), 2u);
1594}
1595
1600 static uint8_t CalculateDesertLine()
1601{
1602 /* CalculateCoverageLine() runs from top to bottom, so we need to invert the coverage. */
1603 return CalculateCoverageLine(100 - _settings_game.game_creation.desert_coverage, 4);
1604}
1605
1606 bool GenerateLandscape(uint8_t mode)
1607{
1608 /* Number of steps of landscape generation */
1609 static constexpr uint GLS_HEIGHTMAP = 3;
1610 static constexpr uint GLS_TERRAGENESIS = 4;
1611 static constexpr uint GLS_ORIGINAL = 2;
1612 static constexpr uint GLS_TROPIC = 12;
1613 static constexpr uint GLS_OTHER = 0;
1614 uint steps = (_settings_game.game_creation.landscape == LandscapeType::Tropic) ? GLS_TROPIC : GLS_OTHER;
1615
1616 if (mode == GWM_HEIGHTMAP) {
1617 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_HEIGHTMAP);
1618 if (!LoadHeightmap(_file_to_saveload.ftype.detailed, _file_to_saveload.name)) {
1619 return false;
1620 }
1621 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
1622 } else if (_settings_game.game_creation.land_generator == LG_TERRAGENESIS) {
1623 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_TERRAGENESIS);
1624 GenerateTerrainPerlin();
1625 } else {
1626 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_ORIGINAL);
1627 if (_settings_game.construction.freeform_edges) {
1628 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, 0));
1629 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(0, y));
1630 }
1631 switch (_settings_game.game_creation.landscape) {
1632 case LandscapeType::Arctic: {
1633 uint32_t r = Random();
1634
1635 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 950); i != 0; --i) {
1636 GenerateTerrain(2, 0);
1637 }
1638
1639 uint flag = GB(r, 7, 2) | 4;
1640 for (uint i = Map::ScaleBySize(GB(r, 9, 7) + 450); i != 0; --i) {
1641 GenerateTerrain(4, flag);
1642 }
1643 break;
1644 }
1645
1646 case LandscapeType::Tropic: {
1647 uint32_t r = Random();
1648
1649 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 170); i != 0; --i) {
1650 GenerateTerrain(0, 0);
1651 }
1652
1653 uint flag = GB(r, 7, 2) | 4;
1654 for (uint i = Map::ScaleBySize(GB(r, 9, 8) + 1700); i != 0; --i) {
1655 GenerateTerrain(0, flag);
1656 }
1657
1658 flag ^= 2;
1659
1660 for (uint i = Map::ScaleBySize(GB(r, 17, 7) + 410); i != 0; --i) {
1661 GenerateTerrain(3, flag);
1662 }
1663 break;
1664 }
1665
1666 default: {
1667 uint32_t r = Random();
1668
1669 assert(_settings_game.difficulty.quantity_sea_lakes != CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY);
1670 uint i = Map::ScaleBySize(GB(r, 0, 7) + (3 - _settings_game.difficulty.quantity_sea_lakes) * 256 + 100);
1671 for (; i != 0; --i) {
1672 /* Make sure we do not overflow. */
1673 GenerateTerrain(Clamp(_settings_game.difficulty.terrain_type, 0, 3), 0);
1674 }
1675 break;
1676 }
1677 }
1678 }
1679
1680 /* Do not call IncreaseGeneratingWorldProgress() before FixSlopes(),
1681 * it allows screen redraw. Drawing of broken slopes crashes the game */
1682 FixSlopes();
1683 MarkWholeScreenDirty();
1684 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
1685
1686 ConvertGroundTilesIntoWaterTiles();
1687 MarkWholeScreenDirty();
1688 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
1689
1690 switch (_settings_game.game_creation.landscape) {
1691 case LandscapeType::Arctic:
1692 CalculateSnowLine();
1693 break;
1694
1695 case LandscapeType::Tropic: {
1696 uint desert_tropic_line = CalculateDesertLine();
1697 CreateDesertOrRainForest(desert_tropic_line);
1698 break;
1699 }
1700
1701 default:
1702 break;
1703 }
1704
1705 CreateRivers();
1706 return true;
1707}
1708
1709void OnTick_Town();
1710void OnTick_Trees();
1711void OnTick_Station();
1712void OnTick_Industry();
1713
1714void OnTick_Companies();
1715void OnTick_LinkGraph();
1716
1717void CallLandscapeTick()
1718{
1719 {
1720 PerformanceAccumulator framerate(PFE_GL_LANDSCAPE);
1721
1722 OnTick_Town();
1723 OnTick_Trees();
1724 OnTick_Station();
1725 OnTick_Industry();
1726 }
1727
1728 OnTick_Companies();
1729 OnTick_LinkGraph();
1730}
DeleteAnimatedTile
void DeleteAnimatedTile(TileIndex tile, bool immediate)
Stops animation on the given tile.
Definition animated_tile.cpp:27
animated_tile_func.h
Tile animation!
GB
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition bitmath_func.hpp:32
ClearBridgeMiddle
void ClearBridgeMiddle(Tile t)
Removes bridges from the given, that is bridges along the X and Y axis.
Definition bridge_map.h:103
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
BaseBitSet::None
constexpr bool None() const
Test if none of the values are set.
Definition base_bitset_type.hpp:188
BaseBitSet::Reset
constexpr Timpl & Reset()
Reset all bits.
Definition base_bitset_type.hpp:83
BaseBitSet::Set
constexpr Timpl & Set()
Set all bits.
Definition base_bitset_type.hpp:40
BaseBitSet::Any
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Definition base_bitset_type.hpp:170
CommandCost
Common return value for all commands.
Definition command_type.h:24
CommandCost::AddCost
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition command_type.h:98
CommandCost::GetCost
Money GetCost() const
The costs as made up to this moment.
Definition command_type.h:118
CommandCost::Failed
bool Failed() const
Did this command fail?
Definition command_type.h:177
EnumBitSet
Enum-as-bit-set wrapper.
Definition enum_type.hpp:177
OverflowSafeInt< int64_t >
PerformanceAccumulator
RAII class for measuring multi-step elements of performance.
Definition framerate_type.h:113
SpiralTileSequence
Generate TileIndices around a center tile or tile area, with increasing distance.
Definition tilearea_type.h:316
TileIterator::Create
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:291
TimerGameCalendar::ConvertDateToYMD
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
Definition timer_game_calendar.cpp:42
TimerGameCalendar::date
static Date date
Current date in days (day counter).
Definition timer_game_calendar.h:33
TimerGameTick::counter
static TickCounter counter
Monotonic counter, in ticks, since start of game.
Definition timer_game_tick.h:60
clear_map.h
Map accessors for 'clear' tiles.
IsClearGround
bool IsClearGround(Tile t, ClearGround ct)
Set the type of clear tile.
Definition clear_map.h:59
CLEAR_GRASS
@ CLEAR_GRASS
0-3
Definition clear_map.h:20
CLEAR_DESERT
@ CLEAR_DESERT
1,3
Definition clear_map.h:25
CLEAR_ROUGH
@ CLEAR_ROUGH
3
Definition clear_map.h:21
MakeClear
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition clear_map.h:247
SetClearGroundDensity
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:146
command_func.h
Functions related to commands.
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition command_func.h:28
DoCommandFlag::Auto
@ Auto
don't allow building on structures
DoCommandFlag::NoWater
@ NoWater
don't allow building on water
DoCommandFlag::Execute
@ Execute
execute the given command
DoCommandFlag::Bankrupt
@ Bankrupt
company bankrupts, skip money check, skip vehicle on tile check in some cases
DoCommandFlag::ForceClearTile
@ ForceClearTile
do not only remove the object on the tile, but also clear any water left on it
GetAvailableMoneyForCommand
Money GetAvailableMoneyForCommand()
This functions returns the money which can be used to execute a command.
Definition company_cmd.cpp:252
_current_company
CompanyID _current_company
Company currently doing an action.
Definition company_cmd.cpp:56
company_func.h
Functions related to companies.
DirtyCompanyInfrastructureWindows
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
Definition company_gui.cpp:2318
company_gui.h
GUI Functions related to companies.
ReverseDiagDir
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
Definition direction_func.h:118
ChangeDiagDir
DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
Applies a difference on a DiagDirection.
Definition direction_func.h:149
DiagDirToAxis
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
Definition direction_func.h:214
DiagDirDiff
DiagDirDiff
Enumeration for the difference between to DiagDirection.
Definition direction_type.h:102
DIAGDIRDIFF_END
@ DIAGDIRDIFF_END
Used for iterations.
Definition direction_type.h:108
DIAGDIRDIFF_90RIGHT
@ DIAGDIRDIFF_90RIGHT
90 degrees right
Definition direction_type.h:105
DIAGDIRDIFF_90LEFT
@ DIAGDIRDIFF_90LEFT
90 degrees left
Definition direction_type.h:107
DIAGDIRDIFF_REVERSE
@ DIAGDIRDIFF_REVERSE
Reverse directions.
Definition direction_type.h:106
DIAGDIRDIFF_SAME
@ DIAGDIRDIFF_SAME
Same directions.
Definition direction_type.h:104
DIAGDIRDIFF_BEGIN
@ DIAGDIRDIFF_BEGIN
Used for iterations.
Definition direction_type.h:103
AXIS_Y
@ AXIS_Y
The y axis.
Definition direction_type.h:125
DiagDirection
DiagDirection
Enumeration for diagonal directions.
Definition direction_type.h:78
DIAGDIR_NE
@ DIAGDIR_NE
Northeast, upper right on your monitor.
Definition direction_type.h:80
DIAGDIR_NW
@ DIAGDIR_NW
Northwest.
Definition direction_type.h:83
DIAGDIR_SE
@ DIAGDIR_SE
Southeast.
Definition direction_type.h:81
DIAGDIR_END
@ DIAGDIR_END
Used for iterations.
Definition direction_type.h:84
DIAGDIR_BEGIN
@ DIAGDIR_BEGIN
Used for iterations.
Definition direction_type.h:79
DIAGDIR_SW
@ DIAGDIR_SW
Southwest.
Definition direction_type.h:82
EXPENSES_CONSTRUCTION
@ EXPENSES_CONSTRUCTION
Construction costs.
Definition economy_type.h:179
CreateEffectVehicleAbove
EffectVehicle * CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular location.
Definition effectvehicle.cpp:594
effectvehicle_func.h
Functions related to effect vehicles.
EV_EXPLOSION_SMALL
@ EV_EXPLOSION_SMALL
Various explosions.
Definition effectvehicle_func.h:24
EV_EXPLOSION_LARGE
@ EV_EXPLOSION_LARGE
Various explosions.
Definition effectvehicle_func.h:22
error_func.h
Error reporting related functions.
fios.h
Declarations for savegames operations.
framerate_type.h
Types for recording game performance data.
PFE_GL_LANDSCAPE
@ PFE_GL_LANDSCAPE
Time spent processing other world features.
Definition framerate_type.h:54
genland.h
Table used to generate deserts and/or rainforests.
_generating_world
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:74
genworld.h
Functions related to world/map generation.
IncreaseGeneratingWorldProgress
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
Definition genworld_gui.cpp:1539
LG_TERRAGENESIS
@ LG_TERRAGENESIS
TerraGenesis Perlin landscape generator.
Definition genworld.h:22
CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
static const uint CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
Value for custom sea level in difficulty settings.
Definition genworld.h:48
GWP_LANDSCAPE
@ GWP_LANDSCAPE
Create the landscape.
Definition genworld.h:63
GWP_RIVER
@ GWP_RIVER
Create the rivers.
Definition genworld.h:64
SetGeneratingWorldProgress
void SetGeneratingWorldProgress(GenWorldProgress cls, uint total)
Set the total of a stage of the world generation.
Definition genworld_gui.cpp:1525
GWM_HEIGHTMAP
@ GWM_HEIGHTMAP
Generate a newgame from a heightmap.
Definition genworld.h:32
_pause_mode
PauseModes _pause_mode
The current pause mode.
Definition gfx.cpp:50
SpriteID
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
SpriteType::MapGen
@ MapGen
Special sprite for the map generator.
LowestSnowLine
uint8_t LowestSnowLine()
Get the lowest possible snow line height, either variable or static.
Definition landscape.cpp:629
GetSnowLine
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
Definition landscape.cpp:606
IsSnowLineSet
bool IsSnowLineSet()
Has a snow line table already been loaded.
Definition landscape.cpp:586
ClearSnowLine
void ClearSnowLine()
Clear the variable snow line table and free the memory.
Definition landscape.cpp:638
_snow_line
static std::unique_ptr< SnowLine > _snow_line
Description of the snow line throughout the year.
Definition landscape.cpp:100
SetSnowLine
void SetSnowLine(std::unique_ptr< SnowLine > &&snow_line)
Set a variable snow line, as loaded from a newgrf file.
Definition landscape.cpp:596
HighestSnowLine
uint8_t HighestSnowLine()
Get the highest possible snow line height, either variable or static.
Definition landscape.cpp:619
MarkWholeScreenDirty
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1549
MarkTileDirtyByTile
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition viewport.cpp:2128
LoadHeightmap
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...
Definition heightmap.cpp:517
FixSlopes
void FixSlopes()
This function takes care of the fact that land in OpenTTD can never differ more than 1 in height.
Definition heightmap.cpp:403
heightmap.h
Functions related to creating heightmaps from files.
GetPartialPixelZ
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Definition landscape.cpp:232
FlowRiver
static std::tuple< bool, bool > FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
Try to flow the river down from a given begin.
Definition landscape.cpp:1373
GetSlopePixelZOutsideMap
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"...
Definition landscape.cpp:322
GetTileTrackStatus
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition landscape.cpp:560
OnTick_Companies
void OnTick_Companies()
Called every tick for updating some company info.
Definition company_cmd.cpp:770
TryMakeRiverTerminus
static bool TryMakeRiverTerminus(TileIndex tile, TileIndex begin)
Try to end a river at a tile which is not the sea.
Definition landscape.cpp:1134
CalculateCoverageLine
static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
Calculate what height would be needed to cover N% of the landmass.
Definition landscape.cpp:1521
IsValidRiverTerminusTile
static bool IsValidRiverTerminusTile(TileIndex tile, uint height)
Is this a valid tile for the water feature at the end of a river?
Definition landscape.cpp:1058
CalculateSnowLine
static void CalculateSnowLine()
Calculate the line from which snow begins.
Definition landscape.cpp:1590
TILE_UPDATE_FREQUENCY_LOG
static const uint TILE_UPDATE_FREQUENCY_LOG
The logarithm of how many ticks it takes between tile updates (log base 2).
Definition landscape.cpp:89
ChangeTileOwner
void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
Change the owner of a tile.
Definition landscape.cpp:571
RunTileLoop
void RunTileLoop()
Gradually iterate over all tiles on the map, calling their TileLoopProcs once every TILE_UPDATE_FREQU...
Definition landscape.cpp:798
FindSpring
static bool FindSpring(TileIndex tile)
Find the spring of a river.
Definition landscape.cpp:1022
RiverFlowsDown
bool RiverFlowsDown(TileIndex begin, TileIndex end)
Check whether a river at begin could (logically) flow down to end.
Definition landscape.cpp:1312
CreateRivers
static void CreateRivers()
Actually (try to) create some rivers.
Definition landscape.cpp:1455
DrawFoundation
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
Definition landscape.cpp:429
GetSlopeZInCorner
int GetSlopeZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
Definition landscape.cpp:340
GetFoundationSlope
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,...
Definition landscape.cpp:386
GetSlopePixelZOnEdge
void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int &z1, int &z2)
Determine the Z height of the corners of a specific tile edge.
Definition landscape.cpp:358
MakeWetlands
static void MakeWetlands(TileIndex centre, uint height, uint river_length)
Make wetlands around the given tile.
Definition landscape.cpp:1097
OnTick_LinkGraph
void OnTick_LinkGraph()
Spawn or join a link graph job or compress a link graph if any link graph is due to do so.
Definition linkgraphschedule.cpp:202
_tile_type_procs
const TileTypeProcs *const _tile_type_procs[16]
Tile callback functions for each type of tile.
Definition landscape.cpp:69
InverseRemapCoords2
Point InverseRemapCoords2(int x, int y, bool clamp_to_map, bool *clamped)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
Definition landscape.cpp:115
_tile_type_town_procs
const TileTypeProcs _tile_type_town_procs
Tile callback functions for a town.
Definition landscape.cpp:55
MakeLake
static void MakeLake(TileIndex lake_centre, uint height_lake)
Make a lake centred on the given tile, of a random diameter.
Definition landscape.cpp:1071
OnTick_Town
void OnTick_Town()
Iterate through all towns and call their tick handler.
Definition town_cmd.cpp:940
CalculateDesertLine
static uint8_t CalculateDesertLine()
Calculate the line (in height) between desert and tropic.
Definition landscape.cpp:1600
_slope_to_sprite_offset
const uint8_t _slope_to_sprite_offset[32]
landscape slope => sprite
CmdClearArea
std::tuple< CommandCost, Money > CmdClearArea(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, bool diagonal)
Clear a big piece of landscape.
Definition landscape.cpp:740
_tile_type_road_procs
const TileTypeProcs _tile_type_road_procs
Tile callback functions for road tiles.
Definition landscape.cpp:54
ApplyFoundationToSlope
uint ApplyFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition landscape.cpp:174
IsMapSurroundedByWater
bool IsMapSurroundedByWater()
Check if all tiles on the map edge should be considered water borders.
Definition landscape.cpp:647
CountConnectedSeaTiles
static bool CountConnectedSeaTiles(TileIndex tile, std::unordered_set< TileIndex > &sea, const uint limit)
Find the size of a patch of connected sea tiles.
Definition landscape.cpp:1340
GenerateLandscape
bool GenerateLandscape(uint8_t mode)
Definition landscape.cpp:1606
CmdLandscapeClear
CommandCost CmdLandscapeClear(DoCommandFlags flags, TileIndex tile)
Clear a piece of landscape.
Definition landscape.cpp:679
RiverMakeWider
void RiverMakeWider(TileIndex tile, TileIndex origin_tile)
Widen a river by expanding into adjacent tiles via circular tile search.
Definition landscape.cpp:1169
TILE_UPDATE_FREQUENCY
static const uint TILE_UPDATE_FREQUENCY
How many ticks it takes between tile updates (has to be a power of 2).
Definition landscape.cpp:90
GetSlopePixelZ
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Definition landscape.cpp:307
landscape.h
Functions related to OTTD's landscape.
GetFoundationPixelSlope
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
ApplyPixelFoundationToSlope
uint ApplyPixelFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition landscape.h:128
InverseRemapCoords
Point InverseRemapCoords(int x, int y)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
Definition landscape.h:111
landscape_cmd.h
Command definitions related to landscape (slopes etc.).
landscape_type.h
Types related to the landscape.
BorderFlag::Random
@ Random
Randomise borders.
DistanceSquare
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:186
DistanceFromEdge
uint DistanceFromEdge(TileIndex tile)
Param the minimum distance to an edge.
Definition map.cpp:229
TileAddWrap
TileIndex TileAddWrap(TileIndex tile, int addx, int addy)
This function checks if we add addx/addy to tile, if we do wrap around the edges.
Definition map.cpp:120
DistanceManhattan
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:169
TileAddXY
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:483
TileVirtXY
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:416
AddTileIndexDiffCWrap
TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
Add a TileIndexDiffC to a TileIndex and returns the new one.
Definition map_func.h:528
TileAddByDiagDir
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:624
TileDiffXY
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:401
TileXY
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition map_func.h:385
TileY
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:438
TileIndexDiffCByDiagDir
TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
Returns the TileIndexDiffC offset from a DiagDirection.
Definition map_func.h:496
TileX
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:428
RandomTile
#define RandomTile()
Get a valid random tile.
Definition map_func.h:665
TileOffsByDiagDir
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:583
MIN_MAP_SIZE_BITS
static const uint MIN_MAP_SIZE_BITS
Minimal and maximal map width and height.
Definition map_type.h:37
MAX_MAP_SIZE_BITS
static const uint MAX_MAP_SIZE_BITS
Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS.
Definition map_type.h:38
IsInsideBS
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.
Definition math_func.hpp:252
CeilDiv
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition math_func.hpp:310
Clamp
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
object_base.h
Base for all objects.
FindClearedObject
ClearedObjectArea * FindClearedObject(TileIndex tile)
Find the entry in _cleared_object_areas which occupies a certain tile.
Definition object_cmd.cpp:531
random_func.hpp
Pseudo random number generator.
RandomRange
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.
Definition random_func.hpp:88
Chance16
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.
Definition random_func.hpp:134
safeguards.h
A number of safeguards to prevent using unsafe methods.
_file_to_saveload
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition saveload.cpp:78
saveload.h
Functions/types related to saving and loading games.
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
TP_NONE
@ TP_NONE
No tree placer algorithm.
Definition settings_type.h:108
IsSpecialRailFoundation
bool IsSpecialRailFoundation(Foundation f)
Tests if a foundation is a special rail foundation for single horizontal/vertical track.
Definition slope_func.h:345
SlopeWithThreeCornersRaised
Slope SlopeWithThreeCornersRaised(Corner corner)
Returns the slope with all except one corner raised.
Definition slope_func.h:206
OppositeCorner
Corner OppositeCorner(Corner corner)
Returns the opposite corner.
Definition slope_func.h:184
GetHalftileSlopeCorner
static constexpr Corner GetHalftileSlopeCorner(Slope s)
Returns the leveled halftile of a halftile slope.
Definition slope_func.h:148
RemoveHalftileSlope
static constexpr Slope RemoveHalftileSlope(Slope s)
Removes a halftile slope from a slope.
Definition slope_func.h:60
IsSlopeWithOneCornerRaised
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:88
IsNonContinuousFoundation
bool IsNonContinuousFoundation(Foundation f)
Tests if a foundation is a non-continuous foundation, i.e.
Definition slope_func.h:320
GetHighestSlopeCorner
Corner GetHighestSlopeCorner(Slope s)
Returns the highest corner of a slope (one corner raised or a steep slope).
Definition slope_func.h:126
GetHalftileFoundationCorner
Corner GetHalftileFoundationCorner(Foundation f)
Returns the halftile corner of a halftile-foundation.
Definition slope_func.h:333
IsLeveledFoundation
bool IsLeveledFoundation(Foundation f)
Tests if the foundation is a leveled foundation.
Definition slope_func.h:298
IsFoundation
bool IsFoundation(Foundation f)
Tests for FOUNDATION_NONE.
Definition slope_func.h:287
IsSteepSlope
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
IsSlopeWithThreeCornersRaised
bool IsSlopeWithThreeCornersRaised(Slope s)
Tests if a specific slope has exactly three corners raised.
Definition slope_func.h:195
IsInclinedSlope
bool IsInclinedSlope(Slope s)
Tests if a specific slope is an inclined slope.
Definition slope_func.h:228
SteepSlope
Slope SteepSlope(Corner corner)
Returns a specific steep slope.
Definition slope_func.h:217
GetRailFoundationCorner
Corner GetRailFoundationCorner(Foundation f)
Returns the track corner of a special rail foundation.
Definition slope_func.h:356
IsHalftileSlope
static constexpr bool IsHalftileSlope(Slope s)
Checks for non-continuous slope on halftile foundations.
Definition slope_func.h:47
GetSlopeMaxPixelZ
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:173
GetInclinedSlopeDirection
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition slope_func.h:239
HalftileSlope
static constexpr Slope HalftileSlope(Slope s, Corner corner)
Adds a halftile slope to a slope.
Definition slope_func.h:274
ComplementSlope
Slope ComplementSlope(Slope s)
Return the complement of a slope.
Definition slope_func.h:76
SlopeWithOneCornerRaised
Slope SlopeWithOneCornerRaised(Corner corner)
Returns the slope with a specific corner raised.
Definition slope_func.h:99
IsInclinedFoundation
bool IsInclinedFoundation(Foundation f)
Tests if the foundation is an inclined foundation.
Definition slope_func.h:309
Corner
Corner
Enumeration of tile corners.
Definition slope_type.h:22
Slope
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
SLOPE_W
@ SLOPE_W
the west corner of the tile is raised
Definition slope_type.h:50
SLOPE_ELEVATED
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:61
SLOPE_NS
@ SLOPE_NS
north and south corner are raised
Definition slope_type.h:60
SLOPE_E
@ SLOPE_E
the east corner of the tile is raised
Definition slope_type.h:52
SLOPE_WSE
@ SLOPE_WSE
west, south and east corner are raised
Definition slope_type.h:63
SLOPE_S
@ SLOPE_S
the south corner of the tile is raised
Definition slope_type.h:51
SLOPE_N
@ SLOPE_N
the north corner of the tile is raised
Definition slope_type.h:53
SLOPE_SEN
@ SLOPE_SEN
south, east and north corner are raised
Definition slope_type.h:64
SLOPE_ENW
@ SLOPE_ENW
east, north and west corner are raised
Definition slope_type.h:65
SLOPE_SW
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:56
SLOPE_FLAT
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:49
SLOPE_STEEP_W
@ SLOPE_STEEP_W
a steep slope falling to east (from west)
Definition slope_type.h:66
SLOPE_NE
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:58
SLOPE_STEEP_E
@ SLOPE_STEEP_E
a steep slope falling to west (from east)
Definition slope_type.h:68
SLOPE_SE
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:57
SLOPE_NWS
@ SLOPE_NWS
north, west and south corner are raised
Definition slope_type.h:62
SLOPE_NW
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:55
SLOPE_STEEP_N
@ SLOPE_STEEP_N
a steep slope falling to south (from north)
Definition slope_type.h:69
SLOPE_STEEP_S
@ SLOPE_STEEP_S
a steep slope falling to north (from south)
Definition slope_type.h:67
SLOPE_EW
@ SLOPE_EW
east and west corner are raised
Definition slope_type.h:59
SLOPE_STEEP
@ SLOPE_STEEP
indicates the slope is steep
Definition slope_type.h:54
Foundation
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
FOUNDATION_INCLINED_X
@ FOUNDATION_INCLINED_X
The tile has an along X-axis inclined foundation.
Definition slope_type.h:96
FOUNDATION_STEEP_BOTH
@ FOUNDATION_STEEP_BOTH
The tile has a steep slope. The lowest corner is raised by a foundation and the upper halftile is lev...
Definition slope_type.h:101
FOUNDATION_INCLINED_Y
@ FOUNDATION_INCLINED_Y
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:97
FOUNDATION_STEEP_LOWER
@ FOUNDATION_STEEP_LOWER
The tile has a steep slope. The lowest corner is raised by a foundation to allow building railroad on...
Definition slope_type.h:98
spritecache.h
Functions to cache sprites in memory.
sprites.h
This file contains all sprite-related enums and defines.
SPR_HALFTILE_FOUNDATION_BASE
static const SpriteID SPR_HALFTILE_FOUNDATION_BASE
Halftile foundations.
Definition sprites.h:212
station_func.h
Functions related to stations.
station_map.h
Maps accessors for stations.
IsBuoyTile
bool IsBuoyTile(Tile t)
Is tile t a buoy tile?
Definition station_map.h:410
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
lengthof
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
ClearedObjectArea
Keeps track of removed objects during execution/testruns of commands.
Definition object_base.h:86
ClearedObjectArea::first_tile
TileIndex first_tile
The first tile being cleared, which then causes the whole object to be cleared.
Definition object_base.h:87
CommandHelper
Definition command_func.h:84
CompanyProperties::clear_limit
uint32_t clear_limit
Amount of tiles we can (still) clear (times 65536).
Definition company_base.h:106
Company
Definition company_base.h:127
ConstructionSettings::freeform_edges
bool freeform_edges
allow terraforming the tiles at the map edges
Definition settings_type.h:423
ConstructionSettings::map_height_limit
uint8_t map_height_limit
the maximum allowed heightlevel
Definition settings_type.h:410
Coord2D< int >
Coord2D::y
T y
Y coordinate.
Definition geometry_type.hpp:35
Coord2D::x
T x
X coordinate.
Definition geometry_type.hpp:34
Coord3D::x
T x
X coordinate.
Definition geometry_type.hpp:44
Coord3D::z
T z
Z coordinate.
Definition geometry_type.hpp:46
DifficultySettings::terrain_type
uint8_t terrain_type
the mountainousness of the landscape
Definition settings_type.h:137
DifficultySettings::quantity_sea_lakes
uint8_t quantity_sea_lakes
the amount of seas/lakes
Definition settings_type.h:138
FileToSaveLoad::ftype
FiosType ftype
File type.
Definition saveload.h:429
FileToSaveLoad::name
std::string name
Name of the file.
Definition saveload.h:430
FiosType::detailed
DetailedFileType detailed
Detailed file type.
Definition fileio_type.h:65
GameCreationSettings::tree_placer
uint8_t tree_placer
the tree placer algorithm
Definition settings_type.h:391
GameCreationSettings::amount_of_rivers
uint8_t amount_of_rivers
the amount of rivers
Definition settings_type.h:405
GameCreationSettings::min_river_length
uint8_t min_river_length
the minimum river length
Definition settings_type.h:403
GameCreationSettings::snow_coverage
uint8_t snow_coverage
the amount of snow coverage on the map
Definition settings_type.h:387
GameCreationSettings::desert_coverage
uint8_t desert_coverage
the amount of desert coverage on the map
Definition settings_type.h:388
GameCreationSettings::landscape
LandscapeType landscape
the landscape we're currently in
Definition settings_type.h:395
GameCreationSettings::snow_line_height
uint8_t snow_line_height
the configured snow line height (deduced from "snow_coverage")
Definition settings_type.h:386
GameCreationSettings::land_generator
uint8_t land_generator
the landscape generator
Definition settings_type.h:384
GameSettings::construction
ConstructionSettings construction
construction of things in-game
Definition settings_type.h:635
GameSettings::difficulty
DifficultySettings difficulty
settings related to the difficulty
Definition settings_type.h:633
GameSettings::game_creation
GameCreationSettings game_creation
settings used during the creation of a game (map)
Definition settings_type.h:634
Map
Size related data of the map.
Definition map_func.h:206
Map::SizeX
static uint SizeX()
Get the size of the map along the X.
Definition map_func.h:272
Map::ScaleBySize
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:340
Map::SizeY
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:281
Map::Iterate
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:375
Map::LogX
static uint LogX()
Logarithm of the map size along the X side.
Definition map_func.h:253
Map::LogY
static uint LogY()
Logarithm of the map size along the y side.
Definition map_func.h:263
Map::MaxY
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition map_func.h:308
Map::MaxX
static uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition map_func.h:299
Map::Size
static uint Size()
Get the size of the map.
Definition map_func.h:290
PoolID< uint8_t, struct CompanyIDTag, 0xF, 0xFF >
Pool::PoolItem<&_company_pool >::Get
static Titem * Get(auto index)
Returns Titem with given index.
Definition pool_type.hpp:387
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:376
Pool::PoolItem<&_company_pool >::GetIfValid
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Definition pool_type.hpp:398
SpriteBounds
Definition sprite.h:18
SpriteBounds::extent
Coord3D< uint8_t > extent
Size of bounding box.
Definition sprite.h:20
Sprite
Data structure describing a sprite.
Definition spritecache_type.h:16
Sprite::width
uint16_t width
Width of the sprite.
Definition spritecache_type.h:18
Sprite::height
uint16_t height
Height of the sprite.
Definition spritecache_type.h:17
Sprite::data
std::byte data[]
Sprite data.
Definition spritecache_type.h:21
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
TileDesc
Tile description for the 'land area information' tool.
Definition tile_cmd.h:36
TileInfo
Tile information, used while rendering the tile.
Definition tile_cmd.h:30
TileInfo::tileh
Slope tileh
Slope of the tile.
Definition tile_cmd.h:31
TileInfo::tile
TileIndex tile
Tile index.
Definition tile_cmd.h:32
TileTypeProcs
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:152
TileTypeProcs::get_tile_desc_proc
GetTileDescProc * get_tile_desc_proc
Get a description of a tile (for the 'land area information' tool)
Definition tile_cmd.h:157
TileTypeProcs::get_tile_track_status_proc
GetTileTrackStatusProc * get_tile_track_status_proc
Get available tracks and status of a tile.
Definition tile_cmd.h:158
terraform_cmd.h
Command definitions related to terraforming.
GenerateTerrainPerlin
void GenerateTerrainPerlin()
The main new land generator using Perlin noise.
Definition tgp.cpp:979
tgp.h
Functions for the Perlin noise enhanced map generator.
MayAnimateTile
bool MayAnimateTile(TileIndex tile)
Test if a tile may be animated.
Definition tile_cmd.h:197
IsTileFlat
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition tile_map.cpp:95
GetTilePixelSlopeOutsideMap
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:78
GetTileSlopeZ
std::tuple< Slope, int > GetTileSlopeZ(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.cpp:55
GetTileMaxZ
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:136
GetTileZ
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
IsTileType
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
TileHeight
static uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
GetTileOwner
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
IsValidTile
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
GetTropicZone
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
SetTileHeight
void SetTileHeight(Tile tile, uint height)
Sets the height of a tile.
Definition tile_map.h:57
GetTileSlope
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
SetTropicZone
void SetTropicZone(Tile tile, TropicZone type)
Set the tropic zone.
Definition tile_map.h:225
GetTileType
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
MAX_TILE_HEIGHT
static constexpr uint MAX_TILE_HEIGHT
Maximum allowed tile height.
Definition tile_type.h:24
TROPICZONE_RAINFOREST
@ TROPICZONE_RAINFOREST
Rainforest tile.
Definition tile_type.h:79
TROPICZONE_DESERT
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
TROPICZONE_NORMAL
@ TROPICZONE_NORMAL
Normal tropiczone.
Definition tile_type.h:77
INVALID_TILE
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
TILE_SIZE
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
TILE_PIXELS
static constexpr uint TILE_PIXELS
Pixel distance between tile columns/rows in ZOOM_BASE.
Definition tile_type.h:17
TILE_HEIGHT
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
MP_CLEAR
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:48
MP_WATER
@ MP_WATER
Water tile.
Definition tile_type.h:54
MP_VOID
@ MP_VOID
Invisible tiles at the SW and SE border.
Definition tile_type.h:55
timer_game_calendar.h
Definition of the game-calendar-timer.
timer_game_tick.h
Definition of the tick-based game-timer.
TransportType
TransportType
Available types of transport.
Definition transport_type.h:17
PlaceTree
void PlaceTree(TileIndex tile, uint32_t r, bool keep_density)
Make a random tree tile of the given tile.
Definition tree_cmd.cpp:161
tree_cmd.h
Command definitions related to tree tiles.
OffsetGroundSprite
void OffsetGroundSprite(int x, int y)
Called when a foundation has been drawn for the current tile.
Definition viewport.cpp:591
AddSortableSpriteToDraw
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:663
viewport_func.h
Functions related to (drawing on) viewports.
void_map.h
Map accessors for void tiles.
MakeVoid
void MakeVoid(Tile t)
Make a nice void tile ;)
Definition void_map.h:19
water.h
Functions related to water (management)
ClearNeighbourNonFloodingStates
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:97
MakeRiverAndModifyDesertZoneAround
void MakeRiverAndModifyDesertZoneAround(TileIndex tile)
Make a river tile and remove desert directly around it.
Definition water_cmd.cpp:472
IsTileOnWater
bool IsTileOnWater(Tile t)
Tests if the tile was built on water.
Definition water_map.h:138
IsRiver
bool IsRiver(Tile t)
Is it a river water tile?
Definition water_map.h:182
WaterClass::Canal
@ Canal
Canal.
WaterClass::Sea
@ Sea
Sea.
HasTileWaterClass
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:103
IsCanal
bool IsCanal(Tile t)
Is it a canal tile?
Definition water_map.h:171
GetWaterClass
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:114
IsCoastTile
bool IsCoastTile(Tile t)
Is it a coast tile.
Definition water_map.h:213
IsDockingTile
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:373
IsWaterTile
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition water_map.h:192
InvalidateWaterRegion
void InvalidateWaterRegion(TileIndex tile)
Marks the water region that tile is part of as invalid.
Definition water_regions.cpp:313
water_regions.h
Handles dividing the water in the map into regions to assist pathfinding.
YapfBuildRiver
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.
Definition yapf_river_builder.cpp:144
yapf_river_builder.h
Pathfinder for river building.