summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortron <tron@openttd.org>2006-02-22 21:09:55 +0000
committertron <tron@openttd.org>2006-02-22 21:09:55 +0000
commit9d4400c89f5faaa4d94f8aca41dc6924a40bd080 (patch)
tree31da74e699446fb7c61427f8ee5862e9e0e322ff
parent9541bea15baf6223508f554565598b49b10914ae (diff)
downloadopenttd-9d4400c89f5faaa4d94f8aca41dc6924a40bd080.tar.xz
(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
-rw-r--r--tunnelbridge_cmd.c183
1 files changed, 57 insertions, 126 deletions
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)