landscape.cpp

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