OpenTTD Source  20241124-master-g9399a92a4f
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"
25 #include "timer/timer_game_tick.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 
47 extern 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 
65 const 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 
80 extern 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 
85 static const uint TILE_UPDATE_FREQUENCY_LOG = 8;
87 
96 static SnowLine *_snow_line = nullptr;
97 
111 Point 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 
185  if (IsSpecialRailFoundation(f)) {
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 
228 uint 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 
303 int 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 
318 int GetSlopePixelZOutsideMap(int x, int y)
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 
336 int GetSlopeZInCorner(Slope tileh, Corner corner)
337 {
338  assert(!IsHalftileSlope(tileh));
339  return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? 1 : 0) + (tileh == SteepSlope(corner) ? 1 : 0);
340 }
341 
354 void 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 
382 std::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 
391 bool 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 
406 bool 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)) {
450  if (!IsNonContinuousFoundation(f)) {
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,
465  f == FOUNDATION_INCLINED_X ? TILE_SIZE : 1,
466  f == FOUNDATION_INCLINED_Y ? TILE_SIZE : 1,
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 */
508  spr = leveled_base + SlopeWithThreeCornersRaised(GetRailFoundationCorner(f));
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,
520  f == FOUNDATION_INCLINED_X ? TILE_SIZE : 1,
521  f == FOUNDATION_INCLINED_Y ? TILE_SIZE : 1,
522  TILE_HEIGHT, ti->z
523  );
524  OffsetGroundSprite(0, 0);
525  }
526  ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
527  }
528 }
529 
530 void DoClearSquare(TileIndex tile)
531 {
532  /* If the tile can have animation and we clear it, delete it from the animated tile list. */
533  if (_tile_type_procs[GetTileType(tile)]->animate_tile_proc != nullptr) DeleteAnimatedTile(tile);
534 
535  bool remove = IsDockingTile(tile);
536  MakeClear(tile, CLEAR_GRASS, _generating_world ? 3 : 0);
537  MarkTileDirtyByTile(tile);
538  if (remove) RemoveDockingTile(tile);
539 
541  InvalidateWaterRegion(tile);
542 }
543 
554 TrackStatus 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 
565 void 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 
570 void 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 
609 uint8_t GetSnowLine()
610 {
612 
613  TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
614  return _snow_line->table[ymd.month][ymd.day];
615 }
616 
623 {
625 }
626 
632 uint8_t LowestSnowLine()
633 {
635 }
636 
642 {
643  free(_snow_line);
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_cmd_error(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_cmd_error(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_cmd_error(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 
711 std::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 
764 TileIndex _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 
809 void 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);
816  ClearBridgeMiddle(TileXY(x, y));
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 
824 static const uint8_t _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 };
825 static const uint8_t _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
826 
827 static 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 
949 static void CreateDesertOrRainForest(uint desert_tropic_line)
950 {
951  uint update_freq = Map::Size() / 4;
952 
953  for (TileIndex tile = 0; tile != Map::Size(); ++tile) {
954  if ((tile.base() % 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 (TileIndex tile = 0; tile != Map::Size(); ++tile) {
974  if ((tile.base() % 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 
993 static 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 
1029 static 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 
1052 static 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 
1180  MakeRiverAndModifyDesertZoneAround(upstream_tile);
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 
1199 static 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 
1216  bool main_river;
1217 };
1218 
1219 /* AyStar callback for checking whether we reached our destination. */
1220 static int32_t River_EndNodeCheck(const AyStar *aystar, const PathNode *current)
1221 {
1222  return current->GetTile() == *(TileIndex*)aystar->user_target ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
1223 }
1224 
1225 /* AyStar callback for getting the cost of the current node. */
1226 static int32_t River_CalculateG(AyStar *, AyStarNode *, PathNode *)
1227 {
1229 }
1230 
1231 /* AyStar callback for getting the estimated cost to the destination. */
1232 static 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. */
1238 static 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. */
1254 static 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  */
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 
1295 static 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 
1322 static 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 
1403 static 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++) {
1437  if (i % 64 == 0) IncreaseGeneratingWorldProgress(GWP_RIVER);
1438  RunTileLoop();
1439  }
1440 }
1441 
1459 static 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 (TileIndex tile = 0; tile < Map::Size(); tile++) {
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 
1535 static void CalculateSnowLine()
1536 {
1537  /* We do not have snow sprites on coastal tiles, so never allow "1" as height. */
1539 }
1540 
1545 static uint8_t CalculateDesertLine()
1546 {
1547  /* CalculateCoverageLine() runs from top to bottom, so we need to invert the coverage. */
1549 }
1550 
1551 bool 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 
1654 void OnTick_Town();
1655 void OnTick_Trees();
1656 void OnTick_Station();
1657 void OnTick_Industry();
1658 
1659 void OnTick_Companies();
1660 void OnTick_LinkGraph();
1661 
1662 void CallLandscapeTick()
1663 {
1664  {
1666 
1667  OnTick_Town();
1668  OnTick_Trees();
1669  OnTick_Station();
1670  OnTick_Industry();
1671  }
1672 
1673  OnTick_Companies();
1674  OnTick_LinkGraph();
1675 }
void DeleteAnimatedTile(TileIndex tile)
Removes the given tile from the animated tile table.
Tile animation!
This file has the header for AyStar.
@ AYSTAR_DONE
Not an end-tile, or wrong direction.
Definition: aystar.h:37
@ AYSTAR_FOUND_END_NODE
An end node was found.
Definition: aystar.h:32
constexpr static debug_inline 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.
Definition: command_type.h:23
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:63
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
bool Failed() const
Did this command fail?
Definition: command_type.h:171
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.
Definition: command_func.h:28
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:38
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_AUTO
don't allow building on structures
Definition: command_type.h:377
@ DC_FORCE_CLEAR_TILE
do not only remove the object on the tile, but also clear any water left on it
Definition: command_type.h:387
@ DC_NO_WATER
don't allow building on water
Definition: command_type.h:379
@ DC_BANKRUPT
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:382
@ DC_EXEC
execute the given command
Definition: command_type.h:376
Money GetAvailableMoneyForCommand()
This functions returns the money which can be used to execute a command.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
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.
Definition: company_type.h:18
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.
Definition: economy_type.h:173
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.
Definition: landscape.cpp:590
uint8_t LowestSnowLine()
Get the lowest possible snow line height, either variable or static.
Definition: landscape.cpp:632
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
Definition: landscape.cpp:609
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.
Definition: landscape.cpp:580
void ClearSnowLine()
Clear the variable snow line table and free the memory.
Definition: landscape.cpp:641
uint8_t HighestSnowLine()
Get the highest possible snow line height, either variable or static.
Definition: landscape.cpp:622
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.
Definition: viewport.cpp:2057
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...
Definition: heightmap.cpp:500
void FixSlopes()
This function takes care of the fact that land in OpenTTD can never differ more than 1 in height.
Definition: heightmap.cpp:399
Functions related to creating heightmaps from files.
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Definition: landscape.cpp:228
int GetSlopePixelZOutsideMap(int x, int y)
Return world z coordinate of a given point of a tile, also for tiles outside the map (virtual "black"...
Definition: landscape.cpp:318
static bool FlowsDown(TileIndex begin, TileIndex end)
Check whether a river at begin could (logically) flow down to end.
Definition: landscape.cpp:1199
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:554
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.
Definition: landscape.cpp:1459
static void CalculateSnowLine()
Calculate the line from which snow begins.
Definition: landscape.cpp:1535
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.
Definition: landscape.cpp:653
static bool FindSpring(TileIndex tile, void *)
Find the spring of a river.
Definition: landscape.cpp:993
void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
Change the owner of a tile.
Definition: landscape.cpp:565
void RunTileLoop()
Gradually iterate over all tiles on the map, calling their TileLoopProcs once every TILE_UPDATE_FREQU...
Definition: landscape.cpp:769
static void CreateRivers()
Actually (try to) create some rivers.
Definition: landscape.cpp:1403
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
Definition: landscape.cpp:425
int GetSlopeZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
Definition: landscape.cpp:336
static void BuildRiver(TileIndex begin, TileIndex end, TileIndex spring, bool main_river)
Actually build the river between the begin and end tiles using AyStar.
Definition: landscape.cpp:1295
void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int &z1, int &z2)
Determine the Z height of the corners of a specific tile edge.
Definition: landscape.cpp:354
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.
Definition: landscape.cpp:111
std::tuple< Slope, int > GetFoundationSlope(TileIndex tile)
Get slope of a tile on top of a (possible) foundation If a tile does not have a foundation,...
Definition: landscape.cpp:382
static bool RiverMakeWider(TileIndex tile, void *data)
Widen a river by expanding into adjacent tiles via circular tile search.
Definition: landscape.cpp:1052
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.
Definition: landscape.cpp:1029
void OnTick_Town()
Iterate through all towns and call their tick handler.
Definition: town_cmd.cpp:901
static uint8_t CalculateDesertLine()
Calculate the line (in height) between desert and tropic.
Definition: landscape.cpp:1545
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.
Definition: landscape.cpp:170
std::tuple< CommandCost, Money > CmdClearArea(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, bool diagonal)
Clear a big piece of landscape.
Definition: landscape.cpp:711
static std::tuple< bool, bool > FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
Try to flow the river down from a given begin.
Definition: landscape.cpp:1322
bool GenerateLandscape(uint8_t mode)
Definition: landscape.cpp:1551
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.
Definition: landscape.cpp:303
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.
Definition: math_func.hpp:252
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:23
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition: math_func.hpp:320
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.
Definition: math_func.hpp:283
Base for all objects.
ClearedObjectArea * FindClearedObject(TileIndex tile)
Find the entry in _cleared_object_areas which occupies a certain tile.
Definition: object_cmd.cpp:531
@ 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.
Definition: random_func.hpp:88
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
void AddStartNode(AyStarNode *start_node, int g)
Adds a node from where to start an algorithm.
Definition: aystar.cpp:168
int Main()
This is the function you call to run AyStar.
Definition: aystar.cpp:137
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).
Definition: company_base.h:104
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:410
std::string name
Name of the file.
Definition: saveload.h:412
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)
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 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 Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
Parameters for river generation to pass as AyStar user data.
Definition: landscape.cpp:1214
TileIndex spring
The current spring during river generation.
Definition: landscape.cpp:1215
bool main_river
Whether the current river is a big river that others flow into.
Definition: landscape.cpp:1216
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 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.
Definition: water_cmd.cpp:454
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.