landscape.cpp

Go to the documentation of this file.
00001 /* $Id: landscape.cpp 16744 2009-07-04 21:06:17Z rubidium $ */
00002 
00007 #include "stdafx.h"
00008 #include "heightmap.h"
00009 #include "clear_map.h"
00010 #include "spritecache.h"
00011 #include "viewport_func.h"
00012 #include "command_func.h"
00013 #include "landscape.h"
00014 #include "variables.h"
00015 #include "void_map.h"
00016 #include "tgp.h"
00017 #include "genworld.h"
00018 #include "fios.h"
00019 #include "functions.h"
00020 #include "date_func.h"
00021 #include "water.h"
00022 #include "effectvehicle_func.h"
00023 #include "landscape_type.h"
00024 #include "settings_type.h"
00025 #include "animated_tile_func.h"
00026 
00027 #include "table/sprites.h"
00028 
00029 extern const TileTypeProcs
00030   _tile_type_clear_procs,
00031   _tile_type_rail_procs,
00032   _tile_type_road_procs,
00033   _tile_type_town_procs,
00034   _tile_type_trees_procs,
00035   _tile_type_station_procs,
00036   _tile_type_water_procs,
00037   _tile_type_dummy_procs,
00038   _tile_type_industry_procs,
00039   _tile_type_tunnelbridge_procs,
00040   _tile_type_unmovable_procs;
00041 
00045 const TileTypeProcs * const _tile_type_procs[16] = {
00046   &_tile_type_clear_procs,        
00047   &_tile_type_rail_procs,         
00048   &_tile_type_road_procs,         
00049   &_tile_type_town_procs,         
00050   &_tile_type_trees_procs,        
00051   &_tile_type_station_procs,      
00052   &_tile_type_water_procs,        
00053   &_tile_type_dummy_procs,        
00054   &_tile_type_industry_procs,     
00055   &_tile_type_tunnelbridge_procs, 
00056   &_tile_type_unmovable_procs,    
00057 };
00058 
00059 /* landscape slope => sprite */
00060 const byte _tileh_to_sprite[32] = {
00061   0, 1, 2, 3, 4, 5, 6,  7, 8, 9, 10, 11, 12, 13, 14, 0,
00062   0, 0, 0, 0, 0, 0, 0, 16, 0, 0,  0, 17,  0, 15, 18, 0,
00063 };
00064 
00072 SnowLine *_snow_line = NULL;
00073 
00082 uint ApplyFoundationToSlope(Foundation f, Slope *s)
00083 {
00084   if (!IsFoundation(f)) return 0;
00085 
00086   if (IsLeveledFoundation(f)) {
00087     uint dz = TILE_HEIGHT + (IsSteepSlope(*s) ? TILE_HEIGHT : 0);
00088     *s = SLOPE_FLAT;
00089     return dz;
00090   }
00091 
00092   if (f != FOUNDATION_STEEP_BOTH && IsNonContinuousFoundation(f)) {
00093     *s = HalftileSlope(*s, GetHalftileFoundationCorner(f));
00094     return 0;
00095   }
00096 
00097   if (IsSpecialRailFoundation(f)) {
00098     *s = SlopeWithThreeCornersRaised(OppositeCorner(GetRailFoundationCorner(f)));
00099     return 0;
00100   }
00101 
00102   uint dz = IsSteepSlope(*s) ? TILE_HEIGHT : 0;
00103   Corner highest_corner = GetHighestSlopeCorner(*s);
00104 
00105   switch (f) {
00106     case FOUNDATION_INCLINED_X:
00107       *s = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? SLOPE_SW : SLOPE_NE);
00108       break;
00109 
00110     case FOUNDATION_INCLINED_Y:
00111       *s = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? SLOPE_SE : SLOPE_NW);
00112       break;
00113 
00114     case FOUNDATION_STEEP_LOWER:
00115       *s = SlopeWithOneCornerRaised(highest_corner);
00116       break;
00117 
00118     case FOUNDATION_STEEP_BOTH:
00119       *s = HalftileSlope(SlopeWithOneCornerRaised(highest_corner), highest_corner);
00120       break;
00121 
00122     default: NOT_REACHED();
00123   }
00124   return dz;
00125 }
00126 
00127 
00135 uint GetPartialZ(int x, int y, Slope corners)
00136 {
00137   if (IsHalftileSlope(corners)) {
00138     switch (GetHalftileSlopeCorner(corners)) {
00139       case CORNER_W:
00140         if (x - y >= 0) return GetSlopeMaxZ(corners);
00141         break;
00142 
00143       case CORNER_S:
00144         if (x - (y ^ 0xF) >= 0) return GetSlopeMaxZ(corners);
00145         break;
00146 
00147       case CORNER_E:
00148         if (y - x >= 0) return GetSlopeMaxZ(corners);
00149         break;
00150 
00151       case CORNER_N:
00152         if ((y ^ 0xF) - x >= 0) return GetSlopeMaxZ(corners);
00153         break;
00154 
00155       default: NOT_REACHED();
00156     }
00157   }
00158 
00159   int z = 0;
00160 
00161   switch (RemoveHalftileSlope(corners)) {
00162     case SLOPE_W:
00163       if (x - y >= 0) {
00164         z = (x - y) >> 1;
00165       }
00166       break;
00167 
00168     case SLOPE_S:
00169       y ^= 0xF;
00170       if ((x - y) >= 0) {
00171         z = (x - y) >> 1;
00172       }
00173       break;
00174 
00175     case SLOPE_SW:
00176       z = (x >> 1) + 1;
00177       break;
00178 
00179     case SLOPE_E:
00180       if (y - x >= 0) {
00181         z = (y - x) >> 1;
00182       }
00183       break;
00184 
00185     case SLOPE_EW:
00186     case SLOPE_NS:
00187     case SLOPE_ELEVATED:
00188       z = 4;
00189       break;
00190 
00191     case SLOPE_SE:
00192       z = (y >> 1) + 1;
00193       break;
00194 
00195     case SLOPE_WSE:
00196       z = 8;
00197       y ^= 0xF;
00198       if (x - y < 0) {
00199         z += (x - y) >> 1;
00200       }
00201       break;
00202 
00203     case SLOPE_N:
00204       y ^= 0xF;
00205       if (y - x >= 0) {
00206         z = (y - x) >> 1;
00207       }
00208       break;
00209 
00210     case SLOPE_NW:
00211       z = (y ^ 0xF) >> 1;
00212       break;
00213 
00214     case SLOPE_NWS:
00215       z = 8;
00216       if (x - y < 0) {
00217         z += (x - y) >> 1;
00218       }
00219       break;
00220 
00221     case SLOPE_NE:
00222       z = (x ^ 0xF) >> 1;
00223       break;
00224 
00225     case SLOPE_ENW:
00226       z = 8;
00227       y ^= 0xF;
00228       if (y - x < 0) {
00229         z += (y - x) >> 1;
00230       }
00231       break;
00232 
00233     case SLOPE_SEN:
00234       z = 8;
00235       if (y - x < 0) {
00236         z += (y - x) >> 1;
00237       }
00238       break;
00239 
00240     case SLOPE_STEEP_S:
00241       z = 1 + ((x + y) >> 1);
00242       break;
00243 
00244     case SLOPE_STEEP_W:
00245       z = 1 + ((x + (y ^ 0xF)) >> 1);
00246       break;
00247 
00248     case SLOPE_STEEP_N:
00249       z = 1 + (((x ^ 0xF) + (y ^ 0xF)) >> 1);
00250       break;
00251 
00252     case SLOPE_STEEP_E:
00253       z = 1 + (((x ^ 0xF) + y) >> 1);
00254       break;
00255 
00256     default: break;
00257   }
00258 
00259   return z;
00260 }
00261 
00262 uint GetSlopeZ(int x, int y)
00263 {
00264   TileIndex tile = TileVirtXY(x, y);
00265 
00266   return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y);
00267 }
00268 
00278 int GetSlopeZInCorner(Slope tileh, Corner corner)
00279 {
00280   assert(!IsHalftileSlope(tileh));
00281   return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? TILE_HEIGHT : 0) + (tileh == SteepSlope(corner) ? TILE_HEIGHT : 0);
00282 }
00283 
00296 void GetSlopeZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2)
00297 {
00298   static const Slope corners[4][4] = {
00299     /*    corner     |          steep slope
00300      *  z1      z2   |       z1             z2        */
00301     {SLOPE_E, SLOPE_N, SLOPE_STEEP_E, SLOPE_STEEP_N}, // DIAGDIR_NE, z1 = E, z2 = N
00302     {SLOPE_S, SLOPE_E, SLOPE_STEEP_S, SLOPE_STEEP_E}, // DIAGDIR_SE, z1 = S, z2 = E
00303     {SLOPE_S, SLOPE_W, SLOPE_STEEP_S, SLOPE_STEEP_W}, // DIAGDIR_SW, z1 = S, z2 = W
00304     {SLOPE_W, SLOPE_N, SLOPE_STEEP_W, SLOPE_STEEP_N}, // DIAGDIR_NW, z1 = W, z2 = N
00305   };
00306 
00307   int halftile_test = (IsHalftileSlope(tileh) ? SlopeWithOneCornerRaised(GetHalftileSlopeCorner(tileh)) : 0);
00308   if (halftile_test == corners[edge][0]) *z2 += TILE_HEIGHT; // The slope is non-continuous in z2. z2 is on the upper side.
00309   if (halftile_test == corners[edge][1]) *z1 += TILE_HEIGHT; // The slope is non-continuous in z1. z1 is on the upper side.
00310 
00311   if ((tileh & corners[edge][0]) != 0) *z1 += TILE_HEIGHT; // z1 is raised
00312   if ((tileh & corners[edge][1]) != 0) *z2 += TILE_HEIGHT; // z2 is raised
00313   if (RemoveHalftileSlope(tileh) == corners[edge][2]) *z1 += TILE_HEIGHT; // z1 is highest corner of a steep slope
00314   if (RemoveHalftileSlope(tileh) == corners[edge][3]) *z2 += TILE_HEIGHT; // z2 is highest corner of a steep slope
00315 }
00316 
00325 Slope GetFoundationSlope(TileIndex tile, uint *z)
00326 {
00327   Slope tileh = GetTileSlope(tile, z);
00328   Foundation f = _tile_type_procs[GetTileType(tile)]->get_foundation_proc(tile, tileh);
00329   uint z_inc = ApplyFoundationToSlope(f, &tileh);
00330   if (z != NULL) *z += z_inc;
00331   return tileh;
00332 }
00333 
00334 
00335 static bool HasFoundationNW(TileIndex tile, Slope slope_here, uint z_here)
00336 {
00337   uint z;
00338 
00339   int z_W_here = z_here;
00340   int z_N_here = z_here;
00341   GetSlopeZOnEdge(slope_here, DIAGDIR_NW, &z_W_here, &z_N_here);
00342 
00343   Slope slope = GetFoundationSlope(TILE_ADDXY(tile, 0, -1), &z);
00344   int z_W = z;
00345   int z_N = z;
00346   GetSlopeZOnEdge(slope, DIAGDIR_SE, &z_W, &z_N);
00347 
00348   return (z_N_here > z_N) || (z_W_here > z_W);
00349 }
00350 
00351 
00352 static bool HasFoundationNE(TileIndex tile, Slope slope_here, uint z_here)
00353 {
00354   uint z;
00355 
00356   int z_E_here = z_here;
00357   int z_N_here = z_here;
00358   GetSlopeZOnEdge(slope_here, DIAGDIR_NE, &z_E_here, &z_N_here);
00359 
00360   Slope slope = GetFoundationSlope(TILE_ADDXY(tile, -1, 0), &z);
00361   int z_E = z;
00362   int z_N = z;
00363   GetSlopeZOnEdge(slope, DIAGDIR_SW, &z_E, &z_N);
00364 
00365   return (z_N_here > z_N) || (z_E_here > z_E);
00366 }
00367 
00373 void DrawFoundation(TileInfo *ti, Foundation f)
00374 {
00375   if (!IsFoundation(f)) return;
00376 
00377   /* Two part foundations must be drawn separately */
00378   assert(f != FOUNDATION_STEEP_BOTH);
00379 
00380   uint sprite_block = 0;
00381   uint z;
00382   Slope slope = GetFoundationSlope(ti->tile, &z);
00383 
00384   /* Select the needed block of foundations sprites
00385    * Block 0: Walls at NW and NE edge
00386    * Block 1: Wall  at        NE edge
00387    * Block 2: Wall  at NW        edge
00388    * Block 3: No walls at NW or NE edge
00389    */
00390   if (!HasFoundationNW(ti->tile, slope, z)) sprite_block += 1;
00391   if (!HasFoundationNE(ti->tile, slope, z)) sprite_block += 2;
00392 
00393   /* Use the original slope sprites if NW and NE borders should be visible */
00394   SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * SPR_TRKFOUND_BLOCK_SIZE));
00395   SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SPR_SLOPES_INCLINED_OFFSET + sprite_block * SPR_TRKFOUND_BLOCK_SIZE;
00396   SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * SPR_HALFTILE_BLOCK_SIZE;
00397 
00398   if (IsSteepSlope(ti->tileh)) {
00399     if (!IsNonContinuousFoundation(f)) {
00400       /* Lower part of foundation */
00401       AddSortableSpriteToDraw(
00402         leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z
00403       );
00404     }
00405 
00406     Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
00407     ti->z += ApplyFoundationToSlope(f, &ti->tileh);
00408 
00409     if (IsInclinedFoundation(f)) {
00410       /* inclined foundation */
00411       byte inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
00412 
00413       AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
00414         f == FOUNDATION_INCLINED_X ? 16 : 1,
00415         f == FOUNDATION_INCLINED_Y ? 16 : 1,
00416         TILE_HEIGHT, ti->z
00417       );
00418       OffsetGroundSprite(31, 9);
00419     } else if (IsLeveledFoundation(f)) {
00420       AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z - TILE_HEIGHT);
00421       OffsetGroundSprite(31, 1);
00422     } else if (f == FOUNDATION_STEEP_LOWER) {
00423       /* one corner raised */
00424       OffsetGroundSprite(31, 1);
00425     } else {
00426       /* halftile foundation */
00427       int x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? 8 : 0);
00428       int y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? 8 : 0);
00429 
00430       AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z + TILE_HEIGHT);
00431       OffsetGroundSprite(31, 9);
00432     }
00433   } else {
00434     if (IsLeveledFoundation(f)) {
00435       /* leveled foundation */
00436       AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
00437       OffsetGroundSprite(31, 1);
00438     } else if (IsNonContinuousFoundation(f)) {
00439       /* halftile foundation */
00440       Corner halftile_corner = GetHalftileFoundationCorner(f);
00441       int x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? 8 : 0);
00442       int y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? 8 : 0);
00443 
00444       AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z);
00445       OffsetGroundSprite(31, 9);
00446     } else if (IsSpecialRailFoundation(f)) {
00447       /* anti-zig-zag foundation */
00448       SpriteID spr;
00449       if (ti->tileh == SLOPE_NS || ti->tileh == SLOPE_EW) {
00450         /* half of leveled foundation under track corner */
00451         spr = leveled_base + SlopeWithThreeCornersRaised(GetRailFoundationCorner(f));
00452       } else {
00453         /* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
00454         spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
00455       }
00456       AddSortableSpriteToDraw(spr, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
00457       OffsetGroundSprite(31, 9);
00458     } else {
00459       /* inclined foundation */
00460       byte inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
00461 
00462       AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
00463         f == FOUNDATION_INCLINED_X ? 16 : 1,
00464         f == FOUNDATION_INCLINED_Y ? 16 : 1,
00465         TILE_HEIGHT, ti->z
00466       );
00467       OffsetGroundSprite(31, 9);
00468     }
00469     ti->z += ApplyFoundationToSlope(f, &ti->tileh);
00470   }
00471 }
00472 
00473 void DoClearSquare(TileIndex tile)
00474 {
00475   /* If the tile can have animation and we clear it, delete it from the animated tile list. */
00476   if (_tile_type_procs[GetTileType(tile)]->animate_tile_proc != NULL) DeleteAnimatedTile(tile);
00477 
00478   MakeClear(tile, CLEAR_GRASS, _generating_world ? 3 : 0);
00479   MarkTileDirtyByTile(tile);
00480 }
00481 
00491 TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00492 {
00493   return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode, sub_mode, side);
00494 }
00495 
00502 void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
00503 {
00504   _tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_owner, new_owner);
00505 }
00506 
00507 void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac)
00508 {
00509   memset(ac, 0, sizeof(AcceptedCargo));
00510   _tile_type_procs[GetTileType(tile)]->get_accepted_cargo_proc(tile, ac);
00511 }
00512 
00513 void GetTileDesc(TileIndex tile, TileDesc *td)
00514 {
00515   _tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
00516 }
00517 
00523 bool IsSnowLineSet(void)
00524 {
00525   return _snow_line != NULL;
00526 }
00527 
00533 void SetSnowLine(byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
00534 {
00535   _snow_line = CallocT<SnowLine>(1);
00536   _snow_line->lowest_value = 0xFF;
00537   memcpy(_snow_line->table, table, sizeof(_snow_line->table));
00538 
00539   for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
00540     for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
00541       _snow_line->highest_value = max(_snow_line->highest_value, table[i][j]);
00542       _snow_line->lowest_value = min(_snow_line->lowest_value, table[i][j]);
00543     }
00544   }
00545 }
00546 
00552 byte GetSnowLine(void)
00553 {
00554   if (_snow_line == NULL) return _settings_game.game_creation.snow_line;
00555 
00556   YearMonthDay ymd;
00557   ConvertDateToYMD(_date, &ymd);
00558   return _snow_line->table[ymd.month][ymd.day];
00559 }
00560 
00566 byte HighestSnowLine(void)
00567 {
00568   return _snow_line == NULL ? _settings_game.game_creation.snow_line : _snow_line->highest_value;
00569 }
00570 
00576 byte LowestSnowLine(void)
00577 {
00578   return _snow_line == NULL ? _settings_game.game_creation.snow_line : _snow_line->lowest_value;
00579 }
00580 
00585 void ClearSnowLine(void)
00586 {
00587   free(_snow_line);
00588   _snow_line = NULL;
00589 }
00590 
00597 CommandCost CmdLandscapeClear(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00598 {
00599   return _tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags);
00600 }
00601 
00608 CommandCost CmdClearArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00609 {
00610   if (p1 >= MapSize()) return CMD_ERROR;
00611 
00612   /* make sure sx,sy are smaller than ex,ey */
00613   int ex = TileX(tile);
00614   int ey = TileY(tile);
00615   int sx = TileX(p1);
00616   int sy = TileY(p1);
00617   if (ex < sx) Swap(ex, sx);
00618   if (ey < sy) Swap(ey, sy);
00619 
00620   Money money = GetAvailableMoneyForCommand();
00621   CommandCost cost(EXPENSES_CONSTRUCTION);
00622   bool success = false;
00623 
00624   for (int x = sx; x <= ex; ++x) {
00625     for (int y = sy; y <= ey; ++y) {
00626       CommandCost ret = DoCommand(TileXY(x, y), 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
00627       if (CmdFailed(ret)) continue;
00628       success = true;
00629 
00630       if (flags & DC_EXEC) {
00631         money -= ret.GetCost();
00632         if (ret.GetCost() > 0 && money < 0) {
00633           _additional_cash_required = ret.GetCost();
00634           return cost;
00635         }
00636         DoCommand(TileXY(x, y), 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00637 
00638         /* draw explosion animation... */
00639         if ((x == sx || x == ex) && (y == sy || y == ey)) {
00640           /* big explosion in each corner, or small explosion for single tiles */
00641           CreateEffectVehicleAbove(x * TILE_SIZE + TILE_SIZE / 2, y * TILE_SIZE + TILE_SIZE / 2, 2,
00642             sy == ey && sx == ex ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
00643           );
00644         }
00645       }
00646       cost.AddCost(ret);
00647     }
00648   }
00649 
00650   return (success) ? cost : CMD_ERROR;
00651 }
00652 
00653 
00654 TileIndex _cur_tileloop_tile;
00655 #define TILELOOP_BITS 4
00656 #define TILELOOP_SIZE (1 << TILELOOP_BITS)
00657 #define TILELOOP_ASSERTMASK ((TILELOOP_SIZE - 1) + ((TILELOOP_SIZE - 1) << MapLogX()))
00658 #define TILELOOP_CHKMASK (((1 << (MapLogX() - TILELOOP_BITS))-1) << TILELOOP_BITS)
00659 
00660 void RunTileLoop()
00661 {
00662   TileIndex tile = _cur_tileloop_tile;
00663 
00664   assert((tile & ~TILELOOP_ASSERTMASK) == 0);
00665   uint count = (MapSizeX() / TILELOOP_SIZE) * (MapSizeY() / TILELOOP_SIZE);
00666   do {
00667     _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
00668 
00669     if (TileX(tile) < MapSizeX() - TILELOOP_SIZE) {
00670       tile += TILELOOP_SIZE; // no overflow
00671     } else {
00672       tile = TILE_MASK(tile - TILELOOP_SIZE * (MapSizeX() / TILELOOP_SIZE - 1) + TileDiffXY(0, TILELOOP_SIZE)); // x would overflow, also increase y
00673     }
00674   } while (--count != 0);
00675   assert((tile & ~TILELOOP_ASSERTMASK) == 0);
00676 
00677   tile += 9;
00678   if (tile & TILELOOP_CHKMASK) {
00679     tile = (tile + MapSizeX()) & TILELOOP_ASSERTMASK;
00680   }
00681   _cur_tileloop_tile = tile;
00682 }
00683 
00684 void InitializeLandscape()
00685 {
00686   uint maxx = MapMaxX();
00687   uint maxy = MapMaxY();
00688   uint sizex = MapSizeX();
00689 
00690   uint y;
00691   for (y = _settings_game.construction.freeform_edges ? 1 : 0; y < maxy; y++) {
00692     uint x;
00693     for (x = _settings_game.construction.freeform_edges ? 1 : 0; x < maxx; x++) {
00694       MakeClear(sizex * y + x, CLEAR_GRASS, 3);
00695       SetTileHeight(sizex * y + x, 0);
00696       SetTropicZone(sizex * y + x, TROPICZONE_NORMAL);
00697       ClearBridgeMiddle(sizex * y + x);
00698     }
00699     MakeVoid(sizex * y + x);
00700   }
00701   for (uint x = 0; x < sizex; x++) MakeVoid(sizex * y + x);
00702 }
00703 
00704 static const byte _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4  };
00705 static const byte _genterrain_tbl_2[5] = {  0,  0,  0,  0, 33 };
00706 
00707 static void GenerateTerrain(int type, uint flag)
00708 {
00709   uint32 r = Random();
00710 
00711   const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845, ST_MAPGEN);
00712 
00713   uint x = r & MapMaxX();
00714   uint y = (r >> MapLogX()) & MapMaxY();
00715 
00716   if (x < 2 || y < 2) return;
00717 
00718   DiagDirection direction = (DiagDirection)GB(r, 22, 2);
00719   uint w = templ->width;
00720   uint h = templ->height;
00721 
00722   if (DiagDirToAxis(direction) == AXIS_Y) Swap(w, h);
00723 
00724   const byte *p = templ->data;
00725 
00726   if ((flag & 4) != 0) {
00727     uint xw = x * MapSizeY();
00728     uint yw = y * MapSizeX();
00729     uint bias = (MapSizeX() + MapSizeY()) * 16;
00730 
00731     switch (flag & 3) {
00732       default: NOT_REACHED();
00733       case 0:
00734         if (xw + yw > MapSize() - bias) return;
00735         break;
00736 
00737       case 1:
00738         if (yw < xw + bias) return;
00739         break;
00740 
00741       case 2:
00742         if (xw + yw < MapSize() + bias) return;
00743         break;
00744 
00745       case 3:
00746         if (xw < yw + bias) return;
00747         break;
00748     }
00749   }
00750 
00751   if (x + w >= MapMaxX() - 1) return;
00752   if (y + h >= MapMaxY() - 1) return;
00753 
00754   Tile *tile = &_m[TileXY(x, y)];
00755 
00756   switch (direction) {
00757     default: NOT_REACHED();
00758     case DIAGDIR_NE:
00759       do {
00760         Tile *tile_cur = tile;
00761 
00762         for (uint w_cur = w; w_cur != 0; --w_cur) {
00763           if (GB(*p, 0, 4) >= tile_cur->type_height) tile_cur->type_height = GB(*p, 0, 4);
00764           p++;
00765           tile_cur++;
00766         }
00767         tile += TileDiffXY(0, 1);
00768       } while (--h != 0);
00769       break;
00770 
00771     case DIAGDIR_SE:
00772       do {
00773         Tile *tile_cur = tile;
00774 
00775         for (uint h_cur = h; h_cur != 0; --h_cur) {
00776           if (GB(*p, 0, 4) >= tile_cur->type_height) tile_cur->type_height = GB(*p, 0, 4);
00777           p++;
00778           tile_cur += TileDiffXY(0, 1);
00779         }
00780         tile += TileDiffXY(1, 0);
00781       } while (--w != 0);
00782       break;
00783 
00784     case DIAGDIR_SW:
00785       tile += TileDiffXY(w - 1, 0);
00786       do {
00787         Tile *tile_cur = tile;
00788 
00789         for (uint w_cur = w; w_cur != 0; --w_cur) {
00790           if (GB(*p, 0, 4) >= tile_cur->type_height) tile_cur->type_height = GB(*p, 0, 4);
00791           p++;
00792           tile_cur--;
00793         }
00794         tile += TileDiffXY(0, 1);
00795       } while (--h != 0);
00796       break;
00797 
00798     case DIAGDIR_NW:
00799       tile += TileDiffXY(0, h - 1);
00800       do {
00801         Tile *tile_cur = tile;
00802 
00803         for (uint h_cur = h; h_cur != 0; --h_cur) {
00804           if (GB(*p, 0, 4) >= tile_cur->type_height) tile_cur->type_height = GB(*p, 0, 4);
00805           p++;
00806           tile_cur -= TileDiffXY(0, 1);
00807         }
00808         tile += TileDiffXY(1, 0);
00809       } while (--w != 0);
00810       break;
00811   }
00812 }
00813 
00814 
00815 #include "table/genland.h"
00816 
00817 static void CreateDesertOrRainForest()
00818 {
00819   TileIndex update_freq = MapSize() / 4;
00820   const TileIndexDiffC *data;
00821 
00822   for (TileIndex tile = 0; tile != MapSize(); ++tile) {
00823     if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00824 
00825     for (data = _make_desert_or_rainforest_data;
00826         data != endof(_make_desert_or_rainforest_data); ++data) {
00827       TileIndex t = AddTileIndexDiffCWrap(tile, *data);
00828       if (t != INVALID_TILE && (TileHeight(t) >= 4 || IsTileType(t, MP_WATER))) break;
00829     }
00830     if (data == endof(_make_desert_or_rainforest_data))
00831       SetTropicZone(tile, TROPICZONE_DESERT);
00832   }
00833 
00834   for (uint i = 0; i != 256; i++) {
00835     if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00836 
00837     RunTileLoop();
00838   }
00839 
00840   for (TileIndex tile = 0; tile != MapSize(); ++tile) {
00841     if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00842 
00843     for (data = _make_desert_or_rainforest_data;
00844         data != endof(_make_desert_or_rainforest_data); ++data) {
00845       TileIndex t = AddTileIndexDiffCWrap(tile, *data);
00846       if (t != INVALID_TILE && IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_DESERT)) break;
00847     }
00848     if (data == endof(_make_desert_or_rainforest_data))
00849       SetTropicZone(tile, TROPICZONE_RAINFOREST);
00850   }
00851 }
00852 
00853 void GenerateLandscape(byte mode)
00854 {
00855   static const int gwp_desert_amount = 4 + 8;
00856 
00857   if (mode == GW_HEIGHTMAP) {
00858     SetGeneratingWorldProgress(GWP_LANDSCAPE, (_settings_game.game_creation.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1);
00859     LoadHeightmap(_file_to_saveload.name);
00860     IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00861   } else if (_settings_game.game_creation.land_generator == LG_TERRAGENESIS) {
00862     SetGeneratingWorldProgress(GWP_LANDSCAPE, (_settings_game.game_creation.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3);
00863     GenerateTerrainPerlin();
00864   } else {
00865     if (_settings_game.construction.freeform_edges) {
00866       for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0));
00867       for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y));
00868     }
00869     switch (_settings_game.game_creation.landscape) {
00870       case LT_ARCTIC: {
00871         SetGeneratingWorldProgress(GWP_LANDSCAPE, 2);
00872 
00873         uint32 r = Random();
00874 
00875         for (uint i = ScaleByMapSize(GB(r, 0, 7) + 950); i != 0; --i) {
00876           GenerateTerrain(2, 0);
00877         }
00878         IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00879 
00880         uint flag = GB(r, 7, 2) | 4;
00881         for (uint i = ScaleByMapSize(GB(r, 9, 7) + 450); i != 0; --i) {
00882           GenerateTerrain(4, flag);
00883         }
00884         IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00885       } break;
00886 
00887       case LT_TROPIC: {
00888         SetGeneratingWorldProgress(GWP_LANDSCAPE, 3 + gwp_desert_amount);
00889 
00890         uint32 r = Random();
00891 
00892         for (uint i = ScaleByMapSize(GB(r, 0, 7) + 170); i != 0; --i) {
00893           GenerateTerrain(0, 0);
00894         }
00895         IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00896 
00897         uint flag = GB(r, 7, 2) | 4;
00898         for (uint i = ScaleByMapSize(GB(r, 9, 8) + 1700); i != 0; --i) {
00899           GenerateTerrain(0, flag);
00900         }
00901         IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00902 
00903         flag ^= 2;
00904 
00905         for (uint i = ScaleByMapSize(GB(r, 17, 7) + 410); i != 0; --i) {
00906           GenerateTerrain(3, flag);
00907         }
00908         IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00909       } break;
00910 
00911       default: {
00912         SetGeneratingWorldProgress(GWP_LANDSCAPE, 1);
00913 
00914         uint32 r = Random();
00915 
00916         uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _settings_game.difficulty.quantity_sea_lakes) * 256 + 100);
00917         for (; i != 0; --i) {
00918           GenerateTerrain(_settings_game.difficulty.terrain_type, 0);
00919         }
00920         IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00921       } break;
00922     }
00923   }
00924 
00925   FixSlopes();
00926   ConvertGroundTilesIntoWaterTiles();
00927 
00928   if (_settings_game.game_creation.landscape == LT_TROPIC) CreateDesertOrRainForest();
00929 }
00930 
00931 void OnTick_Town();
00932 void OnTick_Trees();
00933 void OnTick_Station();
00934 void OnTick_Industry();
00935 
00936 void OnTick_Companies();
00937 void OnTick_Train();
00938 
00939 void CallLandscapeTick()
00940 {
00941   OnTick_Town();
00942   OnTick_Trees();
00943   OnTick_Station();
00944   OnTick_Industry();
00945 
00946   OnTick_Companies();
00947   OnTick_Train();
00948 }

Generated on Wed Dec 23 20:12:48 2009 for OpenTTD by  doxygen 1.5.6