diff --git a/Makefile b/Makefile index 0bb4372153..59079a8b47 100644 --- a/Makefile +++ b/Makefile @@ -700,6 +700,7 @@ SRCS += town_gui.c SRCS += train_cmd.c SRCS += train_gui.c SRCS += tree_cmd.c +SRCS += tunnel_map.c SRCS += tunnelbridge_cmd.c SRCS += unmovable_cmd.c SRCS += vehicle.c diff --git a/direction.h b/direction.h index 33c465aac2..fb99071f3a 100644 --- a/direction.h +++ b/direction.h @@ -52,4 +52,10 @@ typedef enum Axis { AXIS_Y = 1 } Axis; + +static inline Axis DiagDirToAxis(DiagDirection d) +{ + return (Axis)(d & 1); +} + #endif diff --git a/npf.c b/npf.c index abefe239df..18818f6799 100644 --- a/npf.c +++ b/npf.c @@ -11,6 +11,7 @@ #include "station.h" #include "tile.h" #include "depot.h" +#include "tunnel_map.h" static AyStar _npf_aystar; @@ -162,7 +163,7 @@ static uint NPFTunnelCost(AyStarNode* current) { DiagDirection exitdir = TrackdirToExitdir((Trackdir)current->direction); TileIndex tile = current->tile; - if ((DiagDirection)GB(_m[tile].m5, 0, 2) == ReverseDiagDir(exitdir)) { + if (GetTunnelDirection(tile) == ReverseDiagDir(exitdir)) { /* We just popped out if this tunnel, since were * facing the tunnel exit */ FindLengthOfTunnelResult flotr; @@ -519,7 +520,7 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current) /* Find dest tile */ if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GB(_m[src_tile].m5, 4, 4) == 0 && - (DiagDirection)GB(_m[src_tile].m5, 0, 2) == src_exitdir) { + GetTunnelDirection(src_tile) == src_exitdir) { /* This is a tunnel. We know this tunnel is our type, * otherwise we wouldn't have got here. It is also facing us, * so we should skip it's body */ diff --git a/pathfind.c b/pathfind.c index 8e0621bd9e..b0518f6fd1 100644 --- a/pathfind.c +++ b/pathfind.c @@ -8,6 +8,7 @@ #include "pathfind.h" #include "rail.h" #include "debug.h" +#include "tunnel_map.h" #include "variables.h" // remember which tiles we have already visited so we don't visit them again. @@ -232,8 +233,8 @@ FindLengthOfTunnelResult FindLengthOfTunnel(TileIndex tile, uint direction) if (IsTileType(tile, MP_TUNNELBRIDGE) && GB(_m[tile].m5, 4, 4) == 0 && // tunnel entrance/exit - // GB(_m[tile].m5, 2, 2) == type && // rail/road-tunnel <-- This is not necesary to check, right? - (GB(_m[tile].m5, 0, 2) ^ 2) == direction && // entrance towards: 0 = NE, 1 = SE, 2 = SW, 3 = NW + // GetTunnelTransportType(tile) == type && // rail/road-tunnel <-- This is not necesary to check, right? + ReverseDiagDir(GetTunnelDirection(tile)) == direction && GetSlopeZ(x + 8, y + 8) == z) { break; } @@ -283,8 +284,8 @@ static void TPFMode1(TrackPathFinder* tpf, TileIndex tile, DiagDirection directi TileIndex tile_org = tile; if (IsTileType(tile, MP_TUNNELBRIDGE) && GB(_m[tile].m5, 4, 4) == 0) { - if (GB(_m[tile].m5, 0, 2) != direction || - GB(_m[tile].m5, 2, 2) != tpf->tracktype) { + if (GetTunnelDirection(tile) != direction || + GetTunnelTransportType(tile) != tpf->tracktype) { return; } tile = SkipToEndOfTunnel(tpf, tile, direction); @@ -717,13 +718,14 @@ start_at: // need to find the exit of the tunnel. if (IsTileType(tile, MP_TUNNELBRIDGE)) { if (GB(_m[tile].m5, 4, 4) == 0 && - GB(_m[tile].m5, 0, 2) != (direction ^ 2)) { + GetTunnelDirection(tile) != ReverseDiagDir(direction)) { /* This is a tunnel tile */ /* We are not just driving out of the tunnel */ - if (GB(_m[tile].m5, 0, 2) != direction || GB(_m[tile].m5, 2, 2) != tpf->tracktype) - /* We are not driving into the tunnel, or it - * is an invalid tunnel */ + if (GetTunnelDirection(tile) != direction || + GetTunnelTransportType(tile) != tpf->tracktype) { + // We are not driving into the tunnel, or it is an invalid tunnel continue; + } flotr = FindLengthOfTunnel(tile, direction); si.cur_length += flotr.length * DIAG_FACTOR; tile = flotr.tile; diff --git a/rail_cmd.c b/rail_cmd.c index f00ca595c0..3aad4431e3 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -10,6 +10,7 @@ #include "table/strings.h" #include "map.h" #include "tile.h" +#include "tunnel_map.h" #include "vehicle.h" #include "viewport.h" #include "command.h" @@ -1627,21 +1628,21 @@ static bool SignalVehicleCheck(TileIndex tile, uint track) if (IsTileType(tile, MP_TUNNELBRIDGE) && GB(_m[tile].m5, 4, 4) == 0) { // It is a tunnel we're checking, we need to do some special stuff // because VehicleFromPos will not find the vihicle otherwise - byte direction = GB(_m[tile].m5, 0, 2); - FindLengthOfTunnelResult flotr; - flotr = FindLengthOfTunnel(tile, direction); + TileIndex end = GetOtherTunnelEnd(tile); + DiagDirection direction = GetTunnelDirection(tile); + dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible) // check for a vehicle with that trackdir on the start tile of the tunnel if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true; // check for a vehicle with that trackdir on the end tile of the tunnel - if (VehicleFromPos(flotr.tile, &dest, SignalVehicleCheckProc) != NULL) return true; + if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true; // now check all tiles from start to end for a "hidden" vehicle // NOTE: the hashes for tiles may overlap, so this could maybe be optimised a bit by not checking every tile? dest.track = 0x40; // trackbit for vehicles "hidden" inside a tunnel - for (; tile != flotr.tile; tile += TileOffsByDir(direction)) { + for (; tile != end; tile += TileOffsByDir(direction)) { if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true; } diff --git a/road_map.c b/road_map.c index 45aba06057..14611e88bd 100644 --- a/road_map.c +++ b/road_map.c @@ -5,6 +5,7 @@ #include "functions.h" #include "road_map.h" #include "station.h" +#include "tunnel_map.h" RoadBits GetAnyRoadBits(TileIndex tile) @@ -36,8 +37,8 @@ RoadBits GetAnyRoadBits(TileIndex tile) } } else { // tunnel - if (GB(_m[tile].m5, 2, 2) != TRANSPORT_ROAD) return 0; // not a road tunnel - return DiagDirToRoadBits(ReverseDiagDir(GB(_m[tile].m5, 0, 2))); + if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) return 0; + return DiagDirToRoadBits(ReverseDiagDir(GetTunnelDirection(tile))); } default: return 0; diff --git a/town_cmd.c b/town_cmd.c index 920601397e..9813f5312b 100644 --- a/town_cmd.c +++ b/town_cmd.c @@ -9,10 +9,10 @@ #include "table/sprites.h" #include "map.h" #include "tile.h" +#include "tunnel_map.h" #include "viewport.h" #include "town.h" #include "command.h" -#include "pathfind.h" #include "gfx.h" #include "industry.h" #include "station.h" @@ -624,9 +624,10 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town* int i; // Reached a tunnel? Then continue at the other side of it. - if (IsTileType(tile, MP_TUNNELBRIDGE) && (_m[tile].m5& ~3) == 4) { - FindLengthOfTunnelResult flotr = FindLengthOfTunnel(tile, GB(_m[tile].m5, 0, 2)); - *tile_ptr = flotr.tile; + if (IsTileType(tile, MP_TUNNELBRIDGE) && + GB(_m[tile].m5, 4, 4) == 0 && + GetTunnelTransportType(tile) == TRANSPORT_ROAD) { + *tile_ptr = GetOtherTunnelEnd(tile); return; } diff --git a/train_cmd.c b/train_cmd.c index 291c2ea016..4d0f434ae9 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -8,6 +8,7 @@ #include "table/strings.h" #include "map.h" #include "tile.h" +#include "tunnel_map.h" #include "vehicle.h" #include "command.h" #include "pathfind.h" @@ -3121,8 +3122,10 @@ static bool TrainCheckIfLineEnds(Vehicle *v) tile = v->tile; // tunnel entrance? - if (IsTunnelTile(tile) && DiagDirToDir(GB(_m[tile].m5, 0, 2)) == v->direction) + if (IsTunnelTile(tile) && + DiagDirToDir(GetTunnelDirection(tile)) == v->direction) { return true; + } // depot? /* XXX -- When enabled, this makes it possible to crash trains of others diff --git a/tunnel_map.c b/tunnel_map.c new file mode 100644 index 0000000000..d39c7ef042 --- /dev/null +++ b/tunnel_map.c @@ -0,0 +1,25 @@ +/* $Id$ */ + +#include "stdafx.h" +#include "openttd.h" +#include "tile.h" +#include "tunnel_map.h" + +TileIndex GetOtherTunnelEnd(TileIndex tile) +{ + DiagDirection dir = GetTunnelDirection(tile); + TileIndexDiff delta = TileOffsByDir(dir); + uint z = GetTileZ(tile); + + dir = ReverseDiagDir(dir); + do { + tile += delta; + } while ( + !IsTileType(tile, MP_TUNNELBRIDGE) || + GB(_m[tile].m5, 4, 4) != 0 || + GetTunnelDirection(tile) != dir || + GetTileZ(tile) != z + ); + + return tile; +} diff --git a/tunnel_map.h b/tunnel_map.h new file mode 100644 index 0000000000..aa30e12c3a --- /dev/null +++ b/tunnel_map.h @@ -0,0 +1,47 @@ +/* $Id$ */ + +#ifndef TUNNEL_MAP_H +#define TUNNEL_MAP_H + +#include "direction.h" +#include "macros.h" +#include "map.h" +#include "rail.h" + + +static inline DiagDirection GetTunnelDirection(TileIndex t) +{ + return (DiagDirection)GB(_m[t].m5, 0, 2); +} + + +static inline TransportType GetTunnelTransportType(TileIndex t) +{ + return (TransportType)GB(_m[t].m5, 2, 2); +} + + +TileIndex GetOtherTunnelEnd(TileIndex); + + +static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d) +{ + SetTileType(t, MP_TUNNELBRIDGE); + SetTileOwner(t, o); + _m[t].m2 = 0; + _m[t].m3 = 0; + _m[t].m4 = 0; + _m[t].m5 = TRANSPORT_ROAD << 2 | d; +} + +static inline void MakeRailTunnel(TileIndex t, Owner o, DiagDirection d, RailType r) +{ + SetTileType(t, MP_TUNNELBRIDGE); + SetTileOwner(t, o); + _m[t].m2 = 0; + _m[t].m3 = r; + _m[t].m4 = 0; + _m[t].m5 = TRANSPORT_RAIL << 2 | d; +} + +#endif diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index 982b81d9c2..50f38f16e9 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -13,6 +13,7 @@ #include "functions.h" #include "map.h" #include "tile.h" +#include "tunnel_map.h" #include "vehicle.h" #include "viewport.h" #include "command.h" @@ -440,7 +441,7 @@ static bool DoCheckTunnelInWay(TileIndex tile, uint z, DiagDirection dir) if (z == height && IsTileType(tile, MP_TUNNELBRIDGE) && GB(_m[tile].m5, 4, 4) == 0 && - GB(_m[tile].m5, 0, 2) == dir) { + GetTunnelDirection(tile) == dir) { _error_message = STR_5003_ANOTHER_TUNNEL_IN_THE_WAY; return false; } @@ -526,15 +527,13 @@ int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2) cost += _price.build_tunnel + ret; if (flags & DC_EXEC) { - SetTileType(start_tile, MP_TUNNELBRIDGE); - SetTileOwner(start_tile, _current_player); - _m[start_tile].m3 = GB(p1, 0, 4); // rail type (if any) - _m[start_tile].m5 = (GB(p1, 9, 1) << 2) | direction; // transport type and entrance direction - - SetTileType(end_tile, MP_TUNNELBRIDGE); - SetTileOwner(end_tile, _current_player); - _m[end_tile].m3 = GB(p1, 0, 4); // rail type (if any) - _m[end_tile].m5 = (GB(p1, 9, 1) << 2) | (direction ^ 2); // transport type and entrance direction + if (GB(p1, 9, 1) == TRANSPORT_RAIL) { + MakeRailTunnel(start_tile, _current_player, direction, GB(p1, 0, 4)); + MakeRailTunnel(end_tile, _current_player, ReverseDiagDir(direction), GB(p1, 0, 4)); + } else { + MakeRoadTunnel(start_tile, _current_player, direction); + MakeRoadTunnel(end_tile, _current_player, ReverseDiagDir(direction)); + } if (GB(p1, 9, 1) == 0) UpdateSignalsOnSegment(start_tile, DiagDirToDir(direction)); } @@ -545,8 +544,8 @@ int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2) TileIndex CheckTunnelBusy(TileIndex tile, uint *length) { uint z = GetTileZ(tile); - byte m5 = _m[tile].m5; - TileIndexDiff delta = TileOffsByDir(m5 & 3); + DiagDirection dir = GetTunnelDirection(tile); + TileIndexDiff delta = TileOffsByDir(dir); uint len = 0; TileIndex starttile = tile; Vehicle *v; @@ -557,7 +556,7 @@ TileIndex CheckTunnelBusy(TileIndex tile, uint *length) } while ( !IsTileType(tile, MP_TUNNELBRIDGE) || GB(_m[tile].m5, 4, 4) != 0 || - (_m[tile].m5 ^ 2) != m5 || + ReverseDiagDir(GetTunnelDirection(tile)) != dir || GetTileZ(tile) != z ); @@ -605,8 +604,8 @@ static int32 DoClearTunnel(TileIndex tile, uint32 flags) if (flags & DC_EXEC) { // We first need to request the direction before calling DoClearSquare // else the direction is always 0.. dah!! ;) - byte tile_dir = GB(_m[tile].m5, 0, 2); - byte endtile_dir = GB(_m[endtile].m5, 0, 2); + DiagDirection tile_dir = GetTunnelDirection(tile); + DiagDirection endtile_dir = GetTunnelDirection(endtile); // Adjust the town's player rating. Do this before removing the tile owner info. if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) @@ -996,7 +995,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) // draw tunnel? if ((ti->map5 & 0xF0) == 0) { - if (GB(ti->map5, 2, 2) == 0) { /* Rail tunnel? */ + if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) { image = GetRailTypeInfo(GB(_m[ti->tile].m3, 0, 4))->base_sprites.tunnel; } else { image = SPR_TUNNEL_ENTRY_REAR_ROAD; @@ -1004,7 +1003,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) if (ice) image += 32; - image += GB(ti->map5, 0, 2) * 2; + image += GetTunnelDirection(ti->tile) * 2; DrawGroundSprite(image); AddSortableSpriteToDraw(image+1, ti->x + 15, ti->y + 15, 1, 1, 8, (byte)ti->z); @@ -1266,8 +1265,8 @@ static const StringID _bridge_tile_str[(MAX_BRIDGES + 3) + (MAX_BRIDGES + 3)] = static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td) { if ((_m[tile].m5 & 0x80) == 0) { - td->str = - (GB(_m[tile].m5, 2, 2) == 0) ? STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL; + td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ? + STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL; } else { td->str = _bridge_tile_str[GB(_m[tile].m5, 1, 2) << 4 | GB(_m[tile].m2, 4, 4)]; @@ -1329,9 +1328,8 @@ static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode if ((m5 & 0xF0) == 0) { /* This is a tunnel */ - if (GB(m5, 2, 2) == mode) { - /* Tranport in the tunnel is compatible */ - return m5&1 ? 0x202 : 0x101; + if (GetTunnelTransportType(tile) == mode) { + return DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? 0x101 : 0x202; } } else if (m5 & 0x80) { /* This is a bridge */ @@ -1419,7 +1417,7 @@ static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y if (v->type == VEH_Train) { fc = (x & 0xF) + (y << 4); - dir = GB(_m[tile].m5, 0, 2); + dir = GetTunnelDirection(tile); vdir = DirToDiagDir(v->direction); if (v->u.rail.track != 0x40 && dir == vdir) { @@ -1446,7 +1444,7 @@ static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y } } else if (v->type == VEH_Road) { fc = (x & 0xF) + (y << 4); - dir = GB(_m[tile].m5, 0, 2); + dir = GetTunnelDirection(tile); vdir = DirToDiagDir(v->direction); // Enter tunnel?