/** * Determine if a player could possibly build a ship lock that would cover this tile. * * @param bridge_ramp The tile to possibly outrule a bridge position * @param bridge_dir The bridge direction * @return true if a player could possibly build a ship lock on this tile. * @see GrowTownWithBridge */ static bool IsPossibleLockLocationOnTownBridgeTile(const TileIndex bridge_tile, const DiagDirection bridge_dir) { const DiagDirection dir_side = ChangeDiagDir(bridge_dir, DIAGDIRDIFF_90LEFT); const TileIndexDiff 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; }