@@ -358,26 +358,52 @@ static void assign_nobles(color_ostream &out) {
358358 }
359359}
360360
361+ static bool scrub_id_from_entries (int32_t id, int32_t key, unordered_map<int32_t , vector<int32_t >> & entries) {
362+ auto it = entries.find (key);
363+ if (it == entries.end ())
364+ return false ;
365+ auto & entry_ids = it->second ;
366+ vector_erase_at (entry_ids, linear_index (entry_ids, id));
367+ if (entry_ids.empty ()) {
368+ entries.erase (it);
369+ return true ;
370+ }
371+ return false ;
372+ }
373+
374+ // clear the reservation for a zone
361375static void clear_reservation (color_ostream &out, int32_t zone_id, df::building_civzonest * zone = NULL ) {
362376 auto it = reserved_zones.find (zone_id);
363377 if (it == reserved_zones.end ())
364378 return ;
365- for (auto hfid : it->second ) {
366- auto pending_it = pending_reassignment.find (hfid);
367- if (pending_it != pending_reassignment.end ()) {
368- auto & zone_ids = pending_it->second ;
369- vector_erase_at (zone_ids, linear_index (zone_ids, zone_id));
370- if (zone_ids.empty ())
371- pending_reassignment.erase (pending_it);
372- }
373- }
379+ for (int32_t hfid : it->second )
380+ scrub_id_from_entries (zone_id, hfid, pending_reassignment);
374381 reserved_zones.erase (zone_id);
375382 if (!zone)
376383 zone = virtual_cast<df::building_civzonest>(df::building::find (zone_id));
377384 if (zone)
378385 zone->spec_sub_flag .bits .active = true ;
379386}
380387
388+ // stop reserving zones for dead units
389+ static void scrub_reservations (color_ostream &out) {
390+ vector<int32_t > hfids_to_scrub;
391+ for (auto &[hfid, zone_ids] : pending_reassignment) {
392+ if (auto hf = df::historical_figure::find (hfid); hf && hf->died_year == -1 )
393+ continue ;
394+ DEBUG (cycle,out).print (" removed reservation for dead or culled hfid %d\n " , hfid);
395+ hfids_to_scrub.push_back (hfid);
396+ for (int32_t zone_id : zone_ids) {
397+ if (scrub_id_from_entries (hfid, zone_id, reserved_zones)) {
398+ if (auto zone = virtual_cast<df::building_civzonest>(df::building::find (zone_id)))
399+ zone->spec_sub_flag .bits .active = true ;
400+ }
401+ }
402+ }
403+ for (int32_t hfid : hfids_to_scrub)
404+ pending_reassignment.erase (hfid);
405+ }
406+
381407// handles when units disappear from their assignments compared to the last scan
382408static void handle_missing_assignments (color_ostream &out,
383409 const unordered_set<int32_t > & active_unit_ids,
@@ -411,9 +437,9 @@ static void handle_missing_assignments(color_ostream &out,
411437 continue ;
412438 // unit is off-map or is dead; if we can assign room to spouse then we don't need to reserve the room
413439 auto spouse_hf = df::historical_figure::find (spouse_hfid);
440+ auto spouse = spouse_hf ? df::unit::find (spouse_hf->unit_id ) : nullptr ;
414441 if (spouse_hf && share_with_spouse) {
415- if (auto spouse = df::unit::find (spouse_hf->unit_id );
416- spouse && Units::isActive (spouse) && !Units::isDead (spouse) && active_unit_ids.contains (spouse->id ))
442+ if (spouse && Units::isActive (spouse) && !Units::isDead (spouse) && active_unit_ids.contains (spouse->id ))
417443 {
418444 DEBUG (cycle,out).print (" assigning zone %d (%s) to spouse %s\n " ,
419445 zone_id, ENUM_KEY_STR (civzone_type, zone->type ).c_str (),
@@ -430,7 +456,7 @@ static void handle_missing_assignments(color_ostream &out,
430456 DF2CONSOLE (Units::getReadableName (unit)).c_str ());
431457 pending_reassignment[hfid].push_back (zone_id);
432458 reserved_zones[zone_id].push_back (hfid);
433- if (share_with_spouse && spouse_hfid > - 1 ) {
459+ if (share_with_spouse && spouse ) {
434460 DEBUG (cycle,out).print (" registering spouse unit for reassignment to zone %d (%s): hfid=%d\n " ,
435461 zone_id, ENUM_KEY_STR (civzone_type, zone->type ).c_str (), spouse_hfid);
436462 pending_reassignment[spouse_hfid].push_back (zone_id);
@@ -489,6 +515,8 @@ static void do_cycle(color_ostream &out) {
489515 DEBUG (cycle,out).print (" tracking zone assignments: bedrooms: %zd, offices: %zd, dining halls: %zd, tombs: %zd\n " ,
490516 last_known_assignments_bedroom.size (), last_known_assignments_office.size (),
491517 last_known_assignments_dining.size (), last_known_assignments_tomb.size ());
518+
519+ scrub_reservations (out);
492520 }
493521
494522 if (config.get_bool (CONFIG_TRACK_ROLES)) {
0 commit comments