OpenTTD Source 20250522-master-g467f832c2f
clear_cmd.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
10#include "stdafx.h"
11#include "clear_map.h"
12#include "command_func.h"
13#include "landscape.h"
14#include "genworld.h"
15#include "viewport_func.h"
16#include "core/random_func.hpp"
17#include "newgrf_generic.h"
18#include "landscape_cmd.h"
19
20#include "table/strings.h"
21#include "table/sprites.h"
22#include "table/clear_land.h"
23
24#include "safeguards.h"
25
26static CommandCost ClearTile_Clear(TileIndex tile, DoCommandFlags flags)
27{
28 static constexpr Price clear_price_table[] = {
29 PR_CLEAR_GRASS,
30 PR_CLEAR_ROUGH,
31 PR_CLEAR_ROCKS,
32 PR_CLEAR_FIELDS,
33 PR_CLEAR_ROUGH,
34 PR_CLEAR_ROUGH,
35 };
37
38 ClearGround ground = GetClearGround(tile);
39 uint8_t density = GetClearDensity(tile);
40 if (IsSnowTile(tile)) {
41 price.AddCost(_price[clear_price_table[ground]]);
42 /* Add a little more for removing snow. */
43 price.AddCost(std::abs(_price[PR_CLEAR_ROUGH] - _price[PR_CLEAR_GRASS]));
44 } else if (ground != CLEAR_GRASS || density != 0) {
45 price.AddCost(_price[clear_price_table[ground]]);
46 }
47
48 if (flags.Test(DoCommandFlag::Execute)) DoClearSquare(tile);
49
50 return price;
51}
52
53void DrawClearLandTile(const TileInfo *ti, uint8_t set)
54{
55 DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh) + set * 19, PAL_NONE);
56}
57
58void DrawHillyLandTile(const TileInfo *ti)
59{
60 if (ti->tileh != SLOPE_FLAT) {
61 DrawGroundSprite(SPR_FLAT_ROUGH_LAND + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
62 } else {
63 DrawGroundSprite(_landscape_clear_sprites_rough[GB(TileHash(ti->x, ti->y), 0, 3)], PAL_NONE);
64 }
65}
66
67static void DrawClearLandFence(const TileInfo *ti)
68{
69 /* combine fences into one sprite object */
71
72 int maxz = GetSlopeMaxPixelZ(ti->tileh);
73
74 uint fence_nw = GetFence(ti->tile, DIAGDIR_NW);
75 if (fence_nw != 0) {
76 int z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
77 SpriteID sprite = _clear_land_fence_sprites[fence_nw - 1] + _fence_mod_by_tileh_nw[ti->tileh];
78 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y - 16, 16, 32, maxz - z + 4, ti->z + z, false, 0, 16, -z);
79 }
80
81 uint fence_ne = GetFence(ti->tile, DIAGDIR_NE);
82 if (fence_ne != 0) {
83 int z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
84 SpriteID sprite = _clear_land_fence_sprites[fence_ne - 1] + _fence_mod_by_tileh_ne[ti->tileh];
85 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x - 16, ti->y, 32, 16, maxz - z + 4, ti->z + z, false, 16, 0, -z);
86 }
87
88 uint fence_sw = GetFence(ti->tile, DIAGDIR_SW);
89 uint fence_se = GetFence(ti->tile, DIAGDIR_SE);
90
91 if (fence_sw != 0 || fence_se != 0) {
92 int z = GetSlopePixelZInCorner(ti->tileh, CORNER_S);
93
94 if (fence_sw != 0) {
95 SpriteID sprite = _clear_land_fence_sprites[fence_sw - 1] + _fence_mod_by_tileh_sw[ti->tileh];
96 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
97 }
98
99 if (fence_se != 0) {
100 SpriteID sprite = _clear_land_fence_sprites[fence_se - 1] + _fence_mod_by_tileh_se[ti->tileh];
101 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
102 }
103 }
105}
106
107static void DrawTile_Clear(TileInfo *ti)
108{
109 ClearGround real_ground = GetClearGround(ti->tile);
110 ClearGround ground = IsSnowTile(ti->tile) ? CLEAR_SNOW : real_ground;
111
112 switch (ground) {
113 case CLEAR_GRASS:
114 DrawClearLandTile(ti, GetClearDensity(ti->tile));
115 break;
116
117 case CLEAR_ROUGH:
118 DrawHillyLandTile(ti);
119 break;
120
121 case CLEAR_ROCKS:
122 DrawGroundSprite((HasGrfMiscBit(GrfMiscBit::SecondRockyTileSet) && (TileHash(ti->x, ti->y) & 1) ? SPR_FLAT_ROCKY_LAND_2 : SPR_FLAT_ROCKY_LAND_1) + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
123 break;
124
125 case CLEAR_FIELDS:
126 DrawGroundSprite(_clear_land_sprites_farmland[GetFieldType(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
127 DrawClearLandFence(ti);
128 break;
129
130 case CLEAR_SNOW: {
131 uint8_t density = GetClearDensity(ti->tile);
132 DrawGroundSprite(_clear_land_sprites_snow_desert[density] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
133 if (real_ground == CLEAR_ROCKS) {
134 /* There 4 levels of snowy overlay rocks, each with 19 sprites. */
135 ++density;
136 DrawGroundSprite(SPR_OVERLAY_ROCKS_BASE + (density * 19) + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
137 }
138 break;
139 }
140
141 case CLEAR_DESERT:
142 DrawGroundSprite(_clear_land_sprites_snow_desert[GetClearDensity(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
143 break;
144 }
145
147}
148
149static int GetSlopePixelZ_Clear(TileIndex tile, uint x, uint y, bool)
150{
151 auto [tileh, z] = GetTilePixelSlope(tile);
152
153 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
154}
155
156static Foundation GetFoundation_Clear(TileIndex, Slope)
157{
158 return FOUNDATION_NONE;
159}
160
161static void UpdateFences(TileIndex tile)
162{
163 assert(IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
164 bool dirty = false;
165
166 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
167 if (GetFence(tile, dir) != 0) continue;
168 TileIndex neighbour = tile + TileOffsByDiagDir(dir);
169 if (IsTileType(neighbour, MP_CLEAR) && IsClearGround(neighbour, CLEAR_FIELDS)) continue;
170 SetFence(tile, dir, 3);
171 dirty = true;
172 }
173
174 if (dirty) MarkTileDirtyByTile(tile);
175}
176
177
180{
181 int k = GetTileZ(tile) - GetSnowLine() + 1;
182
183 if (!IsSnowTile(tile)) {
184 /* Below the snow line, do nothing if no snow. */
185 /* At or above the snow line, make snow tile if needed. */
186 if (k >= 0) {
187 /* Snow density is started at 0 so that it can gradually reach the required density. */
188 MakeSnow(tile, 0);
190 }
191 return;
192 }
193
194 /* Update snow density. */
195 uint current_density = GetClearDensity(tile);
196 uint req_density = (k < 0) ? 0u : std::min<uint>(k, 3u);
197
198 if (current_density == req_density) {
199 /* Density at the required level. */
200 if (k >= 0) return;
201 ClearSnow(tile);
202 } else {
203 AddClearDensity(tile, current_density < req_density ? 1 : -1);
204 }
205
207}
208
214static inline bool NeighbourIsNormal(TileIndex tile)
215{
216 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
217 TileIndex t = tile + TileOffsByDiagDir(dir);
218 if (!IsValidTile(t)) continue;
219 if (GetTropicZone(t) != TROPICZONE_DESERT) return true;
220 if (HasTileWaterClass(t) && GetWaterClass(t) == WATER_CLASS_SEA) return true;
221 }
222 return false;
223}
224
225static void TileLoopClearDesert(TileIndex tile)
226{
227 /* Current desert level - 0 if it is not desert */
228 uint current = 0;
229 if (IsClearGround(tile, CLEAR_DESERT)) current = GetClearDensity(tile);
230
231 /* Expected desert level - 0 if it shouldn't be desert */
232 uint expected = 0;
233 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
234 expected = NeighbourIsNormal(tile) ? 1 : 3;
235 }
236
237 if (current == expected) return;
238
239 if (expected == 0) {
241 } else {
242 /* Transition from clear to desert is not smooth (after clearing desert tile) */
243 SetClearGroundDensity(tile, CLEAR_DESERT, expected);
244 }
245
247}
248
249static void TileLoop_Clear(TileIndex tile)
250{
251 AmbientSoundEffect(tile);
252
254 case LandscapeType::Tropic: TileLoopClearDesert(tile); break;
255 case LandscapeType::Arctic: TileLoopClearAlps(tile); break;
256 default: break;
257 }
258
259 if (IsSnowTile(tile)) return;
260
261 switch (GetClearGround(tile)) {
262 case CLEAR_GRASS:
263 if (GetClearDensity(tile) == 3) return;
264
265 if (_game_mode != GM_EDITOR) {
266 if (GetClearCounter(tile) < 7) {
267 AddClearCounter(tile, 1);
268 return;
269 } else {
270 SetClearCounter(tile, 0);
271 AddClearDensity(tile, 1);
272 }
273 } else {
274 SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
275 }
276 break;
277
278 case CLEAR_FIELDS:
279 UpdateFences(tile);
280
281 if (_game_mode == GM_EDITOR) return;
282
283 if (GetClearCounter(tile) < 7) {
284 AddClearCounter(tile, 1);
285 return;
286 } else {
287 SetClearCounter(tile, 0);
288 }
289
290 if (GetIndustryIndexOfField(tile) == IndustryID::Invalid() && GetFieldType(tile) >= 7) {
291 /* This farmfield is no longer farmfield, so make it grass again */
292 MakeClear(tile, CLEAR_GRASS, 2);
293 } else {
294 uint field_type = GetFieldType(tile);
295 field_type = (field_type < 8) ? field_type + 1 : 0;
296 SetFieldType(tile, field_type);
297 }
298 break;
299
300 default:
301 return;
302 }
303
305}
306
307void GenerateClearTile()
308{
309 uint i, gi;
310 TileIndex tile;
311
312 /* add rough tiles */
313 i = Map::ScaleBySize(GB(Random(), 0, 10) + 0x400);
314 gi = Map::ScaleBySize(GB(Random(), 0, 7) + 0x80);
315
317 do {
319 tile = RandomTile();
321 } while (--i);
322
323 /* add rocky tiles */
324 i = gi;
325 do {
326 uint32_t r = Random();
327 tile = RandomTileSeed(r);
328
330 if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
331 uint j = GB(r, 16, 4) + 5;
332 for (;;) {
333 TileIndex tile_new;
334
337 do {
338 if (--j == 0) goto get_out;
339 tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
340 } while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
341 tile = tile_new;
342 }
343get_out:;
344 }
345 } while (--i);
346}
347
348static TrackStatus GetTileTrackStatus_Clear(TileIndex, TransportType, uint, DiagDirection)
349{
350 return 0;
351}
352
353static void GetTileDesc_Clear(TileIndex tile, TileDesc &td)
354{
355 /* Each pair holds a normal and a snowy ClearGround description. */
356 static constexpr std::pair<StringID, StringID> clear_land_str[] = {
357 {STR_LAI_CLEAR_DESCRIPTION_GRASS, STR_LAI_CLEAR_DESCRIPTION_SNOWY_GRASS},
358 {STR_LAI_CLEAR_DESCRIPTION_ROUGH_LAND, STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROUGH_LAND},
359 {STR_LAI_CLEAR_DESCRIPTION_ROCKS, STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROCKS},
360 {STR_LAI_CLEAR_DESCRIPTION_FIELDS, STR_EMPTY},
361 {STR_EMPTY, STR_EMPTY}, // CLEAR_SNOW does not appear in the map.
362 {STR_LAI_CLEAR_DESCRIPTION_DESERT, STR_EMPTY},
363 };
364
365 if (!IsSnowTile(tile) && IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
366 td.str = STR_LAI_CLEAR_DESCRIPTION_BARE_LAND;
367 } else {
368 const auto &[name, snowy_name] = clear_land_str[GetClearGround(tile)];
369 td.str = IsSnowTile(tile) ? snowy_name : name;
370 }
371 td.owner[0] = GetTileOwner(tile);
372}
373
374static void ChangeTileOwner_Clear(TileIndex, Owner, Owner)
375{
376 return;
377}
378
379static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlags flags, int, Slope)
380{
381 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
382}
383
384extern const TileTypeProcs _tile_type_clear_procs = {
385 DrawTile_Clear,
386 GetSlopePixelZ_Clear,
387 ClearTile_Clear,
388 nullptr,
389 GetTileDesc_Clear,
390 GetTileTrackStatus_Clear,
391 nullptr,
392 nullptr,
393 TileLoop_Clear,
394 ChangeTileOwner_Clear,
395 nullptr,
396 nullptr,
397 GetFoundation_Clear,
398 TerraformTile_Clear,
399};
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 DrawBridgeMiddle(const TileInfo *ti)
Draw the middle bits of a bridge.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Common return value for all commands.
Enum-as-bit-set wrapper.
static bool NeighbourIsNormal(TileIndex tile)
Tests if at least one surrounding tile is non-desert.
static void TileLoopClearAlps(TileIndex tile)
Convert to or from snowy tiles.
Tables with sprites for clear land and fences.
Map accessors for 'clear' tiles.
void SetFieldType(Tile t, uint f)
Set the field type (production stage) of the field.
Definition clear_map.h:171
void AddClearCounter(Tile t, int c)
Increments the counter used to advance to the next clear density/field type.
Definition clear_map.h:120
uint GetFieldType(Tile t)
Get the field type (production stage) of the field.
Definition clear_map.h:159
void AddClearDensity(Tile t, int d)
Increment the density of a non-field clear tile.
Definition clear_map.h:83
void ClearSnow(Tile t)
Clear the snow from a tile and return it to its previous type.
Definition clear_map.h:304
bool IsClearGround(Tile t, ClearGround ct)
Set the type of clear tile.
Definition clear_map.h:59
void MakeSnow(Tile t, uint density=0)
Make a snow tile.
Definition clear_map.h:288
void SetFence(Tile t, DiagDirection side, uint h)
Sets the type of fence (and whether there is one) for the given border.
Definition clear_map.h:228
IndustryID GetIndustryIndexOfField(Tile t)
Get the industry (farm) that made the field.
Definition clear_map.h:183
ClearGround
Ground types.
Definition clear_map.h:19
@ CLEAR_GRASS
0-3
Definition clear_map.h:20
@ CLEAR_FIELDS
3
Definition clear_map.h:23
@ CLEAR_DESERT
1,3
Definition clear_map.h:25
@ CLEAR_SNOW
0-3 (Not stored in map.)
Definition clear_map.h:24
@ CLEAR_ROUGH
3
Definition clear_map.h:21
@ CLEAR_ROCKS
3
Definition clear_map.h:22
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition clear_map.h:247
ClearGround GetClearGround(Tile t)
Get the type of clear tile.
Definition clear_map.h:47
void SetClearCounter(Tile t, uint c)
Sets the counter used to advance to the next clear density/field type.
Definition clear_map.h:132
void SetClearGroundDensity(Tile t, ClearGround type, uint density)
Sets ground type and density in one go, also sets the counter to 0.
Definition clear_map.h:146
uint GetFence(Tile t, DiagDirection side)
Is there a fence at the given border?
Definition clear_map.h:209
uint GetClearCounter(Tile t)
Get the counter used to advance to the next clear density/field type.
Definition clear_map.h:108
bool IsSnowTile(Tile t)
Test if a tile is covered with snow.
Definition clear_map.h:35
uint GetClearDensity(Tile t)
Get the density of a non-field clear tile.
Definition clear_map.h:71
Functions related to commands.
@ Execute
execute the given command
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_END
Used for iterations.
@ DIAGDIR_BEGIN
Used for iterations.
@ DIAGDIR_SW
Southwest.
@ EXPENSES_CONSTRUCTION
Construction costs.
Price
Enumeration of all base prices for use with Prices.
Functions related to world/map generation.
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
@ GWP_ROUGH_ROCKY
Make rough and rocky areas.
Definition genworld.h:65
void SetGeneratingWorldProgress(GenWorldProgress cls, uint total)
Set the total of a stage of the world generation.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Functions related to OTTD's landscape.
int GetSlopePixelZInCorner(Slope tileh, Corner corner)
Determine the Z height of a corner relative to TileZ.
Definition landscape.h:53
Command definitions related to landscape (slopes etc.).
@ Random
Randomise borders.
TileIndex RandomTileSeed(uint32_t r)
Get a random tile out of a given seed.
Definition map_func.h:640
#define RandomTile()
Get a valid random tile.
Definition map_func.h:651
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:569
bool HasGrfMiscBit(GrfMiscBit bit)
Check for grf miscellaneous bits.
Definition newgrf.h:210
Functions related to generic callbacks.
void AmbientSoundEffect(TileIndex tile)
Play an ambient sound effect for an empty tile.
Pseudo random number generator.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:60
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition slope_func.h:415
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
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:49
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:94
This file contains all sprite-related enums and defines.
static constexpr SpriteID SPR_OVERLAY_ROCKS_BASE
Overlay rocks sprites.
Definition sprites.h:319
Definition of base types and functions in a cross-platform compatible way.
LandscapeType landscape
the landscape we're currently in
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:327
Tile description for the 'land area information' tool.
Definition tile_cmd.h:38
StringID str
Description of the tile.
Definition tile_cmd.h:39
std::array< Owner, 4 > owner
Name of the owner(s)
Definition tile_cmd.h:41
Tile information, used while rendering the tile.
Definition tile_cmd.h:29
int z
Height.
Definition tile_cmd.h:34
int x
X position of the tile in unit coordinates.
Definition tile_cmd.h:30
Slope tileh
Slope of the tile.
Definition tile_cmd.h:32
TileIndex tile
Tile index.
Definition tile_cmd.h:33
int y
Y position of the tile in unit coordinates.
Definition tile_cmd.h:31
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:144
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
uint TileHash(uint x, uint y)
Calculate a hash value from a tile position.
Definition tile_map.h:324
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition tile_map.h:289
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
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:48
TransportType
Available types of transport.
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition viewport.cpp:759
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:663
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition viewport.cpp:769
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition viewport.cpp:579
Functions related to (drawing on) viewports.
@ WATER_CLASS_SEA
Sea.
Definition water_map.h:40
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:101
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:112