From 9d4400c89f5faaa4d94f8aca41dc6924a40bd080 Mon Sep 17 00:00:00 2001 From: tron Date: Wed, 22 Feb 2006 21:09:55 +0000 Subject: (svn r3652) Rewrite CmdBuildTunnel in the hope to make it a bit more comprehensible This implementation is also significantly shorter because it removes many redundant checks --- tunnelbridge_cmd.c | 183 +++++++++++++++++------------------------------------ 1 file changed, 57 insertions(+), 126 deletions(-) (limited to 'tunnelbridge_cmd.c') diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index a56a7f593..a8e07e787 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -454,159 +454,90 @@ bool CheckTunnelInWay(TileIndex tile, int z) DoCheckTunnelInWay(tile,z,3); } -static byte _build_tunnel_bh; -static byte _build_tunnel_railtype; -static int32 DoBuildTunnel(int x, int y, int x2, int y2, uint32 flags, uint exc_tile) +/** Build Tunnel. + * @param x,y start tile coord of tunnel + * @param p1 railtype, 0x200 for road tunnel + * @param p2 unused + */ +int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2) { + TileIndexDiff delta; + TileIndex start_tile; TileIndex end_tile; - int direction; - int32 cost, ret; - TileInfo ti; - uint z; + DiagDirection direction; + uint start_tileh; + uint end_tileh; + uint start_z; + uint end_z; + int32 cost; + int32 ret; - if ((uint)x > MapMaxX() * 16 - 1 || (uint)y > MapMaxY() * 16 - 1) - return CMD_ERROR; - - /* check if valid, and make sure that (x,y) is smaller than (x2,y2) */ - direction = 0; - if (x == x2) { - if (y == y2) return_cmd_error(STR_5008_CANNOT_START_AND_END_ON); - direction++; - if (y > y2) { - intswap(y,y2); - intswap(x,x2); - exc_tile |= 2; - } - } else if (y == y2) { - if (x > x2) { - intswap(y,y2); - intswap(x,x2); - exc_tile |= 2; - } - } else { - return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN); - } + _build_tunnel_endtile = 0; - cost = 0; + if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR; - FindLandscapeHeight(&ti, x2, y2); - end_tile = ti.tile; - z = ti.z; + start_tile = TileVirtXY(x, y); + start_tileh = GetTileSlope(start_tile, &start_z); - if (exc_tile != 3) { - if ((direction ? 9U : 12U) != ti.tileh) - return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); - ret = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (CmdFailed(ret)) return CMD_ERROR; - cost += ret; + switch (start_tileh) { + case 3: direction = DIAGDIR_SW; break; + case 6: direction = DIAGDIR_SE; break; + case 9: direction = DIAGDIR_NW; break; + case 12: direction = DIAGDIR_NE; break; + default: return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL); } - cost += _price.build_tunnel; - for (;;) { - if (direction) y2-=16; else x2-=16; + ret = DoCommandByTile(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (CmdFailed(ret)) return ret; + cost = _price.build_tunnel + ret; - if (x2 == x && y2 == y) break; + delta = TileOffsByDir(direction); + end_tile = start_tile; + for (;;) { + end_tile += delta; + end_tileh = GetTileSlope(end_tile, &end_z); - FindLandscapeHeight(&ti, x2, y2); - if (ti.z <= z) return CMD_ERROR; + if (start_z == end_z) break; - if (!_cheats.crossing_tunnels.value && !CheckTunnelInWay(ti.tile, z)) + if (!_cheats.crossing_tunnels.value && !CheckTunnelInWay(end_tile, start_z)) { return CMD_ERROR; + } cost += _price.build_tunnel; - cost += (cost >> 3); - + cost += cost >> 3; if (cost >= 400000000) cost = 400000000; } - FindLandscapeHeight(&ti, x2, y2); - if (ti.z != z) return CMD_ERROR; + // if the command fails from here on we want the end tile to be highlighted + _build_tunnel_endtile = end_tile; - if (exc_tile != 1) { - if ((direction ? 6U : 3U) != ti.tileh) - return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); - - ret = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (CmdFailed(ret)) return CMD_ERROR; + // slope of end tile must be complementary to the slope of the start tile + if (end_tileh != (15 ^ start_tileh)) { + ret = DoCommandByTile(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); + if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); + } else { + ret = DoCommandByTile(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (CmdFailed(ret)) return ret; cost += ret; } + cost += _price.build_tunnel; if (flags & DC_EXEC) { - ModifyTile(ti.tile, - MP_SETTYPE(MP_TUNNELBRIDGE) | - MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5, - _build_tunnel_railtype, /* map3lo */ - ((_build_tunnel_bh << 1) | 2) - direction /* map5 */ - ); - - ModifyTile(end_tile, - MP_SETTYPE(MP_TUNNELBRIDGE) | - MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5, - _build_tunnel_railtype, /* map3lo */ - (_build_tunnel_bh << 1) | (direction ? 3:0)/* map5 */ - ); - - UpdateSignalsOnSegment(end_tile, direction?7:1); - } - - return cost + _price.build_tunnel; -} - -/** Build Tunnel. - * @param x,y start tile coord of tunnel - * @param p1 railtype, 0x200 for road tunnel - * @param p2 unused - */ -int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2) -{ - TileInfo ti, tiorg; - int direction; - uint z; - static const int8 _build_tunnel_coord_mod[4+1] = { -16, 0, 16, 0, -16 }; - static const byte _build_tunnel_tileh[4] = {3, 9, 12, 6}; - TileIndex excavated_tile; + 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 - SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + 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 (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR; - - _build_tunnel_railtype = GB(p1, 0, 8); - _build_tunnel_bh = GB(p1, 8, 8); - - _build_tunnel_endtile = 0; - excavated_tile = 0; - - FindLandscapeHeight(&tiorg, x, y); - - if (!EnsureNoVehicle(tiorg.tile)) - return CMD_ERROR; - - if (!(direction=0, tiorg.tileh == 12) && - !(direction++, tiorg.tileh == 6) && - !(direction++, tiorg.tileh == 3) && - !(direction++, tiorg.tileh == 9)) { - return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL); + if (GB(p1, 9, 1) == 0) UpdateSignalsOnSegment(start_tile, direction << 1); } - z = tiorg.z; - do { - x += _build_tunnel_coord_mod[direction]; - y += _build_tunnel_coord_mod[direction+1]; - FindLandscapeHeight(&ti, x, y); - } while (z != ti.z); - _build_tunnel_endtile = ti.tile; - - - if (!EnsureNoVehicle(ti.tile)) return CMD_ERROR; - - if (ti.tileh != _build_tunnel_tileh[direction]) { - if (CmdFailed(DoCommandByTile(ti.tile, ti.tileh & ~_build_tunnel_tileh[direction], 0, flags, CMD_TERRAFORM_LAND))) - return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); - excavated_tile = 1; - } - - return DoBuildTunnel(x, y, tiorg.x, tiorg.y, flags, excavated_tile); + return cost; } TileIndex CheckTunnelBusy(TileIndex tile, uint *length) -- cgit v1.2.3-54-g00ecf