OpenTTD Source 20250205-master-gfd85ab1e2c
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 <http://www.gnu.org/licenses/>.
6 */
7
12#include "stdafx.h"
13#include "heightmap.h"
14#include "clear_map.h"
15#include "spritecache.h"
16#include "viewport_func.h"
17#include "command_func.h"
18#include "landscape.h"
19#include "void_map.h"
20#include "tgp.h"
21#include "genworld.h"
22#include "fios.h"
23#include "error_func.h"
26#include "water.h"
27#include "effectvehicle_func.h"
28#include "landscape_type.h"
29#include "animated_tile_func.h"
30#include "core/random_func.hpp"
31#include "object_base.h"
32#include "company_func.h"
33#include "company_gui.h"
34#include "pathfinder/aystar.h"
35#include "saveload/saveload.h"
36#include "framerate_type.h"
37#include "landscape_cmd.h"
38#include "terraform_cmd.h"
39#include "station_func.h"
41
42#include "table/strings.h"
43#include "table/sprites.h"
44
45#include "safeguards.h"
46
47extern const TileTypeProcs
48 _tile_type_clear_procs,
49 _tile_type_rail_procs,
52 _tile_type_trees_procs,
53 _tile_type_station_procs,
54 _tile_type_water_procs,
55 _tile_type_void_procs,
56 _tile_type_industry_procs,
57 _tile_type_tunnelbridge_procs,
58 _tile_type_object_procs;
59
65const TileTypeProcs * const _tile_type_procs[16] = {
66 &_tile_type_clear_procs,
67 &_tile_type_rail_procs,
70 &_tile_type_trees_procs,
71 &_tile_type_station_procs,
72 &_tile_type_water_procs,
73 &_tile_type_void_procs,
74 &_tile_type_industry_procs,
75 &_tile_type_tunnelbridge_procs,
76 &_tile_type_object_procs,
77};
78
80extern const uint8_t _slope_to_sprite_offset[32] = {
81 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0,
82 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 15, 18, 0,
83};
84
85static const uint TILE_UPDATE_FREQUENCY_LOG = 8;
87
96static std::unique_ptr<SnowLine> _snow_line;
97
111Point InverseRemapCoords2(int x, int y, bool clamp_to_map, bool *clamped)
112{
113 if (clamped != nullptr) *clamped = false; // Not clamping yet.
114
115 /* Initial x/y world coordinate is like if the landscape
116 * was completely flat on height 0. */
117 Point pt = InverseRemapCoords(x, y);
118
119 const uint min_coord = _settings_game.construction.freeform_edges ? TILE_SIZE : 0;
120 const uint max_x = Map::MaxX() * TILE_SIZE - 1;
121 const uint max_y = Map::MaxY() * TILE_SIZE - 1;
122
123 if (clamp_to_map) {
124 /* Bring the coordinates near to a valid range. At the top we allow a number
125 * of extra tiles. This is mostly due to the tiles on the north side of
126 * the map possibly being drawn higher due to the extra height levels. */
128 Point old_pt = pt;
129 pt.x = Clamp(pt.x, -extra_tiles * TILE_SIZE, max_x);
130 pt.y = Clamp(pt.y, -extra_tiles * TILE_SIZE, max_y);
131 if (clamped != nullptr) *clamped = (pt.x != old_pt.x) || (pt.y != old_pt.y);
132 }
133
134 /* Now find the Z-world coordinate by fix point iteration.
135 * This is a bit tricky because the tile height is non-continuous at foundations.
136 * The clicked point should be approached from the back, otherwise there are regions that are not clickable.
137 * (FOUNDATION_HALFTILE_LOWER on SLOPE_STEEP_S hides north halftile completely)
138 * So give it a z-malus of 4 in the first iterations. */
139 int z = 0;
140 if (clamp_to_map) {
141 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;
142 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;
143 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;
144 } else {
145 for (int i = 0; i < 5; i++) z = GetSlopePixelZOutsideMap(pt.x + std::max(z, 4) - 4, pt.y + std::max(z, 4) - 4) / 2;
146 for (int m = 3; m > 0; m--) z = GetSlopePixelZOutsideMap(pt.x + std::max(z, m) - m, pt.y + std::max(z, m) - m) / 2;
147 for (int i = 0; i < 5; i++) z = GetSlopePixelZOutsideMap(pt.x + z, pt.y + z ) / 2;
148 }
149
150 pt.x += z;
151 pt.y += z;
152 if (clamp_to_map) {
153 Point old_pt = pt;
154 pt.x = Clamp(pt.x, min_coord, max_x);
155 pt.y = Clamp(pt.y, min_coord, max_y);
156 if (clamped != nullptr) *clamped = *clamped || (pt.x != old_pt.x) || (pt.y != old_pt.y);
157 }
158
159 return pt;
160}
161
171{
172 if (!IsFoundation(f)) return 0;
173
174 if (IsLeveledFoundation(f)) {
175 uint dz = 1 + (IsSteepSlope(s) ? 1 : 0);
176 s = SLOPE_FLAT;
177 return dz;
178 }
179
182 return 0;
183 }
184
187 return 0;
188 }
189
190 uint dz = IsSteepSlope(s) ? 1 : 0;
191 Corner highest_corner = GetHighestSlopeCorner(s);
192
193 switch (f) {
195 s = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? SLOPE_SW : SLOPE_NE);
196 break;
197
199 s = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? SLOPE_SE : SLOPE_NW);
200 break;
201
203 s = SlopeWithOneCornerRaised(highest_corner);
204 break;
205
207 s = HalftileSlope(SlopeWithOneCornerRaised(highest_corner), highest_corner);
208 break;
209
210 default: NOT_REACHED();
211 }
212 return dz;
213}
214
215
228uint GetPartialPixelZ(int x, int y, Slope corners)
229{
230 if (IsHalftileSlope(corners)) {
231 /* A foundation is placed on half the tile at a specific corner. This means that,
232 * depending on the corner, that one half of the tile is at the maximum height. */
233 switch (GetHalftileSlopeCorner(corners)) {
234 case CORNER_W:
235 if (x > y) return GetSlopeMaxPixelZ(corners);
236 break;
237
238 case CORNER_S:
239 if (x + y >= (int)TILE_SIZE) return GetSlopeMaxPixelZ(corners);
240 break;
241
242 case CORNER_E:
243 if (x <= y) return GetSlopeMaxPixelZ(corners);
244 break;
245
246 case CORNER_N:
247 if (x + y < (int)TILE_SIZE) return GetSlopeMaxPixelZ(corners);
248 break;
249
250 default: NOT_REACHED();
251 }
252 }
253
254 switch (RemoveHalftileSlope(corners)) {
255 case SLOPE_FLAT: return 0;
256
257 /* One corner is up.*/
258 case SLOPE_N: return x + y <= (int)TILE_SIZE ? (TILE_SIZE - x - y) >> 1 : 0;
259 case SLOPE_E: return y >= x ? (1 + y - x) >> 1 : 0;
260 case SLOPE_S: return x + y >= (int)TILE_SIZE ? (1 + x + y - TILE_SIZE) >> 1 : 0;
261 case SLOPE_W: return x >= y ? (x - y) >> 1 : 0;
262
263 /* Two corners next to eachother are up. */
264 case SLOPE_NE: return (TILE_SIZE - x) >> 1;
265 case SLOPE_SE: return (y + 1) >> 1;
266 case SLOPE_SW: return (x + 1) >> 1;
267 case SLOPE_NW: return (TILE_SIZE - y) >> 1;
268
269 /* Three corners are up on the same level. */
270 case SLOPE_ENW: return x + y >= (int)TILE_SIZE ? TILE_HEIGHT - ((1 + x + y - TILE_SIZE) >> 1) : TILE_HEIGHT;
271 case SLOPE_SEN: return y < x ? TILE_HEIGHT - ((x - y) >> 1) : TILE_HEIGHT;
272 case SLOPE_WSE: return x + y <= (int)TILE_SIZE ? TILE_HEIGHT - ((TILE_SIZE - x - y) >> 1) : TILE_HEIGHT;
273 case SLOPE_NWS: return x < y ? TILE_HEIGHT - ((1 + y - x) >> 1) : TILE_HEIGHT;
274
275 /* Two corners at opposite sides are up. */
276 case SLOPE_NS: return x + y < (int)TILE_SIZE ? (TILE_SIZE - x - y) >> 1 : (1 + x + y - TILE_SIZE) >> 1;
277 case SLOPE_EW: return x >= y ? (x - y) >> 1 : (1 + y - x) >> 1;
278
279 /* Very special cases. */
280 case SLOPE_ELEVATED: return TILE_HEIGHT;
281
282 /* Steep slopes. The top is at 2 * TILE_HEIGHT. */
283 case SLOPE_STEEP_N: return (TILE_SIZE - x + TILE_SIZE - y) >> 1;
284 case SLOPE_STEEP_E: return (TILE_SIZE + 1 + y - x) >> 1;
285 case SLOPE_STEEP_S: return (1 + x + y) >> 1;
286 case SLOPE_STEEP_W: return (TILE_SIZE + x - y) >> 1;
287
288 default: NOT_REACHED();
289 }
290}
291
303int GetSlopePixelZ(int x, int y, bool ground_vehicle)
304{
305 TileIndex tile = TileVirtXY(x, y);
306
307 return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y, ground_vehicle);
308}
309
319{
320 if (IsInsideBS(x, 0, Map::SizeX() * TILE_SIZE) && IsInsideBS(y, 0, Map::SizeY() * TILE_SIZE)) {
321 return GetSlopePixelZ(x, y, false);
322 } else {
323 return _tile_type_procs[MP_VOID]->get_slope_z_proc(INVALID_TILE, x, y, false);
324 }
325}
326
337{
338 assert(!IsHalftileSlope(tileh));
339 return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? 1 : 0) + (tileh == SteepSlope(corner) ? 1 : 0);
340}
341
354void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int &z1, int &z2)
355{
356 static const Slope corners[4][4] = {
357 /* corner | steep slope
358 * z1 z2 | z1 z2 */
359 {SLOPE_E, SLOPE_N, SLOPE_STEEP_E, SLOPE_STEEP_N}, // DIAGDIR_NE, z1 = E, z2 = N
360 {SLOPE_S, SLOPE_E, SLOPE_STEEP_S, SLOPE_STEEP_E}, // DIAGDIR_SE, z1 = S, z2 = E
361 {SLOPE_S, SLOPE_W, SLOPE_STEEP_S, SLOPE_STEEP_W}, // DIAGDIR_SW, z1 = S, z2 = W
362 {SLOPE_W, SLOPE_N, SLOPE_STEEP_W, SLOPE_STEEP_N}, // DIAGDIR_NW, z1 = W, z2 = N
363 };
364
365 int halftile_test = (IsHalftileSlope(tileh) ? SlopeWithOneCornerRaised(GetHalftileSlopeCorner(tileh)) : 0);
366 if (halftile_test == corners[edge][0]) z2 += TILE_HEIGHT; // The slope is non-continuous in z2. z2 is on the upper side.
367 if (halftile_test == corners[edge][1]) z1 += TILE_HEIGHT; // The slope is non-continuous in z1. z1 is on the upper side.
368
369 if ((tileh & corners[edge][0]) != 0) z1 += TILE_HEIGHT; // z1 is raised
370 if ((tileh & corners[edge][1]) != 0) z2 += TILE_HEIGHT; // z2 is raised
371 if (RemoveHalftileSlope(tileh) == corners[edge][2]) z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
372 if (RemoveHalftileSlope(tileh) == corners[edge][3]) z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
373}
374
382std::tuple<Slope, int> GetFoundationSlope(TileIndex tile)
383{
384 auto [tileh, z] = GetTileSlopeZ(tile);
385 Foundation f = _tile_type_procs[GetTileType(tile)]->get_foundation_proc(tile, tileh);
386 z += ApplyFoundationToSlope(f, tileh);
387 return {tileh, z};
388}
389
390
391bool HasFoundationNW(TileIndex tile, Slope slope_here, uint z_here)
392{
393 int z_W_here = z_here;
394 int z_N_here = z_here;
395 GetSlopePixelZOnEdge(slope_here, DIAGDIR_NW, z_W_here, z_N_here);
396
397 auto [slope, z] = GetFoundationPixelSlope(TileAddXY(tile, 0, -1));
398 int z_W = z;
399 int z_N = z;
400 GetSlopePixelZOnEdge(slope, DIAGDIR_SE, z_W, z_N);
401
402 return (z_N_here > z_N) || (z_W_here > z_W);
403}
404
405
406bool HasFoundationNE(TileIndex tile, Slope slope_here, uint z_here)
407{
408 int z_E_here = z_here;
409 int z_N_here = z_here;
410 GetSlopePixelZOnEdge(slope_here, DIAGDIR_NE, z_E_here, z_N_here);
411
412 auto [slope, z] = GetFoundationPixelSlope(TileAddXY(tile, -1, 0));
413 int z_E = z;
414 int z_N = z;
415 GetSlopePixelZOnEdge(slope, DIAGDIR_SW, z_E, z_N);
416
417 return (z_N_here > z_N) || (z_E_here > z_E);
418}
419
426{
427 if (!IsFoundation(f)) return;
428
429 /* Two part foundations must be drawn separately */
430 assert(f != FOUNDATION_STEEP_BOTH);
431
432 uint sprite_block = 0;
433 auto [slope, z] = GetFoundationPixelSlope(ti->tile);
434
435 /* Select the needed block of foundations sprites
436 * Block 0: Walls at NW and NE edge
437 * Block 1: Wall at NE edge
438 * Block 2: Wall at NW edge
439 * Block 3: No walls at NW or NE edge
440 */
441 if (!HasFoundationNW(ti->tile, slope, z)) sprite_block += 1;
442 if (!HasFoundationNE(ti->tile, slope, z)) sprite_block += 2;
443
444 /* Use the original slope sprites if NW and NE borders should be visible */
445 SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * TRKFOUND_BLOCK_SIZE));
446 SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SLOPES_INCLINED_OFFSET + sprite_block * TRKFOUND_BLOCK_SIZE;
447 SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * HALFTILE_BLOCK_SIZE;
448
449 if (IsSteepSlope(ti->tileh)) {
451 /* Lower part of foundation */
453 leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z
454 );
455 }
456
457 Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
458 ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
459
460 if (IsInclinedFoundation(f)) {
461 /* inclined foundation */
462 uint8_t inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
463
464 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
467 TILE_HEIGHT, ti->z
468 );
469 OffsetGroundSprite(0, 0);
470 } else if (IsLeveledFoundation(f)) {
471 AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z - TILE_HEIGHT);
473 } else if (f == FOUNDATION_STEEP_LOWER) {
474 /* one corner raised */
476 } else {
477 /* halftile foundation */
478 int x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
479 int y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
480
481 AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1, ti->z + TILE_HEIGHT);
482 /* Reposition ground sprite back to original position after bounding box change above. This is similar to
483 * RemapCoords() but without zoom scaling. */
484 Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
485 OffsetGroundSprite(-pt.x, -pt.y);
486 }
487 } else {
488 if (IsLeveledFoundation(f)) {
489 /* leveled foundation */
490 AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z);
492 } else if (IsNonContinuousFoundation(f)) {
493 /* halftile foundation */
494 Corner halftile_corner = GetHalftileFoundationCorner(f);
495 int x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
496 int y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
497
498 AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1, ti->z);
499 /* Reposition ground sprite back to original position after bounding box change above. This is similar to
500 * RemapCoords() but without zoom scaling. */
501 Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
502 OffsetGroundSprite(-pt.x, -pt.y);
503 } else if (IsSpecialRailFoundation(f)) {
504 /* anti-zig-zag foundation */
505 SpriteID spr;
506 if (ti->tileh == SLOPE_NS || ti->tileh == SLOPE_EW) {
507 /* half of leveled foundation under track corner */
509 } else {
510 /* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
511 spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
512 }
513 AddSortableSpriteToDraw(spr, PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z);
514 OffsetGroundSprite(0, 0);
515 } else {
516 /* inclined foundation */
517 uint8_t inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
518
519 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
522 TILE_HEIGHT, ti->z
523 );
524 OffsetGroundSprite(0, 0);
525 }
526 ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
527 }
528}
529
530void DoClearSquare(TileIndex tile)
531{
532 /* If the tile can have animation and we clear it, delete it from the animated tile list. */
533 if (MayAnimateTile(tile)) DeleteAnimatedTile(tile, true);
534
535 bool remove = IsDockingTile(tile);
538 if (remove) RemoveDockingTile(tile);
539
542}
543
554TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
555{
556 return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode, sub_mode, side);
557}
558
565void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
566{
567 _tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_owner, new_owner);
568}
569
570void GetTileDesc(TileIndex tile, TileDesc *td)
571{
573}
574
581{
582 return _snow_line != nullptr;
583}
584
590void SetSnowLine(std::unique_ptr<SnowLine> &&snow_line)
591{
592 _snow_line = std::move(snow_line);
593}
594
600uint8_t GetSnowLine()
601{
603
604 TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
605 return _snow_line->table[ymd.month][ymd.day];
606}
607
614{
615 return _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->highest_value;
616}
617
624{
625 return _snow_line == nullptr ? _settings_game.game_creation.snow_line_height : _snow_line->lowest_value;
626}
627
633{
634 _snow_line = nullptr;
635}
636
644{
646 bool do_clear = false;
647 /* Test for stuff which results in water when cleared. Then add the cost to also clear the water. */
648 if ((flags & DC_FORCE_CLEAR_TILE) && HasTileWaterClass(tile) && IsTileOnWater(tile) && !IsWaterTile(tile) && !IsCoastTile(tile)) {
649 if ((flags & DC_AUTO) && GetWaterClass(tile) == WATER_CLASS_CANAL) return CommandCost(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
650 do_clear = true;
651 cost.AddCost(GetWaterClass(tile) == WATER_CLASS_CANAL ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER]);
652 }
653
654 Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? nullptr : Company::GetIfValid(_current_company);
655 if (c != nullptr && (int)GB(c->clear_limit, 16, 16) < 1) {
656 return CommandCost(STR_ERROR_CLEARING_LIMIT_REACHED);
657 }
658
659 const ClearedObjectArea *coa = FindClearedObject(tile);
660
661 /* If this tile was the first tile which caused object destruction, always
662 * pass it on to the tile_type_proc. That way multiple test runs and the exec run stay consistent. */
663 if (coa != nullptr && coa->first_tile != tile) {
664 /* If this tile belongs to an object which was already cleared via another tile, pretend it has been
665 * already removed.
666 * However, we need to check stuff, which is not the same for all object tiles. (e.g. being on water or not) */
667
668 /* If a object is removed, it leaves either bare land or water. */
669 if ((flags & DC_NO_WATER) && HasTileWaterClass(tile) && IsTileOnWater(tile)) {
670 return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
671 }
672 } else {
673 cost.AddCost(_tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags));
674 }
675
676 if (flags & DC_EXEC) {
677 if (c != nullptr) c->clear_limit -= 1 << 16;
678 if (do_clear) {
679 if (IsWaterTile(tile) && IsCanal(tile)) {
680 Owner owner = GetTileOwner(tile);
681 if (Company::IsValidID(owner)) {
682 Company::Get(owner)->infrastructure.water--;
684 }
685 }
686 DoClearSquare(tile);
688 }
689 }
690 return cost;
691}
692
701std::tuple<CommandCost, Money> CmdClearArea(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, bool diagonal)
702{
703 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
704
707 CommandCost last_error = CMD_ERROR;
708 bool had_success = false;
709
710 const Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? nullptr : Company::GetIfValid(_current_company);
711 int limit = (c == nullptr ? INT32_MAX : GB(c->clear_limit, 16, 16));
712
713 if (tile != start_tile) flags |= DC_FORCE_CLEAR_TILE;
714
715 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
716 for (; *iter != INVALID_TILE; ++(*iter)) {
717 TileIndex t = *iter;
719 if (ret.Failed()) {
720 last_error = ret;
721
722 /* We may not clear more tiles. */
723 if (c != nullptr && GB(c->clear_limit, 16, 16) < 1) break;
724 continue;
725 }
726
727 had_success = true;
728 if (flags & DC_EXEC) {
729 money -= ret.GetCost();
730 if (ret.GetCost() > 0 && money < 0) {
731 return { cost, ret.GetCost() };
732 }
734
735 /* draw explosion animation...
736 * Disable explosions when game is paused. Looks silly and blocks the view. */
737 if ((t == tile || t == start_tile) && _pause_mode == PM_UNPAUSED) {
738 /* big explosion in two corners, or small explosion for single tiles */
740 TileX(tile) == TileX(start_tile) && TileY(tile) == TileY(start_tile) ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
741 );
742 }
743 } else {
744 /* When we're at the clearing limit we better bail (unneed) testing as well. */
745 if (ret.GetCost() != 0 && --limit <= 0) break;
746 }
747 cost.AddCost(ret);
748 }
749
750 return { had_success ? cost : last_error, 0 };
751}
752
753
754TileIndex _cur_tileloop_tile;
755
760{
762
763 /* The pseudorandom sequence of tiles is generated using a Galois linear feedback
764 * shift register (LFSR). This allows a deterministic pseudorandom ordering, but
765 * still with minimal state and fast iteration. */
766
767 /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 24-bit (for 4096x4096 maps).
768 * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */
769 static const uint32_t feedbacks[] = {
770 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87
771 };
772 static_assert(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1);
773 const uint32_t feedback = feedbacks[Map::LogX() + Map::LogY() - 2 * MIN_MAP_SIZE_BITS];
774
775 /* We update every tile every TILE_UPDATE_FREQUENCY ticks, so divide the map size by 2^TILE_UPDATE_FREQUENCY_LOG = TILE_UPDATE_FREQUENCY */
776 static_assert(2 * MIN_MAP_SIZE_BITS >= TILE_UPDATE_FREQUENCY_LOG);
777 uint count = 1 << (Map::LogX() + Map::LogY() - TILE_UPDATE_FREQUENCY_LOG);
778
779 TileIndex tile = _cur_tileloop_tile;
780 /* The LFSR cannot have a zeroed state. */
781 assert(tile != 0);
782
783 /* Manually update tile 0 every TILE_UPDATE_FREQUENCY ticks - the LFSR never iterates over it itself. */
785 _tile_type_procs[GetTileType(0)]->tile_loop_proc(TileIndex{});
786 count--;
787 }
788
789 while (count--) {
790 _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
791
792 /* Get the next tile in sequence using a Galois LFSR. */
793 tile = TileIndex{(tile.base() >> 1) ^ (-(int32_t)(tile.base() & 1) & feedback)};
794 }
795
796 _cur_tileloop_tile = tile;
797}
798
799void InitializeLandscape()
800{
801 for (uint y = _settings_game.construction.freeform_edges ? 1 : 0; y < Map::MaxY(); y++) {
802 for (uint x = _settings_game.construction.freeform_edges ? 1 : 0; x < Map::MaxX(); x++) {
803 MakeClear(TileXY(x, y), CLEAR_GRASS, 3);
804 SetTileHeight(TileXY(x, y), 0);
807 }
808 }
809
810 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, Map::MaxY()));
811 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(Map::MaxX(), y));
812}
813
814static const uint8_t _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 };
815static const uint8_t _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
816
817static void GenerateTerrain(int type, uint flag)
818{
819 uint32_t r = Random();
820
821 /* Choose one of the templates from the graphics file. */
822 const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + SPR_MAPGEN_BEGIN, SpriteType::MapGen);
823 if (templ == nullptr) UserError("Map generator sprites could not be loaded");
824
825 /* Chose a random location to apply the template to. */
826 uint x = r & Map::MaxX();
827 uint y = (r >> Map::LogX()) & Map::MaxY();
828
829 /* Make sure the template is not too close to the upper edges; bottom edges are checked later. */
830 uint edge_distance = 1 + (_settings_game.construction.freeform_edges ? 1 : 0);
831 if (x <= edge_distance || y <= edge_distance) return;
832
833 DiagDirection direction = (DiagDirection)GB(r, 22, 2);
834 uint w = templ->width;
835 uint h = templ->height;
836
837 if (DiagDirToAxis(direction) == AXIS_Y) Swap(w, h);
838
839 const uint8_t *p = templ->data;
840
841 if ((flag & 4) != 0) {
842 /* This is only executed in secondary/tertiary loops to generate the terrain for arctic and tropic.
843 * It prevents the templates to be applied to certain parts of the map based on the flags, thus
844 * creating regions with different elevations/topography. */
845 uint xw = x * Map::SizeY();
846 uint yw = y * Map::SizeX();
847 uint bias = (Map::SizeX() + Map::SizeY()) * 16;
848
849 switch (flag & 3) {
850 default: NOT_REACHED();
851 case 0:
852 if (xw + yw > Map::Size() - bias) return;
853 break;
854
855 case 1:
856 if (yw < xw + bias) return;
857 break;
858
859 case 2:
860 if (xw + yw < Map::Size() + bias) return;
861 break;
862
863 case 3:
864 if (xw < yw + bias) return;
865 break;
866 }
867 }
868
869 /* Ensure the template does not overflow at the bottom edges of the map; upper edges were checked before. */
870 if (x + w >= Map::MaxX()) return;
871 if (y + h >= Map::MaxY()) return;
872
873 TileIndex tile = TileXY(x, y);
874
875 /* Get the template and overlay in a particular direction over the map's height from the given
876 * origin point (tile), and update the map's height everywhere where the height from the template
877 * is higher than the height of the map. In other words, this only raises the tile heights. */
878 switch (direction) {
879 default: NOT_REACHED();
880 case DIAGDIR_NE:
881 do {
882 TileIndex tile_cur = tile;
883
884 for (uint w_cur = w; w_cur != 0; --w_cur) {
885 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
886 p++;
887 tile_cur += TileDiffXY(1, 0);
888 }
889 tile += TileDiffXY(0, 1);
890 } while (--h != 0);
891 break;
892
893 case DIAGDIR_SE:
894 do {
895 TileIndex tile_cur = tile;
896
897 for (uint h_cur = h; h_cur != 0; --h_cur) {
898 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
899 p++;
900 tile_cur += TileDiffXY(0, 1);
901 }
902 tile += TileDiffXY(1, 0);
903 } while (--w != 0);
904 break;
905
906 case DIAGDIR_SW:
907 tile += TileDiffXY(w - 1, 0);
908 do {
909 TileIndex tile_cur = tile;
910
911 for (uint w_cur = w; w_cur != 0; --w_cur) {
912 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
913 p++;
914 tile_cur -= TileDiffXY(1, 0);
915 }
916 tile += TileDiffXY(0, 1);
917 } while (--h != 0);
918 break;
919
920 case DIAGDIR_NW:
921 tile += TileDiffXY(0, h - 1);
922 do {
923 TileIndex tile_cur = tile;
924
925 for (uint h_cur = h; h_cur != 0; --h_cur) {
926 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
927 p++;
928 tile_cur -= TileDiffXY(0, 1);
929 }
930 tile += TileDiffXY(1, 0);
931 } while (--w != 0);
932 break;
933 }
934}
935
936
937#include "table/genland.h"
938
939static void CreateDesertOrRainForest(uint desert_tropic_line)
940{
941 uint update_freq = Map::Size() / 4;
942
943 for (const auto tile : Map::Iterate()) {
944 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
945
946 if (!IsValidTile(tile)) continue;
947
948 auto allows_desert = [tile, desert_tropic_line](auto &offset) {
949 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
950 return t == INVALID_TILE || (TileHeight(t) < desert_tropic_line && !IsTileType(t, MP_WATER));
951 };
952 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_desert)) {
954 }
955 }
956
957 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
959
960 RunTileLoop();
961 }
962
963 for (const auto tile : Map::Iterate()) {
964 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
965
966 if (!IsValidTile(tile)) continue;
967
968 auto allows_rainforest = [tile](auto &offset) {
969 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
970 return t == INVALID_TILE || !IsTileType(t, MP_CLEAR) || !IsClearGround(t, CLEAR_DESERT);
971 };
972 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_rainforest)) {
974 }
975 }
976}
977
983static bool FindSpring(TileIndex tile, void *)
984{
985 int reference_height;
986 if (!IsTileFlat(tile, &reference_height) || IsWaterTile(tile)) return false;
987
988 /* In the tropics rivers start in the rainforest. */
989 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) != TROPICZONE_RAINFOREST) return false;
990
991 /* Are there enough higher tiles to warrant a 'spring'? */
992 uint num = 0;
993 for (int dx = -1; dx <= 1; dx++) {
994 for (int dy = -1; dy <= 1; dy++) {
995 TileIndex t = TileAddWrap(tile, dx, dy);
996 if (t != INVALID_TILE && GetTileMaxZ(t) > reference_height) num++;
997 }
998 }
999
1000 if (num < 4) return false;
1001
1002 /* Are we near the top of a hill? */
1003 for (int dx = -16; dx <= 16; dx++) {
1004 for (int dy = -16; dy <= 16; dy++) {
1005 TileIndex t = TileAddWrap(tile, dx, dy);
1006 if (t != INVALID_TILE && GetTileMaxZ(t) > reference_height + 2) return false;
1007 }
1008 }
1009
1010 return true;
1011}
1012
1019static bool MakeLake(TileIndex tile, void *user_data)
1020{
1021 uint height_lake = *static_cast<uint *>(user_data);
1022 if (!IsValidTile(tile) || TileHeight(tile) != height_lake || !IsTileFlat(tile)) return false;
1023 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) == TROPICZONE_DESERT) return false;
1024
1025 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1026 TileIndex t = tile + TileOffsByDiagDir(d);
1027 if (IsWaterTile(t)) {
1029 return false;
1030 }
1031 }
1032
1033 return false;
1034}
1035
1042static bool RiverMakeWider(TileIndex tile, void *user_data)
1043{
1044 /* Don't expand into void tiles. */
1045 if (!IsValidTile(tile)) return false;
1046
1047 /* If the tile is already sea or river, don't expand. */
1048 if (IsWaterTile(tile)) return false;
1049
1050 /* If the tile is at height 0 after terraforming but the ocean hasn't flooded yet, don't build river. */
1051 if (GetTileMaxZ(tile) == 0) return false;
1052
1053 TileIndex origin_tile = *static_cast<TileIndex *>(user_data);
1054 Slope cur_slope = GetTileSlope(tile);
1055 Slope desired_slope = GetTileSlope(origin_tile); // Initialize matching the origin tile as a shortcut if no terraforming is needed.
1056
1057 /* Never flow uphill. */
1058 if (GetTileMaxZ(tile) > GetTileMaxZ(origin_tile)) return false;
1059
1060 /* If the new tile can't hold a river tile, try terraforming. */
1061 if (!IsTileFlat(tile) && !IsInclinedSlope(cur_slope)) {
1062 /* Don't try to terraform steep slopes. */
1063 if (IsSteepSlope(cur_slope)) return false;
1064
1065 bool flat_river_found = false;
1066 bool sloped_river_found = false;
1067
1068 /* There are two common possibilities:
1069 * 1. River flat, adjacent tile has one corner lowered.
1070 * 2. River descending, adjacent tile has either one or three corners raised.
1071 */
1072
1073 /* First, determine the desired slope based on adjacent river tiles. This doesn't necessarily match the origin tile for the CircularTileSearch. */
1074 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1075 TileIndex other_tile = TileAddByDiagDir(tile, d);
1076 Slope other_slope = GetTileSlope(other_tile);
1077
1078 /* Only consider river tiles. */
1079 if (IsWaterTile(other_tile) && IsRiver(other_tile)) {
1080 /* If the adjacent river tile flows downhill, we need to check where we are relative to the slope. */
1081 if (IsInclinedSlope(other_slope) && GetTileMaxZ(tile) == GetTileMaxZ(other_tile)) {
1082 /* Check for a parallel slope. If we don't find one, we're above or below the slope instead. */
1085 desired_slope = other_slope;
1086 sloped_river_found = true;
1087 break;
1088 }
1089 }
1090 /* If we find an adjacent river tile, remember it. We'll terraform to match it later if we don't find a slope. */
1091 if (IsTileFlat(other_tile)) flat_river_found = true;
1092 }
1093 }
1094 /* We didn't find either an inclined or flat river, so we're climbing the wrong slope. Bail out. */
1095 if (!sloped_river_found && !flat_river_found) return false;
1096
1097 /* We didn't find an inclined river, but there is a flat river. */
1098 if (!sloped_river_found && flat_river_found) desired_slope = SLOPE_FLAT;
1099
1100 /* Now that we know the desired slope, it's time to terraform! */
1101
1102 /* If the river is flat and the adjacent tile has one corner lowered, we want to raise it. */
1103 if (desired_slope == SLOPE_FLAT && IsSlopeWithThreeCornersRaised(cur_slope)) {
1104 /* Make sure we're not affecting an existing river slope tile. */
1105 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1106 TileIndex other_tile = TileAddByDiagDir(tile, d);
1107 if (IsInclinedSlope(GetTileSlope(other_tile)) && IsWaterTile(other_tile)) return false;
1108 }
1110
1111 /* If the river is descending and the adjacent tile has either one or three corners raised, we want to make it match the slope. */
1112 } else if (IsInclinedSlope(desired_slope)) {
1113 /* Don't break existing flat river tiles by terraforming under them. */
1114 DiagDirection river_direction = ReverseDiagDir(GetInclinedSlopeDirection(desired_slope));
1115
1116 for (DiagDirDiff d = DIAGDIRDIFF_BEGIN; d < DIAGDIRDIFF_END; d++) {
1117 /* We don't care about downstream or upstream tiles, just the riverbanks. */
1118 if (d == DIAGDIRDIFF_SAME || d == DIAGDIRDIFF_REVERSE) continue;
1119
1120 TileIndex other_tile = (TileAddByDiagDir(tile, ChangeDiagDir(river_direction, d)));
1121 if (IsWaterTile(other_tile) && IsRiver(other_tile) && IsTileFlat(other_tile)) return false;
1122 }
1123
1124 /* Get the corners which are different between the current and desired slope. */
1125 Slope to_change = cur_slope ^ desired_slope;
1126
1127 /* Lower unwanted corners first. If only one corner is raised, no corners need lowering. */
1128 if (!IsSlopeWithOneCornerRaised(cur_slope)) {
1129 to_change = to_change & ComplementSlope(desired_slope);
1130 Command<CMD_TERRAFORM_LAND>::Do(DC_EXEC | DC_AUTO, tile, to_change, false);
1131 }
1132
1133 /* Now check the match and raise any corners needed. */
1134 cur_slope = GetTileSlope(tile);
1135 if (cur_slope != desired_slope && IsSlopeWithOneCornerRaised(cur_slope)) {
1136 to_change = cur_slope ^ desired_slope;
1137 Command<CMD_TERRAFORM_LAND>::Do(DC_EXEC | DC_AUTO, tile, to_change, true);
1138 }
1139 }
1140 /* Update cur_slope after possibly terraforming. */
1141 cur_slope = GetTileSlope(tile);
1142 }
1143
1144 /* Sloped rivers need water both upstream and downstream. */
1145 if (IsInclinedSlope(cur_slope)) {
1146 DiagDirection slope_direction = GetInclinedSlopeDirection(cur_slope);
1147
1148 TileIndex upstream_tile = TileAddByDiagDir(tile, slope_direction);
1149 TileIndex downstream_tile = TileAddByDiagDir(tile, ReverseDiagDir(slope_direction));
1150
1151 /* Don't look outside the map. */
1152 if (!IsValidTile(upstream_tile) || !IsValidTile(downstream_tile)) return false;
1153
1154 /* Downstream might be new ocean created by our terraforming, and it hasn't flooded yet. */
1155 bool downstream_is_ocean = GetTileZ(downstream_tile) == 0 && (GetTileSlope(downstream_tile) == SLOPE_FLAT || IsSlopeWithOneCornerRaised(GetTileSlope(downstream_tile)));
1156
1157 /* If downstream is dry, flat, and not ocean, try making it a river tile. */
1158 if (!IsWaterTile(downstream_tile) && !downstream_is_ocean) {
1159 /* If the tile upstream isn't flat, don't bother. */
1160 if (GetTileSlope(downstream_tile) != SLOPE_FLAT) return false;
1161
1162 MakeRiverAndModifyDesertZoneAround(downstream_tile);
1163 }
1164
1165 /* If upstream is dry and flat, try making it a river tile. */
1166 if (!IsWaterTile(upstream_tile)) {
1167 /* If the tile upstream isn't flat, don't bother. */
1168 if (GetTileSlope(upstream_tile) != SLOPE_FLAT) return false;
1169
1171 }
1172 }
1173
1174 /* If the tile slope matches the desired slope, add a river tile. */
1175 if (cur_slope == desired_slope) {
1177 }
1178
1179 /* Always return false to keep searching. */
1180 return false;
1181}
1182
1189static bool FlowsDown(TileIndex begin, TileIndex end)
1190{
1191 assert(DistanceManhattan(begin, end) == 1);
1192
1193 auto [slope_end, height_end] = GetTileSlopeZ(end);
1194
1195 /* Slope either is inclined or flat; rivers don't support other slopes. */
1196 if (slope_end != SLOPE_FLAT && !IsInclinedSlope(slope_end)) return false;
1197
1198 auto [slope_begin, height_begin] = GetTileSlopeZ(begin);
1199
1200 /* It can't flow uphill. */
1201 if (height_end > height_begin) return false;
1202
1203 /* Slope continues, then it must be lower... */
1204 if (slope_end == slope_begin && height_end < height_begin) return true;
1205
1206 /* ... or either end must be flat. */
1207 return slope_end == SLOPE_FLAT || slope_begin == SLOPE_FLAT;
1208}
1209
1215
1216/* AyStar callback for checking whether we reached our destination. */
1217static AyStarStatus River_EndNodeCheck(const AyStar *aystar, const PathNode *current)
1218{
1219 return current->GetTile() == *static_cast<TileIndex *>(aystar->user_target) ? AyStarStatus::FoundEndNode : AyStarStatus::Done;
1220}
1221
1222/* AyStar callback for getting the cost of the current node. */
1223static int32_t River_CalculateG(AyStar *, AyStarNode *, PathNode *)
1224{
1226}
1227
1228/* AyStar callback for getting the estimated cost to the destination. */
1229static int32_t River_CalculateH(AyStar *aystar, AyStarNode *current, PathNode *)
1230{
1231 return DistanceManhattan(*static_cast<TileIndex *>(aystar->user_target), current->tile);
1232}
1233
1234/* AyStar callback for getting the neighbouring nodes of the given node. */
1235static void River_GetNeighbours(AyStar *aystar, PathNode *current)
1236{
1237 TileIndex tile = current->GetTile();
1238
1239 aystar->neighbours.clear();
1240 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1241 TileIndex t = tile + TileOffsByDiagDir(d);
1242 if (IsValidTile(t) && FlowsDown(tile, t)) {
1243 auto &neighbour = aystar->neighbours.emplace_back();
1244 neighbour.tile = t;
1245 neighbour.td = INVALID_TRACKDIR;
1246 }
1247 }
1248}
1249
1250/* AyStar callback when an route has been found. */
1251static void River_FoundEndNode(AyStar *aystar, PathNode *current)
1252{
1253 River_UserData *data = static_cast<River_UserData *>(aystar->user_data);
1254
1255 /* First, build the river without worrying about its width. */
1256 for (PathNode *path = current->parent; path != nullptr; path = path->parent) {
1257 TileIndex tile = path->GetTile();
1258 if (!IsWaterTile(tile)) {
1260 }
1261 }
1262
1263 /* If the river is a main river, go back along the path to widen it.
1264 * Don't make wide rivers if we're using the original landscape generator.
1265 */
1267 const uint long_river_length = _settings_game.game_creation.min_river_length * 4;
1268
1269 for (PathNode *path = current->parent; path != nullptr; path = path->parent) {
1270 TileIndex tile = path->GetTile();
1271
1272 /* Check if we should widen river depending on how far we are away from the source. */
1273 uint current_river_length = DistanceManhattan(data->spring, tile);
1274 uint radius = std::min(3u, (current_river_length / (long_river_length / 3u)) + 1u);
1275
1276 if (radius > 1) CircularTileSearch(&tile, radius, RiverMakeWider, &path->key.tile);
1277 }
1278 }
1279}
1280
1288static void BuildRiver(TileIndex begin, TileIndex end, TileIndex spring, bool main_river)
1289{
1290 River_UserData user_data = { spring, main_river };
1291
1292 AyStar finder = {};
1293 finder.CalculateG = River_CalculateG;
1294 finder.CalculateH = River_CalculateH;
1295 finder.GetNeighbours = River_GetNeighbours;
1296 finder.EndNodeCheck = River_EndNodeCheck;
1297 finder.FoundEndNode = River_FoundEndNode;
1298 finder.user_target = &end;
1299 finder.user_data = &user_data;
1300
1301 AyStarNode start;
1302 start.tile = begin;
1303 start.td = INVALID_TRACKDIR;
1304 finder.AddStartNode(&start, 0);
1305 finder.Main();
1306}
1307
1315static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
1316{
1317 uint height_begin = TileHeight(begin);
1318
1319 if (IsWaterTile(begin)) {
1320 return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 };
1321 }
1322
1323 std::set<TileIndex> marks;
1324 marks.insert(begin);
1325
1326 /* Breadth first search for the closest tile we can flow down to. */
1327 std::list<TileIndex> queue;
1328 queue.push_back(begin);
1329
1330 bool found = false;
1331 uint count = 0; // Number of tiles considered; to be used for lake location guessing.
1332 TileIndex end;
1333 do {
1334 end = queue.front();
1335 queue.pop_front();
1336
1337 uint height_end = TileHeight(end);
1338 if (IsTileFlat(end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) {
1339 found = true;
1340 break;
1341 }
1342
1343 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1344 TileIndex t = end + TileOffsByDiagDir(d);
1345 if (IsValidTile(t) && !marks.contains(t) && FlowsDown(end, t)) {
1346 marks.insert(t);
1347 count++;
1348 queue.push_back(t);
1349 }
1350 }
1351 } while (!queue.empty());
1352
1353 bool main_river = false;
1354 if (found) {
1355 /* Flow further down hill. */
1356 std::tie(found, main_river) = FlowRiver(spring, end, min_river_length);
1357 } else if (count > 32) {
1358 /* Maybe we can make a lake. Find the Nth of the considered tiles. */
1359 std::set<TileIndex>::const_iterator cit = marks.cbegin();
1360 std::advance(cit, RandomRange(count - 1));
1361 TileIndex lake_centre = *cit;
1362
1363 if (IsValidTile(lake_centre) &&
1364 /* A river, or lake, can only be built on flat slopes. */
1365 IsTileFlat(lake_centre) &&
1366 /* We want the lake to be built at the height of the river. */
1367 TileHeight(begin) == TileHeight(lake_centre) &&
1368 /* We don't want the lake at the entry of the valley. */
1369 lake_centre != begin &&
1370 /* We don't want lakes in the desert. */
1371 (_settings_game.game_creation.landscape != LandscapeType::Tropic || GetTropicZone(lake_centre) != TROPICZONE_DESERT) &&
1372 /* We only want a lake if the river is long enough. */
1373 DistanceManhattan(spring, lake_centre) > min_river_length) {
1374 end = lake_centre;
1376 uint range = RandomRange(8) + 3;
1377 CircularTileSearch(&lake_centre, range, MakeLake, &height_begin);
1378 /* Call the search a second time so artefacts from going circular in one direction get (mostly) hidden. */
1379 lake_centre = end;
1380 CircularTileSearch(&lake_centre, range, MakeLake, &height_begin);
1381 found = true;
1382 }
1383 }
1384
1385 marks.clear();
1386 if (found) BuildRiver(begin, end, spring, main_river);
1387 return { found, main_river };
1388}
1389
1393static void CreateRivers()
1394{
1396 if (amount == 0) return;
1397
1399 const uint num_short_rivers = wells - std::max(1u, wells / 10);
1400 SetGeneratingWorldProgress(GWP_RIVER, wells + TILE_UPDATE_FREQUENCY / 64); // Include the tile loop calls below.
1401
1402 /* Try to create long rivers. */
1403 for (; wells > num_short_rivers; wells--) {
1405 for (int tries = 0; tries < 512; tries++) {
1406 TileIndex t = RandomTile();
1407 if (!CircularTileSearch(&t, 8, FindSpring, nullptr)) continue;
1408 if (std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length * 4))) break;
1409 }
1410 }
1411
1412 /* Try to create short rivers. */
1413 for (; wells != 0; wells--) {
1415 for (int tries = 0; tries < 128; tries++) {
1416 TileIndex t = RandomTile();
1417 if (!CircularTileSearch(&t, 8, FindSpring, nullptr)) continue;
1418 if (std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length))) break;
1419 }
1420 }
1421
1422 /* Widening rivers may have left some tiles requiring to be watered. */
1423 ConvertGroundTilesIntoWaterTiles();
1424
1425 /* Run tile loop to update the ground density. */
1426 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
1428 RunTileLoop();
1429 }
1430}
1431
1449static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
1450{
1451 /* Histogram of how many tiles per height level exist. */
1452 std::array<int, MAX_TILE_HEIGHT + 1> histogram = {};
1453 /* Histogram of how many neighbour tiles are lower than the tiles of the height level. */
1454 std::array<int, MAX_TILE_HEIGHT + 1> edge_histogram = {};
1455
1456 /* Build a histogram of the map height. */
1457 for (const auto tile : Map::Iterate()) {
1458 uint h = TileHeight(tile);
1459 histogram[h]++;
1460
1461 if (edge_multiplier != 0) {
1462 /* Check if any of our neighbours is below us. */
1463 for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) {
1464 TileIndex neighbour_tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(dir));
1465 if (IsValidTile(neighbour_tile) && TileHeight(neighbour_tile) < h) {
1466 edge_histogram[h]++;
1467 }
1468 }
1469 }
1470 }
1471
1472 /* The amount of land we have is the map size minus the first (sea) layer. */
1473 uint land_tiles = Map::Size() - histogram[0];
1474 int best_score = land_tiles;
1475
1476 /* Our goal is the coverage amount of the land-mass. */
1477 int goal_tiles = land_tiles * coverage / 100;
1478
1479 /* We scan from top to bottom. */
1480 uint h = MAX_TILE_HEIGHT;
1481 uint best_h = h;
1482
1483 int current_tiles = 0;
1484 for (; h > 0; h--) {
1485 current_tiles += histogram[h];
1486 int current_score = goal_tiles - current_tiles;
1487
1488 /* Tropic grows from water and mountains into the desert. This is a
1489 * great visual, but it also means we* need to take into account how
1490 * much less desert tiles are being created if we are on this
1491 * height-level. We estimate this based on how many neighbouring
1492 * tiles are below us for a given length, assuming that is where
1493 * tropic is growing from.
1494 */
1495 if (edge_multiplier != 0 && h > 1) {
1496 /* From water tropic tiles grow for a few tiles land inward. */
1497 current_score -= edge_histogram[1] * edge_multiplier;
1498 /* Tropic tiles grow into the desert for a few tiles. */
1499 current_score -= edge_histogram[h] * edge_multiplier;
1500 }
1501
1502 if (std::abs(current_score) < std::abs(best_score)) {
1503 best_score = current_score;
1504 best_h = h;
1505 }
1506
1507 /* Always scan all height-levels, as h == 1 might give a better
1508 * score than any before. This is true for example with 0% desert
1509 * coverage. */
1510 }
1511
1512 return best_h;
1513}
1514
1519{
1520 /* We do not have snow sprites on coastal tiles, so never allow "1" as height. */
1522}
1523
1528static uint8_t CalculateDesertLine()
1529{
1530 /* CalculateCoverageLine() runs from top to bottom, so we need to invert the coverage. */
1532}
1533
1534bool GenerateLandscape(uint8_t mode)
1535{
1536 /* Number of steps of landscape generation */
1537 static constexpr uint GLS_HEIGHTMAP = 3;
1538 static constexpr uint GLS_TERRAGENESIS = 5;
1539 static constexpr uint GLS_ORIGINAL = 2;
1540 static constexpr uint GLS_TROPIC = 12;
1541 static constexpr uint GLS_OTHER = 0;
1542 uint steps = (_settings_game.game_creation.landscape == LandscapeType::Tropic) ? GLS_TROPIC : GLS_OTHER;
1543
1544 if (mode == GWM_HEIGHTMAP) {
1545 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_HEIGHTMAP);
1547 return false;
1548 }
1551 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_TERRAGENESIS);
1553 } else {
1554 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_ORIGINAL);
1556 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, 0));
1557 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(0, y));
1558 }
1560 case LandscapeType::Arctic: {
1561 uint32_t r = Random();
1562
1563 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 950); i != 0; --i) {
1564 GenerateTerrain(2, 0);
1565 }
1566
1567 uint flag = GB(r, 7, 2) | 4;
1568 for (uint i = Map::ScaleBySize(GB(r, 9, 7) + 450); i != 0; --i) {
1569 GenerateTerrain(4, flag);
1570 }
1571 break;
1572 }
1573
1574 case LandscapeType::Tropic: {
1575 uint32_t r = Random();
1576
1577 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 170); i != 0; --i) {
1578 GenerateTerrain(0, 0);
1579 }
1580
1581 uint flag = GB(r, 7, 2) | 4;
1582 for (uint i = Map::ScaleBySize(GB(r, 9, 8) + 1700); i != 0; --i) {
1583 GenerateTerrain(0, flag);
1584 }
1585
1586 flag ^= 2;
1587
1588 for (uint i = Map::ScaleBySize(GB(r, 17, 7) + 410); i != 0; --i) {
1589 GenerateTerrain(3, flag);
1590 }
1591 break;
1592 }
1593
1594 default: {
1595 uint32_t r = Random();
1596
1598 uint i = Map::ScaleBySize(GB(r, 0, 7) + (3 - _settings_game.difficulty.quantity_sea_lakes) * 256 + 100);
1599 for (; i != 0; --i) {
1600 /* Make sure we do not overflow. */
1601 GenerateTerrain(Clamp(_settings_game.difficulty.terrain_type, 0, 3), 0);
1602 }
1603 break;
1604 }
1605 }
1606 }
1607
1608 /* Do not call IncreaseGeneratingWorldProgress() before FixSlopes(),
1609 * it allows screen redraw. Drawing of broken slopes crashes the game */
1610 FixSlopes();
1613
1614 ConvertGroundTilesIntoWaterTiles();
1617
1619 case LandscapeType::Arctic:
1621 break;
1622
1623 case LandscapeType::Tropic: {
1624 uint desert_tropic_line = CalculateDesertLine();
1625 CreateDesertOrRainForest(desert_tropic_line);
1626 break;
1627 }
1628
1629 default:
1630 break;
1631 }
1632
1633 CreateRivers();
1634 return true;
1635}
1636
1637void OnTick_Town();
1638void OnTick_Trees();
1639void OnTick_Station();
1640void OnTick_Industry();
1641
1642void OnTick_Companies();
1643void OnTick_LinkGraph();
1644
1645void CallLandscapeTick()
1646{
1647 {
1649
1650 OnTick_Town();
1651 OnTick_Trees();
1652 OnTick_Station();
1653 OnTick_Industry();
1654 }
1655
1658}
void DeleteAnimatedTile(TileIndex tile, bool immediate)
Stops animation on the given tile.
Tile animation!
This file has the header for AyStar.
AyStarStatus
Return status of AyStar methods.
Definition aystar.h:25
@ FoundEndNode
An end node was found.
@ Done
Not an end-tile, or wrong direction.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
void ClearBridgeMiddle(Tile t)
Removes bridges from the given, that is bridges along the X and Y axis.
Definition bridge_map.h:103
Common return value for all commands.
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Money GetCost() const
The costs as made up to this moment.
bool Failed() const
Did this command fail?
RAII class for measuring multi-step elements of performance.
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
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static Date date
Current date in days (day counter).
static TickCounter counter
Monotonic counter, in ticks, since start of game.
Map accessors for 'clear' tiles.
bool IsClearGround(Tile t, ClearGround ct)
Set the type of clear tile.
Definition clear_map.h:71
@ CLEAR_GRASS
0-3
Definition clear_map.h:20
@ CLEAR_DESERT
1,3
Definition clear_map.h:25
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition clear_map.h:259
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
DoCommandFlag
List of flags for a command.
@ DC_AUTO
don't allow building on structures
@ DC_FORCE_CLEAR_TILE
do not only remove the object on the tile, but also clear any water left on it
@ DC_NO_WATER
don't allow building on water
@ DC_BANKRUPT
company bankrupts, skip money check, skip vehicle on tile check in some cases
@ DC_EXEC
execute the given command
Money GetAvailableMoneyForCommand()
This functions returns the money which can be used to execute a command.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
Owner
Enum for all companies/owners.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
Applies a difference on a DiagDirection.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
DiagDirDiff
Enumeration for the difference between to DiagDirection.
@ DIAGDIRDIFF_END
Used for iterations.
@ DIAGDIRDIFF_90RIGHT
90 degrees right
@ DIAGDIRDIFF_90LEFT
90 degrees left
@ DIAGDIRDIFF_REVERSE
Reverse directions.
@ DIAGDIRDIFF_SAME
Same directions.
@ DIAGDIRDIFF_BEGIN
Used for iterations.
@ AXIS_Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_END
Used for iterations.
@ DIAGDIR_BEGIN
Used for iterations.
@ DIAGDIR_SW
Southwest.
@ EXPENSES_CONSTRUCTION
Construction costs.
EffectVehicle * CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular location.
Functions related to effect vehicles.
@ EV_EXPLOSION_SMALL
Various explosions.
@ EV_EXPLOSION_LARGE
Various explosions.
Error reporting related functions.
Declarations for savegames operations.
Types for recording game performance data.
@ PFE_GL_LANDSCAPE
Time spent processing other world features.
Table used to generate deserts and/or rainforests.
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:69
Functions related to world/map generation.
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
@ LG_ORIGINAL
The original landscape generator.
Definition genworld.h:21
@ LG_TERRAGENESIS
TerraGenesis Perlin landscape generator.
Definition genworld.h:22
static const uint CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
Value for custom sea level in difficulty settings.
Definition genworld.h:48
@ GWP_LANDSCAPE
Create the landscape.
Definition genworld.h:74
@ GWP_RIVER
Create the rivers.
Definition genworld.h:75
void SetGeneratingWorldProgress(GenWorldProgress cls, uint total)
Set the total of a stage of the world generation.
@ GWM_HEIGHTMAP
Generate a newgame from a heightmap.
Definition genworld.h:32
PauseMode _pause_mode
The current pause mode.
Definition gfx.cpp:50
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ MapGen
Special sprite for the map generator.
uint8_t LowestSnowLine()
Get the lowest possible snow line height, either variable or static.
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
bool IsSnowLineSet()
Has a snow line table already been loaded.
void ClearSnowLine()
Clear the variable snow line table and free the memory.
static std::unique_ptr< SnowLine > _snow_line
Description of the snow line throughout the year.
Definition landscape.cpp:96
void SetSnowLine(std::unique_ptr< SnowLine > &&snow_line)
Set a variable snow line, as loaded from a newgrf file.
uint8_t HighestSnowLine()
Get the highest possible snow line height, either variable or static.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1529
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
bool LoadHeightmap(DetailedFileType dft, const char *filename)
Load a heightmap from file and change the map in its current dimensions to a landscape representing t...
void FixSlopes()
This function takes care of the fact that land in OpenTTD can never differ more than 1 in height.
Functions related to creating heightmaps from files.
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
static std::tuple< bool, bool > FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
Try to flow the river down from a given begin.
int GetSlopePixelZOutsideMap(int x, int y)
Return world z coordinate of a given point of a tile, also for tiles outside the map (virtual "black"...
static bool FlowsDown(TileIndex begin, TileIndex end)
Check whether a river at begin could (logically) flow down to end.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
static bool RiverMakeWider(TileIndex tile, void *user_data)
Widen a river by expanding into adjacent tiles via circular tile search.
void OnTick_Companies()
Called every tick for updating some company info.
static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
Calculate what height would be needed to cover N% of the landmass.
static void CalculateSnowLine()
Calculate the line from which snow begins.
static const uint TILE_UPDATE_FREQUENCY_LOG
The logarithm of how many ticks it takes between tile updates (log base 2).
Definition landscape.cpp:85
CommandCost CmdLandscapeClear(DoCommandFlag flags, TileIndex tile)
Clear a piece of landscape.
static bool FindSpring(TileIndex tile, void *)
Find the spring of a river.
std::tuple< CommandCost, Money > CmdClearArea(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, bool diagonal)
Clear a big piece of landscape.
void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
Change the owner of a tile.
void RunTileLoop()
Gradually iterate over all tiles on the map, calling their TileLoopProcs once every TILE_UPDATE_FREQU...
static void CreateRivers()
Actually (try to) create some rivers.
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
int GetSlopeZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
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,...
static void BuildRiver(TileIndex begin, TileIndex end, TileIndex spring, bool main_river)
Actually build the river between the begin and end tiles using AyStar.
void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int &z1, int &z2)
Determine the Z height of the corners of a specific tile edge.
void OnTick_LinkGraph()
Spawn or join a link graph job or compress a link graph if any link graph is due to do so.
const TileTypeProcs *const _tile_type_procs[16]
Tile callback functions for each type of tile.
Definition landscape.cpp:65
Point InverseRemapCoords2(int x, int y, bool clamp_to_map, bool *clamped)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
const TileTypeProcs _tile_type_town_procs
Tile callback functions for a town.
Definition landscape.cpp:51
static bool MakeLake(TileIndex tile, void *user_data)
Make a connected lake; fill all tiles in the circular tile search that are connected.
void OnTick_Town()
Iterate through all towns and call their tick handler.
Definition town_cmd.cpp:935
static uint8_t CalculateDesertLine()
Calculate the line (in height) between desert and tropic.
const uint8_t _slope_to_sprite_offset[32]
landscape slope => sprite
const TileTypeProcs _tile_type_road_procs
Tile callback functions for road tiles.
Definition landscape.cpp:50
uint ApplyFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
bool GenerateLandscape(uint8_t mode)
static const uint TILE_UPDATE_FREQUENCY
How many ticks it takes between tile updates (has to be a power of 2).
Definition landscape.cpp:86
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Functions related to OTTD's landscape.
std::tuple< Slope, int > GetFoundationPixelSlope(TileIndex tile)
Get slope of a tile on top of a (possible) foundation If a tile does not have a foundation,...
Definition landscape.h:65
uint ApplyPixelFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition landscape.h:126
Point InverseRemapCoords(int x, int y)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
Definition landscape.h:109
Command definitions related to landscape (slopes etc.).
Types related to the landscape.
@ Random
Randomise borders.
bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data)
Function performing a search around a center tile and going outward, thus in circle.
Definition map.cpp:244
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:94
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:143
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:470
TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
Add a TileIndexDiffC to a TileIndex and returns the new one.
Definition map_func.h:515
static debug_inline TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition map_func.h:373
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:611
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:389
TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
Returns the TileIndexDiffC offset from a DiagDirection.
Definition map_func.h:483
#define RandomTile()
Get a valid random tile.
Definition map_func.h:664
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:415
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:570
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:404
static const uint MIN_MAP_SIZE_BITS
Minimal and maximal map width and height.
Definition map_type.h:37
static const uint MAX_MAP_SIZE_BITS
Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS.
Definition map_type.h:38
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
constexpr void Swap(T &a, T &b)
Type safe swap operation.
Base for all objects.
ClearedObjectArea * FindClearedObject(TileIndex tile)
Find the entry in _cleared_object_areas which occupies a certain tile.
@ PM_UNPAUSED
A normal unpaused game.
Definition openttd.h:69
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
A number of safeguards to prevent using unsafe methods.
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition saveload.cpp:63
Functions/types related to saving and loading games.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:57
bool IsSpecialRailFoundation(Foundation f)
Tests if a foundation is a special rail foundation for single horizontal/vertical track.
Definition slope_func.h:345
Slope SlopeWithThreeCornersRaised(Corner corner)
Returns the slope with all except one corner raised.
Definition slope_func.h:206
Corner OppositeCorner(Corner corner)
Returns the opposite corner.
Definition slope_func.h:184
static constexpr Corner GetHalftileSlopeCorner(Slope s)
Returns the leveled halftile of a halftile slope.
Definition slope_func.h:148
static constexpr Slope RemoveHalftileSlope(Slope s)
Removes a halftile slope from a slope.
Definition slope_func.h:60
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:88
bool IsNonContinuousFoundation(Foundation f)
Tests if a foundation is a non-continuous foundation, i.e.
Definition slope_func.h:320
Corner GetHighestSlopeCorner(Slope s)
Returns the highest corner of a slope (one corner raised or a steep slope).
Definition slope_func.h:126
Corner GetHalftileFoundationCorner(Foundation f)
Returns the halftile corner of a halftile-foundation.
Definition slope_func.h:333
bool IsLeveledFoundation(Foundation f)
Tests if the foundation is a leveled foundation.
Definition slope_func.h:298
bool IsFoundation(Foundation f)
Tests for FOUNDATION_NONE.
Definition slope_func.h:287
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
bool IsSlopeWithThreeCornersRaised(Slope s)
Tests if a specific slope has exactly three corners raised.
Definition slope_func.h:195
bool IsInclinedSlope(Slope s)
Tests if a specific slope is an inclined slope.
Definition slope_func.h:228
Slope SteepSlope(Corner corner)
Returns a specific steep slope.
Definition slope_func.h:217
Corner GetRailFoundationCorner(Foundation f)
Returns the track corner of a special rail foundation.
Definition slope_func.h:356
static constexpr bool IsHalftileSlope(Slope s)
Checks for non-continuous slope on halftile foundations.
Definition slope_func.h:47
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
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition slope_func.h:239
static constexpr Slope HalftileSlope(Slope s, Corner corner)
Adds a halftile slope to a slope.
Definition slope_func.h:274
Slope ComplementSlope(Slope s)
Return the complement of a slope.
Definition slope_func.h:76
Slope SlopeWithOneCornerRaised(Corner corner)
Returns the slope with a specific corner raised.
Definition slope_func.h:99
bool IsInclinedFoundation(Foundation f)
Tests if the foundation is an inclined foundation.
Definition slope_func.h:309
Corner
Enumeration of tile corners.
Definition slope_type.h:22
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
@ SLOPE_W
the west corner of the tile is raised
Definition slope_type.h:50
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:61
@ SLOPE_NS
north and south corner are raised
Definition slope_type.h:60
@ SLOPE_E
the east corner of the tile is raised
Definition slope_type.h:52
@ SLOPE_WSE
west, south and east corner are raised
Definition slope_type.h:63
@ SLOPE_S
the south corner of the tile is raised
Definition slope_type.h:51
@ SLOPE_N
the north corner of the tile is raised
Definition slope_type.h:53
@ SLOPE_SEN
south, east and north corner are raised
Definition slope_type.h:64
@ SLOPE_ENW
east, north and west corner are raised
Definition slope_type.h:65
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:56
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:49
@ SLOPE_STEEP_W
a steep slope falling to east (from west)
Definition slope_type.h:66
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:58
@ SLOPE_STEEP_E
a steep slope falling to west (from east)
Definition slope_type.h:68
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:57
@ SLOPE_NWS
north, west and south corner are raised
Definition slope_type.h:62
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:55
@ SLOPE_STEEP_N
a steep slope falling to south (from north)
Definition slope_type.h:69
@ SLOPE_STEEP_S
a steep slope falling to north (from south)
Definition slope_type.h:67
@ SLOPE_EW
east and west corner are raised
Definition slope_type.h:59
@ SLOPE_STEEP
indicates the slope is steep
Definition slope_type.h:54
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
@ FOUNDATION_INCLINED_X
The tile has an along X-axis inclined foundation.
Definition slope_type.h:96
@ 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
The tile has an along Y-axis inclined foundation.
Definition slope_type.h:97
@ 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
Functions to cache sprites in memory.
This file contains all sprite-related enums and defines.
static const SpriteID SPR_HALFTILE_FOUNDATION_BASE
Halftile foundations.
Definition sprites.h:210
Functions related to stations.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:277
AyStar search algorithm struct.
Definition aystar.h:95
AyStarStatus Main()
This is the function you call to run AyStar.
Definition aystar.cpp:137
void AddStartNode(AyStarNode *start_node, int g)
Adds a node from where to start an algorithm.
Definition aystar.cpp:169
Keeps track of removed objects during execution/testruns of commands.
Definition object_base.h:84
TileIndex first_tile
The first tile being cleared, which then causes the whole object to be cleared.
Definition object_base.h:85
uint32_t clear_limit
Amount of tiles we can (still) clear (times 65536).
bool freeform_edges
allow terraforming the tiles at the map edges
uint8_t map_height_limit
the maximum allowed heightlevel
uint8_t terrain_type
the mountainousness of the landscape
uint8_t quantity_sea_lakes
the amount of seas/lakes
DetailedFileType detail_ftype
Concrete file type (PNG, BMP, old save, etc).
Definition saveload.h:413
std::string name
Name of the file.
Definition saveload.h:415
uint8_t amount_of_rivers
the amount of rivers
uint8_t min_river_length
the minimum river length
uint8_t snow_coverage
the amount of snow coverage on the map
uint8_t desert_coverage
the amount of desert coverage on the map
LandscapeType landscape
the landscape we're currently in
uint8_t snow_line_height
the configured snow line height (deduced from "snow_coverage")
uint8_t land_generator
the landscape generator
uint8_t river_route_random
the amount of randomicity for the route finding
ConstructionSettings construction
construction of things in-game
DifficultySettings difficulty
settings related to the difficulty
GameCreationSettings game_creation
settings used during the creation of a game (map)
Size related data of the map.
Definition map_func.h:206
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:328
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:279
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:363
static debug_inline uint SizeX()
Get the size of the map along the X.
Definition map_func.h:270
static debug_inline uint LogX()
Logarithm of the map size along the X side.
Definition map_func.h:251
static uint LogY()
Logarithm of the map size along the y side.
Definition map_func.h:261
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition map_func.h:306
static debug_inline uint Size()
Get the size of the map.
Definition map_func.h:288
static debug_inline uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition map_func.h:297
Coordinates of a point in 2D.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
static Titem * Get(size_t index)
Returns Titem with given index.
Parameters for river generation to pass as AyStar user data.
TileIndex spring
The current spring during river generation.
bool main_river
Whether the current river is a big river that others flow into.
Data structure describing a sprite.
Definition spritecache.h:17
uint16_t width
Width of the sprite.
Definition spritecache.h:19
uint16_t height
Height of the sprite.
Definition spritecache.h:18
uint8_t data[]
Sprite data.
Definition spritecache.h:22
Tile description for the 'land area information' tool.
Definition tile_cmd.h:52
Tile information, used while rendering the tile.
Definition tile_cmd.h:43
int z
Height.
Definition tile_cmd.h:48
int x
X position of the tile in unit coordinates.
Definition tile_cmd.h:44
Slope tileh
Slope of the tile.
Definition tile_cmd.h:46
TileIndex tile
Tile index.
Definition tile_cmd.h:47
int y
Y position of the tile in unit coordinates.
Definition tile_cmd.h:45
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:158
GetTileDescProc * get_tile_desc_proc
Get a description of a tile (for the 'land area information' tool)
Definition tile_cmd.h:163
GetTileTrackStatusProc * get_tile_track_status_proc
Get available tracks and status of a tile.
Definition tile_cmd.h:164
Command definitions related to terraforming.
void GenerateTerrainPerlin()
The main new land generator using Perlin noise.
Definition tgp.cpp:981
Functions for the Perlin noise enhanced map generator.
bool MayAnimateTile(TileIndex tile)
Test if a tile may be animated.
Definition tile_cmd.h:202
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition tile_map.cpp:95
std::tuple< Slope, int > GetTileSlopeZ(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.cpp:55
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:136
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
void SetTileHeight(Tile tile, uint height)
Sets the height of a tile.
Definition tile_map.h:57
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
void SetTropicZone(Tile tile, TropicZone type)
Set the tropic zone.
Definition tile_map.h:225
static debug_inline uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
static const uint TILE_PIXELS
Pixel distance between tile columns/rows in ZOOM_BASE.
Definition tile_type.h:17
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
static const uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
static const uint MAX_TILE_HEIGHT
Maximum allowed tile height.
Definition tile_type.h:24
@ TROPICZONE_RAINFOREST
Rainforest tile.
Definition tile_type.h:79
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
@ TROPICZONE_NORMAL
Normal tropiczone.
Definition tile_type.h:77
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:48
@ MP_WATER
Water tile.
Definition tile_type.h:54
@ MP_VOID
Invisible tiles at the SW and SE border.
Definition tile_type.h:55
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:86
TransportType
Available types of transport.
void OffsetGroundSprite(int x, int y)
Called when a foundation has been drawn for the current tile.
Definition viewport.cpp:599
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:671
Functions related to (drawing on) viewports.
Map accessors for void tiles.
void MakeVoid(Tile t)
Make a nice void tile ;)
Definition void_map.h:19
Functions related to water (management)
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:97
void MakeRiverAndModifyDesertZoneAround(TileIndex tile)
Make a river tile and remove desert directly around it.
bool IsTileOnWater(Tile t)
Tests if the tile was built on water.
Definition water_map.h:136
bool IsRiver(Tile t)
Is it a river water tile?
Definition water_map.h:180
@ WATER_CLASS_CANAL
Canal.
Definition water_map.h:41
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:101
bool IsCanal(Tile t)
Is it a canal tile?
Definition water_map.h:169
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:112
bool IsCoastTile(Tile t)
Is it a coast tile.
Definition water_map.h:211
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:371
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition water_map.h:190
void InvalidateWaterRegion(TileIndex tile)
Marks the water region that tile is part of as invalid.
Handles dividing the water in the map into regions to assist pathfinding.