| 548 | } |
| 549 | |
| 550 | void suspendDeadend (color_ostream &out, df::job* job) { |
| 551 | auto building = Job::getHolder(job); |
| 552 | if (!building) return; |
| 553 | coord pos(building->centerx,building->centery,building->z); |
| 554 | |
| 555 | for (size_t count = 0; count < max_deadend_depth; ++count){ |
| 556 | |
| 557 | df::building* exit = nullptr; |
| 558 | for (auto npos : neighbors | transform(around(pos))) { |
| 559 | if (!isPotentialSuitableAccess(npos)) |
| 560 | // non walkable neighbour, nor planned to become one, not an exit |
| 561 | continue; |
| 562 | |
| 563 | auto impassiblePlan = plannedImpassibleAt(npos); |
| 564 | if (!impassiblePlan) |
| 565 | // walkable neighbour with no building scheduled, not in a dead end |
| 566 | return; |
| 567 | |
| 568 | if (leadsToDeadend.contains(impassiblePlan->id)) |
| 569 | continue; // already visited, not an exit |
| 570 | |
| 571 | if (exit) |
| 572 | return; // more than one exit, not in a dead end |
| 573 | |
| 574 | exit = impassiblePlan; |
| 575 | } |
| 576 | |
| 577 | |
| 578 | if (!exit) { |
| 579 | // there is no exit at all |
| 580 | if (isImpassable(building)) { |
| 581 | // suspend the current construction job to leave the entire plan suspended |
| 582 | suspendBuilding(building, Reason::DEADEND); |
| 583 | } |
| 584 | // and stop here |
| 585 | return; |
| 586 | } |
| 587 | |
| 588 | // exit is the single exit point of this corridor, suspend its construction job... |
| 589 | suspendBuilding(exit, Reason::DEADEND); |
| 590 | // ...mark the current tile of the corridor as leading to a dead-end... |
| 591 | leadsToDeadend.insert(building->id); |
| 592 | |
| 593 | // ...and continue the exploration from its position |
| 594 | building = exit; |
| 595 | pos = coord(building->centerx,building->centery,building->z); |
| 596 | } |
| 597 | } |
| 598 | |
| 599 | void preserveDesigations (df::job* job){ |
| 600 | CHECK_NULL_POINTER(job) |