True for buildings planned on a tile with an item that cannot be moved aside
| 315 | |
| 316 | // True for buildings planned on a tile with an item that cannot be moved aside |
| 317 | static bool isOnUnmovableItem(df::job *job) { |
| 318 | CHECK_NULL_POINTER(job); |
| 319 | auto building = Job::getHolder(job); |
| 320 | if (!building) |
| 321 | return false; |
| 322 | |
| 323 | // Check for items on the building, look into all the map blocks overlapping |
| 324 | // the building |
| 325 | bool has_item = false; |
| 326 | for (int32_t block_x = building->x1 >> 4; block_x <= building->x2 >> 4; ++block_x) { |
| 327 | for (int32_t block_y = building->y1 >> 4; block_y <= building->y2 >> 4; ++block_y) { |
| 328 | auto block = Maps::getBlock(block_x,block_y,building->z); |
| 329 | if (!block) |
| 330 | continue; |
| 331 | |
| 332 | for (df::item *item : block->items | transform(df::item::find)) { |
| 333 | if (!item) |
| 334 | continue; |
| 335 | if (item->pos.x < building->x1 || item->pos.x > building->x2 || |
| 336 | item->pos.y < building->y1 || item->pos.y > building->y2) |
| 337 | continue; |
| 338 | |
| 339 | // Ok if it's an item of the job |
| 340 | if (std::ranges::any_of(job->items, [item](df::job_item_ref *j) {return j->item == item;})) |
| 341 | continue; |
| 342 | if (item->flags.bits.in_job || item->flags.bits.forbid) |
| 343 | return true; // Assigned to a different task or forbidden, not movable |
| 344 | has_item = true; |
| 345 | } |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | if (!has_item) |
| 350 | return false; |
| 351 | |
| 352 | // When there is an item on top of the building, check for the surrounding of the building |
| 353 | // for a place where the dwarves would be able to move the item to. |
| 354 | // The dwarves will move an item if there is a walkable space without any |
| 355 | // building planned, non-diagonally neighbouring the building. |
| 356 | // The position of the item does not matter, in multi-tile buildings |
| 357 | // dwarves will move the item multiple tiles if necessary |
| 358 | for (auto x : {building->x1-1, building->x2+1}) { |
| 359 | for (auto y = building->y1; y <= building->y2; ++y) { |
| 360 | if (suitableToMoveItemTo(coord(x,y,building->z))) |
| 361 | return false; |
| 362 | } |
| 363 | } |
| 364 | for (auto y : {building->y1-1, building->y2+1}) { |
| 365 | for (auto x = building->x1; x <= building->x2; ++x) { |
| 366 | if (suitableToMoveItemTo(coord(x,y,building->z))) |
| 367 | return false; |
| 368 | } |
| 369 | } |
| 370 | |
| 371 | return true; |
| 372 | } |
| 373 | |
| 374 | // check if the tile is suitable tile to stand on for construction (walkable & not a tree branch) |
nothing calls this directly
no test coverage detected