View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0013167 | Dwarf Fortress | Dwarf Mode -- Interface, Rooms | public | 2025-05-09 04:05 | 2025-05-15 10:21 |
Reporter | AirToob | Assigned To | |||
Priority | high | Severity | major | Reproducibility | always |
Status | new | Resolution | open | ||
Platform | PC | OS | Windows | OS Version | 11 |
Product Version | 51.11 | ||||
Summary | 0013167: Bedrooms not automatically unassigned on death, results in tedious manual cleanup | ||||
Description | Example: I just got a burst of 21 deaths (mostly tavern brawl). So what I have to do now: Look at alerts, note the name of the first (next) dead dwarf. Open Zones menu, search for the first part of that name. From the list of matches, identify the bedroom belonging to the dead dwarf. Open the details for that bedroom, remove the assignment to that dwarf. Escape out. Repeat steps 1. to 5. N times, where this time N=21 - this is indescribably tedious and time consuming. This is in addition to the usual check on Nobles/Administrators, Hospital positions and Squad members for new vacancies. SUGGESTION (Probably not new) EITHER provide a DFHack one-shot command to unassign the bedrooms of all dead entities OR Fix the game somehow that automatic unassignment of dead owners' bedrooms happens automatically again Whichever, could this be fixed PDQ, please? | ||||
Steps To Reproduce | Wait for some entity to die | ||||
Tags | No tags attached. | ||||
|
Can confirm, just noticed this when I saw I had about 200 bedrooms, 198 assigned but only 175 live Dwarves. To reproduce: > Create a bedroom > Wait for a Dwarf to claim the bedroom > When a Dwarf claims the bedroom, kill them via any means. Preferably while they are on the map (not abroad) ----> The bedroom will still be claimed by the Dwarf, whose portrait is now naked Maybe this is this a consequence of the recent code change that stopped units from unclaiming their beds when they left the map? My save file: https://dffd.bay12games.com/file.php?id=17419 |
|
This can be fixed via a custom DFHack lua script. I have not tested the ramifications of doing this, as I was up late toying around. One unfortunate effect is that it unassigns tomb zones, but the dwarves are still listed as having graves. I'm going to potentially ruin my save testing this! This script scans all bedroom and tomb zones in your fortress and automatically unassigns any that are still linked to dwarves who have died. It works even in the stripped-down DFHack version bundled with the Steam release, without needing plugins or hidden fields. While the zones are cleared of ownership, the dwarves are still considered to have graves, so burial records remain intact — this prevents issues like "ghost" ownership or cluttered assignment lists without interfering with slab inscriptions or memorialization. Use notepad++ or somthing similar to save this as a lua script called 'clean_dead_beds' and run from the DFHack launcher: local isDead = dfhack.units.isDead local cleared = 0 for _, bld in ipairs(df.global.world.buildings.all) do if bld:getType() == df.building_type.Civzone then -- skip tombs by checking for the tomb settings field local is_tomb = pcall(function() return bld.zone_settings.tomb end) if is_tomb then -- skip this one else local success, assigned_unit_id = pcall(function() return bld.assigned_unit_id end) if success and assigned_unit_id and assigned_unit_id ~= -1 then local unit = df.unit.find(assigned_unit_id) if not unit or isDead(unit) then print(string.format("Clearing dead unit %d from civzone ID %d", assigned_unit_id, bld.id)) bld.assigned_unit_id = -1 cleared = cleared + 1 end end end end end print("Done. Cleared", cleared, "civzone assignments from dead dwarves.") |
|
I saved these under the C:\Program Files (x86)\Steam\steamapps\common\Dwarf Fortress\hack\scripts folder to run in DFHack. DFHack provides a lot of useful tools and has been around almost as long as dwarf fortress, you can install it on the Steam version by searching the store for DFHack. I hope that this doesn't engender too much unintentional !!FUN!! as I just winged it after a few beers and 20 years of programming experience. |
|
Okay! I have a better alternative. This checks all bedroom zones in the fortress, and if any are still assigned to dead dwarves, it automatically unassigns them. No need to cross-reference alerts, zones, or assignments manually. It also includes a --dry-run option so you can preview what would change before committing. IT doesn't unassign tombs now! This will unassign any dead dwarves from their bedrooms and print what it did. Want to preview first? Use the "--dry-run" argument, so clean_dead_beds --dry-run in the DFHack launcher, or just run clean_dead_beds - or whatever you save it as Hope this saves others from the tedium. Would love to see this kind of cleanup eventually integrated into base game behavior or as a standard DFHack plugin. In the meantime, this makes life much easier. Here's the lua script to be put into DF Hack's scripts folder, (saved as a .lua): local args = {...} local dry_run = args[1] == '--dry-run' local isDead = dfhack.units.isDead -- Step 1: Build lookup of bed positions local beds_by_pos = {} for _, bld in ipairs(df.global.world.buildings.all) do if bld:getType() == df.building_type.Bed then local key = string.format("%d,%d,%d", bld.centerx, bld.centery, bld.z) beds_by_pos[key] = true end end -- Step 2: Iterate zones and check conditions local unassigned_count = 0 for _, bld in ipairs(df.global.world.buildings.all) do if bld:getType() == df.building_type.Civzone and bld.assigned_unit_id ~= -1 then local unit = df.unit.find(bld.assigned_unit_id) if unit and isDead(unit) then local has_bed = false for x = bld.x1, bld.x2 do for y = bld.y1, bld.y2 do local key = string.format("%d,%d,%d", x, y, bld.z) if beds_by_pos[key] then has_bed = true break end end if has_bed then break end end if has_bed then if dry_run then print(string.format("[DRY RUN] Zone %d would be unassigned from unit %d (was BEDROOM)", bld.id, bld.assigned_unit_id)) else print(string.format("Zone %d unassigned from unit %d (was BEDROOM)", bld.id, bld.assigned_unit_id)) bld.assigned_unit_id = -1 end unassigned_count = unassigned_count + 1 end end end end -- Step 3: Summary if dry_run then print(string.format("Dry run complete. %d bedroom assignments would be removed.", unassigned_count)) else print(string.format("Done. %d bedroom assignments removed.", unassigned_count)) end |
|
Side note: there's a much easier way to detect if a civzone is a bedroom - just check if its .type is equal to df.civzone_type.Bedroom . Alternatively, just iterate across df.global.world.buildings.other.ZONE_BEDROOM .Also, using DFHack is only a workaround, as it doesn't actually fix the underlying issue. |
|
Yeah, it was a pretty terrible algorithm for detecting bedrooms, I'm pretty unfamiliar with the data structures, thanks! By noting it is only a workaround, I presume you mean because it cleans up rooms after the fact, but doesn't cure the bug if rooms not being unassigned? If so, I agree, this is a management solution and not a true fix, and would need to be run each time an issue arises. |
Date Modified | Username | Field | Change |
---|---|---|---|
2025-05-09 04:05 | AirToob | New Issue | |
2025-05-12 12:52 | Kijiro | Note Added: 0042691 | |
2025-05-12 12:53 | Kijiro | Note Edited: 0042691 | |
2025-05-14 21:10 | andrewzeidell | Note Added: 0042698 | |
2025-05-14 21:12 | andrewzeidell | Note Added: 0042699 | |
2025-05-14 21:20 | andrewzeidell | Note Edited: 0042698 | |
2025-05-15 05:18 | andrewzeidell | Note Added: 0042702 | |
2025-05-15 07:12 | Quietust | Note Added: 0042703 | |
2025-05-15 07:13 | Quietust | Note Edited: 0042703 | |
2025-05-15 07:16 | Quietust | Note Edited: 0042703 | |
2025-05-15 10:21 | andrewzeidell | Note Added: 0042704 |