| 271 | } |
| 272 | |
| 273 | static bool is_wagon_traversible(FloodCtx & ctx, const df::coord & pos, const df::coord & prev_pos) { |
| 274 | auto tt = Maps::getTileType(pos); |
| 275 | if (!tt) |
| 276 | return false; |
| 277 | |
| 278 | auto shape = tileShape(*tt); |
| 279 | auto occp = Maps::getTileOccupancy(pos); |
| 280 | if (!occp) |
| 281 | return false; |
| 282 | auto & occ = *occp; |
| 283 | switch (occ.bits.building) { |
| 284 | case tile_building_occ::Obstacle: // Statues, windmills (middle tile) |
| 285 | //FALLTHROUGH |
| 286 | case tile_building_occ::Well: |
| 287 | //FALLTHROUGH |
| 288 | case tile_building_occ::Impassable: // Raised bridges |
| 289 | return false; |
| 290 | |
| 291 | case tile_building_occ::Dynamic: |
| 292 | // doors(block), levers (block), traps (block), hatches (OK, but block on down ramp) |
| 293 | // closed floor grates (OK), closed floor bars (OK) |
| 294 | if (is_wagon_dynamic_traversible(shape, pos) == false) |
| 295 | return false; |
| 296 | break; |
| 297 | |
| 298 | case tile_building_occ::None: // Not occupied by a building |
| 299 | //FALLTHROUGH |
| 300 | case tile_building_occ::Planned: |
| 301 | //FALLTHROUGH |
| 302 | case tile_building_occ::Passable: |
| 303 | // Any tile with no building or a passable building including |
| 304 | // beds, supports, rollers, armor/weapon stands, cages (not traps), |
| 305 | // open wall grate/vertical bars, retracted bridges, open floodgates, |
| 306 | // workshops (tiles with open space are handled by the tile check) |
| 307 | if (is_wagon_tile_traversible(*tt) == false) |
| 308 | return false; |
| 309 | break; |
| 310 | case tile_building_occ::Floored: |
| 311 | // depot, lowered bridges or retractable bridges, forbidden hatches |
| 312 | break; |
| 313 | } |
| 314 | |
| 315 | if (ctx.wgroup == Maps::getWalkableGroup(pos)) |
| 316 | return true; |
| 317 | |
| 318 | if (shape == df::tiletype_shape::RAMP_TOP ) { |
| 319 | df::coord pos_below = pos + df::coord(0, 0, -1); |
| 320 | if (Maps::getWalkableGroup(pos_below)) { |
| 321 | ctx.search_edge.emplace(pos_below); |
| 322 | return true; |
| 323 | } |
| 324 | } else if (shape == df::tiletype_shape::WALL) { |
| 325 | auto prev_tt = Maps::getTileType(prev_pos); |
| 326 | if (prev_tt && tileShape(*prev_tt) == df::tiletype_shape::RAMP) { |
| 327 | df::coord pos_above = pos + df::coord(0, 0, 1); |
| 328 | if (Maps::getWalkableGroup(pos_above)) { |
| 329 | ctx.search_edge.emplace(pos_above); |
| 330 | return true; |
no test coverage detected