landscape.cpp

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