src/tunnelbridge_cmd.cpp
branchnoai
changeset 9629 66dde6412125
parent 9627 6a7c8ead2328
child 9631 8a2d1c2ceb88
--- a/src/tunnelbridge_cmd.cpp	Sun Jun 17 21:31:00 2007 +0000
+++ b/src/tunnelbridge_cmd.cpp	Tue Jun 26 23:40:58 2007 +0000
@@ -110,32 +110,32 @@
  * - rest is invalid
  */
 #define M(x) (1 << (x))
-static int32 CheckBridgeSlopeNorth(Axis axis, Slope tileh)
+static CommandCost CheckBridgeSlopeNorth(Axis axis, Slope tileh)
 {
 	uint32 valid;
 
 	valid = M(SLOPE_FLAT) | (axis == AXIS_X ? M(SLOPE_NE) : M(SLOPE_NW));
-	if (HASBIT(valid, tileh)) return 0;
+	if (HASBIT(valid, tileh)) return CommandCost();
 
 	valid =
 		BRIDGE_FULL_LEVELED_FOUNDATION | M(SLOPE_N) | M(SLOPE_STEEP_N) |
 		(axis == AXIS_X ? M(SLOPE_E) | M(SLOPE_STEEP_E) : M(SLOPE_W) | M(SLOPE_STEEP_W));
-	if (HASBIT(valid, tileh)) return _price.terraform;
+	if (HASBIT(valid, tileh)) return CommandCost(_price.terraform);
 
 	return CMD_ERROR;
 }
 
-static int32 CheckBridgeSlopeSouth(Axis axis, Slope tileh)
+static CommandCost CheckBridgeSlopeSouth(Axis axis, Slope tileh)
 {
 	uint32 valid;
 
 	valid = M(SLOPE_FLAT) | (axis == AXIS_X ? M(SLOPE_SW) : M(SLOPE_SE));
-	if (HASBIT(valid, tileh)) return 0;
+	if (HASBIT(valid, tileh)) return CommandCost();
 
 	valid =
 		BRIDGE_FULL_LEVELED_FOUNDATION | M(SLOPE_S) | M(SLOPE_STEEP_S) |
 		(axis == AXIS_X ? M(SLOPE_W) | M(SLOPE_STEEP_W) : M(SLOPE_E) | M(SLOPE_STEEP_E));
-	if (HASBIT(valid, tileh)) return _price.terraform;
+	if (HASBIT(valid, tileh)) return CommandCost(_price.terraform);
 
 	return CMD_ERROR;
 }
@@ -175,7 +175,7 @@
  * - p2 = (bit 8-..) - rail type or road types.
  * - p2 = (bit 15  ) - set means road bridge.
  */
-int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	uint bridge_type;
 	RailType railtype;
@@ -194,7 +194,7 @@
 	TileIndexDiff delta;
 	uint bridge_len;
 	Axis direction;
-	int32 cost, terraformcost, ret;
+	CommandCost cost, terraformcost, ret;
 	bool allow_on_slopes;
 	bool replace_bridge = false;
 	uint replaced_bridge_type;
@@ -300,7 +300,7 @@
 			return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
 		}
 
-		cost = (bridge_len + 1) * _price.clear_bridge; // The cost of clearing the current bridge.
+		cost.AddCost((bridge_len + 1) * _price.clear_bridge); // The cost of clearing the current bridge.
 		replace_bridge = true;
 		replaced_bridge_type = GetBridgeType(tile_start);
 
@@ -315,20 +315,20 @@
 		cost = ret;
 
 		terraformcost = CheckBridgeSlopeNorth(direction, tileh_start);
-		if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
+		if (CmdFailed(terraformcost) || (terraformcost.GetCost() != 0 && !allow_on_slopes))
 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
-		cost += terraformcost;
+		cost.AddCost(terraformcost);
 
 		/* Try and clear the end landscape */
 		ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 		if (CmdFailed(ret)) return ret;
-		cost += ret;
+		cost.AddCost(ret);
 
 		/* false - end tile slope check */
 		terraformcost = CheckBridgeSlopeSouth(direction, tileh_end);
-		if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
+		if (CmdFailed(terraformcost) || (terraformcost.GetCost() != 0 && !allow_on_slopes))
 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
-		cost += terraformcost;
+		cost.AddCost(terraformcost);
 	}
 
 	if (!replace_bridge) {
@@ -411,7 +411,7 @@
 				/* try and clear the middle landscape */
 				ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 				if (CmdFailed(ret)) return ret;
-				cost += ret;
+				cost.AddCost(ret);
 				break;
 		}
 
@@ -439,7 +439,7 @@
 		if (IsValidPlayer(_current_player))
 			bridge_len = CalcBridgeLenCostFactor(bridge_len);
 
-		cost += (int64)bridge_len * _price.build_bridge * b->price >> 8;
+		cost.AddCost((int64)bridge_len * _price.build_bridge * b->price >> 8);
 	}
 
 	return cost;
@@ -452,7 +452,7 @@
  * @param p1 railtype or roadtypes. bit 9 set means road tunnel
  * @param p2 unused
  */
-int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	TileIndexDiff delta;
 	TileIndex end_tile;
@@ -461,8 +461,8 @@
 	Slope end_tileh;
 	uint start_z;
 	uint end_z;
-	int32 cost;
-	int32 ret;
+	CommandCost cost;
+	CommandCost ret;
 
 	_build_tunnel_endtile = 0;
 	if (!HASBIT(p1, 9)) {
@@ -488,8 +488,15 @@
 	 * for the clearing of the entrance of the tunnel. Assigning it to
 	 * cost before the loop will yield different costs depending on start-
 	 * position, because of increased-cost-by-length: 'cost += cost >> 3' */
-	cost = 0;
+
 	delta = TileOffsByDiagDir(direction);
+	DiagDirection tunnel_in_way_dir;
+	if (OtherAxis(DiagDirToAxis(direction)) == AXIS_X) {
+		tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
+	} else {
+		tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
+	}
+
 	end_tile = start_tile;
 	for (;;) {
 		end_tile += delta;
@@ -497,30 +504,40 @@
 
 		if (start_z == end_z) break;
 
-		if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z)) {
+		if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
 			return_cmd_error(STR_5003_ANOTHER_TUNNEL_IN_THE_WAY);
 		}
 
-		cost += _price.build_tunnel;
-		cost += cost >> 3; // add a multiplier for longer tunnels
-		if (cost >= 400000000) cost = 400000000;
+		cost.AddCost(_price.build_tunnel);
+		cost.AddCost(cost.GetCost() >> 3); // add a multiplier for longer tunnels
 	}
 
 	/* Add the cost of the entrance */
-	cost += _price.build_tunnel + ret;
+	cost.AddCost(_price.build_tunnel);
+	cost.AddCost(ret);
 
 	/* if the command fails from here on we want the end tile to be highlighted */
 	_build_tunnel_endtile = end_tile;
 
 	/* slope of end tile must be complementary to the slope of the start tile */
 	if (end_tileh != ComplementSlope(start_tileh)) {
+		/* Some (rail) track bits might be terraformed into the correct direction,
+		 * but that would still leave tracks on foundation. Therefor excavation will
+		 * always fail for rail tiles. On the other hand, for road tiles it might
+		 * succeed when there is only one road bit on the tile, but then that road
+		 * bit is removed leaving a clear tile.
+		 * This therefor preserves the behaviour that half road tiles are always removable.
+		 */
+		if (IsTileType(end_tile, MP_RAILWAY)) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
+
 		ret = DoCommand(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 = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 		if (CmdFailed(ret)) return ret;
 	}
-	cost += _price.build_tunnel + ret;
+	cost.AddCost(_price.build_tunnel);
+	cost.AddCost(ret);
 
 	if (flags & DC_EXEC) {
 		if (GB(p1, 9, 1) == TRANSPORT_RAIL) {
@@ -577,7 +594,7 @@
 	return false;
 }
 
-static int32 DoClearTunnel(TileIndex tile, uint32 flags)
+static CommandCost DoClearTunnel(TileIndex tile, uint32 flags)
 {
 	Town *t = NULL;
 	TileIndex endtile;
@@ -621,7 +638,7 @@
 		YapfNotifyTrackLayoutChange(tile, track);
 		YapfNotifyTrackLayoutChange(endtile, track);
 	}
-	return _price.clear_tunnel * (length + 1);
+	return CommandCost(_price.clear_tunnel * (length + 1));
 }
 
 
@@ -637,7 +654,7 @@
 	return false;
 }
 
-static int32 DoClearBridge(TileIndex tile, uint32 flags)
+static CommandCost DoClearBridge(TileIndex tile, uint32 flags)
 {
 	DiagDirection direction;
 	TileIndexDiff delta;
@@ -694,10 +711,10 @@
 		YapfNotifyTrackLayoutChange(endtile, track);
 	}
 
-	return (DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge;
+	return CommandCost((DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge);
 }
 
-static int32 ClearTile_TunnelBridge(TileIndex tile, byte flags)
+static CommandCost ClearTile_TunnelBridge(TileIndex tile, byte flags)
 {
 	if (IsTunnel(tile)) {
 		if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
@@ -720,7 +737,7 @@
  * @return            The cost and state of the operation
  * @retval CMD_ERROR  An error occured during the operation.
  */
-int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
+CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
 {
 	TileIndex endtile;
 
@@ -748,7 +765,7 @@
 			YapfNotifyTrackLayoutChange(tile, track);
 			YapfNotifyTrackLayoutChange(endtile, track);
 		}
-		return (length + 1) * (_price.build_rail / 2);
+		return CommandCost((length + 1) * (_price.build_rail / 2));
 	} else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
 
 		if (!CheckTileOwnership(tile)) return CMD_ERROR;
@@ -783,7 +800,7 @@
 			}
 		}
 
-		return (DistanceManhattan(tile, endtile) + 1) * (_price.build_rail / 2);
+		return CommandCost((DistanceManhattan(tile, endtile) + 1) * (_price.build_rail / 2));
 	} else {
 		return CMD_ERROR;
 	}
@@ -1008,6 +1025,8 @@
 		}
 
 		DrawBridgeMiddle(ti);
+	} else {
+		NOT_REACHED();
 	}
 }