/**
* Helper function
*
* @param bridge_tile
* @param bridge_dir
* @return true
* @see GrowTownWithBridge
*/
static bool IsPossibleLockLocationOnTownBridgeTile(const TileIndex bridge_tile, const DiagDirection bridge_dir)
{
const DiagDirection dir_side = ChangeDiagDir(bridge_dir, DIAGDIRDIFF_90LEFT);
const int delta_side = TileOffsByDiagDir(dir_side);
if (IsValidTile(bridge_tile) && IsPossibleLockLocationOnDiagDir(bridge_tile, bridge_dir, true) && IsWaterTile(bridge_tile) ||
IsValidTile(bridge_tile + delta_side) && IsPossibleLockLocationOnDiagDir(bridge_tile + delta_side, dir_side, true) && IsWaterTile(bridge_tile + delta_side) ||
IsValidTile(bridge_tile - delta_side) && IsPossibleLockLocationOnDiagDir(bridge_tile - delta_side, ReverseDiagDir(dir_side), true) && IsWaterTile(bridge_tile - delta_side)) {
return true;
}
return false;
}
/**
* Grows the town with a bridge.
* At first we check if a bridge is reasonable.
* If so we check if we are able to build it.
*
* @param t The current town
* @param tile The current tile
* @param bridge_dir The valid direction in which to grow a bridge
* @return true if a bridge has been build else false
*/
static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDirection bridge_dir)
{
assert(bridge_dir < DIAGDIR_END);
const Slope slope = GetTileSlope(tile);
/* Make sure the direction is compatible with the slope.
* Well we check if the slope has an up bit set in the
* reverse direction. */
if (slope != SLOPE_FLAT && slope & InclinedSlope(bridge_dir)) return false;
/* Assure that the bridge is connectable to the start side */
if (!(GetTownRoadBits(TileAddByDiagDir(tile, ReverseDiagDir(bridge_dir))) & DiagDirToRoadBits(bridge_dir))) return false;
/* We are in the right direction */
uint8 bridge_length = 0; // This value stores the length of the possible bridge
TileIndex bridge_tile = tile; // Used to store the other waterside
const int delta = TileOffsByDiagDir(bridge_dir);
// const int delta_side = TileOffsByDiagDir(ChangeDiagDir(bridge_dir, DIAGDIRDIFF_90LEFT));
if (slope == SLOPE_FLAT) {
/* Bridges starting on flat tiles are only allowed when crossing rivers. */
do {
if (bridge_length++ >= 4) {
/* Allow to cross rivers, not big lakes. */
return false;
}
bridge_tile += delta;
if (IsPossibleLockLocationOnTownBridgeTile(bridge_tile, bridge_dir)) return false;
// if (IsValidTile(bridge_tile) && IsPossibleLockLocationOnDiagDir(bridge_tile, bridge_dir, true) && IsWaterTile(bridge_tile) ||
// IsValidTile(bridge_tile + delta_side) && IsPossibleLockLocationOnDiagDir(bridge_tile + delta_side, ChangeDiagDir(bridge_dir, DIAGDIRDIFF_90LEFT), true) && IsWaterTile(bridge_tile + delta_side) ||
// IsValidTile(bridge_tile - delta_side) && IsPossibleLockLocationOnDiagDir(bridge_tile - delta_side, ChangeDiagDir(bridge_dir, DIAGDIRDIFF_90RIGHT), true) && IsWaterTile(bridge_tile - delta_side)) {
// return false;
// }
} while (IsValidTile(bridge_tile) && IsWaterTile(bridge_tile) && !IsSea(bridge_tile));
} else {
do {
if (bridge_length++ >= 11) {
/* Max 11 tile long bridges */
return false;
}
bridge_tile += delta;
if (IsPossibleLockLocationOnTownBridgeTile(bridge_tile, bridge_dir)) return false;
// if (IsValidTile(bridge_tile) && IsPossibleLockLocationOnDiagDir(bridge_tile, bridge_dir, true) && IsWaterTile(bridge_tile) ||
// IsValidTile(bridge_tile + delta_side) && IsPossibleLockLocationOnDiagDir(bridge_tile + delta_side, ChangeDiagDir(bridge_dir, DIAGDIRDIFF_90LEFT), true) && IsWaterTile(bridge_tile + delta_side) ||
// IsValidTile(bridge_tile - delta_side) && IsPossibleLockLocationOnDiagDir(bridge_tile - delta_side, ChangeDiagDir(bridge_dir, DIAGDIRDIFF_90RIGHT), true) && IsWaterTile(bridge_tile - delta_side)) {
// return false;
// }
} while (IsValidTile(bridge_tile) && IsWaterTile(bridge_tile));
}
/* no water tiles in between? */
if (bridge_length == 1) return false;
for (uint8 times = 0; times <= 22; times++) {
byte bridge_type = RandomRange(MAX_BRIDGES - 1);
/* Can we actually build the bridge? */
if (DoCommand(tile, bridge_tile, bridge_type | ROADTYPES_ROAD << 8 | TRANSPORT_ROAD << 15, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE).Succeeded()) {
DoCommand(tile, bridge_tile, bridge_type | ROADTYPES_ROAD << 8 | TRANSPORT_ROAD << 15, DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE);
_grow_town_result = GROWTH_SUCCEED;
return true;
}
}
/* Quit if it selecting an appropriate bridge type fails a large number of times. */
return false;
}