# landscape.cpp

Go to the documentation of this file.

    00001 /* $Id: landscape.cpp 26323 2014-02-09 15:00:30Z fonsinchen $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00014 #include "stdafx.h"
    00015 #include "heightmap.h"
    00016 #include "clear_map.h"
    00017 #include "spritecache.h"
    00018 #include "viewport_func.h"
    00019 #include "command_func.h"
    00020 #include "landscape.h"
    00021 #include "void_map.h"
    00022 #include "tgp.h"
    00023 #include "genworld.h"
    00024 #include "fios.h"
    00025 #include "date_func.h"
    00026 #include "water.h"
    00027 #include "effectvehicle_func.h"
    00028 #include "landscape_type.h"
    00029 #include "animated_tile_func.h"
    00030 #include "core/random_func.hpp"
    00031 #include "object_base.h"
    00032 #include "company_func.h"
    00033 #include "pathfinder/npf/aystar.h"
    00034 #include <list>
    00035 #include <set>
    00036
    00037 #include "table/strings.h"
    00038 #include "table/sprites.h"
    00039
    00040 extern const TileTypeProcs
    00041   _tile_type_clear_procs,
    00042   _tile_type_rail_procs,
    00043   _tile_type_road_procs,
    00044   _tile_type_town_procs,
    00045   _tile_type_trees_procs,
    00046   _tile_type_station_procs,
    00047   _tile_type_water_procs,
    00048   _tile_type_void_procs,
    00049   _tile_type_industry_procs,
    00050   _tile_type_tunnelbridge_procs,
    00051   _tile_type_object_procs;
    00052
    00058 const TileTypeProcs * const _tile_type_procs[16] = {
    00059   &_tile_type_clear_procs,
    00060   &_tile_type_rail_procs,
    00061   &_tile_type_road_procs,
    00062   &_tile_type_town_procs,
    00063   &_tile_type_trees_procs,
    00064   &_tile_type_station_procs,
    00065   &_tile_type_water_procs,
    00066   &_tile_type_void_procs,
    00067   &_tile_type_industry_procs,
    00068   &_tile_type_tunnelbridge_procs,
    00069   &_tile_type_object_procs,
    00070 };
    00071
    00073 extern const byte _slope_to_sprite_offset[32] = {
    00074   0, 1, 2, 3, 4, 5, 6,  7, 8, 9, 10, 11, 12, 13, 14, 0,
    00075   0, 0, 0, 0, 0, 0, 0, 16, 0, 0,  0, 17,  0, 15, 18, 0,
    00076 };
    00077
    00086 static SnowLine *_snow_line = NULL;
    00087
    00096 uint ApplyFoundationToSlope(Foundation f, Slope *s)
    00097 {
    00098   if (!IsFoundation(f)) return 0;
    00099
    00100   if (IsLeveledFoundation(f)) {
    00101     uint dz = 1 + (IsSteepSlope(*s) ? 1 : 0);
    00102     *s = SLOPE_FLAT;
    00103     return dz;
    00104   }
    00105
    00106   if (f != FOUNDATION_STEEP_BOTH && IsNonContinuousFoundation(f)) {
    00107     *s = HalftileSlope(*s, GetHalftileFoundationCorner(f));
    00108     return 0;
    00109   }
    00110
    00111   if (IsSpecialRailFoundation(f)) {
    00112     *s = SlopeWithThreeCornersRaised(OppositeCorner(GetRailFoundationCorner(f)));
    00113     return 0;
    00114   }
    00115
    00116   uint dz = IsSteepSlope(*s) ? 1 : 0;
    00117   Corner highest_corner = GetHighestSlopeCorner(*s);
    00118
    00119   switch (f) {
    00120     case FOUNDATION_INCLINED_X:
    00121       *s = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? SLOPE_SW : SLOPE_NE);
    00122       break;
    00123
    00124     case FOUNDATION_INCLINED_Y:
    00125       *s = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? SLOPE_SE : SLOPE_NW);
    00126       break;
    00127
    00128     case FOUNDATION_STEEP_LOWER:
    00129       *s = SlopeWithOneCornerRaised(highest_corner);
    00130       break;
    00131
    00132     case FOUNDATION_STEEP_BOTH:
    00133       *s = HalftileSlope(SlopeWithOneCornerRaised(highest_corner), highest_corner);
    00134       break;
    00135
    00136     default: NOT_REACHED();
    00137   }
    00138   return dz;
    00139 }
    00140
    00141
    00149 uint GetPartialPixelZ(int x, int y, Slope corners)
    00150 {
    00151   if (IsHalftileSlope(corners)) {
    00152     switch (GetHalftileSlopeCorner(corners)) {
    00153       case CORNER_W:
    00154         if (x - y >= 0) return GetSlopeMaxPixelZ(corners);
    00155         break;
    00156
    00157       case CORNER_S:
    00158         if (x - (y ^ 0xF) >= 0) return GetSlopeMaxPixelZ(corners);
    00159         break;
    00160
    00161       case CORNER_E:
    00162         if (y - x >= 0) return GetSlopeMaxPixelZ(corners);
    00163         break;
    00164
    00165       case CORNER_N:
    00166         if ((y ^ 0xF) - x >= 0) return GetSlopeMaxPixelZ(corners);
    00167         break;
    00168
    00169       default: NOT_REACHED();
    00170     }
    00171   }
    00172
    00173   int z = 0;
    00174
    00175   switch (RemoveHalftileSlope(corners)) {
    00176     case SLOPE_W:
    00177       if (x - y >= 0) {
    00178         z = (x - y) >> 1;
    00179       }
    00180       break;
    00181
    00182     case SLOPE_S:
    00183       y ^= 0xF;
    00184       if ((x - y) >= 0) {
    00185         z = (x - y) >> 1;
    00186       }
    00187       break;
    00188
    00189     case SLOPE_SW:
    00190       z = (x >> 1) + 1;
    00191       break;
    00192
    00193     case SLOPE_E:
    00194       if (y - x >= 0) {
    00195         z = (y - x) >> 1;
    00196       }
    00197       break;
    00198
    00199     case SLOPE_EW:
    00200     case SLOPE_NS:
    00201     case SLOPE_ELEVATED:
    00202       z = 4;
    00203       break;
    00204
    00205     case SLOPE_SE:
    00206       z = (y >> 1) + 1;
    00207       break;
    00208
    00209     case SLOPE_WSE:
    00210       z = 8;
    00211       y ^= 0xF;
    00212       if (x - y < 0) {
    00213         z += (x - y) >> 1;
    00214       }
    00215       break;
    00216
    00217     case SLOPE_N:
    00218       y ^= 0xF;
    00219       if (y - x >= 0) {
    00220         z = (y - x) >> 1;
    00221       }
    00222       break;
    00223
    00224     case SLOPE_NW:
    00225       z = (y ^ 0xF) >> 1;
    00226       break;
    00227
    00228     case SLOPE_NWS:
    00229       z = 8;
    00230       if (x - y < 0) {
    00231         z += (x - y) >> 1;
    00232       }
    00233       break;
    00234
    00235     case SLOPE_NE:
    00236       z = (x ^ 0xF) >> 1;
    00237       break;
    00238
    00239     case SLOPE_ENW:
    00240       z = 8;
    00241       y ^= 0xF;
    00242       if (y - x < 0) {
    00243         z += (y - x) >> 1;
    00244       }
    00245       break;
    00246
    00247     case SLOPE_SEN:
    00248       z = 8;
    00249       if (y - x < 0) {
    00250         z += (y - x) >> 1;
    00251       }
    00252       break;
    00253
    00254     case SLOPE_STEEP_S:
    00255       z = 1 + ((x + y) >> 1);
    00256       break;
    00257
    00258     case SLOPE_STEEP_W:
    00259       z = 1 + ((x + (y ^ 0xF)) >> 1);
    00260       break;
    00261
    00262     case SLOPE_STEEP_N:
    00263       z = 1 + (((x ^ 0xF) + (y ^ 0xF)) >> 1);
    00264       break;
    00265
    00266     case SLOPE_STEEP_E:
    00267       z = 1 + (((x ^ 0xF) + y) >> 1);
    00268       break;
    00269
    00270     default: break;
    00271   }
    00272
    00273   return z;
    00274 }
    00275
    00276 int GetSlopePixelZ(int x, int y)
    00277 {
    00278   TileIndex tile = TileVirtXY(x, y);
    00279
    00280   return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y);
    00281 }
    00282
    00292 int GetSlopeZInCorner(Slope tileh, Corner corner)
    00293 {
    00294   assert(!IsHalftileSlope(tileh));
    00295   return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? 1 : 0) + (tileh == SteepSlope(corner) ? 1 : 0);
    00296 }
    00297
    00310 void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2)
    00311 {
    00312   static const Slope corners[4][4] = {
    00313     /*    corner     |          steep slope
    00314      *  z1      z2   |       z1             z2        */
    00315     {SLOPE_E, SLOPE_N, SLOPE_STEEP_E, SLOPE_STEEP_N}, // DIAGDIR_NE, z1 = E, z2 = N
    00316     {SLOPE_S, SLOPE_E, SLOPE_STEEP_S, SLOPE_STEEP_E}, // DIAGDIR_SE, z1 = S, z2 = E
    00317     {SLOPE_S, SLOPE_W, SLOPE_STEEP_S, SLOPE_STEEP_W}, // DIAGDIR_SW, z1 = S, z2 = W
    00318     {SLOPE_W, SLOPE_N, SLOPE_STEEP_W, SLOPE_STEEP_N}, // DIAGDIR_NW, z1 = W, z2 = N
    00319   };
    00320
    00321   int halftile_test = (IsHalftileSlope(tileh) ? SlopeWithOneCornerRaised(GetHalftileSlopeCorner(tileh)) : 0);
    00322   if (halftile_test == corners[edge][0]) *z2 += TILE_HEIGHT; // The slope is non-continuous in z2. z2 is on the upper side.
    00323   if (halftile_test == corners[edge][1]) *z1 += TILE_HEIGHT; // The slope is non-continuous in z1. z1 is on the upper side.
    00324
    00325   if ((tileh & corners[edge][0]) != 0) *z1 += TILE_HEIGHT; // z1 is raised
    00326   if ((tileh & corners[edge][1]) != 0) *z2 += TILE_HEIGHT; // z2 is raised
    00327   if (RemoveHalftileSlope(tileh) == corners[edge][2]) *z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
    00328   if (RemoveHalftileSlope(tileh) == corners[edge][3]) *z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
    00329 }
    00330
    00339 Slope GetFoundationSlope(TileIndex tile, int *z)
    00340 {
    00341   Slope tileh = GetTileSlope(tile, z);
    00342   Foundation f = _tile_type_procs[GetTileType(tile)]->get_foundation_proc(tile, tileh);
    00343   uint z_inc = ApplyFoundationToSlope(f, &tileh);
    00344   if (z != NULL) *z += z_inc;
    00345   return tileh;
    00346 }
    00347
    00348
    00349 bool HasFoundationNW(TileIndex tile, Slope slope_here, uint z_here)
    00350 {
    00351   int z;
    00352
    00353   int z_W_here = z_here;
    00354   int z_N_here = z_here;
    00355   GetSlopePixelZOnEdge(slope_here, DIAGDIR_NW, &z_W_here, &z_N_here);
    00356
    00357   Slope slope = GetFoundationPixelSlope(TILE_ADDXY(tile, 0, -1), &z);
    00358   int z_W = z;
    00359   int z_N = z;
    00360   GetSlopePixelZOnEdge(slope, DIAGDIR_SE, &z_W, &z_N);
    00361
    00362   return (z_N_here > z_N) || (z_W_here > z_W);
    00363 }
    00364
    00365
    00366 bool HasFoundationNE(TileIndex tile, Slope slope_here, uint z_here)
    00367 {
    00368   int z;
    00369
    00370   int z_E_here = z_here;
    00371   int z_N_here = z_here;
    00372   GetSlopePixelZOnEdge(slope_here, DIAGDIR_NE, &z_E_here, &z_N_here);
    00373
    00374   Slope slope = GetFoundationPixelSlope(TILE_ADDXY(tile, -1, 0), &z);
    00375   int z_E = z;
    00376   int z_N = z;
    00377   GetSlopePixelZOnEdge(slope, DIAGDIR_SW, &z_E, &z_N);
    00378
    00379   return (z_N_here > z_N) || (z_E_here > z_E);
    00380 }
    00381
    00387 void DrawFoundation(TileInfo *ti, Foundation f)
    00388 {
    00389   if (!IsFoundation(f)) return;
    00390
    00391   /* Two part foundations must be drawn separately */
    00392   assert(f != FOUNDATION_STEEP_BOTH);
    00393
    00394   uint sprite_block = 0;
    00395   int z;
    00396   Slope slope = GetFoundationPixelSlope(ti->tile, &z);
    00397
    00398   /* Select the needed block of foundations sprites
    00399    * Block 0: Walls at NW and NE edge
    00400    * Block 1: Wall  at        NE edge
    00401    * Block 2: Wall  at NW        edge
    00402    * Block 3: No walls at NW or NE edge
    00403    */
    00404   if (!HasFoundationNW(ti->tile, slope, z)) sprite_block += 1;
    00405   if (!HasFoundationNE(ti->tile, slope, z)) sprite_block += 2;
    00406
    00407   /* Use the original slope sprites if NW and NE borders should be visible */
    00408   SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * SPR_TRKFOUND_BLOCK_SIZE));
    00409   SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SPR_SLOPES_INCLINED_OFFSET + sprite_block * SPR_TRKFOUND_BLOCK_SIZE;
    00410   SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * SPR_HALFTILE_BLOCK_SIZE;
    00411
    00412   if (IsSteepSlope(ti->tileh)) {
    00413     if (!IsNonContinuousFoundation(f)) {
    00414       /* Lower part of foundation */
    00415       AddSortableSpriteToDraw(
    00416         leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z
    00417       );
    00418     }
    00419
    00420     Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
    00421     ti->z += ApplyPixelFoundationToSlope(f, &ti->tileh);
    00422
    00423     if (IsInclinedFoundation(f)) {
    00424       /* inclined foundation */
    00425       byte inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
    00426
    00427       AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
    00428         f == FOUNDATION_INCLINED_X ? 16 : 1,
    00429         f == FOUNDATION_INCLINED_Y ? 16 : 1,
    00430         TILE_HEIGHT, ti->z
    00431       );
    00432       OffsetGroundSprite(31, 9);
    00433     } else if (IsLeveledFoundation(f)) {
    00434       AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z - TILE_HEIGHT);
    00435       OffsetGroundSprite(31, 1);
    00436     } else if (f == FOUNDATION_STEEP_LOWER) {
    00437       /* one corner raised */
    00438       OffsetGroundSprite(31, 1);
    00439     } else {
    00440       /* halftile foundation */
    00441       int x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? 8 : 0);
    00442       int y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? 8 : 0);
    00443
    00444       AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z + TILE_HEIGHT);
    00445       OffsetGroundSprite(31, 9);
    00446     }
    00447   } else {
    00448     if (IsLeveledFoundation(f)) {
    00449       /* leveled foundation */
    00450       AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
    00451       OffsetGroundSprite(31, 1);
    00452     } else if (IsNonContinuousFoundation(f)) {
    00453       /* halftile foundation */
    00454       Corner halftile_corner = GetHalftileFoundationCorner(f);
    00455       int x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? 8 : 0);
    00456       int y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? 8 : 0);
    00457
    00458       AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z);
    00459       OffsetGroundSprite(31, 9);
    00460     } else if (IsSpecialRailFoundation(f)) {
    00461       /* anti-zig-zag foundation */
    00462       SpriteID spr;
    00463       if (ti->tileh == SLOPE_NS || ti->tileh == SLOPE_EW) {
    00464         /* half of leveled foundation under track corner */
    00465         spr = leveled_base + SlopeWithThreeCornersRaised(GetRailFoundationCorner(f));
    00466       } else {
    00467         /* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
    00468         spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
    00469       }
    00470       AddSortableSpriteToDraw(spr, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
    00471       OffsetGroundSprite(31, 9);
    00472     } else {
    00473       /* inclined foundation */
    00474       byte inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
    00475
    00476       AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
    00477         f == FOUNDATION_INCLINED_X ? 16 : 1,
    00478         f == FOUNDATION_INCLINED_Y ? 16 : 1,
    00479         TILE_HEIGHT, ti->z
    00480       );
    00481       OffsetGroundSprite(31, 9);
    00482     }
    00483     ti->z += ApplyPixelFoundationToSlope(f, &ti->tileh);
    00484   }
    00485 }
    00486
    00487 void DoClearSquare(TileIndex tile)
    00488 {
    00489   /* If the tile can have animation and we clear it, delete it from the animated tile list. */
    00490   if (_tile_type_procs[GetTileType(tile)]->animate_tile_proc != NULL) DeleteAnimatedTile(tile);
    00491
    00492   MakeClear(tile, CLEAR_GRASS, _generating_world ? 3 : 0);
    00493   MarkTileDirtyByTile(tile);
    00494 }
    00495
    00506 TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
    00507 {
    00508   return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode, sub_mode, side);
    00509 }
    00510
    00517 void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
    00518 {
    00519   _tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_owner, new_owner);
    00520 }
    00521
    00522 void GetTileDesc(TileIndex tile, TileDesc *td)
    00523 {
    00524   _tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
    00525 }
    00526
    00532 bool IsSnowLineSet()
    00533 {
    00534   return _snow_line != NULL;
    00535 }
    00536
    00542 void SetSnowLine(byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
    00543 {
    00544   _snow_line = CallocT<SnowLine>(1);
    00545   _snow_line->lowest_value = 0xFF;
    00546   memcpy(_snow_line->table, table, sizeof(_snow_line->table));
    00547
    00548   for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
    00549     for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
    00550       _snow_line->highest_value = max(_snow_line->highest_value, table[i][j]);
    00551       _snow_line->lowest_value = min(_snow_line->lowest_value, table[i][j]);
    00552     }
    00553   }
    00554 }
    00555
    00561 byte GetSnowLine()
    00562 {
    00563   if (_snow_line == NULL) return _settings_game.game_creation.snow_line_height;
    00564
    00565   YearMonthDay ymd;
    00566   ConvertDateToYMD(_date, &ymd);
    00567   return _snow_line->table[ymd.month][ymd.day];
    00568 }
    00569
    00575 byte HighestSnowLine()
    00576 {
    00577   return _snow_line == NULL ? _settings_game.game_creation.snow_line_height : _snow_line->highest_value;
    00578 }
    00579
    00585 byte LowestSnowLine()
    00586 {
    00587   return _snow_line == NULL ? _settings_game.game_creation.snow_line_height : _snow_line->lowest_value;
    00588 }
    00589
    00594 void ClearSnowLine()
    00595 {
    00596   free(_snow_line);
    00597   _snow_line = NULL;
    00598 }
    00599
    00609 CommandCost CmdLandscapeClear(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00610 {
    00611   CommandCost cost(EXPENSES_CONSTRUCTION);
    00612   bool do_clear = false;
    00613   /* Test for stuff which results in water when cleared. Then add the cost to also clear the water. */
    00614   if ((flags & DC_FORCE_CLEAR_TILE) && HasTileWaterClass(tile) && IsTileOnWater(tile) && !IsWaterTile(tile) && !IsCoastTile(tile)) {
    00615     if ((flags & DC_AUTO) && GetWaterClass(tile) == WATER_CLASS_CANAL) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
    00616     do_clear = true;
    00617     cost.AddCost(GetWaterClass(tile) == WATER_CLASS_CANAL ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER]);
    00618   }
    00619
    00620   Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? NULL : Company::GetIfValid(_current_company);
    00621   if (c != NULL && (int)GB(c->clear_limit, 16, 16) < 1) {
    00622     return_cmd_error(STR_ERROR_CLEARING_LIMIT_REACHED);
    00623   }
    00624
    00625   const ClearedObjectArea *coa = FindClearedObject(tile);
    00626
    00627   /* If this tile was the first tile which caused object destruction, always
    00628    * pass it on to the tile_type_proc. That way multiple test runs and the exec run stay consistent. */
    00629   if (coa != NULL && coa->first_tile != tile) {
    00630     /* If this tile belongs to an object which was already cleared via another tile, pretend it has been
    00631      * already removed.
    00632      * However, we need to check stuff, which is not the same for all object tiles. (e.g. being on water or not) */
    00633
    00634     /* If a object is removed, it leaves either bare land or water. */
    00635     if ((flags & DC_NO_WATER) && HasTileWaterClass(tile) && IsTileOnWater(tile)) {
    00636       return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
    00637     }
    00638   } else {
    00639     cost.AddCost(_tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags));
    00640   }
    00641
    00642   if (flags & DC_EXEC) {
    00643     if (c != NULL) c->clear_limit -= 1 << 16;
    00644     if (do_clear) DoClearSquare(tile);
    00645   }
    00646   return cost;
    00647 }
    00648
    00659 CommandCost CmdClearArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00660 {
    00661   if (p1 >= MapSize()) return CMD_ERROR;
    00662
    00663   Money money = GetAvailableMoneyForCommand();
    00664   CommandCost cost(EXPENSES_CONSTRUCTION);
    00665   CommandCost last_error = CMD_ERROR;
    00666   bool had_success = false;
    00667
    00668   const Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? NULL : Company::GetIfValid(_current_company);
    00669   int limit = (c == NULL ? INT32_MAX : GB(c->clear_limit, 16, 16));
    00670
    00671   TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(tile, p1);
    00672   for (; *iter != INVALID_TILE; ++(*iter)) {
    00673     TileIndex t = *iter;
    00674     CommandCost ret = DoCommand(t, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
    00675     if (ret.Failed()) {
    00676       last_error = ret;
    00677
    00678       /* We may not clear more tiles. */
    00679       if (c != NULL && GB(c->clear_limit, 16, 16) < 1) break;
    00680       continue;
    00681     }
    00682
    00683     had_success = true;
    00684     if (flags & DC_EXEC) {
    00685       money -= ret.GetCost();
    00686       if (ret.GetCost() > 0 && money < 0) {
    00687         _additional_cash_required = ret.GetCost();
    00688         delete iter;
    00689         return cost;
    00690       }
    00691       DoCommand(t, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
    00692
    00693       /* draw explosion animation...
    00694        * Disable explosions when game is paused. Looks silly and blocks the view. */
    00695       if ((t == tile || t == p1) && _pause_mode == PM_UNPAUSED) {
    00696         /* big explosion in two corners, or small explosion for single tiles */
    00697         CreateEffectVehicleAbove(TileX(t) * TILE_SIZE + TILE_SIZE / 2, TileY(t) * TILE_SIZE + TILE_SIZE / 2, 2,
    00698           TileX(tile) == TileX(p1) && TileY(tile) == TileY(p1) ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
    00699         );
    00700       }
    00701     } else {
    00702       /* When we're at the clearing limit we better bail (unneed) testing as well. */
    00703       if (ret.GetCost() != 0 && --limit <= 0) break;
    00704     }
    00705     cost.AddCost(ret);
    00706   }
    00707
    00708   delete iter;
    00709   return had_success ? cost : last_error;
    00710 }
    00711
    00712
    00713 TileIndex _cur_tileloop_tile;
    00714
    00718 void RunTileLoop()
    00719 {
    00720   /* The pseudorandom sequence of tiles is generated using a Galois linear feedback
    00721    * shift register (LFSR). This allows a deterministic pseudorandom ordering, but
    00722    * still with minimal state and fast iteration. */
    00723
    00724   /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 24-bit (for 4096x4096 maps).
    00725    * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */
    00726   static const uint32 feedbacks[] = {
    00727     0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87
    00728   };
    00729   assert_compile(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1);
    00730   const uint32 feedback = feedbacks[MapLogX() + MapLogY() - 2 * MIN_MAP_SIZE_BITS];
    00731
    00732   /* We update every tile every 256 ticks, so divide the map size by 2^8 = 256 */
    00733   uint count = 1 << (MapLogX() + MapLogY() - 8);
    00734
    00735   TileIndex tile = _cur_tileloop_tile;
    00736   /* The LFSR cannot have a zeroed state. */
    00737   assert(tile != 0);
    00738
    00739   /* Manually update tile 0 every 256 ticks - the LFSR never iterates over it itself.  */
    00740   if (_tick_counter % 256 == 0) {
    00741     _tile_type_procs[GetTileType(0)]->tile_loop_proc(0);
    00742     count--;
    00743   }
    00744
    00745   while (count--) {
    00746     _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
    00747
    00748     /* Get the next tile in sequence using a Galois LFSR. */
    00749     tile = (tile >> 1) ^ (-(int32)(tile & 1) & feedback);
    00750   }
    00751
    00752   _cur_tileloop_tile = tile;
    00753 }
    00754
    00755 void InitializeLandscape()
    00756 {
    00757   uint maxx = MapMaxX();
    00758   uint maxy = MapMaxY();
    00759   uint sizex = MapSizeX();
    00760
    00761   uint y;
    00762   for (y = _settings_game.construction.freeform_edges ? 1 : 0; y < maxy; y++) {
    00763     uint x;
    00764     for (x = _settings_game.construction.freeform_edges ? 1 : 0; x < maxx; x++) {
    00765       MakeClear(sizex * y + x, CLEAR_GRASS, 3);
    00766       SetTileHeight(sizex * y + x, 0);
    00767       SetTropicZone(sizex * y + x, TROPICZONE_NORMAL);
    00768       ClearBridgeMiddle(sizex * y + x);
    00769     }
    00770     MakeVoid(sizex * y + x);
    00771   }
    00772   for (uint x = 0; x < sizex; x++) MakeVoid(sizex * y + x);
    00773 }
    00774
    00775 static const byte _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4  };
    00776 static const byte _genterrain_tbl_2[5] = {  0,  0,  0,  0, 33 };
    00777
    00778 static void GenerateTerrain(int type, uint flag)
    00779 {
    00780   uint32 r = Random();
    00781
    00782   const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845, ST_MAPGEN);
    00783   if (templ == NULL) usererror("Map generator sprites could not be loaded");
    00784
    00785   uint x = r & MapMaxX();
    00786   uint y = (r >> MapLogX()) & MapMaxY();
    00787
    00788   if (x < 2 || y < 2) return;
    00789
    00790   DiagDirection direction = (DiagDirection)GB(r, 22, 2);
    00791   uint w = templ->width;
    00792   uint h = templ->height;
    00793
    00794   if (DiagDirToAxis(direction) == AXIS_Y) Swap(w, h);
    00795
    00796   const byte *p = templ->data;
    00797
    00798   if ((flag & 4) != 0) {
    00799     uint xw = x * MapSizeY();
    00800     uint yw = y * MapSizeX();
    00801     uint bias = (MapSizeX() + MapSizeY()) * 16;
    00802
    00803     switch (flag & 3) {
    00804       default: NOT_REACHED();
    00805       case 0:
    00806         if (xw + yw > MapSize() - bias) return;
    00807         break;
    00808
    00809       case 1:
    00810         if (yw < xw + bias) return;
    00811         break;
    00812
    00813       case 2:
    00814         if (xw + yw < MapSize() + bias) return;
    00815         break;
    00816
    00817       case 3:
    00818         if (xw < yw + bias) return;
    00819         break;
    00820     }
    00821   }
    00822
    00823   if (x + w >= MapMaxX() - 1) return;
    00824   if (y + h >= MapMaxY() - 1) return;
    00825
    00826   TileIndex tile = TileXY(x, y);
    00827
    00828   switch (direction) {
    00829     default: NOT_REACHED();
    00830     case DIAGDIR_NE:
    00831       do {
    00832         TileIndex tile_cur = tile;
    00833
    00834         for (uint w_cur = w; w_cur != 0; --w_cur) {
    00835           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
    00836           p++;
    00837           tile_cur++;
    00838         }
    00839         tile += TileDiffXY(0, 1);
    00840       } while (--h != 0);
    00841       break;
    00842
    00843     case DIAGDIR_SE:
    00844       do {
    00845         TileIndex tile_cur = tile;
    00846
    00847         for (uint h_cur = h; h_cur != 0; --h_cur) {
    00848           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
    00849           p++;
    00850           tile_cur += TileDiffXY(0, 1);
    00851         }
    00852         tile += TileDiffXY(1, 0);
    00853       } while (--w != 0);
    00854       break;
    00855
    00856     case DIAGDIR_SW:
    00857       tile += TileDiffXY(w - 1, 0);
    00858       do {
    00859         TileIndex tile_cur = tile;
    00860
    00861         for (uint w_cur = w; w_cur != 0; --w_cur) {
    00862           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
    00863           p++;
    00864           tile_cur--;
    00865         }
    00866         tile += TileDiffXY(0, 1);
    00867       } while (--h != 0);
    00868       break;
    00869
    00870     case DIAGDIR_NW:
    00871       tile += TileDiffXY(0, h - 1);
    00872       do {
    00873         TileIndex tile_cur = tile;
    00874
    00875         for (uint h_cur = h; h_cur != 0; --h_cur) {
    00876           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
    00877           p++;
    00878           tile_cur -= TileDiffXY(0, 1);
    00879         }
    00880         tile += TileDiffXY(1, 0);
    00881       } while (--w != 0);
    00882       break;
    00883   }
    00884 }
    00885
    00886
    00887 #include "table/genland.h"
    00888
    00889 static void CreateDesertOrRainForest()
    00890 {
    00891   TileIndex update_freq = MapSize() / 4;
    00892   const TileIndexDiffC *data;
    00893
    00894   for (TileIndex tile = 0; tile != MapSize(); ++tile) {
    00895     if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
    00896
    00897     if (!IsValidTile(tile)) continue;
    00898
    00899     for (data = _make_desert_or_rainforest_data;
    00900         data != endof(_make_desert_or_rainforest_data); ++data) {
    00901       TileIndex t = AddTileIndexDiffCWrap(tile, *data);
    00902       if (t != INVALID_TILE && (TileHeight(t) >= 4 || IsTileType(t, MP_WATER))) break;
    00903     }
    00904     if (data == endof(_make_desert_or_rainforest_data)) {
    00905       SetTropicZone(tile, TROPICZONE_DESERT);
    00906     }
    00907   }
    00908
    00909   for (uint i = 0; i != 256; i++) {
    00910     if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
    00911
    00912     RunTileLoop();
    00913   }
    00914
    00915   for (TileIndex tile = 0; tile != MapSize(); ++tile) {
    00916     if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
    00917
    00918     if (!IsValidTile(tile)) continue;
    00919
    00920     for (data = _make_desert_or_rainforest_data;
    00921         data != endof(_make_desert_or_rainforest_data); ++data) {
    00922       TileIndex t = AddTileIndexDiffCWrap(tile, *data);
    00923       if (t != INVALID_TILE && IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_DESERT)) break;
    00924     }
    00925     if (data == endof(_make_desert_or_rainforest_data)) {
    00926       SetTropicZone(tile, TROPICZONE_RAINFOREST);
    00927     }
    00928   }
    00929 }
    00930
    00937 static bool FindSpring(TileIndex tile, void *user_data)
    00938 {
    00939   int referenceHeight;
    00940   if (!IsTileFlat(tile, &referenceHeight) || IsWaterTile(tile)) return false;
    00941
    00942   /* In the tropics rivers start in the rainforest. */
    00943   if (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(tile) != TROPICZONE_RAINFOREST) return false;
    00944
    00945   /* Are there enough higher tiles to warrant a 'spring'? */
    00946   uint num = 0;
    00947   for (int dx = -1; dx <= 1; dx++) {
    00948     for (int dy = -1; dy <= 1; dy++) {
    00949       TileIndex t = TileAddWrap(tile, dx, dy);
    00950       if (t != INVALID_TILE && GetTileMaxZ(t) > referenceHeight) num++;
    00951     }
    00952   }
    00953
    00954   if (num < 4) return false;
    00955
    00956   /* Are we near the top of a hill? */
    00957   for (int dx = -16; dx <= 16; dx++) {
    00958     for (int dy = -16; dy <= 16; dy++) {
    00959       TileIndex t = TileAddWrap(tile, dx, dy);
    00960       if (t != INVALID_TILE && GetTileMaxZ(t) > referenceHeight + 2) return false;
    00961     }
    00962   }
    00963
    00964   return true;
    00965 }
    00966
    00973 static bool MakeLake(TileIndex tile, void *user_data)
    00974 {
    00975   uint height = *(uint*)user_data;
    00976   if (!IsValidTile(tile) || TileHeight(tile) != height || !IsTileFlat(tile)) return false;
    00977   if (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(tile) == TROPICZONE_DESERT) return false;
    00978
    00979   for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
    00980     TileIndex t2 = tile + TileOffsByDiagDir(d);
    00981     if (IsWaterTile(t2)) {
    00982       MakeRiver(tile, Random());
    00983       return false;
    00984     }
    00985   }
    00986
    00987   return false;
    00988 }
    00989
    00996 static bool FlowsDown(TileIndex begin, TileIndex end)
    00997 {
    00998   assert(DistanceManhattan(begin, end) == 1);
    00999
    01000   int heightBegin;
    01001   int heightEnd;
    01002   Slope slopeBegin = GetTileSlope(begin, &heightBegin);
    01003   Slope slopeEnd   = GetTileSlope(end, &heightEnd);
    01004
    01005   return heightEnd <= heightBegin &&
    01006       /* Slope either is inclined or flat; rivers don't support other slopes. */
    01007       (slopeEnd == SLOPE_FLAT || IsInclinedSlope(slopeEnd)) &&
    01008       /* Slope continues, then it must be lower... or either end must be flat. */
    01009       ((slopeEnd == slopeBegin && heightEnd < heightBegin) || slopeEnd == SLOPE_FLAT || slopeBegin == SLOPE_FLAT);
    01010 }
    01011
    01012 /* AyStar callback for checking whether we reached our destination. */
    01013 static int32 River_EndNodeCheck(AyStar *aystar, OpenListNode *current)
    01014 {
    01015   return current->path.node.tile == *(TileIndex*)aystar->user_target ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
    01016 }
    01017
    01018 /* AyStar callback for getting the cost of the current node. */
    01019 static int32 River_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
    01020 {
    01021   return 1 + RandomRange(_settings_game.game_creation.river_route_random);
    01022 }
    01023
    01024 /* AyStar callback for getting the estimated cost to the destination. */
    01025 static int32 River_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
    01026 {
    01027   return DistanceManhattan(*(TileIndex*)aystar->user_target, current->tile);
    01028 }
    01029
    01030 /* AyStar callback for getting the neighbouring nodes of the given node. */
    01031 static void River_GetNeighbours(AyStar *aystar, OpenListNode *current)
    01032 {
    01033   TileIndex tile = current->path.node.tile;
    01034
    01035   aystar->num_neighbours = 0;
    01036   for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
    01037     TileIndex t2 = tile + TileOffsByDiagDir(d);
    01038     if (IsValidTile(t2) && FlowsDown(tile, t2)) {
    01039       aystar->neighbours[aystar->num_neighbours].tile = t2;
    01040       aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
    01041       aystar->num_neighbours++;
    01042     }
    01043   }
    01044 }
    01045
    01046 /* AyStar callback when an route has been found. */
    01047 static void River_FoundEndNode(AyStar *aystar, OpenListNode *current)
    01048 {
    01049   for (PathNode *path = &current->path; path != NULL; path = path->parent) {
    01050     TileIndex tile = path->node.tile;
    01051     if (!IsWaterTile(tile)) {
    01052       MakeRiver(tile, Random());
    01053       /* Remove desert directly around the river tile. */
    01054       CircularTileSearch(&tile, 5, RiverModifyDesertZone, NULL);
    01055     }
    01056   }
    01057 }
    01058
    01059 static const uint RIVER_HASH_SIZE = 8;
    01060
    01067 static uint River_Hash(uint tile, uint dir)
    01068 {
    01069   return GB(TileHash(TileX(tile), TileY(tile)), 0, RIVER_HASH_SIZE);
    01070 }
    01071
    01077 static void BuildRiver(TileIndex begin, TileIndex end)
    01078 {
    01079   AyStar finder;
    01080   MemSetT(&finder, 0);
    01081   finder.CalculateG = River_CalculateG;
    01082   finder.CalculateH = River_CalculateH;
    01083   finder.GetNeighbours = River_GetNeighbours;
    01084   finder.EndNodeCheck = River_EndNodeCheck;
    01085   finder.FoundEndNode = River_FoundEndNode;
    01086   finder.user_target = &end;
    01087
    01088   finder.Init(River_Hash, 1 << RIVER_HASH_SIZE);
    01089
    01090   AyStarNode start;
    01091   start.tile = begin;
    01092   start.direction = INVALID_TRACKDIR;
    01093   finder.AddStartNode(&start, 0);
    01094   finder.Main();
    01095   finder.Free();
    01096 }
    01097
    01104 static bool FlowRiver(TileIndex spring, TileIndex begin)
    01105 {
    01106   #define SET_MARK(x) marks.insert(x)
    01107   #define IS_MARKED(x) (marks.find(x) != marks.end())
    01108
    01109   uint height = TileHeight(begin);
    01110   if (IsWaterTile(begin)) return DistanceManhattan(spring, begin) > _settings_game.game_creation.min_river_length;
    01111
    01112   std::set<TileIndex> marks;
    01113   SET_MARK(begin);
    01114
    01115   /* Breadth first search for the closest tile we can flow down to. */
    01116   std::list<TileIndex> queue;
    01117   queue.push_back(begin);
    01118
    01119   bool found = false;
    01120   uint count = 0; // Number of tiles considered; to be used for lake location guessing.
    01121   TileIndex end;
    01122   do {
    01123     end = queue.front();
    01124     queue.pop_front();
    01125
    01126     uint height2 = TileHeight(end);
    01127     if (IsTileFlat(end) && (height2 < height || (height2 == height && IsWaterTile(end)))) {
    01128       found = true;
    01129       break;
    01130     }
    01131
    01132     for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
    01133       TileIndex t2 = end + TileOffsByDiagDir(d);
    01134       if (IsValidTile(t2) && !IS_MARKED(t2) && FlowsDown(end, t2)) {
    01135         SET_MARK(t2);
    01136         count++;
    01137         queue.push_back(t2);
    01138       }
    01139     }
    01140   } while (!queue.empty());
    01141
    01142   if (found) {
    01143     /* Flow further down hill. */
    01144     found = FlowRiver(spring, end);
    01145   } else if (count > 32) {
    01146     /* Maybe we can make a lake. Find the Nth of the considered tiles. */
    01147     TileIndex lakeCenter = 0;
    01148     int i = RandomRange(count - 1) + 1;
    01149     std::set<TileIndex>::const_iterator cit = marks.begin();
    01150     while (--i) cit++;
    01151     lakeCenter = *cit;
    01152
    01153     if (IsValidTile(lakeCenter) &&
    01154         /* A river, or lake, can only be built on flat slopes. */
    01155         IsTileFlat(lakeCenter) &&
    01156         /* We want the lake to be built at the height of the river. */
    01157         TileHeight(begin) == TileHeight(lakeCenter) &&
    01158         /* We don't want the lake at the entry of the valley. */
    01159         lakeCenter != begin &&
    01160         /* We don't want lakes in the desert. */
    01161         (_settings_game.game_creation.landscape != LT_TROPIC || GetTropicZone(lakeCenter) != TROPICZONE_DESERT) &&
    01162         /* We only want a lake if the river is long enough. */
    01163         DistanceManhattan(spring, lakeCenter) > _settings_game.game_creation.min_river_length) {
    01164       end = lakeCenter;
    01165       MakeRiver(lakeCenter, Random());
    01166       uint range = RandomRange(8) + 3;
    01167       CircularTileSearch(&lakeCenter, range, MakeLake, &height);
    01168       /* Call the search a second time so artefacts from going circular in one direction get (mostly) hidden. */
    01169       lakeCenter = end;
    01170       CircularTileSearch(&lakeCenter, range, MakeLake, &height);
    01171       found = true;
    01172     }
    01173   }
    01174
    01175   marks.clear();
    01176   if (found) BuildRiver(begin, end);
    01177   return found;
    01178 }
    01179
    01183 static void CreateRivers()
    01184 {
    01185   int amount = _settings_game.game_creation.amount_of_rivers;
    01186   if (amount == 0) return;
    01187
    01188   uint wells = ScaleByMapSize(4 << _settings_game.game_creation.amount_of_rivers);
    01189   SetGeneratingWorldProgress(GWP_RIVER, wells + 256 / 64); // Include the tile loop calls below.
    01190
    01191   for (; wells != 0; wells--) {
    01192     IncreaseGeneratingWorldProgress(GWP_RIVER);
    01193     for (int tries = 0; tries < 128; tries++) {
    01194       TileIndex t = RandomTile();
    01195       if (!CircularTileSearch(&t, 8, FindSpring, NULL)) continue;
    01196       if (FlowRiver(t, t)) break;
    01197     }
    01198   }
    01199
    01200   /* Run tile loop to update the ground density. */
    01201   for (uint i = 0; i != 256; i++) {
    01202     if (i % 64 == 0) IncreaseGeneratingWorldProgress(GWP_RIVER);
    01203     RunTileLoop();
    01204   }
    01205 }
    01206
    01207 void GenerateLandscape(byte mode)
    01208 {
    01210   enum GenLandscapeSteps {
    01211     GLS_HEIGHTMAP    =  3,
    01212     GLS_TERRAGENESIS =  5,
    01213     GLS_ORIGINAL     =  2,
    01214     GLS_TROPIC       = 12,
    01215     GLS_OTHER        =  0,
    01216   };
    01217   uint steps = (_settings_game.game_creation.landscape == LT_TROPIC) ? GLS_TROPIC : GLS_OTHER;
    01218
    01219   if (mode == GWM_HEIGHTMAP) {
    01220     SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_HEIGHTMAP);
    01221     LoadHeightmap(_file_to_saveload.name);
    01222     IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
    01223   } else if (_settings_game.game_creation.land_generator == LG_TERRAGENESIS) {
    01224     SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_TERRAGENESIS);
    01225     GenerateTerrainPerlin();
    01226   } else {
    01227     SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_ORIGINAL);
    01228     if (_settings_game.construction.freeform_edges) {
    01229       for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0));
    01230       for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y));
    01231     }
    01232     switch (_settings_game.game_creation.landscape) {
    01233       case LT_ARCTIC: {
    01234         uint32 r = Random();
    01235
    01236         for (uint i = ScaleByMapSize(GB(r, 0, 7) + 950); i != 0; --i) {
    01237           GenerateTerrain(2, 0);
    01238         }
    01239
    01240         uint flag = GB(r, 7, 2) | 4;
    01241         for (uint i = ScaleByMapSize(GB(r, 9, 7) + 450); i != 0; --i) {
    01242           GenerateTerrain(4, flag);
    01243         }
    01244         break;
    01245       }
    01246
    01247       case LT_TROPIC: {
    01248         uint32 r = Random();
    01249
    01250         for (uint i = ScaleByMapSize(GB(r, 0, 7) + 170); i != 0; --i) {
    01251           GenerateTerrain(0, 0);
    01252         }
    01253
    01254         uint flag = GB(r, 7, 2) | 4;
    01255         for (uint i = ScaleByMapSize(GB(r, 9, 8) + 1700); i != 0; --i) {
    01256           GenerateTerrain(0, flag);
    01257         }
    01258
    01259         flag ^= 2;
    01260
    01261         for (uint i = ScaleByMapSize(GB(r, 17, 7) + 410); i != 0; --i) {
    01262           GenerateTerrain(3, flag);
    01263         }
    01264         break;
    01265       }
    01266
    01267       default: {
    01268         uint32 r = Random();
    01269
    01270         assert(_settings_game.difficulty.quantity_sea_lakes != CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY);
    01271         uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _settings_game.difficulty.quantity_sea_lakes) * 256 + 100);
    01272         for (; i != 0; --i) {
    01273           GenerateTerrain(_settings_game.difficulty.terrain_type, 0);
    01274         }
    01275         break;
    01276       }
    01277     }
    01278   }
    01279
    01280   /* Do not call IncreaseGeneratingWorldProgress() before FixSlopes(),
    01281    * it allows screen redraw. Drawing of broken slopes crashes the game */
    01282   FixSlopes();
    01283   IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
    01284   ConvertGroundTilesIntoWaterTiles();
    01285   IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
    01286
    01287   if (_settings_game.game_creation.landscape == LT_TROPIC) CreateDesertOrRainForest();
    01288
    01289   CreateRivers();
    01290 }
    01291
    01292 void OnTick_Town();
    01293 void OnTick_Trees();
    01294 void OnTick_Station();
    01295 void OnTick_Industry();
    01296
    01297 void OnTick_Companies();
    01298 void OnTick_LinkGraph();
    01299
    01300 void CallLandscapeTick()
    01301 {
    01302   OnTick_Town();
    01303   OnTick_Trees();
    01304   OnTick_Station();
    01305   OnTick_Industry();
    01306
    01307   OnTick_Companies();
    01308   OnTick_LinkGraph();
    01309 }