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 
00773   uint x = r & MapMaxX();
00774   uint y = (r >> MapLogX()) & MapMaxY();
00775 
00776   if (x < 2 || y < 2) return;
00777 
00778   DiagDirection direction = (DiagDirection)GB(r, 22, 2);
00779   uint w = templ->width;
00780   uint h = templ->height;
00781 
00782   if (DiagDirToAxis(direction) == AXIS_Y) Swap(w, h);
00783 
00784   const byte *p = templ->data;
00785 
00786   if ((flag & 4) != 0) {
00787     uint xw = x * MapSizeY();
00788     uint yw = y * MapSizeX();
00789     uint bias = (MapSizeX() + MapSizeY()) * 16;
00790 
00791     switch (flag & 3) {
00792       default: NOT_REACHED();
00793       case 0:
00794         if (xw + yw > MapSize() - bias) return;
00795         break;
00796 
00797       case 1:
00798         if (yw < xw + bias) return;
00799         break;
00800 
00801       case 2:
00802         if (xw + yw < MapSize() + bias) return;
00803         break;
00804 
00805       case 3:
00806         if (xw < yw + bias) return;
00807         break;
00808     }
00809   }
00810 
00811   if (x + w >= MapMaxX() - 1) return;
00812   if (y + h >= MapMaxY() - 1) return;
00813 
00814   TileIndex tile = TileXY(x, y);
00815 
00816   switch (direction) {
00817     default: NOT_REACHED();
00818     case DIAGDIR_NE:
00819       do {
00820         TileIndex tile_cur = tile;
00821 
00822         for (uint w_cur = w; w_cur != 0; --w_cur) {
00823           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
00824           p++;
00825           tile_cur++;
00826         }
00827         tile += TileDiffXY(0, 1);
00828       } while (--h != 0);
00829       break;
00830 
00831     case DIAGDIR_SE:
00832       do {
00833         TileIndex tile_cur = tile;
00834 
00835         for (uint h_cur = h; h_cur != 0; --h_cur) {
00836           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
00837           p++;
00838           tile_cur += TileDiffXY(0, 1);
00839         }
00840         tile += TileDiffXY(1, 0);
00841       } while (--w != 0);
00842       break;
00843 
00844     case DIAGDIR_SW:
00845       tile += TileDiffXY(w - 1, 0);
00846       do {
00847         TileIndex tile_cur = tile;
00848 
00849         for (uint w_cur = w; w_cur != 0; --w_cur) {
00850           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
00851           p++;
00852           tile_cur--;
00853         }
00854         tile += TileDiffXY(0, 1);
00855       } while (--h != 0);
00856       break;
00857 
00858     case DIAGDIR_NW:
00859       tile += TileDiffXY(0, h - 1);
00860       do {
00861         TileIndex tile_cur = tile;
00862 
00863         for (uint h_cur = h; h_cur != 0; --h_cur) {
00864           if (GB(*p, 0, 4) >= TileHeight(tile_cur)) SetTileHeight(tile_cur, GB(*p, 0, 4));
00865           p++;
00866           tile_cur -= TileDiffXY(0, 1);
00867         }
00868         tile += TileDiffXY(1, 0);
00869       } while (--w != 0);
00870       break;
00871   }
00872 }
00873 
00874 
00875 #include "table/genland.h"
00876 
00877 static void CreateDesertOrRainForest()
00878 {
00879   TileIndex update_freq = MapSize() / 4;
00880   const TileIndexDiffC *data;
00881 
00882   for (TileIndex tile = 0; tile != MapSize(); ++tile) {
00883     if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00884 
00885     if (!IsValidTile(tile)) continue;
00886 
00887     for (data = _make_desert_or_rainforest_data;
00888         data != endof(_make_desert_or_rainforest_data); ++data) {
00889       TileIndex t = AddTileIndexDiffCWrap(tile, *data);
00890       if (t != INVALID_TILE && (TileHeight(t) >= 4 || IsTileType(t, MP_WATER))) break;
00891     }
00892     if (data == endof(_make_desert_or_rainforest_data)) {
00893       SetTropicZone(tile, TROPICZONE_DESERT);
00894     }
00895   }
00896 
00897   for (uint i = 0; i != 256; i++) {
00898     if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00899 
00900     RunTileLoop();
00901   }
00902 
00903   for (TileIndex tile = 0; tile != MapSize(); ++tile) {
00904     if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00905 
00906     if (!IsValidTile(tile)) continue;
00907 
00908     for (data = _make_desert_or_rainforest_data;
00909         data != endof(_make_desert_or_rainforest_data); ++data) {
00910       TileIndex t = AddTileIndexDiffCWrap(tile, *data);
00911       if (t != INVALID_TILE && IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_DESERT)) break;
00912     }
00913     if (data == endof(_make_desert_or_rainforest_data)) {
00914       SetTropicZone(tile, TROPICZONE_RAINFOREST);
00915     }
00916   }
00917 }
00918 
00925 static bool FindSpring(TileIndex tile, void *user_data)
00926 {
00927   int referenceHeight;
00928   Slope s = GetTileSlope(tile, &referenceHeight);
00929   if (s != SLOPE_FLAT || IsWaterTile(tile)) return false;
00930 
00931   /* In the tropics rivers start in the rainforest. */
00932   if (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(tile) != TROPICZONE_RAINFOREST) return false;
00933 
00934   /* Are there enough higher tiles to warrant a 'spring'? */
00935   uint num = 0;
00936   for (int dx = -1; dx <= 1; dx++) {
00937     for (int dy = -1; dy <= 1; dy++) {
00938       TileIndex t = TileAddWrap(tile, dx, dy);
00939       if (t != INVALID_TILE && GetTileMaxZ(t) > referenceHeight) num++;
00940     }
00941   }
00942 
00943   if (num < 4) return false;
00944 
00945   /* Are we near the top of a hill? */
00946   for (int dx = -16; dx <= 16; dx++) {
00947     for (int dy = -16; dy <= 16; dy++) {
00948       TileIndex t = TileAddWrap(tile, dx, dy);
00949       if (t != INVALID_TILE && GetTileMaxZ(t) > referenceHeight + 2) return false;
00950     }
00951   }
00952 
00953   return true;
00954 }
00955 
00962 static bool MakeLake(TileIndex tile, void *user_data)
00963 {
00964   uint height = *(uint*)user_data;
00965   if (!IsValidTile(tile) || TileHeight(tile) != height || GetTileSlope(tile) != SLOPE_FLAT) return false;
00966   if (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(tile) == TROPICZONE_DESERT) return false;
00967 
00968   for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
00969     TileIndex t2 = tile + TileOffsByDiagDir(d);
00970     if (IsWaterTile(t2)) {
00971       MakeRiver(tile, Random());
00972       return false;
00973     }
00974   }
00975 
00976   return false;
00977 }
00978 
00985 static bool FlowsDown(TileIndex begin, TileIndex end)
00986 {
00987   assert(DistanceManhattan(begin, end) == 1);
00988 
00989   int heightBegin;
00990   int heightEnd;
00991   Slope slopeBegin = GetTileSlope(begin, &heightBegin);
00992   Slope slopeEnd   = GetTileSlope(end, &heightEnd);
00993 
00994   return heightEnd <= heightBegin &&
00995       /* Slope either is inclined or flat; rivers don't support other slopes. */
00996       (slopeEnd == SLOPE_FLAT || IsInclinedSlope(slopeEnd)) &&
00997       /* Slope continues, then it must be lower... or either end must be flat. */
00998       ((slopeEnd == slopeBegin && heightEnd < heightBegin) || slopeEnd == SLOPE_FLAT || slopeBegin == SLOPE_FLAT);
00999 }
01000 
01001 /* AyStar callback for checking whether we reached our destination. */
01002 static int32 River_EndNodeCheck(AyStar *aystar, OpenListNode *current)
01003 {
01004   return current->path.node.tile == *(TileIndex*)aystar->user_target ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
01005 }
01006 
01007 /* AyStar callback for getting the cost of the current node. */
01008 static int32 River_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
01009 {
01010   return 1 + RandomRange(_settings_game.game_creation.river_route_random);
01011 }
01012 
01013 /* AyStar callback for getting the estimated cost to the destination. */
01014 static int32 River_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
01015 {
01016   return DistanceManhattan(*(TileIndex*)aystar->user_target, current->tile);
01017 }
01018 
01019 /* AyStar callback for getting the neighbouring nodes of the given node. */
01020 static void River_GetNeighbours(AyStar *aystar, OpenListNode *current)
01021 {
01022   TileIndex tile = current->path.node.tile;
01023 
01024   aystar->num_neighbours = 0;
01025   for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
01026     TileIndex t2 = tile + TileOffsByDiagDir(d);
01027     if (IsValidTile(t2) && FlowsDown(tile, t2)) {
01028       aystar->neighbours[aystar->num_neighbours].tile = t2;
01029       aystar->neighbours[aystar->num_neighbours].direction = INVALID_TRACKDIR;
01030       aystar->num_neighbours++;
01031     }
01032   }
01033 }
01034 
01035 /* AyStar callback when an route has been found. */
01036 static void River_FoundEndNode(AyStar *aystar, OpenListNode *current)
01037 {
01038   for (PathNode *path = &current->path; path != NULL; path = path->parent) {
01039     TileIndex tile = path->node.tile;
01040     if (!IsWaterTile(tile)) {
01041       MakeRiver(tile, Random());
01042       /* Remove desert directly around the river tile. */
01043       CircularTileSearch(&tile, 5, RiverModifyDesertZone, NULL);
01044     }
01045   }
01046 }
01047 
01048 static const uint RIVER_HASH_SIZE = 8; 
01049 
01056 static uint River_Hash(uint tile, uint dir)
01057 {
01058   return GB(TileHash(TileX(tile), TileY(tile)), 0, RIVER_HASH_SIZE);
01059 }
01060 
01066 static void BuildRiver(TileIndex begin, TileIndex end)
01067 {
01068   AyStar finder;
01069   MemSetT(&finder, 0);
01070   finder.CalculateG = River_CalculateG;
01071   finder.CalculateH = River_CalculateH;
01072   finder.GetNeighbours = River_GetNeighbours;
01073   finder.EndNodeCheck = River_EndNodeCheck;
01074   finder.FoundEndNode = River_FoundEndNode;
01075   finder.user_target = &end;
01076 
01077   finder.Init(River_Hash, 1 << RIVER_HASH_SIZE);
01078 
01079   AyStarNode start;
01080   start.tile = begin;
01081   start.direction = INVALID_TRACKDIR;
01082   finder.AddStartNode(&start, 0);
01083   finder.Main();
01084   finder.Free();
01085 }
01086 
01094 static bool FlowRiver(bool *marks, TileIndex spring, TileIndex begin)
01095 {
01096   uint height = TileHeight(begin);
01097   if (IsWaterTile(begin)) return DistanceManhattan(spring, begin) > _settings_game.game_creation.min_river_length;
01098 
01099   MemSetT(marks, 0, MapSize());
01100   marks[begin] = true;
01101 
01102   /* Breadth first search for the closest tile we can flow down to. */
01103   std::list<TileIndex> queue;
01104   queue.push_back(begin);
01105 
01106   bool found = false;
01107   uint count = 0; // Number of tiles considered; to be used for lake location guessing.
01108   TileIndex end;
01109   do {
01110     end = queue.front();
01111     queue.pop_front();
01112 
01113     uint height2 = TileHeight(end);
01114     if (GetTileSlope(end) == SLOPE_FLAT && (height2 < height || (height2 == height && IsWaterTile(end)))) {
01115       found = true;
01116       break;
01117     }
01118 
01119     for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
01120       TileIndex t2 = end + TileOffsByDiagDir(d);
01121       if (IsValidTile(t2) && !marks[t2] && FlowsDown(end, t2)) {
01122         marks[t2] = true;
01123         count++;
01124         queue.push_back(t2);
01125       }
01126     }
01127   } while (!queue.empty());
01128 
01129   if (found) {
01130     /* Flow further down hill. */
01131     found = FlowRiver(marks, spring, end);
01132   } else if (count > 32) {
01133     /* Maybe we can make a lake. Find the Nth of the considered tiles. */
01134     TileIndex lakeCenter = 0;
01135     for (int i = RandomRange(count - 1); i != 0; lakeCenter++) {
01136       if (marks[lakeCenter]) i--;
01137     }
01138 
01139     if (IsValidTile(lakeCenter) &&
01140         /* A river, or lake, can only be built on flat slopes. */
01141         GetTileSlope(lakeCenter) == SLOPE_FLAT &&
01142         /* We want the lake to be built at the height of the river. */
01143         TileHeight(begin) == TileHeight(lakeCenter) &&
01144         /* We don't want the lake at the entry of the valley. */
01145         lakeCenter != begin &&
01146         /* We don't want lakes in the desert. */
01147         (_settings_game.game_creation.landscape != LT_TROPIC || GetTropicZone(lakeCenter) != TROPICZONE_DESERT) &&
01148         /* We only want a lake if the river is long enough. */
01149         DistanceManhattan(spring, lakeCenter) > _settings_game.game_creation.min_river_length) {
01150       end = lakeCenter;
01151       MakeRiver(lakeCenter, Random());
01152       uint range = RandomRange(8) + 3;
01153       CircularTileSearch(&lakeCenter, range, MakeLake, &height);
01154       /* Call the search a second time so artefacts from going circular in one direction get (mostly) hidden. */
01155       lakeCenter = end;
01156       CircularTileSearch(&lakeCenter, range, MakeLake, &height);
01157       found = true;
01158     }
01159   }
01160 
01161   if (found) BuildRiver(begin, end);
01162   return found;
01163 }
01164 
01168 static void CreateRivers()
01169 {
01170   int amount = _settings_game.game_creation.amount_of_rivers;
01171   if (amount == 0) return;
01172 
01173   uint wells = ScaleByMapSize(4 << _settings_game.game_creation.amount_of_rivers);
01174   SetGeneratingWorldProgress(GWP_RIVER, wells + 256 / 64); // Include the tile loop calls below.
01175   bool *marks = CallocT<bool>(MapSize());
01176 
01177   for (; wells != 0; wells--) {
01178     IncreaseGeneratingWorldProgress(GWP_RIVER);
01179     for (int tries = 0; tries < 128; tries++) {
01180       TileIndex t = RandomTile();
01181       if (!CircularTileSearch(&t, 8, FindSpring, NULL)) continue;
01182       if (FlowRiver(marks, t, t)) break;
01183     }
01184   }
01185 
01186   free(marks);
01187 
01188   /* Run tile loop to update the ground density. */
01189   for (uint i = 0; i != 256; i++) {
01190     if (i % 64 == 0) IncreaseGeneratingWorldProgress(GWP_RIVER);
01191     RunTileLoop();
01192   }
01193 }
01194 
01195 void GenerateLandscape(byte mode)
01196 {
01198   enum GenLandscapeSteps {
01199     GLS_HEIGHTMAP    =  3, 
01200     GLS_TERRAGENESIS =  5, 
01201     GLS_ORIGINAL     =  2, 
01202     GLS_TROPIC       = 12, 
01203     GLS_OTHER        =  0, 
01204   };
01205   uint steps = (_settings_game.game_creation.landscape == LT_TROPIC) ? GLS_TROPIC : GLS_OTHER;
01206 
01207   if (mode == GWM_HEIGHTMAP) {
01208     SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_HEIGHTMAP);
01209     LoadHeightmap(_file_to_saveload.name);
01210     IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01211   } else if (_settings_game.game_creation.land_generator == LG_TERRAGENESIS) {
01212     SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_TERRAGENESIS);
01213     GenerateTerrainPerlin();
01214   } else {
01215     SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_ORIGINAL);
01216     if (_settings_game.construction.freeform_edges) {
01217       for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0));
01218       for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y));
01219     }
01220     switch (_settings_game.game_creation.landscape) {
01221       case LT_ARCTIC: {
01222         uint32 r = Random();
01223 
01224         for (uint i = ScaleByMapSize(GB(r, 0, 7) + 950); i != 0; --i) {
01225           GenerateTerrain(2, 0);
01226         }
01227 
01228         uint flag = GB(r, 7, 2) | 4;
01229         for (uint i = ScaleByMapSize(GB(r, 9, 7) + 450); i != 0; --i) {
01230           GenerateTerrain(4, flag);
01231         }
01232         break;
01233       }
01234 
01235       case LT_TROPIC: {
01236         uint32 r = Random();
01237 
01238         for (uint i = ScaleByMapSize(GB(r, 0, 7) + 170); i != 0; --i) {
01239           GenerateTerrain(0, 0);
01240         }
01241 
01242         uint flag = GB(r, 7, 2) | 4;
01243         for (uint i = ScaleByMapSize(GB(r, 9, 8) + 1700); i != 0; --i) {
01244           GenerateTerrain(0, flag);
01245         }
01246 
01247         flag ^= 2;
01248 
01249         for (uint i = ScaleByMapSize(GB(r, 17, 7) + 410); i != 0; --i) {
01250           GenerateTerrain(3, flag);
01251         }
01252         break;
01253       }
01254 
01255       default: {
01256         uint32 r = Random();
01257 
01258         assert(_settings_game.difficulty.quantity_sea_lakes != CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY);
01259         uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _settings_game.difficulty.quantity_sea_lakes) * 256 + 100);
01260         for (; i != 0; --i) {
01261           GenerateTerrain(_settings_game.difficulty.terrain_type, 0);
01262         }
01263         break;
01264       }
01265     }
01266   }
01267 
01268   /* Do not call IncreaseGeneratingWorldProgress() before FixSlopes(),
01269    * it allows screen redraw. Drawing of broken slopes crashes the game */
01270   FixSlopes();
01271   IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01272   ConvertGroundTilesIntoWaterTiles();
01273   IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
01274 
01275   if (_settings_game.game_creation.landscape == LT_TROPIC) CreateDesertOrRainForest();
01276 
01277   CreateRivers();
01278 }
01279 
01280 void OnTick_Town();
01281 void OnTick_Trees();
01282 void OnTick_Station();
01283 void OnTick_Industry();
01284 
01285 void OnTick_Companies();
01286 void OnTick_LinkGraph();
01287 
01288 void CallLandscapeTick()
01289 {
01290   OnTick_Town();
01291   OnTick_Trees();
01292   OnTick_Station();
01293   OnTick_Industry();
01294 
01295   OnTick_Companies();
01296   OnTick_LinkGraph();
01297 }