OpenTTD Source 20241224-master-gf74b0cf984
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 SnowLine *_snow_line = nullptr;
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 * SPR_TRKFOUND_BLOCK_SIZE));
446 SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SPR_SLOPES_INCLINED_OFFSET + sprite_block * SPR_TRKFOUND_BLOCK_SIZE;
447 SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * SPR_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
591{
592 _snow_line = CallocT<SnowLine>(1);
593 _snow_line->lowest_value = 0xFF;
594 memcpy(_snow_line->table, table, sizeof(_snow_line->table));
595
596 for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
597 for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
598 _snow_line->highest_value = std::max(_snow_line->highest_value, table[i][j]);
599 _snow_line->lowest_value = std::min(_snow_line->lowest_value, table[i][j]);
600 }
601 }
602}
603
609uint8_t GetSnowLine()
610{
612
613 TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
614 return _snow_line->table[ymd.month][ymd.day];
615}
616
626
636
642{
644 _snow_line = nullptr;
645}
646
654{
656 bool do_clear = false;
657 /* Test for stuff which results in water when cleared. Then add the cost to also clear the water. */
658 if ((flags & DC_FORCE_CLEAR_TILE) && HasTileWaterClass(tile) && IsTileOnWater(tile) && !IsWaterTile(tile) && !IsCoastTile(tile)) {
659 if ((flags & DC_AUTO) && GetWaterClass(tile) == WATER_CLASS_CANAL) return CommandCost(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
660 do_clear = true;
661 cost.AddCost(GetWaterClass(tile) == WATER_CLASS_CANAL ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER]);
662 }
663
664 Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? nullptr : Company::GetIfValid(_current_company);
665 if (c != nullptr && (int)GB(c->clear_limit, 16, 16) < 1) {
666 return CommandCost(STR_ERROR_CLEARING_LIMIT_REACHED);
667 }
668
669 const ClearedObjectArea *coa = FindClearedObject(tile);
670
671 /* If this tile was the first tile which caused object destruction, always
672 * pass it on to the tile_type_proc. That way multiple test runs and the exec run stay consistent. */
673 if (coa != nullptr && coa->first_tile != tile) {
674 /* If this tile belongs to an object which was already cleared via another tile, pretend it has been
675 * already removed.
676 * However, we need to check stuff, which is not the same for all object tiles. (e.g. being on water or not) */
677
678 /* If a object is removed, it leaves either bare land or water. */
679 if ((flags & DC_NO_WATER) && HasTileWaterClass(tile) && IsTileOnWater(tile)) {
680 return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
681 }
682 } else {
683 cost.AddCost(_tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags));
684 }
685
686 if (flags & DC_EXEC) {
687 if (c != nullptr) c->clear_limit -= 1 << 16;
688 if (do_clear) {
689 if (IsWaterTile(tile) && IsCanal(tile)) {
690 Owner owner = GetTileOwner(tile);
691 if (Company::IsValidID(owner)) {
692 Company::Get(owner)->infrastructure.water--;
694 }
695 }
696 DoClearSquare(tile);
698 }
699 }
700 return cost;
701}
702
711std::tuple<CommandCost, Money> CmdClearArea(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, bool diagonal)
712{
713 if (start_tile >= Map::Size()) return { CMD_ERROR, 0 };
714
717 CommandCost last_error = CMD_ERROR;
718 bool had_success = false;
719
720 const Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? nullptr : Company::GetIfValid(_current_company);
721 int limit = (c == nullptr ? INT32_MAX : GB(c->clear_limit, 16, 16));
722
723 if (tile != start_tile) flags |= DC_FORCE_CLEAR_TILE;
724
725 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
726 for (; *iter != INVALID_TILE; ++(*iter)) {
727 TileIndex t = *iter;
729 if (ret.Failed()) {
730 last_error = ret;
731
732 /* We may not clear more tiles. */
733 if (c != nullptr && GB(c->clear_limit, 16, 16) < 1) break;
734 continue;
735 }
736
737 had_success = true;
738 if (flags & DC_EXEC) {
739 money -= ret.GetCost();
740 if (ret.GetCost() > 0 && money < 0) {
741 return { cost, ret.GetCost() };
742 }
744
745 /* draw explosion animation...
746 * Disable explosions when game is paused. Looks silly and blocks the view. */
747 if ((t == tile || t == start_tile) && _pause_mode == PM_UNPAUSED) {
748 /* big explosion in two corners, or small explosion for single tiles */
750 TileX(tile) == TileX(start_tile) && TileY(tile) == TileY(start_tile) ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
751 );
752 }
753 } else {
754 /* When we're at the clearing limit we better bail (unneed) testing as well. */
755 if (ret.GetCost() != 0 && --limit <= 0) break;
756 }
757 cost.AddCost(ret);
758 }
759
760 return { had_success ? cost : last_error, 0 };
761}
762
763
764TileIndex _cur_tileloop_tile;
765
770{
772
773 /* The pseudorandom sequence of tiles is generated using a Galois linear feedback
774 * shift register (LFSR). This allows a deterministic pseudorandom ordering, but
775 * still with minimal state and fast iteration. */
776
777 /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 24-bit (for 4096x4096 maps).
778 * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */
779 static const uint32_t feedbacks[] = {
780 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87
781 };
782 static_assert(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1);
783 const uint32_t feedback = feedbacks[Map::LogX() + Map::LogY() - 2 * MIN_MAP_SIZE_BITS];
784
785 /* We update every tile every TILE_UPDATE_FREQUENCY ticks, so divide the map size by 2^TILE_UPDATE_FREQUENCY_LOG = TILE_UPDATE_FREQUENCY */
786 static_assert(2 * MIN_MAP_SIZE_BITS >= TILE_UPDATE_FREQUENCY_LOG);
787 uint count = 1 << (Map::LogX() + Map::LogY() - TILE_UPDATE_FREQUENCY_LOG);
788
789 TileIndex tile = _cur_tileloop_tile;
790 /* The LFSR cannot have a zeroed state. */
791 assert(tile != 0);
792
793 /* Manually update tile 0 every TILE_UPDATE_FREQUENCY ticks - the LFSR never iterates over it itself. */
795 _tile_type_procs[GetTileType(0)]->tile_loop_proc(0);
796 count--;
797 }
798
799 while (count--) {
800 _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
801
802 /* Get the next tile in sequence using a Galois LFSR. */
803 tile = (tile.base() >> 1) ^ (-(int32_t)(tile.base() & 1) & feedback);
804 }
805
806 _cur_tileloop_tile = tile;
807}
808
809void InitializeLandscape()
810{
811 for (uint y = _settings_game.construction.freeform_edges ? 1 : 0; y < Map::MaxY(); y++) {
812 for (uint x = _settings_game.construction.freeform_edges ? 1 : 0; x < Map::MaxX(); x++) {
813 MakeClear(TileXY(x, y), CLEAR_GRASS, 3);
814 SetTileHeight(TileXY(x, y), 0);
817 }
818 }
819
820 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, Map::MaxY()));
821 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(Map::MaxX(), y));
822}
823
824static const uint8_t _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 };
825static const uint8_t _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
826
827static void GenerateTerrain(int type, uint flag)
828{
829 uint32_t r = Random();
830
831 /* Choose one of the templates from the graphics file. */
832 const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + SPR_MAPGEN_BEGIN, SpriteType::MapGen);
833 if (templ == nullptr) UserError("Map generator sprites could not be loaded");
834
835 /* Chose a random location to apply the template to. */
836 uint x = r & Map::MaxX();
837 uint y = (r >> Map::LogX()) & Map::MaxY();
838
839 /* Make sure the template is not too close to the upper edges; bottom edges are checked later. */
840 uint edge_distance = 1 + (_settings_game.construction.freeform_edges ? 1 : 0);
841 if (x <= edge_distance || y <= edge_distance) return;
842
843 DiagDirection direction = (DiagDirection)GB(r, 22, 2);
844 uint w = templ->width;
845 uint h = templ->height;
846
847 if (DiagDirToAxis(direction) == AXIS_Y) Swap(w, h);
848
849 const uint8_t *p = templ->data;
850
851 if ((flag & 4) != 0) {
852 /* This is only executed in secondary/tertiary loops to generate the terrain for arctic and tropic.
853 * It prevents the templates to be applied to certain parts of the map based on the flags, thus
854 * creating regions with different elevations/topography. */
855 uint xw = x * Map::SizeY();
856 uint yw = y * Map::SizeX();
857 uint bias = (Map::SizeX() + Map::SizeY()) * 16;
858
859 switch (flag & 3) {
860 default: NOT_REACHED();
861 case 0:
862 if (xw + yw > Map::Size() - bias) return;
863 break;
864
865 case 1:
866 if (yw < xw + bias) return;
867 break;
868
869 case 2:
870 if (xw + yw < Map::Size() + bias) return;
871 break;
872
873 case 3:
874 if (xw < yw + bias) return;
875 break;
876 }
877 }
878
879 /* Ensure the template does not overflow at the bottom edges of the map; upper edges were checked before. */
880 if (x + w >= Map::MaxX()) return;
881 if (y + h >= Map::MaxY()) return;
882
883 TileIndex tile = TileXY(x, y);
884
885 /* Get the template and overlay in a particular direction over the map's height from the given
886 * origin point (tile), and update the map's height everywhere where the height from the template
887 * is higher than the height of the map. In other words, this only raises the tile heights. */
888 switch (direction) {
889 default: NOT_REACHED();
890 case DIAGDIR_NE:
891 do {
892 TileIndex tile_cur = tile;
893
894 for (uint w_cur = w; w_cur != 0; --w_cur) {
895 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
896 p++;
897 tile_cur++;
898 }
899 tile += TileDiffXY(0, 1);
900 } while (--h != 0);
901 break;
902
903 case DIAGDIR_SE:
904 do {
905 TileIndex tile_cur = tile;
906
907 for (uint h_cur = h; h_cur != 0; --h_cur) {
908 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
909 p++;
910 tile_cur += TileDiffXY(0, 1);
911 }
912 tile += TileDiffXY(1, 0);
913 } while (--w != 0);
914 break;
915
916 case DIAGDIR_SW:
917 tile += TileDiffXY(w - 1, 0);
918 do {
919 TileIndex tile_cur = tile;
920
921 for (uint w_cur = w; w_cur != 0; --w_cur) {
922 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
923 p++;
924 tile_cur--;
925 }
926 tile += TileDiffXY(0, 1);
927 } while (--h != 0);
928 break;
929
930 case DIAGDIR_NW:
931 tile += TileDiffXY(0, h - 1);
932 do {
933 TileIndex tile_cur = tile;
934
935 for (uint h_cur = h; h_cur != 0; --h_cur) {
936 if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
937 p++;
938 tile_cur -= TileDiffXY(0, 1);
939 }
940 tile += TileDiffXY(1, 0);
941 } while (--w != 0);
942 break;
943 }
944}
945
946
947#include "table/genland.h"
948
949static void CreateDesertOrRainForest(uint desert_tropic_line)
950{
951 uint update_freq = Map::Size() / 4;
952
953 for (const auto tile : Map::Iterate()) {
954 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
955
956 if (!IsValidTile(tile)) continue;
957
958 auto allows_desert = [tile, desert_tropic_line](auto &offset) {
959 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
960 return t == INVALID_TILE || (TileHeight(t) < desert_tropic_line && !IsTileType(t, MP_WATER));
961 };
962 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_desert)) {
964 }
965 }
966
967 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
969
970 RunTileLoop();
971 }
972
973 for (const auto tile : Map::Iterate()) {
974 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
975
976 if (!IsValidTile(tile)) continue;
977
978 auto allows_rainforest = [tile](auto &offset) {
979 TileIndex t = AddTileIndexDiffCWrap(tile, offset);
980 return t == INVALID_TILE || !IsTileType(t, MP_CLEAR) || !IsClearGround(t, CLEAR_DESERT);
981 };
982 if (std::all_of(std::begin(_make_desert_or_rainforest_data), std::end(_make_desert_or_rainforest_data), allows_rainforest)) {
984 }
985 }
986}
987
993static bool FindSpring(TileIndex tile, void *)
994{
995 int referenceHeight;
996 if (!IsTileFlat(tile, &referenceHeight) || IsWaterTile(tile)) return false;
997
998 /* In the tropics rivers start in the rainforest. */
999 if (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(tile) != TROPICZONE_RAINFOREST) return false;
1000
1001 /* Are there enough higher tiles to warrant a 'spring'? */
1002 uint num = 0;
1003 for (int dx = -1; dx <= 1; dx++) {
1004 for (int dy = -1; dy <= 1; dy++) {
1005 TileIndex t = TileAddWrap(tile, dx, dy);
1006 if (t != INVALID_TILE && GetTileMaxZ(t) > referenceHeight) num++;
1007 }
1008 }
1009
1010 if (num < 4) return false;
1011
1012 /* Are we near the top of a hill? */
1013 for (int dx = -16; dx <= 16; dx++) {
1014 for (int dy = -16; dy <= 16; dy++) {
1015 TileIndex t = TileAddWrap(tile, dx, dy);
1016 if (t != INVALID_TILE && GetTileMaxZ(t) > referenceHeight + 2) return false;
1017 }
1018 }
1019
1020 return true;
1021}
1022
1029static bool MakeLake(TileIndex tile, void *user_data)
1030{
1031 uint height = *(uint*)user_data;
1032 if (!IsValidTile(tile) || TileHeight(tile) != height || !IsTileFlat(tile)) return false;
1033 if (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(tile) == TROPICZONE_DESERT) return false;
1034
1035 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1036 TileIndex t2 = tile + TileOffsByDiagDir(d);
1037 if (IsWaterTile(t2)) {
1039 return false;
1040 }
1041 }
1042
1043 return false;
1044}
1045
1052static bool RiverMakeWider(TileIndex tile, void *data)
1053{
1054 /* Don't expand into void tiles. */
1055 if (!IsValidTile(tile)) return false;
1056
1057 /* If the tile is already sea or river, don't expand. */
1058 if (IsWaterTile(tile)) return false;
1059
1060 /* If the tile is at height 0 after terraforming but the ocean hasn't flooded yet, don't build river. */
1061 if (GetTileMaxZ(tile) == 0) return false;
1062
1063 TileIndex origin_tile = *(TileIndex *)data;
1064 Slope cur_slope = GetTileSlope(tile);
1065 Slope desired_slope = GetTileSlope(origin_tile); // Initialize matching the origin tile as a shortcut if no terraforming is needed.
1066
1067 /* Never flow uphill. */
1068 if (GetTileMaxZ(tile) > GetTileMaxZ(origin_tile)) return false;
1069
1070 /* If the new tile can't hold a river tile, try terraforming. */
1071 if (!IsTileFlat(tile) && !IsInclinedSlope(cur_slope)) {
1072 /* Don't try to terraform steep slopes. */
1073 if (IsSteepSlope(cur_slope)) return false;
1074
1075 bool flat_river_found = false;
1076 bool sloped_river_found = false;
1077
1078 /* There are two common possibilities:
1079 * 1. River flat, adjacent tile has one corner lowered.
1080 * 2. River descending, adjacent tile has either one or three corners raised.
1081 */
1082
1083 /* First, determine the desired slope based on adjacent river tiles. This doesn't necessarily match the origin tile for the CircularTileSearch. */
1084 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1085 TileIndex other_tile = TileAddByDiagDir(tile, d);
1086 Slope other_slope = GetTileSlope(other_tile);
1087
1088 /* Only consider river tiles. */
1089 if (IsWaterTile(other_tile) && IsRiver(other_tile)) {
1090 /* If the adjacent river tile flows downhill, we need to check where we are relative to the slope. */
1091 if (IsInclinedSlope(other_slope) && GetTileMaxZ(tile) == GetTileMaxZ(other_tile)) {
1092 /* Check for a parallel slope. If we don't find one, we're above or below the slope instead. */
1095 desired_slope = other_slope;
1096 sloped_river_found = true;
1097 break;
1098 }
1099 }
1100 /* If we find an adjacent river tile, remember it. We'll terraform to match it later if we don't find a slope. */
1101 if (IsTileFlat(other_tile)) flat_river_found = true;
1102 }
1103 }
1104 /* We didn't find either an inclined or flat river, so we're climbing the wrong slope. Bail out. */
1105 if (!sloped_river_found && !flat_river_found) return false;
1106
1107 /* We didn't find an inclined river, but there is a flat river. */
1108 if (!sloped_river_found && flat_river_found) desired_slope = SLOPE_FLAT;
1109
1110 /* Now that we know the desired slope, it's time to terraform! */
1111
1112 /* If the river is flat and the adjacent tile has one corner lowered, we want to raise it. */
1113 if (desired_slope == SLOPE_FLAT && IsSlopeWithThreeCornersRaised(cur_slope)) {
1114 /* Make sure we're not affecting an existing river slope tile. */
1115 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1116 TileIndex other_tile = TileAddByDiagDir(tile, d);
1117 if (IsInclinedSlope(GetTileSlope(other_tile)) && IsWaterTile(other_tile)) return false;
1118 }
1120
1121 /* If the river is descending and the adjacent tile has either one or three corners raised, we want to make it match the slope. */
1122 } else if (IsInclinedSlope(desired_slope)) {
1123 /* Don't break existing flat river tiles by terraforming under them. */
1124 DiagDirection river_direction = ReverseDiagDir(GetInclinedSlopeDirection(desired_slope));
1125
1126 for (DiagDirDiff d = DIAGDIRDIFF_BEGIN; d < DIAGDIRDIFF_END; d++) {
1127 /* We don't care about downstream or upstream tiles, just the riverbanks. */
1128 if (d == DIAGDIRDIFF_SAME || d == DIAGDIRDIFF_REVERSE) continue;
1129
1130 TileIndex other_tile = (TileAddByDiagDir(tile, ChangeDiagDir(river_direction, d)));
1131 if (IsWaterTile(other_tile) && IsRiver(other_tile) && IsTileFlat(other_tile)) return false;
1132 }
1133
1134 /* Get the corners which are different between the current and desired slope. */
1135 Slope to_change = cur_slope ^ desired_slope;
1136
1137 /* Lower unwanted corners first. If only one corner is raised, no corners need lowering. */
1138 if (!IsSlopeWithOneCornerRaised(cur_slope)) {
1139 to_change = to_change & ComplementSlope(desired_slope);
1140 Command<CMD_TERRAFORM_LAND>::Do(DC_EXEC | DC_AUTO, tile, to_change, false);
1141 }
1142
1143 /* Now check the match and raise any corners needed. */
1144 cur_slope = GetTileSlope(tile);
1145 if (cur_slope != desired_slope && IsSlopeWithOneCornerRaised(cur_slope)) {
1146 to_change = cur_slope ^ desired_slope;
1147 Command<CMD_TERRAFORM_LAND>::Do(DC_EXEC | DC_AUTO, tile, to_change, true);
1148 }
1149 }
1150 /* Update cur_slope after possibly terraforming. */
1151 cur_slope = GetTileSlope(tile);
1152 }
1153
1154 /* Sloped rivers need water both upstream and downstream. */
1155 if (IsInclinedSlope(cur_slope)) {
1156 DiagDirection slope_direction = GetInclinedSlopeDirection(cur_slope);
1157
1158 TileIndex upstream_tile = TileAddByDiagDir(tile, slope_direction);
1159 TileIndex downstream_tile = TileAddByDiagDir(tile, ReverseDiagDir(slope_direction));
1160
1161 /* Don't look outside the map. */
1162 if (!IsValidTile(upstream_tile) || !IsValidTile(downstream_tile)) return false;
1163
1164 /* Downstream might be new ocean created by our terraforming, and it hasn't flooded yet. */
1165 bool downstream_is_ocean = GetTileZ(downstream_tile) == 0 && (GetTileSlope(downstream_tile) == SLOPE_FLAT || IsSlopeWithOneCornerRaised(GetTileSlope(downstream_tile)));
1166
1167 /* If downstream is dry, flat, and not ocean, try making it a river tile. */
1168 if (!IsWaterTile(downstream_tile) && !downstream_is_ocean) {
1169 /* If the tile upstream isn't flat, don't bother. */
1170 if (GetTileSlope(downstream_tile) != SLOPE_FLAT) return false;
1171
1172 MakeRiverAndModifyDesertZoneAround(downstream_tile);
1173 }
1174
1175 /* If upstream is dry and flat, try making it a river tile. */
1176 if (!IsWaterTile(upstream_tile)) {
1177 /* If the tile upstream isn't flat, don't bother. */
1178 if (GetTileSlope(upstream_tile) != SLOPE_FLAT) return false;
1179
1181 }
1182 }
1183
1184 /* If the tile slope matches the desired slope, add a river tile. */
1185 if (cur_slope == desired_slope) {
1187 }
1188
1189 /* Always return false to keep searching. */
1190 return false;
1191}
1192
1199static bool FlowsDown(TileIndex begin, TileIndex end)
1200{
1201 assert(DistanceManhattan(begin, end) == 1);
1202
1203 auto [slopeBegin, heightBegin] = GetTileSlopeZ(begin);
1204 auto [slopeEnd, heightEnd] = GetTileSlopeZ(end);
1205
1206 return heightEnd <= heightBegin &&
1207 /* Slope either is inclined or flat; rivers don't support other slopes. */
1208 (slopeEnd == SLOPE_FLAT || IsInclinedSlope(slopeEnd)) &&
1209 /* Slope continues, then it must be lower... or either end must be flat. */
1210 ((slopeEnd == slopeBegin && heightEnd < heightBegin) || slopeEnd == SLOPE_FLAT || slopeBegin == SLOPE_FLAT);
1211}
1212
1218
1219/* AyStar callback for checking whether we reached our destination. */
1220static AyStarStatus River_EndNodeCheck(const AyStar *aystar, const PathNode *current)
1221{
1222 return current->GetTile() == *(TileIndex*)aystar->user_target ? AyStarStatus::FoundEndNode : AyStarStatus::Done;
1223}
1224
1225/* AyStar callback for getting the cost of the current node. */
1226static int32_t River_CalculateG(AyStar *, AyStarNode *, PathNode *)
1227{
1229}
1230
1231/* AyStar callback for getting the estimated cost to the destination. */
1232static int32_t River_CalculateH(AyStar *aystar, AyStarNode *current, PathNode *)
1233{
1234 return DistanceManhattan(*(TileIndex*)aystar->user_target, current->tile);
1235}
1236
1237/* AyStar callback for getting the neighbouring nodes of the given node. */
1238static void River_GetNeighbours(AyStar *aystar, PathNode *current)
1239{
1240 TileIndex tile = current->GetTile();
1241
1242 aystar->neighbours.clear();
1243 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1244 TileIndex t2 = tile + TileOffsByDiagDir(d);
1245 if (IsValidTile(t2) && FlowsDown(tile, t2)) {
1246 auto &neighbour = aystar->neighbours.emplace_back();
1247 neighbour.tile = t2;
1248 neighbour.td = INVALID_TRACKDIR;
1249 }
1250 }
1251}
1252
1253/* AyStar callback when an route has been found. */
1254static void River_FoundEndNode(AyStar *aystar, PathNode *current)
1255{
1256 River_UserData *data = (River_UserData *)aystar->user_data;
1257
1258 /* First, build the river without worrying about its width. */
1259 uint cur_pos = 0;
1260 for (PathNode *path = current->parent; path != nullptr; path = path->parent, cur_pos++) {
1261 TileIndex tile = path->GetTile();
1262 if (!IsWaterTile(tile)) {
1264 }
1265 }
1266
1267 /* If the river is a main river, go back along the path to widen it.
1268 * Don't make wide rivers if we're using the original landscape generator.
1269 */
1270 if (_settings_game.game_creation.land_generator != LG_ORIGINAL && data->main_river) {
1271 const uint long_river_length = _settings_game.game_creation.min_river_length * 4;
1272 uint current_river_length;
1273 uint radius;
1274
1275 cur_pos = 0;
1276 for (PathNode *path = current->parent; path != nullptr; path = path->parent, cur_pos++) {
1277 TileIndex tile = path->GetTile();
1278
1279 /* Check if we should widen river depending on how far we are away from the source. */
1280 current_river_length = DistanceManhattan(data->spring, tile);
1281 radius = std::min(3u, (current_river_length / (long_river_length / 3u)) + 1u);
1282
1283 if (radius > 1) CircularTileSearch(&tile, radius, RiverMakeWider, (void *)&path->key.tile);
1284 }
1285 }
1286}
1287
1295static void BuildRiver(TileIndex begin, TileIndex end, TileIndex spring, bool main_river)
1296{
1297 River_UserData user_data = { spring, main_river };
1298
1299 AyStar finder = {};
1300 finder.CalculateG = River_CalculateG;
1301 finder.CalculateH = River_CalculateH;
1302 finder.GetNeighbours = River_GetNeighbours;
1303 finder.EndNodeCheck = River_EndNodeCheck;
1304 finder.FoundEndNode = River_FoundEndNode;
1305 finder.user_target = &end;
1306 finder.user_data = &user_data;
1307
1308 AyStarNode start;
1309 start.tile = begin;
1310 start.td = INVALID_TRACKDIR;
1311 finder.AddStartNode(&start, 0);
1312 finder.Main();
1313}
1314
1322static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
1323{
1324# define SET_MARK(x) marks.insert(x)
1325# define IS_MARKED(x) (marks.find(x) != marks.end())
1326
1327 uint height = TileHeight(begin);
1328
1329 if (IsWaterTile(begin)) {
1330 return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 };
1331 }
1332
1333 std::set<TileIndex> marks;
1334 SET_MARK(begin);
1335
1336 /* Breadth first search for the closest tile we can flow down to. */
1337 std::list<TileIndex> queue;
1338 queue.push_back(begin);
1339
1340 bool found = false;
1341 uint count = 0; // Number of tiles considered; to be used for lake location guessing.
1342 TileIndex end;
1343 do {
1344 end = queue.front();
1345 queue.pop_front();
1346
1347 uint height2 = TileHeight(end);
1348 if (IsTileFlat(end) && (height2 < height || (height2 == height && IsWaterTile(end)))) {
1349 found = true;
1350 break;
1351 }
1352
1353 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
1354 TileIndex t2 = end + TileOffsByDiagDir(d);
1355 if (IsValidTile(t2) && !IS_MARKED(t2) && FlowsDown(end, t2)) {
1356 SET_MARK(t2);
1357 count++;
1358 queue.push_back(t2);
1359 }
1360 }
1361 } while (!queue.empty());
1362
1363 bool main_river = false;
1364 if (found) {
1365 /* Flow further down hill. */
1366 std::tie(found, main_river) = FlowRiver(spring, end, min_river_length);
1367 } else if (count > 32) {
1368 /* Maybe we can make a lake. Find the Nth of the considered tiles. */
1369 std::set<TileIndex>::const_iterator cit = marks.cbegin();
1370 std::advance(cit, RandomRange(count - 1));
1371 TileIndex lakeCenter = *cit;
1372
1373 if (IsValidTile(lakeCenter) &&
1374 /* A river, or lake, can only be built on flat slopes. */
1375 IsTileFlat(lakeCenter) &&
1376 /* We want the lake to be built at the height of the river. */
1377 TileHeight(begin) == TileHeight(lakeCenter) &&
1378 /* We don't want the lake at the entry of the valley. */
1379 lakeCenter != begin &&
1380 /* We don't want lakes in the desert. */
1381 (_settings_game.game_creation.landscape != LT_TROPIC || GetTropicZone(lakeCenter) != TROPICZONE_DESERT) &&
1382 /* We only want a lake if the river is long enough. */
1383 DistanceManhattan(spring, lakeCenter) > min_river_length) {
1384 end = lakeCenter;
1386 uint range = RandomRange(8) + 3;
1387 CircularTileSearch(&lakeCenter, range, MakeLake, &height);
1388 /* Call the search a second time so artefacts from going circular in one direction get (mostly) hidden. */
1389 lakeCenter = end;
1390 CircularTileSearch(&lakeCenter, range, MakeLake, &height);
1391 found = true;
1392 }
1393 }
1394
1395 marks.clear();
1396 if (found) BuildRiver(begin, end, spring, main_river);
1397 return { found, main_river };
1398}
1399
1403static void CreateRivers()
1404{
1406 if (amount == 0) return;
1407
1409 const uint num_short_rivers = wells - std::max(1u, wells / 10);
1410 SetGeneratingWorldProgress(GWP_RIVER, wells + TILE_UPDATE_FREQUENCY / 64); // Include the tile loop calls below.
1411
1412 /* Try to create long rivers. */
1413 for (; wells > num_short_rivers; wells--) {
1415 for (int tries = 0; tries < 512; 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 * 4))) break;
1419 }
1420 }
1421
1422 /* Try to create short rivers. */
1423 for (; wells != 0; wells--) {
1425 for (int tries = 0; tries < 128; tries++) {
1426 TileIndex t = RandomTile();
1427 if (!CircularTileSearch(&t, 8, FindSpring, nullptr)) continue;
1428 if (std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length))) break;
1429 }
1430 }
1431
1432 /* Widening rivers may have left some tiles requiring to be watered. */
1433 ConvertGroundTilesIntoWaterTiles();
1434
1435 /* Run tile loop to update the ground density. */
1436 for (uint i = 0; i != TILE_UPDATE_FREQUENCY; i++) {
1438 RunTileLoop();
1439 }
1440}
1441
1459static uint CalculateCoverageLine(uint coverage, uint edge_multiplier)
1460{
1461 const DiagDirection neighbour_dir[] = {
1462 DIAGDIR_NE,
1463 DIAGDIR_SE,
1464 DIAGDIR_SW,
1465 DIAGDIR_NW,
1466 };
1467
1468 /* Histogram of how many tiles per height level exist. */
1469 std::array<int, MAX_TILE_HEIGHT + 1> histogram = {};
1470 /* Histogram of how many neighbour tiles are lower than the tiles of the height level. */
1471 std::array<int, MAX_TILE_HEIGHT + 1> edge_histogram = {};
1472
1473 /* Build a histogram of the map height. */
1474 for (const auto tile : Map::Iterate()) {
1475 uint h = TileHeight(tile);
1476 histogram[h]++;
1477
1478 if (edge_multiplier != 0) {
1479 /* Check if any of our neighbours is below us. */
1480 for (auto dir : neighbour_dir) {
1481 TileIndex neighbour_tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDiagDir(dir));
1482 if (IsValidTile(neighbour_tile) && TileHeight(neighbour_tile) < h) {
1483 edge_histogram[h]++;
1484 }
1485 }
1486 }
1487 }
1488
1489 /* The amount of land we have is the map size minus the first (sea) layer. */
1490 uint land_tiles = Map::Size() - histogram[0];
1491 int best_score = land_tiles;
1492
1493 /* Our goal is the coverage amount of the land-mass. */
1494 int goal_tiles = land_tiles * coverage / 100;
1495
1496 /* We scan from top to bottom. */
1497 uint h = MAX_TILE_HEIGHT;
1498 uint best_h = h;
1499
1500 int current_tiles = 0;
1501 for (; h > 0; h--) {
1502 current_tiles += histogram[h];
1503 int current_score = goal_tiles - current_tiles;
1504
1505 /* Tropic grows from water and mountains into the desert. This is a
1506 * great visual, but it also means we* need to take into account how
1507 * much less desert tiles are being created if we are on this
1508 * height-level. We estimate this based on how many neighbouring
1509 * tiles are below us for a given length, assuming that is where
1510 * tropic is growing from.
1511 */
1512 if (edge_multiplier != 0 && h > 1) {
1513 /* From water tropic tiles grow for a few tiles land inward. */
1514 current_score -= edge_histogram[1] * edge_multiplier;
1515 /* Tropic tiles grow into the desert for a few tiles. */
1516 current_score -= edge_histogram[h] * edge_multiplier;
1517 }
1518
1519 if (std::abs(current_score) < std::abs(best_score)) {
1520 best_score = current_score;
1521 best_h = h;
1522 }
1523
1524 /* Always scan all height-levels, as h == 1 might give a better
1525 * score than any before. This is true for example with 0% desert
1526 * coverage. */
1527 }
1528
1529 return best_h;
1530}
1531
1536{
1537 /* We do not have snow sprites on coastal tiles, so never allow "1" as height. */
1539}
1540
1545static uint8_t CalculateDesertLine()
1546{
1547 /* CalculateCoverageLine() runs from top to bottom, so we need to invert the coverage. */
1549}
1550
1551bool GenerateLandscape(uint8_t mode)
1552{
1553 /* Number of steps of landscape generation */
1554 static constexpr uint GLS_HEIGHTMAP = 3;
1555 static constexpr uint GLS_TERRAGENESIS = 5;
1556 static constexpr uint GLS_ORIGINAL = 2;
1557 static constexpr uint GLS_TROPIC = 12;
1558 static constexpr uint GLS_OTHER = 0;
1559 uint steps = (_settings_game.game_creation.landscape == LT_TROPIC) ? GLS_TROPIC : GLS_OTHER;
1560
1561 if (mode == GWM_HEIGHTMAP) {
1562 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_HEIGHTMAP);
1564 return false;
1565 }
1568 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_TERRAGENESIS);
1570 } else {
1571 SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_ORIGINAL);
1573 for (uint x = 0; x < Map::SizeX(); x++) MakeVoid(TileXY(x, 0));
1574 for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(0, y));
1575 }
1577 case LT_ARCTIC: {
1578 uint32_t r = Random();
1579
1580 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 950); i != 0; --i) {
1581 GenerateTerrain(2, 0);
1582 }
1583
1584 uint flag = GB(r, 7, 2) | 4;
1585 for (uint i = Map::ScaleBySize(GB(r, 9, 7) + 450); i != 0; --i) {
1586 GenerateTerrain(4, flag);
1587 }
1588 break;
1589 }
1590
1591 case LT_TROPIC: {
1592 uint32_t r = Random();
1593
1594 for (uint i = Map::ScaleBySize(GB(r, 0, 7) + 170); i != 0; --i) {
1595 GenerateTerrain(0, 0);
1596 }
1597
1598 uint flag = GB(r, 7, 2) | 4;
1599 for (uint i = Map::ScaleBySize(GB(r, 9, 8) + 1700); i != 0; --i) {
1600 GenerateTerrain(0, flag);
1601 }
1602
1603 flag ^= 2;
1604
1605 for (uint i = Map::ScaleBySize(GB(r, 17, 7) + 410); i != 0; --i) {
1606 GenerateTerrain(3, flag);
1607 }
1608 break;
1609 }
1610
1611 default: {
1612 uint32_t r = Random();
1613
1615 uint i = Map::ScaleBySize(GB(r, 0, 7) + (3 - _settings_game.difficulty.quantity_sea_lakes) * 256 + 100);
1616 for (; i != 0; --i) {
1617 /* Make sure we do not overflow. */
1618 GenerateTerrain(Clamp(_settings_game.difficulty.terrain_type, 0, 3), 0);
1619 }
1620 break;
1621 }
1622 }
1623 }
1624
1625 /* Do not call IncreaseGeneratingWorldProgress() before FixSlopes(),
1626 * it allows screen redraw. Drawing of broken slopes crashes the game */
1627 FixSlopes();
1630
1631 ConvertGroundTilesIntoWaterTiles();
1634
1636 case LT_ARCTIC:
1638 break;
1639
1640 case LT_TROPIC: {
1641 uint desert_tropic_line = CalculateDesertLine();
1642 CreateDesertOrRainForest(desert_tropic_line);
1643 break;
1644 }
1645
1646 default:
1647 break;
1648 }
1649
1650 CreateRivers();
1651 return true;
1652}
1653
1654void OnTick_Town();
1655void OnTick_Trees();
1656void OnTick_Station();
1657void OnTick_Industry();
1658
1659void OnTick_Companies();
1660void OnTick_LinkGraph();
1661
1662void CallLandscapeTick()
1663{
1664 {
1666
1667 OnTick_Town();
1668 OnTick_Trees();
1669 OnTick_Station();
1670 OnTick_Industry();
1671 }
1672
1675}
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:31
@ 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.
@ 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.
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.
@ 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 rain forests.
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:67
Functions related to world/map generation.
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
@ GWM_HEIGHTMAP
Generate a newgame from a heightmap.
Definition genworld.h:31
static const uint CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY
Value for custom sea level in difficulty settings.
Definition genworld.h:47
@ GWP_LANDSCAPE
Create the landscape.
Definition genworld.h:71
@ GWP_RIVER
Create the rivers.
Definition genworld.h:72
void SetGeneratingWorldProgress(GenWorldProgress cls, uint total)
Set the total of a stage of the world generation.
@ LG_ORIGINAL
The original landscape generator.
Definition genworld.h:20
@ LG_TERRAGENESIS
TerraGenesis Perlin landscape generator.
Definition genworld.h:21
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:18
@ MapGen
Special sprite for the map generator.
void SetSnowLine(uint8_t table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
Set a variable snow line, as loaded from a newgrf file.
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.
static SnowLine * _snow_line
Description of the snow line throughout the year.
Definition landscape.cpp:96
bool IsSnowLineSet()
Has a snow line table already been loaded.
void ClearSnowLine()
Clear the variable snow line table and free the memory.
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.
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.
static bool RiverMakeWider(TileIndex tile, void *data)
Widen a river by expanding into adjacent tiles via circular tile search.
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:928
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
static const uint SNOW_LINE_DAYS
Number of days in each month in the snow line table.
Definition landscape.h:17
Point InverseRemapCoords(int x, int y)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
Definition landscape.h:109
static const uint SNOW_LINE_MONTHS
Number of months in the snow line table.
Definition landscape.h:16
Command definitions related to landscape (slopes etc.).
Types related to the landscape.
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:247
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:97
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:146
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:467
TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
Add a TileIndexDiffC to a TileIndex and returns the new one.
Definition map_func.h:512
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:608
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:480
#define RandomTile()
Get a valid random tile.
Definition map_func.h:661
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:567
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:60
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
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
Corner
Enumeration of tile corners.
Definition slope_type.h:22
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.
void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition stdafx.h:334
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:280
AyStar search algorithm struct.
Definition aystar.h:103
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:412
std::string name
Name of the file.
Definition saveload.h:414
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
uint8_t snow_line_height
the configured snow line height (deduced from "snow_coverage")
uint8_t land_generator
the landscape generator
uint8_t landscape
the landscape we're currently in
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.
Structure describing the height of the snow line each day of the year.
Definition landscape.h:23
uint8_t highest_value
Highest snow line of the year.
Definition landscape.h:25
uint8_t lowest_value
Lowest snow line of the year.
Definition landscape.h:26
uint8_t table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS]
Height of the snow line each day of the year.
Definition landscape.h:24
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:976
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
@ 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
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
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.