tunnelbridge_cmd.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 
00016 #include "stdafx.h"
00017 #include "newgrf_object.h"
00018 #include "viewport_func.h"
00019 #include "cmd_helper.h"
00020 #include "command_func.h"
00021 #include "town.h"
00022 #include "train.h"
00023 #include "ship.h"
00024 #include "roadveh.h"
00025 #include "water_map.h"
00026 #include "pathfinder/yapf/yapf_cache.h"
00027 #include "newgrf_sound.h"
00028 #include "autoslope.h"
00029 #include "tunnelbridge_map.h"
00030 #include "strings_func.h"
00031 #include "date_func.h"
00032 #include "clear_func.h"
00033 #include "vehicle_func.h"
00034 #include "sound_func.h"
00035 #include "tunnelbridge.h"
00036 #include "cheat_type.h"
00037 #include "elrail_func.h"
00038 #include "pbs.h"
00039 #include "company_base.h"
00040 #include "newgrf_railtype.h"
00041 #include "object_base.h"
00042 #include "water.h"
00043 #include "company_gui.h"
00044 
00045 #include "table/sprites.h"
00046 #include "table/strings.h"
00047 #include "table/bridge_land.h"
00048 
00049 BridgeSpec _bridge[MAX_BRIDGES]; 
00050 TileIndex _build_tunnel_endtile; 
00051 
00053 static const int BRIDGE_Z_START = 3;
00054 
00056 void ResetBridges()
00057 {
00058   /* First, free sprite table data */
00059   for (BridgeType i = 0; i < MAX_BRIDGES; i++) {
00060     if (_bridge[i].sprite_table != NULL) {
00061       for (BridgePieces j = BRIDGE_PIECE_NORTH; j < BRIDGE_PIECE_INVALID; j++) free(_bridge[i].sprite_table[j]);
00062       free(_bridge[i].sprite_table);
00063     }
00064   }
00065 
00066   /* Then, wipe out current bidges */
00067   memset(&_bridge, 0, sizeof(_bridge));
00068   /* And finally, reinstall default data */
00069   memcpy(&_bridge, &_orig_bridge, sizeof(_orig_bridge));
00070 }
00071 
00078 int CalcBridgeLenCostFactor(int length)
00079 {
00080   if (length < 2) return length;
00081 
00082   length -= 2;
00083   int sum = 2;
00084   for (int delta = 1;; delta++) {
00085     for (int count = 0; count < delta; count++) {
00086       if (length == 0) return sum;
00087       sum += delta;
00088       length--;
00089     }
00090   }
00091 }
00092 
00099 Foundation GetBridgeFoundation(Slope tileh, Axis axis)
00100 {
00101   if (tileh == SLOPE_FLAT ||
00102       ((tileh == SLOPE_NE || tileh == SLOPE_SW) && axis == AXIS_X) ||
00103       ((tileh == SLOPE_NW || tileh == SLOPE_SE) && axis == AXIS_Y)) return FOUNDATION_NONE;
00104 
00105   return (HasSlopeHighestCorner(tileh) ? InclinedFoundation(axis) : FlatteningFoundation(tileh));
00106 }
00107 
00115 bool HasBridgeFlatRamp(Slope tileh, Axis axis)
00116 {
00117   ApplyFoundationToSlope(GetBridgeFoundation(tileh, axis), &tileh);
00118   /* If the foundation slope is flat the bridge has a non-flat ramp and vice versa. */
00119   return (tileh != SLOPE_FLAT);
00120 }
00121 
00122 static inline const PalSpriteID *GetBridgeSpriteTable(int index, BridgePieces table)
00123 {
00124   const BridgeSpec *bridge = GetBridgeSpec(index);
00125   assert(table < BRIDGE_PIECE_INVALID);
00126   if (bridge->sprite_table == NULL || bridge->sprite_table[table] == NULL) {
00127     return _bridge_sprite_table[index][table];
00128   } else {
00129     return bridge->sprite_table[table];
00130   }
00131 }
00132 
00133 
00142 static CommandCost CheckBridgeSlopeNorth(Axis axis, Slope *tileh, int *z)
00143 {
00144   Foundation f = GetBridgeFoundation(*tileh, axis);
00145   *z += ApplyFoundationToSlope(f, tileh);
00146 
00147   Slope valid_inclined = (axis == AXIS_X ? SLOPE_NE : SLOPE_NW);
00148   if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
00149 
00150   if (f == FOUNDATION_NONE) return CommandCost();
00151 
00152   return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
00153 }
00154 
00163 static CommandCost CheckBridgeSlopeSouth(Axis axis, Slope *tileh, int *z)
00164 {
00165   Foundation f = GetBridgeFoundation(*tileh, axis);
00166   *z += ApplyFoundationToSlope(f, tileh);
00167 
00168   Slope valid_inclined = (axis == AXIS_X ? SLOPE_SW : SLOPE_SE);
00169   if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
00170 
00171   if (f == FOUNDATION_NONE) return CommandCost();
00172 
00173   return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
00174 }
00175 
00182 CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags)
00183 {
00184   if (flags & DC_QUERY_COST) {
00185     if (bridge_len <= _settings_game.construction.max_bridge_length) return CommandCost();
00186     return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
00187   }
00188 
00189   if (bridge_type >= MAX_BRIDGES) return CMD_ERROR;
00190 
00191   const BridgeSpec *b = GetBridgeSpec(bridge_type);
00192   if (b->avail_year > _cur_year) return CMD_ERROR;
00193 
00194   uint max = min(b->max_length, _settings_game.construction.max_bridge_length);
00195 
00196   if (b->min_length > bridge_len) return CMD_ERROR;
00197   if (bridge_len <= max) return CommandCost();
00198   return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
00199 }
00200 
00213 CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00214 {
00215   RailType railtype = INVALID_RAILTYPE;
00216   RoadTypes roadtypes = ROADTYPES_NONE;
00217 
00218   /* unpack parameters */
00219   BridgeType bridge_type = GB(p2, 0, 8);
00220 
00221   if (!IsValidTile(p1)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
00222 
00223   TransportType transport_type = Extract<TransportType, 15, 2>(p2);
00224 
00225   /* type of bridge */
00226   switch (transport_type) {
00227     case TRANSPORT_ROAD:
00228       roadtypes = Extract<RoadTypes, 8, 2>(p2);
00229       if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR;
00230       break;
00231 
00232     case TRANSPORT_RAIL:
00233       railtype = Extract<RailType, 8, 4>(p2);
00234       if (!ValParamRailtype(railtype)) return CMD_ERROR;
00235       break;
00236 
00237     case TRANSPORT_WATER:
00238       break;
00239 
00240     default:
00241       /* Airports don't have bridges. */
00242       return CMD_ERROR;
00243   }
00244   TileIndex tile_start = p1;
00245   TileIndex tile_end = end_tile;
00246 
00247   if (tile_start == tile_end) {
00248     return_cmd_error(STR_ERROR_CAN_T_START_AND_END_ON);
00249   }
00250 
00251   Axis direction;
00252   if (TileX(tile_start) == TileX(tile_end)) {
00253     direction = AXIS_Y;
00254   } else if (TileY(tile_start) == TileY(tile_end)) {
00255     direction = AXIS_X;
00256   } else {
00257     return_cmd_error(STR_ERROR_START_AND_END_MUST_BE_IN);
00258   }
00259 
00260   if (tile_end < tile_start) Swap(tile_start, tile_end);
00261 
00262   uint bridge_len = GetTunnelBridgeLength(tile_start, tile_end);
00263   if (transport_type != TRANSPORT_WATER) {
00264     /* set and test bridge length, availability */
00265     CommandCost ret = CheckBridgeAvailability(bridge_type, bridge_len, flags);
00266     if (ret.Failed()) return ret;
00267   } else {
00268     if (bridge_len > _settings_game.construction.max_bridge_length) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
00269   }
00270 
00271   int z_start;
00272   int z_end;
00273   Slope tileh_start = GetTileSlope(tile_start, &z_start);
00274   Slope tileh_end = GetTileSlope(tile_end, &z_end);
00275   bool pbs_reservation = false;
00276 
00277   CommandCost terraform_cost_north = CheckBridgeSlopeNorth(direction, &tileh_start, &z_start);
00278   CommandCost terraform_cost_south = CheckBridgeSlopeSouth(direction, &tileh_end,   &z_end);
00279 
00280   /* Aqueducts can't be built of flat land. */
00281   if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00282   if (z_start != z_end) return_cmd_error(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT);
00283 
00284   CommandCost cost(EXPENSES_CONSTRUCTION);
00285   Owner owner;
00286   if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
00287       GetOtherBridgeEnd(tile_start) == tile_end &&
00288       GetTunnelBridgeTransportType(tile_start) == transport_type) {
00289     /* Replace a current bridge. */
00290 
00291     /* If this is a railway bridge, make sure the railtypes match. */
00292     if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
00293       return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00294     }
00295 
00296     /* Do not replace town bridges with lower speed bridges. */
00297     if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
00298         GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed) {
00299       Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
00300 
00301       if (t == NULL) {
00302         return CMD_ERROR;
00303       } else {
00304         SetDParam(0, t->index);
00305         return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
00306       }
00307     }
00308 
00309     /* Do not replace the bridge with the same bridge type. */
00310     if (!(flags & DC_QUERY_COST) && bridge_type == GetBridgeType(tile_start)) {
00311       return_cmd_error(STR_ERROR_ALREADY_BUILT);
00312     }
00313 
00314     /* Do not allow replacing another company's bridges. */
00315     if (!IsTileOwner(tile_start, _current_company) && !IsTileOwner(tile_start, OWNER_TOWN)) {
00316       return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
00317     }
00318 
00319     cost.AddCost((bridge_len + 1) * _price[PR_CLEAR_BRIDGE]); // The cost of clearing the current bridge.
00320     owner = GetTileOwner(tile_start);
00321 
00322     switch (transport_type) {
00323       case TRANSPORT_RAIL:
00324         /* Keep the reservation, the path stays valid. */
00325         pbs_reservation = HasTunnelBridgeReservation(tile_start);
00326         break;
00327 
00328       case TRANSPORT_ROAD:
00329         /* Do not remove road types when upgrading a bridge */
00330         roadtypes |= GetRoadTypes(tile_start);
00331         break;
00332 
00333       default: break;
00334     }
00335   } else {
00336     /* Build a new bridge. */
00337 
00338     bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
00339 
00340     /* Try and clear the start landscape */
00341     CommandCost ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00342     if (ret.Failed()) return ret;
00343     cost = ret;
00344 
00345     if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00346     cost.AddCost(terraform_cost_north);
00347 
00348     /* Try and clear the end landscape */
00349     ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00350     if (ret.Failed()) return ret;
00351     cost.AddCost(ret);
00352 
00353     /* false - end tile slope check */
00354     if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00355     cost.AddCost(terraform_cost_south);
00356 
00357     const TileIndex heads[] = {tile_start, tile_end};
00358     for (int i = 0; i < 2; i++) {
00359       if (MayHaveBridgeAbove(heads[i])) {
00360         if (IsBridgeAbove(heads[i])) {
00361           TileIndex north_head = GetNorthernBridgeEnd(heads[i]);
00362 
00363           if (direction == GetBridgeAxis(heads[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00364 
00365           if (z_start + 1 == GetBridgeHeight(north_head)) {
00366             return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00367           }
00368         }
00369       }
00370     }
00371 
00372     TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
00373     for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
00374       if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN);
00375 
00376       if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) {
00377         /* Disallow crossing bridges for the time being */
00378         return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00379       }
00380 
00381       switch (GetTileType(tile)) {
00382         case MP_WATER:
00383           if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
00384           break;
00385 
00386         case MP_RAILWAY:
00387           if (!IsPlainRail(tile)) goto not_valid_below;
00388           break;
00389 
00390         case MP_ROAD:
00391           if (IsRoadDepot(tile)) goto not_valid_below;
00392           break;
00393 
00394         case MP_TUNNELBRIDGE:
00395           if (IsTunnel(tile)) break;
00396           if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below;
00397           if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
00398           break;
00399 
00400         case MP_OBJECT: {
00401           const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
00402           if ((spec->flags & OBJECT_FLAG_ALLOW_UNDER_BRIDGE) == 0) goto not_valid_below;
00403           if (GetTileMaxZ(tile) + spec->height > z_start) goto not_valid_below;
00404           break;
00405         }
00406 
00407         case MP_CLEAR:
00408           break;
00409 
00410         default:
00411   not_valid_below:;
00412           /* try and clear the middle landscape */
00413           ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00414           if (ret.Failed()) return ret;
00415           cost.AddCost(ret);
00416           break;
00417       }
00418 
00419       if (flags & DC_EXEC) {
00420         /* We do this here because when replacing a bridge with another
00421          * type calling SetBridgeMiddle isn't needed. After all, the
00422          * tile alread has the has_bridge_above bits set. */
00423         SetBridgeMiddle(tile, direction);
00424       }
00425     }
00426 
00427     owner = _current_company;
00428   }
00429 
00430   /* do the drill? */
00431   if (flags & DC_EXEC) {
00432     DiagDirection dir = AxisToDiagDir(direction);
00433 
00434     Company *c = Company::GetIfValid(owner);
00435     switch (transport_type) {
00436       case TRANSPORT_RAIL:
00437         /* Add to company infrastructure count if building a new bridge. */
00438         if (!IsBridgeTile(tile_start) && c != NULL) c->infrastructure.rail[railtype] += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
00439         MakeRailBridgeRamp(tile_start, owner, bridge_type, dir,                 railtype);
00440         MakeRailBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), railtype);
00441         SetTunnelBridgeReservation(tile_start, pbs_reservation);
00442         SetTunnelBridgeReservation(tile_end,   pbs_reservation);
00443         break;
00444 
00445       case TRANSPORT_ROAD:
00446         if (c != NULL) {
00447           /* Add all new road types to the company infrastructure counter. */
00448           RoadType new_rt;
00449           FOR_EACH_SET_ROADTYPE(new_rt, roadtypes ^ (IsBridgeTile(tile_start) ? GetRoadTypes(tile_start) : ROADTYPES_NONE)) {
00450             /* A full diagonal road tile has two road bits. */
00451             Company::Get(owner)->infrastructure.road[new_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
00452           }
00453         }
00454         MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir,                 roadtypes);
00455         MakeRoadBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), roadtypes);
00456         break;
00457 
00458       case TRANSPORT_WATER:
00459         if (!IsBridgeTile(tile_start) && c != NULL) c->infrastructure.water += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
00460         MakeAqueductBridgeRamp(tile_start, owner, dir);
00461         MakeAqueductBridgeRamp(tile_end,   owner, ReverseDiagDir(dir));
00462         break;
00463 
00464       default:
00465         NOT_REACHED();
00466     }
00467 
00468     /* Mark all tiles dirty */
00469     TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
00470     for (TileIndex tile = tile_start; tile <= tile_end; tile += delta) {
00471       MarkTileDirtyByTile(tile);
00472     }
00473     DirtyCompanyInfrastructureWindows(owner);
00474   }
00475 
00476   if ((flags & DC_EXEC) && transport_type == TRANSPORT_RAIL) {
00477     Track track = AxisToTrack(direction);
00478     AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_company);
00479     YapfNotifyTrackLayoutChange(tile_start, track);
00480   }
00481 
00482   /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
00483    * It's unnecessary to execute this command every time for every bridge. So it is done only
00484    * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
00485    */
00486   Company *c = Company::GetIfValid(_current_company);
00487   if (!(flags & DC_QUERY_COST) || (c != NULL && c->is_ai)) {
00488     bridge_len += 2; // begin and end tiles/ramps
00489 
00490     switch (transport_type) {
00491       case TRANSPORT_ROAD: cost.AddCost(bridge_len * _price[PR_BUILD_ROAD] * 2 * CountBits(roadtypes)); break;
00492       case TRANSPORT_RAIL: cost.AddCost(bridge_len * RailBuildCost(railtype)); break;
00493       default: break;
00494     }
00495 
00496     if (c != NULL) bridge_len = CalcBridgeLenCostFactor(bridge_len);
00497 
00498     if (transport_type != TRANSPORT_WATER) {
00499       cost.AddCost((int64)bridge_len * _price[PR_BUILD_BRIDGE] * GetBridgeSpec(bridge_type)->price >> 8);
00500     } else {
00501       /* Aqueducts use a separate base cost. */
00502       cost.AddCost((int64)bridge_len * _price[PR_BUILD_AQUEDUCT]);
00503     }
00504 
00505   }
00506 
00507   return cost;
00508 }
00509 
00510 
00521 CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00522 {
00523   TransportType transport_type = Extract<TransportType, 8, 2>(p1);
00524 
00525   RailType railtype = INVALID_RAILTYPE;
00526   RoadTypes rts = ROADTYPES_NONE;
00527   _build_tunnel_endtile = 0;
00528   switch (transport_type) {
00529     case TRANSPORT_RAIL:
00530       railtype = Extract<RailType, 0, 4>(p1);
00531       if (!ValParamRailtype(railtype)) return CMD_ERROR;
00532       break;
00533 
00534     case TRANSPORT_ROAD:
00535       rts = Extract<RoadTypes, 0, 2>(p1);
00536       if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
00537       break;
00538 
00539     default: return CMD_ERROR;
00540   }
00541 
00542   int start_z;
00543   int end_z;
00544   Slope start_tileh = GetTileSlope(start_tile, &start_z);
00545   DiagDirection direction = GetInclinedSlopeDirection(start_tileh);
00546   if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL);
00547 
00548   if (HasTileWaterGround(start_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
00549 
00550   CommandCost ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00551   if (ret.Failed()) return ret;
00552 
00553   /* XXX - do NOT change 'ret' in the loop, as it is used as the price
00554    * for the clearing of the entrance of the tunnel. Assigning it to
00555    * cost before the loop will yield different costs depending on start-
00556    * position, because of increased-cost-by-length: 'cost += cost >> 3' */
00557 
00558   TileIndexDiff delta = TileOffsByDiagDir(direction);
00559   DiagDirection tunnel_in_way_dir;
00560   if (DiagDirToAxis(direction) == AXIS_Y) {
00561     tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
00562   } else {
00563     tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
00564   }
00565 
00566   TileIndex end_tile = start_tile;
00567 
00568   /* Tile shift coeficient. Will decrease for very long tunnels to avoid exponential growth of price*/
00569   int tiles_coef = 3;
00570   /* Number of tiles from start of tunnel */
00571   int tiles = 0;
00572   /* Number of tiles at which the cost increase coefficient per tile is halved */
00573   int tiles_bump = 25;
00574 
00575   CommandCost cost(EXPENSES_CONSTRUCTION);
00576   Slope end_tileh;
00577   for (;;) {
00578     end_tile += delta;
00579     if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER);
00580     end_tileh = GetTileSlope(end_tile, &end_z);
00581 
00582     if (start_z == end_z) break;
00583 
00584     if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
00585       return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY);
00586     }
00587 
00588     tiles++;
00589     if (tiles == tiles_bump) {
00590       tiles_coef++;
00591       tiles_bump *= 2;
00592     }
00593 
00594     cost.AddCost(_price[PR_BUILD_TUNNEL]);
00595     cost.AddCost(cost.GetCost() >> tiles_coef); // add a multiplier for longer tunnels
00596   }
00597 
00598   /* Add the cost of the entrance */
00599   cost.AddCost(_price[PR_BUILD_TUNNEL]);
00600   cost.AddCost(ret);
00601 
00602   /* if the command fails from here on we want the end tile to be highlighted */
00603   _build_tunnel_endtile = end_tile;
00604 
00605   if (tiles > _settings_game.construction.max_tunnel_length) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG);
00606 
00607   if (HasTileWaterGround(end_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
00608 
00609   /* Clear the tile in any case */
00610   ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00611   if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
00612   cost.AddCost(ret);
00613 
00614   /* slope of end tile must be complementary to the slope of the start tile */
00615   if (end_tileh != ComplementSlope(start_tileh)) {
00616     /* Mark the tile as already cleared for the terraform command.
00617      * Do this for all tiles (like trees), not only objects. */
00618     ClearedObjectArea *coa = FindClearedObject(end_tile);
00619     if (coa == NULL) {
00620       coa = _cleared_object_areas.Append();
00621       coa->first_tile = end_tile;
00622       coa->area = TileArea(end_tile, 1, 1);
00623     }
00624 
00625     /* Hide the tile from the terraforming command */
00626     TileIndex old_first_tile = coa->first_tile;
00627     coa->first_tile = INVALID_TILE;
00628     ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND);
00629     coa->first_tile = old_first_tile;
00630     if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
00631     cost.AddCost(ret);
00632   }
00633   cost.AddCost(_price[PR_BUILD_TUNNEL]);
00634 
00635   /* Pay for the rail/road in the tunnel including entrances */
00636   switch (transport_type) {
00637     case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * _price[PR_BUILD_ROAD] * 2); break;
00638     case TRANSPORT_RAIL: cost.AddCost((tiles + 2) * RailBuildCost(railtype)); break;
00639     default: break;
00640   }
00641 
00642   if (flags & DC_EXEC) {
00643     Company *c = Company::GetIfValid(_current_company);
00644     uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
00645     if (transport_type == TRANSPORT_RAIL) {
00646       if (!IsTunnelTile(start_tile) && c != NULL) c->infrastructure.rail[railtype] += num_pieces;
00647       MakeRailTunnel(start_tile, _current_company, direction,                 railtype);
00648       MakeRailTunnel(end_tile,   _current_company, ReverseDiagDir(direction), railtype);
00649       AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company);
00650       YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
00651     } else {
00652       if (c != NULL) {
00653         RoadType rt;
00654         FOR_EACH_SET_ROADTYPE(rt, rts ^ (IsTunnelTile(start_tile) ? GetRoadTypes(start_tile) : ROADTYPES_NONE)) {
00655           c->infrastructure.road[rt] += num_pieces * 2; // A full diagonal road has two road bits.
00656         }
00657       }
00658       MakeRoadTunnel(start_tile, _current_company, direction,                 rts);
00659       MakeRoadTunnel(end_tile,   _current_company, ReverseDiagDir(direction), rts);
00660     }
00661     DirtyCompanyInfrastructureWindows(_current_company);
00662   }
00663 
00664   return cost;
00665 }
00666 
00667 
00673 static inline CommandCost CheckAllowRemoveTunnelBridge(TileIndex tile)
00674 {
00675   /* Floods can remove anything as well as the scenario editor */
00676   if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return CommandCost();
00677 
00678   switch (GetTunnelBridgeTransportType(tile)) {
00679     case TRANSPORT_ROAD: {
00680       RoadTypes rts = GetRoadTypes(tile);
00681       Owner road_owner = _current_company;
00682       Owner tram_owner = _current_company;
00683 
00684       if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
00685       if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
00686 
00687       /* We can remove unowned road and if the town allows it */
00688       if (road_owner == OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) {
00689         return CheckTileOwnership(tile);
00690       }
00691       if (road_owner == OWNER_NONE || road_owner == OWNER_TOWN) road_owner = _current_company;
00692       if (tram_owner == OWNER_NONE) tram_owner = _current_company;
00693 
00694       CommandCost ret = CheckOwnership(road_owner, tile);
00695       if (ret.Succeeded()) ret = CheckOwnership(tram_owner, tile);
00696       return ret;
00697     }
00698 
00699     case TRANSPORT_RAIL:
00700       return CheckOwnership(GetTileOwner(tile));
00701 
00702     case TRANSPORT_WATER: {
00703       /* Always allow to remove aqueducts without owner. */
00704       Owner aqueduct_owner = GetTileOwner(tile);
00705       if (aqueduct_owner == OWNER_NONE) aqueduct_owner = _current_company;
00706       return CheckOwnership(aqueduct_owner);
00707     }
00708 
00709     default: NOT_REACHED();
00710   }
00711 }
00712 
00719 static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
00720 {
00721   CommandCost ret = CheckAllowRemoveTunnelBridge(tile);
00722   if (ret.Failed()) return ret;
00723 
00724   TileIndex endtile = GetOtherTunnelEnd(tile);
00725 
00726   ret = TunnelBridgeIsFree(tile, endtile);
00727   if (ret.Failed()) return ret;
00728 
00729   _build_tunnel_endtile = endtile;
00730 
00731   Town *t = NULL;
00732   if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00733     t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
00734 
00735     /* Check if you are allowed to remove the tunnel owned by a town
00736      * Removal depends on difficulty settings */
00737     CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
00738     if (ret.Failed()) return ret;
00739   }
00740 
00741   /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
00742    * you have a "Poor" (0) town rating */
00743   if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00744     ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
00745   }
00746 
00747   uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
00748 
00749   if (flags & DC_EXEC) {
00750     if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
00751       /* We first need to request values before calling DoClearSquare */
00752       DiagDirection dir = GetTunnelBridgeDirection(tile);
00753       Track track = DiagDirToDiagTrack(dir);
00754       Owner owner = GetTileOwner(tile);
00755 
00756       Train *v = NULL;
00757       if (HasTunnelBridgeReservation(tile)) {
00758         v = GetTrainForReservation(tile, track);
00759         if (v != NULL) FreeTrainTrackReservation(v);
00760       }
00761 
00762       if (Company::IsValidID(owner)) {
00763         Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
00764         DirtyCompanyInfrastructureWindows(owner);
00765       }
00766 
00767       DoClearSquare(tile);
00768       DoClearSquare(endtile);
00769 
00770       /* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
00771       AddSideToSignalBuffer(tile,    ReverseDiagDir(dir), owner);
00772       AddSideToSignalBuffer(endtile, dir,                 owner);
00773 
00774       YapfNotifyTrackLayoutChange(tile,    track);
00775       YapfNotifyTrackLayoutChange(endtile, track);
00776 
00777       if (v != NULL) TryPathReserve(v);
00778     } else {
00779       RoadType rt;
00780       FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
00781         /* A full diagonal road tile has two road bits. */
00782         Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
00783         if (c != NULL) {
00784           c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
00785           DirtyCompanyInfrastructureWindows(c->index);
00786         }
00787       }
00788 
00789       DoClearSquare(tile);
00790       DoClearSquare(endtile);
00791     }
00792   }
00793   return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_TUNNEL] * len);
00794 }
00795 
00796 
00803 static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
00804 {
00805   CommandCost ret = CheckAllowRemoveTunnelBridge(tile);
00806   if (ret.Failed()) return ret;
00807 
00808   TileIndex endtile = GetOtherBridgeEnd(tile);
00809 
00810   ret = TunnelBridgeIsFree(tile, endtile);
00811   if (ret.Failed()) return ret;
00812 
00813   DiagDirection direction = GetTunnelBridgeDirection(tile);
00814   TileIndexDiff delta = TileOffsByDiagDir(direction);
00815 
00816   Town *t = NULL;
00817   if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00818     t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
00819 
00820     /* Check if you are allowed to remove the bridge owned by a town
00821      * Removal depends on difficulty settings */
00822     CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
00823     if (ret.Failed()) return ret;
00824   }
00825 
00826   /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
00827    * you have a "Poor" (0) town rating */
00828   if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00829     ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
00830   }
00831 
00832   Money base_cost = (GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) ? _price[PR_CLEAR_BRIDGE] : _price[PR_CLEAR_AQUEDUCT];
00833   uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
00834 
00835   if (flags & DC_EXEC) {
00836     /* read this value before actual removal of bridge */
00837     bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
00838     Owner owner = GetTileOwner(tile);
00839     int height = GetBridgeHeight(tile);
00840     Train *v = NULL;
00841 
00842     if (rail && HasTunnelBridgeReservation(tile)) {
00843       v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
00844       if (v != NULL) FreeTrainTrackReservation(v);
00845     }
00846 
00847     /* Update company infrastructure counts. */
00848     if (rail) {
00849       if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
00850     } else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) {
00851       RoadType rt;
00852       FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
00853         Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
00854         if (c != NULL) {
00855           /* A full diagonal road tile has two road bits. */
00856           c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
00857           DirtyCompanyInfrastructureWindows(c->index);
00858         }
00859       }
00860     } else { // Aqueduct
00861       if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.water -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
00862     }
00863     DirtyCompanyInfrastructureWindows(owner);
00864 
00865     DoClearSquare(tile);
00866     DoClearSquare(endtile);
00867     for (TileIndex c = tile + delta; c != endtile; c += delta) {
00868       /* do not let trees appear from 'nowhere' after removing bridge */
00869       if (IsNormalRoadTile(c) && GetRoadside(c) == ROADSIDE_TREES) {
00870         int minz = GetTileMaxZ(c) + 3;
00871         if (height < minz) SetRoadside(c, ROADSIDE_PAVED);
00872       }
00873       ClearBridgeMiddle(c);
00874       MarkTileDirtyByTile(c);
00875     }
00876 
00877     if (rail) {
00878       /* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
00879       AddSideToSignalBuffer(tile,    ReverseDiagDir(direction), owner);
00880       AddSideToSignalBuffer(endtile, direction,                 owner);
00881 
00882       Track track = DiagDirToDiagTrack(direction);
00883       YapfNotifyTrackLayoutChange(tile,    track);
00884       YapfNotifyTrackLayoutChange(endtile, track);
00885 
00886       if (v != NULL) TryPathReserve(v, true);
00887     }
00888   }
00889 
00890   return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
00891 }
00892 
00899 static CommandCost ClearTile_TunnelBridge(TileIndex tile, DoCommandFlag flags)
00900 {
00901   if (IsTunnel(tile)) {
00902     if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST);
00903     return DoClearTunnel(tile, flags);
00904   } else { // IsBridge(tile)
00905     if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00906     return DoClearBridge(tile, flags);
00907   }
00908 }
00909 
00920 static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
00921 {
00922   static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START; 
00923   AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, w, h, BB_HEIGHT_UNDER_BRIDGE - PILLAR_Z_OFFSET, z, IsTransparencySet(TO_BRIDGES), 0, 0, -PILLAR_Z_OFFSET, subsprite);
00924 }
00925 
00937 static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, int x, int y, int w, int h)
00938 {
00939   int cur_z;
00940   for (cur_z = z_top; cur_z >= z_bottom; cur_z -= TILE_HEIGHT) {
00941     DrawPillar(psid, x, y, cur_z, w, h, NULL);
00942   }
00943   return cur_z;
00944 }
00945 
00957 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
00958 {
00959   static const int bounding_box_size[2]  = {16, 2}; 
00960   static const int back_pillar_offset[2] = { 0, 9}; 
00961 
00962   static const int INF = 1000; 
00963   static const SubSprite half_pillar_sub_sprite[2][2] = {
00964     { {  -14, -INF, INF, INF }, { -INF, -INF, -15, INF } }, // X axis, north and south
00965     { { -INF, -INF,  15, INF }, {   16, -INF, INF, INF } }, // Y axis, north and south
00966   };
00967 
00968   if (psid->sprite == 0) return;
00969 
00970   /* Determine ground height under pillars */
00971   DiagDirection south_dir = AxisToDiagDir(axis);
00972   int z_front_north = ti->z;
00973   int z_back_north = ti->z;
00974   int z_front_south = ti->z;
00975   int z_back_south = ti->z;
00976   GetSlopePixelZOnEdge(ti->tileh, south_dir, &z_front_south, &z_back_south);
00977   GetSlopePixelZOnEdge(ti->tileh, ReverseDiagDir(south_dir), &z_front_north, &z_back_north);
00978 
00979   /* Shared height of pillars */
00980   int z_front = max(z_front_north, z_front_south);
00981   int z_back = max(z_back_north, z_back_south);
00982 
00983   /* x and y size of bounding-box of pillars */
00984   int w = bounding_box_size[axis];
00985   int h = bounding_box_size[OtherAxis(axis)];
00986   /* sprite position of back facing pillar */
00987   int x_back = x - back_pillar_offset[axis];
00988   int y_back = y - back_pillar_offset[OtherAxis(axis)];
00989 
00990   /* Draw front pillars */
00991   int bottom_z = DrawPillarColumn(z_front, z_bridge, psid, x, y, w, h);
00992   if (z_front_north < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
00993   if (z_front_south < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
00994 
00995   /* Draw back pillars, skip top two parts, which are hidden by the bridge */
00996   int z_bridge_back = z_bridge - 2 * (int)TILE_HEIGHT;
00997   if (drawfarpillar && (z_back_north <= z_bridge_back || z_back_south <= z_bridge_back)) {
00998     bottom_z = DrawPillarColumn(z_back, z_bridge_back, psid, x_back, y_back, w, h);
00999     if (z_back_north < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
01000     if (z_back_south < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
01001   }
01002 }
01003 
01013 static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head)
01014 {
01015   static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
01016   static const SpriteID back_offsets[6]    =   {  95,  96,  99, 102, 100, 101 };
01017   static const SpriteID front_offsets[6]   =   {  97,  98, 103, 106, 104, 105 };
01018 
01019   static const uint size_x[6] = {  1, 16, 16,  1, 16,  1 };
01020   static const uint size_y[6] = { 16,  1,  1, 16,  1, 16 };
01021   static const uint front_bb_offset_x[6] = { 15,  0,  0, 15,  0, 15 };
01022   static const uint front_bb_offset_y[6] = {  0, 15, 15,  0, 15,  0 };
01023 
01024   /* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
01025    * The bounding boxes here are the same as for bridge front/roof */
01026   if (head || !IsInvisibilitySet(TO_BRIDGES)) {
01027     AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE,
01028       x, y, size_x[offset], size_y[offset], 0x28, z,
01029       !head && IsTransparencySet(TO_BRIDGES));
01030   }
01031 
01032   /* Do not draw catenary if it is set invisible */
01033   if (!IsInvisibilitySet(TO_CATENARY)) {
01034     AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NONE,
01035       x, y, size_x[offset], size_y[offset], 0x28, z,
01036       IsTransparencySet(TO_CATENARY));
01037   }
01038 
01039   /* Start a new SpriteCombine for the front part */
01040   EndSpriteCombine();
01041   StartSpriteCombine();
01042 
01043   /* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */
01044   if (!IsInvisibilitySet(TO_CATENARY)) {
01045     AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE,
01046       x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
01047       IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]);
01048   }
01049 }
01050 
01064 static void DrawTile_TunnelBridge(TileInfo *ti)
01065 {
01066   TransportType transport_type = GetTunnelBridgeTransportType(ti->tile);
01067   DiagDirection tunnelbridge_direction = GetTunnelBridgeDirection(ti->tile);
01068 
01069   if (IsTunnel(ti->tile)) {
01070     /* Front view of tunnel bounding boxes:
01071      *
01072      *   122223  <- BB_Z_SEPARATOR
01073      *   1    3
01074      *   1    3                1,3 = empty helper BB
01075      *   1    3                  2 = SpriteCombine of tunnel-roof and catenary (tram & elrail)
01076      *
01077      */
01078 
01079     static const int _tunnel_BB[4][12] = {
01080       /*  tunnnel-roof  |  Z-separator  | tram-catenary
01081        * w  h  bb_x bb_y| x   y   w   h |bb_x bb_y w h */
01082       {  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // NE
01083       {  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // SE
01084       {  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // SW
01085       {  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // NW
01086     };
01087     const int *BB_data = _tunnel_BB[tunnelbridge_direction];
01088 
01089     bool catenary = false;
01090 
01091     SpriteID image;
01092     if (transport_type == TRANSPORT_RAIL) {
01093       image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.tunnel;
01094     } else {
01095       image = SPR_TUNNEL_ENTRY_REAR_ROAD;
01096     }
01097 
01098     if (HasTunnelBridgeSnowOrDesert(ti->tile)) image += 32;
01099 
01100     image += tunnelbridge_direction * 2;
01101     DrawGroundSprite(image, PAL_NONE);
01102 
01103     /* PBS debugging, draw reserved tracks darker */
01104     if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && (transport_type == TRANSPORT_RAIL && HasTunnelBridgeReservation(ti->tile))) {
01105       const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
01106       DrawGroundSprite(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH);
01107     }
01108 
01109     if (transport_type == TRANSPORT_ROAD) {
01110       RoadTypes rts = GetRoadTypes(ti->tile);
01111 
01112       if (HasBit(rts, ROADTYPE_TRAM)) {
01113         static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, {  5, 76, 77,  4 } };
01114 
01115         DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][tunnelbridge_direction], PAL_NONE);
01116 
01117         /* Do not draw wires if they are invisible */
01118         if (!IsInvisibilitySet(TO_CATENARY)) {
01119           catenary = true;
01120           StartSpriteCombine();
01121           AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
01122         }
01123       }
01124     } else {
01125       const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
01126       if (rti->UsesOverlay()) {
01127         SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL);
01128         if (surface != 0) DrawGroundSprite(surface + tunnelbridge_direction, PAL_NONE);
01129       }
01130 
01131       if (HasCatenaryDrawn(GetRailType(ti->tile))) {
01132         /* Maybe draw pylons on the entry side */
01133         DrawCatenary(ti);
01134 
01135         catenary = true;
01136         StartSpriteCombine();
01137         /* Draw wire above the ramp */
01138         DrawCatenaryOnTunnel(ti);
01139       }
01140     }
01141 
01142     AddSortableSpriteToDraw(image + 1, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, BB_data[0], BB_data[1], TILE_HEIGHT, ti->z, false, BB_data[2], BB_data[3], BB_Z_SEPARATOR);
01143 
01144     if (catenary) EndSpriteCombine();
01145 
01146     /* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
01147     AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x,              ti->y,              BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
01148     AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x + BB_data[4], ti->y + BB_data[5], BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
01149 
01150     DrawBridgeMiddle(ti);
01151   } else { // IsBridge(ti->tile)
01152     const PalSpriteID *psid;
01153     int base_offset;
01154     bool ice = HasTunnelBridgeSnowOrDesert(ti->tile);
01155 
01156     if (transport_type == TRANSPORT_RAIL) {
01157       base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
01158       assert(base_offset != 8); // This one is used for roads
01159     } else {
01160       base_offset = 8;
01161     }
01162 
01163     /* as the lower 3 bits are used for other stuff, make sure they are clear */
01164     assert( (base_offset & 0x07) == 0x00);
01165 
01166     DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(tunnelbridge_direction)));
01167 
01168     /* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
01169     base_offset += (6 - tunnelbridge_direction) % 4;
01170 
01171     if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
01172 
01173     /* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
01174     if (transport_type != TRANSPORT_WATER) {
01175       psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD)[base_offset];
01176     } else {
01177       psid = _aqueduct_sprites + base_offset;
01178     }
01179 
01180     if (!ice) {
01181       TileIndex next = ti->tile + TileOffsByDiagDir(tunnelbridge_direction);
01182       if (ti->tileh != SLOPE_FLAT && ti->z == 0 && HasTileWaterClass(next) && GetWaterClass(next) == WATER_CLASS_SEA) {
01183         DrawShoreTile(ti->tileh);
01184       } else {
01185         DrawClearLandTile(ti, 3);
01186       }
01187     } else {
01188       DrawGroundSprite(SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
01189     }
01190 
01191     /* draw ramp */
01192 
01193     /* Draw Trambits and PBS Reservation as SpriteCombine */
01194     if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
01195 
01196     /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
01197      * it doesn't disappear behind it
01198      */
01199     /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
01200     AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
01201 
01202     if (transport_type == TRANSPORT_ROAD) {
01203       RoadTypes rts = GetRoadTypes(ti->tile);
01204 
01205       if (HasBit(rts, ROADTYPE_TRAM)) {
01206         uint offset = tunnelbridge_direction;
01207         int z = ti->z;
01208         if (ti->tileh != SLOPE_FLAT) {
01209           offset = (offset + 1) & 1;
01210           z += TILE_HEIGHT;
01211         } else {
01212           offset += 2;
01213         }
01214         /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
01215         DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
01216       }
01217       EndSpriteCombine();
01218     } else if (transport_type == TRANSPORT_RAIL) {
01219       const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
01220       if (rti->UsesOverlay()) {
01221         SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE);
01222         if (surface != 0) {
01223           if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
01224             AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, ti->x, ti->y, 16, 16, 0, ti->z + 8);
01225           } else {
01226             AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, 16, 16, 8, ti->z);
01227           }
01228         }
01229         /* Don't fallback to non-overlay sprite -- the spec states that
01230          * if an overlay is present then the bridge surface must be
01231          * present. */
01232       } else if (_game_mode != GM_MENU &&_settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
01233         if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
01234           AddSortableSpriteToDraw(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
01235         } else {
01236           AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
01237         }
01238       }
01239       EndSpriteCombine();
01240       if (HasCatenaryDrawn(GetRailType(ti->tile))) {
01241         DrawCatenary(ti);
01242       }
01243     }
01244 
01245     DrawBridgeMiddle(ti);
01246   }
01247 }
01248 
01249 
01268 static BridgePieces CalcBridgePiece(uint north, uint south)
01269 {
01270   if (north == 1) {
01271     return BRIDGE_PIECE_NORTH;
01272   } else if (south == 1) {
01273     return BRIDGE_PIECE_SOUTH;
01274   } else if (north < south) {
01275     return north & 1 ? BRIDGE_PIECE_INNER_SOUTH : BRIDGE_PIECE_INNER_NORTH;
01276   } else if (north > south) {
01277     return south & 1 ? BRIDGE_PIECE_INNER_NORTH : BRIDGE_PIECE_INNER_SOUTH;
01278   } else {
01279     return north & 1 ? BRIDGE_PIECE_MIDDLE_EVEN : BRIDGE_PIECE_MIDDLE_ODD;
01280   }
01281 }
01282 
01287 void DrawBridgeMiddle(const TileInfo *ti)
01288 {
01289   /* Sectional view of bridge bounding boxes:
01290    *
01291    *  1           2                                1,2 = SpriteCombine of Bridge front/(back&floor) and TramCatenary
01292    *  1           2                                  3 = empty helper BB
01293    *  1     7     2                                4,5 = pillars under higher bridges
01294    *  1 6 88888 6 2                                  6 = elrail-pylons
01295    *  1 6 88888 6 2                                  7 = elrail-wire
01296    *  1 6 88888 6 2  <- TILE_HEIGHT                  8 = rail-vehicle on bridge
01297    *  3333333333333  <- BB_Z_SEPARATOR
01298    *                 <- unused
01299    *    4       5    <- BB_HEIGHT_UNDER_BRIDGE
01300    *    4       5
01301    *    4       5
01302    *
01303    */
01304 
01305   if (!IsBridgeAbove(ti->tile)) return;
01306 
01307   TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile);
01308   TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile);
01309   TransportType transport_type = GetTunnelBridgeTransportType(rampsouth);
01310 
01311   Axis axis = GetBridgeAxis(ti->tile);
01312   BridgePieces piece = CalcBridgePiece(
01313     GetTunnelBridgeLength(ti->tile, rampnorth) + 1,
01314     GetTunnelBridgeLength(ti->tile, rampsouth) + 1
01315   );
01316 
01317   const PalSpriteID *psid;
01318   bool drawfarpillar;
01319   if (transport_type != TRANSPORT_WATER) {
01320     BridgeType type =  GetBridgeType(rampsouth);
01321     drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
01322 
01323     uint base_offset;
01324     if (transport_type == TRANSPORT_RAIL) {
01325       base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
01326     } else {
01327       base_offset = 8;
01328     }
01329 
01330     psid = base_offset + GetBridgeSpriteTable(type, piece);
01331   } else {
01332     drawfarpillar = true;
01333     psid = _aqueduct_sprites;
01334   }
01335 
01336   if (axis != AXIS_X) psid += 4;
01337 
01338   int x = ti->x;
01339   int y = ti->y;
01340   uint bridge_z = GetBridgePixelHeight(rampsouth);
01341   int z = bridge_z - BRIDGE_Z_START;
01342 
01343   /* Add a bounding box that separates the bridge from things below it. */
01344   AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
01345 
01346   /* Draw Trambits as SpriteCombine */
01347   if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
01348 
01349   /* Draw floor and far part of bridge*/
01350   if (!IsInvisibilitySet(TO_BRIDGES)) {
01351     if (axis == AXIS_X) {
01352       AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
01353     } else {
01354       AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
01355     }
01356   }
01357 
01358   psid++;
01359 
01360   if (transport_type == TRANSPORT_ROAD) {
01361     RoadTypes rts = GetRoadTypes(rampsouth);
01362 
01363     if (HasBit(rts, ROADTYPE_TRAM)) {
01364       /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
01365       DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD), false);
01366     } else {
01367       EndSpriteCombine();
01368       StartSpriteCombine();
01369     }
01370   } else if (transport_type == TRANSPORT_RAIL) {
01371     const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth));
01372     if (rti->UsesOverlay()) {
01373       SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE);
01374       if (surface != 0) {
01375         AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
01376       }
01377     }
01378     EndSpriteCombine();
01379 
01380     if (HasCatenaryDrawn(GetRailType(rampsouth))) {
01381       DrawCatenaryOnBridge(ti);
01382     }
01383   }
01384 
01385   /* draw roof, the component of the bridge which is logically between the vehicle and the camera */
01386   if (!IsInvisibilitySet(TO_BRIDGES)) {
01387     if (axis == AXIS_X) {
01388       y += 12;
01389       if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
01390     } else {
01391       x += 12;
01392       if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
01393     }
01394   }
01395 
01396   /* Draw TramFront as SpriteCombine */
01397   if (transport_type == TRANSPORT_ROAD) EndSpriteCombine();
01398 
01399   /* Do not draw anything more if bridges are invisible */
01400   if (IsInvisibilitySet(TO_BRIDGES)) return;
01401 
01402   psid++;
01403   if (ti->z + 5 == z) {
01404     /* draw poles below for small bridges */
01405     if (psid->sprite != 0) {
01406       SpriteID image = psid->sprite;
01407       SpriteID pal   = psid->pal;
01408       if (IsTransparencySet(TO_BRIDGES)) {
01409         SetBit(image, PALETTE_MODIFIER_TRANSPARENT);
01410         pal = PALETTE_TO_TRANSPARENT;
01411       }
01412 
01413       DrawGroundSpriteAt(image, pal, x - ti->x, y - ti->y, z - ti->z);
01414     }
01415   } else {
01416     /* draw pillars below for high bridges */
01417     DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
01418   }
01419 }
01420 
01421 
01422 static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
01423 {
01424   int z;
01425   Slope tileh = GetTilePixelSlope(tile, &z);
01426 
01427   x &= 0xF;
01428   y &= 0xF;
01429 
01430   if (IsTunnel(tile)) {
01431     uint pos = (DiagDirToAxis(GetTunnelBridgeDirection(tile)) == AXIS_X ? y : x);
01432 
01433     /* In the tunnel entrance? */
01434     if (5 <= pos && pos <= 10) return z;
01435   } else { // IsBridge(tile)
01436     DiagDirection dir = GetTunnelBridgeDirection(tile);
01437     uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
01438 
01439     z += ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh, DiagDirToAxis(dir)), &tileh);
01440 
01441     /* On the bridge ramp? */
01442     if (5 <= pos && pos <= 10) {
01443       int delta;
01444 
01445       if (tileh != SLOPE_FLAT) return z + TILE_HEIGHT;
01446 
01447       switch (dir) {
01448         default: NOT_REACHED();
01449         case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
01450         case DIAGDIR_SE: delta = y / 2; break;
01451         case DIAGDIR_SW: delta = x / 2; break;
01452         case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
01453       }
01454       return z + 1 + delta;
01455     }
01456   }
01457 
01458   return z + GetPartialPixelZ(x, y, tileh);
01459 }
01460 
01461 static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
01462 {
01463   return IsTunnel(tile) ? FOUNDATION_NONE : GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(tile)));
01464 }
01465 
01466 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
01467 {
01468   TransportType tt = GetTunnelBridgeTransportType(tile);
01469 
01470   if (IsTunnel(tile)) {
01471     td->str = (tt == TRANSPORT_RAIL) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD;
01472   } else { // IsBridge(tile)
01473     td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
01474   }
01475   td->owner[0] = GetTileOwner(tile);
01476 
01477   Owner road_owner = INVALID_OWNER;
01478   Owner tram_owner = INVALID_OWNER;
01479   RoadTypes rts = GetRoadTypes(tile);
01480   if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
01481   if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
01482 
01483   /* Is there a mix of owners? */
01484   if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
01485       (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
01486     uint i = 1;
01487     if (road_owner != INVALID_OWNER) {
01488       td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
01489       td->owner[i] = road_owner;
01490       i++;
01491     }
01492     if (tram_owner != INVALID_OWNER) {
01493       td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
01494       td->owner[i] = tram_owner;
01495     }
01496   }
01497 
01498   if (tt == TRANSPORT_RAIL) {
01499     const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
01500     td->rail_speed = rti->max_speed;
01501 
01502     if (!IsTunnel(tile)) {
01503       uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
01504       if (td->rail_speed == 0 || spd < td->rail_speed) {
01505         td->rail_speed = spd;
01506       }
01507     }
01508   }
01509 }
01510 
01511 
01512 static void TileLoop_TunnelBridge(TileIndex tile)
01513 {
01514   bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile);
01515   switch (_settings_game.game_creation.landscape) {
01516     case LT_ARCTIC: {
01517       /* As long as we do not have a snow density, we want to use the density
01518        * from the entry endge. For tunnels this is the lowest point for bridges the highest point.
01519        * (Independent of foundations) */
01520       int z = IsBridge(tile) ? GetTileMaxZ(tile) : GetTileZ(tile);
01521       if (snow_or_desert != (z > GetSnowLine())) {
01522         SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
01523         MarkTileDirtyByTile(tile);
01524       }
01525       break;
01526     }
01527 
01528     case LT_TROPIC:
01529       if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
01530         SetTunnelBridgeSnowOrDesert(tile, true);
01531         MarkTileDirtyByTile(tile);
01532       }
01533       break;
01534 
01535     default:
01536       break;
01537   }
01538 }
01539 
01540 static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
01541 {
01542   TransportType transport_type = GetTunnelBridgeTransportType(tile);
01543   if (transport_type != mode || (transport_type == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0)) return 0;
01544 
01545   DiagDirection dir = GetTunnelBridgeDirection(tile);
01546   if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
01547   return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
01548 }
01549 
01550 static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
01551 {
01552   TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
01553   /* Set number of pieces to zero if it's the southern tile as we
01554    * don't want to update the infrastructure counts twice. */
01555   uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
01556 
01557   for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
01558     /* Update all roadtypes, no matter if they are present */
01559     if (GetRoadOwner(tile, rt) == old_owner) {
01560       if (HasBit(GetRoadTypes(tile), rt)) {
01561         /* Update company infrastructure counts. A full diagonal road tile has two road bits.
01562          * No need to dirty windows here, we'll redraw the whole screen anyway. */
01563         Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2;
01564         if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2;
01565       }
01566 
01567       SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
01568     }
01569   }
01570 
01571   if (!IsTileOwner(tile, old_owner)) return;
01572 
01573   /* Update company infrastructure counts for rail and water as well.
01574    * No need to dirty windows here, we'll redraw the whole screen anyway. */
01575   TransportType tt = GetTunnelBridgeTransportType(tile);
01576   Company *old = Company::Get(old_owner);
01577   if (tt == TRANSPORT_RAIL) {
01578     old->infrastructure.rail[GetRailType(tile)] -= num_pieces;
01579     if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += num_pieces;
01580   } else if (tt == TRANSPORT_WATER) {
01581     old->infrastructure.water -= num_pieces;
01582     if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.water += num_pieces;
01583   }
01584 
01585   if (new_owner != INVALID_OWNER) {
01586     SetTileOwner(tile, new_owner);
01587   } else {
01588     if (tt == TRANSPORT_RAIL) {
01589       /* Since all of our vehicles have been removed, it is safe to remove the rail
01590        * bridge / tunnel. */
01591       CommandCost ret = DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
01592       assert(ret.Succeeded());
01593     } else {
01594       /* In any other case, we can safely reassign the ownership to OWNER_NONE. */
01595       SetTileOwner(tile, OWNER_NONE);
01596     }
01597   }
01598 }
01599 
01605 static const byte TUNNEL_SOUND_FRAME = 1;
01606 
01615 extern const byte _tunnel_visibility_frame[DIAGDIR_END] = {12, 8, 8, 12};
01616 
01617 static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
01618 {
01619   int z = GetSlopePixelZ(x, y) - v->z_pos;
01620 
01621   if (abs(z) > 2) return VETSB_CANNOT_ENTER;
01622   /* Direction into the wormhole */
01623   const DiagDirection dir = GetTunnelBridgeDirection(tile);
01624   /* Direction of the vehicle */
01625   const DiagDirection vdir = DirToDiagDir(v->direction);
01626   /* New position of the vehicle on the tile */
01627   byte pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK;
01628   /* Number of units moved by the vehicle since entering the tile */
01629   byte frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
01630 
01631   if (IsTunnel(tile)) {
01632     if (v->type == VEH_TRAIN) {
01633       Train *t = Train::From(v);
01634 
01635       if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
01636         if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) {
01637           if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
01638             SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
01639           }
01640           return VETSB_CONTINUE;
01641         }
01642         if (frame == _tunnel_visibility_frame[dir]) {
01643           t->tile = tile;
01644           t->track = TRACK_BIT_WORMHOLE;
01645           t->vehstatus |= VS_HIDDEN;
01646           return VETSB_ENTERED_WORMHOLE;
01647         }
01648       }
01649 
01650       if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
01651         /* We're at the tunnel exit ?? */
01652         t->tile = tile;
01653         t->track = DiagDirToDiagTrackBits(vdir);
01654         assert(t->track);
01655         t->vehstatus &= ~VS_HIDDEN;
01656         return VETSB_ENTERED_WORMHOLE;
01657       }
01658     } else if (v->type == VEH_ROAD) {
01659       RoadVehicle *rv = RoadVehicle::From(v);
01660 
01661       /* Enter tunnel? */
01662       if (rv->state != RVSB_WORMHOLE && dir == vdir) {
01663         if (frame == _tunnel_visibility_frame[dir]) {
01664           /* Frame should be equal to the next frame number in the RV's movement */
01665           assert(frame == rv->frame + 1);
01666           rv->tile = tile;
01667           rv->state = RVSB_WORMHOLE;
01668           rv->vehstatus |= VS_HIDDEN;
01669           return VETSB_ENTERED_WORMHOLE;
01670         } else {
01671           return VETSB_CONTINUE;
01672         }
01673       }
01674 
01675       /* We're at the tunnel exit ?? */
01676       if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
01677         rv->tile = tile;
01678         rv->state = DiagDirToDiagTrackdir(vdir);
01679         rv->frame = frame;
01680         rv->vehstatus &= ~VS_HIDDEN;
01681         return VETSB_ENTERED_WORMHOLE;
01682       }
01683     }
01684   } else { // IsBridge(tile)
01685     if (v->type != VEH_SHIP) {
01686       /* modify speed of vehicle */
01687       uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
01688 
01689       if (v->type == VEH_ROAD) spd *= 2;
01690       Vehicle *first = v->First();
01691       first->cur_speed = min(first->cur_speed, spd);
01692     }
01693 
01694     if (vdir == dir) {
01695       /* Vehicle enters bridge at the last frame inside this tile. */
01696       if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
01697       switch (v->type) {
01698         case VEH_TRAIN: {
01699           Train *t = Train::From(v);
01700           t->track = TRACK_BIT_WORMHOLE;
01701           ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
01702           ClrBit(t->gv_flags, GVF_GOINGDOWN_BIT);
01703           break;
01704         }
01705 
01706         case VEH_ROAD: {
01707           RoadVehicle *rv = RoadVehicle::From(v);
01708           rv->state = RVSB_WORMHOLE;
01709           /* There are no slopes inside bridges / tunnels. */
01710           ClrBit(rv->gv_flags, GVF_GOINGUP_BIT);
01711           ClrBit(rv->gv_flags, GVF_GOINGDOWN_BIT);
01712           break;
01713         }
01714 
01715         case VEH_SHIP:
01716           Ship::From(v)->state = TRACK_BIT_WORMHOLE;
01717           break;
01718 
01719         default: NOT_REACHED();
01720       }
01721       return VETSB_ENTERED_WORMHOLE;
01722     } else if (vdir == ReverseDiagDir(dir)) {
01723       v->tile = tile;
01724       switch (v->type) {
01725         case VEH_TRAIN: {
01726           Train *t = Train::From(v);
01727           if (t->track == TRACK_BIT_WORMHOLE) {
01728             t->track = DiagDirToDiagTrackBits(vdir);
01729             return VETSB_ENTERED_WORMHOLE;
01730           }
01731           break;
01732         }
01733 
01734         case VEH_ROAD: {
01735           RoadVehicle *rv = RoadVehicle::From(v);
01736           if (rv->state == RVSB_WORMHOLE) {
01737             rv->state = DiagDirToDiagTrackdir(vdir);
01738             rv->frame = 0;
01739             return VETSB_ENTERED_WORMHOLE;
01740           }
01741           break;
01742         }
01743 
01744         case VEH_SHIP: {
01745           Ship *ship = Ship::From(v);
01746           if (ship->state == TRACK_BIT_WORMHOLE) {
01747             ship->state = DiagDirToDiagTrackBits(vdir);
01748             return VETSB_ENTERED_WORMHOLE;
01749           }
01750           break;
01751         }
01752 
01753         default: NOT_REACHED();
01754       }
01755     }
01756   }
01757   return VETSB_CONTINUE;
01758 }
01759 
01760 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
01761 {
01762   if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() && IsBridge(tile) && GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) {
01763     DiagDirection direction = GetTunnelBridgeDirection(tile);
01764     Axis axis = DiagDirToAxis(direction);
01765     CommandCost res;
01766     int z_old;
01767     Slope tileh_old = GetTileSlope(tile, &z_old);
01768 
01769     /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
01770     if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
01771       CheckBridgeSlopeSouth(axis, &tileh_old, &z_old);
01772       res = CheckBridgeSlopeSouth(axis, &tileh_new, &z_new);
01773     } else {
01774       CheckBridgeSlopeNorth(axis, &tileh_old, &z_old);
01775       res = CheckBridgeSlopeNorth(axis, &tileh_new, &z_new);
01776     }
01777 
01778     /* Surface slope is valid and remains unchanged? */
01779     if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
01780   }
01781 
01782   return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
01783 }
01784 
01785 extern const TileTypeProcs _tile_type_tunnelbridge_procs = {
01786   DrawTile_TunnelBridge,           // draw_tile_proc
01787   GetSlopePixelZ_TunnelBridge,     // get_slope_z_proc
01788   ClearTile_TunnelBridge,          // clear_tile_proc
01789   NULL,                            // add_accepted_cargo_proc
01790   GetTileDesc_TunnelBridge,        // get_tile_desc_proc
01791   GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc
01792   NULL,                            // click_tile_proc
01793   NULL,                            // animate_tile_proc
01794   TileLoop_TunnelBridge,           // tile_loop_proc
01795   ChangeTileOwner_TunnelBridge,    // change_tile_owner_proc
01796   NULL,                            // add_produced_cargo_proc
01797   VehicleEnter_TunnelBridge,       // vehicle_enter_tile_proc
01798   GetFoundation_TunnelBridge,      // get_foundation_proc
01799   TerraformTile_TunnelBridge,      // terraform_tile_proc
01800 };