diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp index 45ddda2e9..89115366a 100644 --- a/plugins/autolabor.cpp +++ b/plugins/autolabor.cpp @@ -8,6 +8,9 @@ #include #include +#include +#include +#include #include "modules/Units.h" #include "modules/World.h" @@ -721,7 +724,7 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out ) static df::building* get_building_from_job(df::job* j) { - for (auto r = j->references.begin(); r != j->references.end(); r++) + for (auto r = j->general_refs.begin(); r != j->general_refs.end(); r++) { if ((*r)->getType() == df::general_ref_type::BUILDING_HOLDER) { @@ -762,12 +765,17 @@ static df::job_skill workshop_build_labor[] = /* Tool */ (df::job_skill) -1 }; -static void find_job_skill_labor(df::job* j, df::job_skill &skill, df::unit_labor &labor) +static df::unit_labor find_job_labor(df::job* j) { + df::job_skill skill; + df::unit_labor labor; + + labor = df::unit_labor::NONE; switch (j->job_type) { case df::job_type::ConstructBuilding: + case df::job_type::DestroyBuilding: { df::building* bld = get_building_from_job (j); switch (bld->getType()) @@ -779,6 +787,7 @@ static void find_job_skill_labor(df::job* j, df::job_skill &skill, df::unit_labo } } break; + case df::job_type::CustomReaction: for (auto r = world->raws.reactions.begin(); r != world->raws.reactions.end(); r++) { @@ -803,6 +812,7 @@ static void find_job_skill_labor(df::job* j, df::job_skill &skill, df::unit_labo { } + return labor; } class AutoLaborManager { @@ -840,7 +850,7 @@ private: int pick_count; int axe_count; - std::vector jobs; + std::map labor_needed; std::vector dwarf_info; std::deque idle_dwarfs; @@ -930,7 +940,7 @@ private: #define F(x) bad_flags.bits.x = true; F(dump); F(forbid); F(garbage_collect); F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(construction); F(artifact1); + F(in_building); F(construction); F(artifact); #undef F for (int i = 0; i < world->items.all.size(); ++i) @@ -957,9 +967,6 @@ private: void collect_job_list() { - std::vector repeating_jobs; - - for (df::job_list_link* jll = world->job_list.next; jll; jll = jll->next) { df::job* j = jll->item; @@ -971,24 +978,21 @@ private: int worker = -1; - for (int r = 0; r < j->references.size(); ++r) - if (j->references[r]->getType() == df::general_ref_type::UNIT_WORKER) - worker = ((df::general_ref_unit_workerst *)(j->references[r]))->unit_id; + for (int r = 0; r < j->general_refs.size(); ++r) + if (j->general_refs[r]->getType() == df::general_ref_type::UNIT_WORKER) + worker = ((df::general_ref_unit_workerst *)(j->general_refs[r]))->unit_id; if (worker != -1) continue; - if (j->flags.bits.repeat) - repeating_jobs.push_back(j); - else - jobs.push_back(j); - } + df::unit_labor labor = find_job_labor (j); - if (print_debug) - out.print("%d repeating jobs, %d nonrepeating jobs\n", repeating_jobs.size(), jobs.size()); + if (print_debug) + out.print ("Job requiring labor %d found\n", labor); - for (int i = 0; i < repeating_jobs.size(); i++) - jobs.push_back(repeating_jobs[i]); + if (labor != df::unit_labor::NONE) + labor_needed[labor]++; + } } @@ -1150,37 +1154,6 @@ private: } } - void assign_one_dwarf (df::job_skill skill, df::unit_labor labor) - { - if (labor == df::unit_labor::NONE) - return; - - std::deque::iterator bestdwarf = idle_dwarfs.begin(); - - if (skill != df::job_skill::NONE) - { - int best_skill_level = -1; - - for (std::deque::iterator k = idle_dwarfs.begin(); k != idle_dwarfs.end(); k++) - { - dwarf_info_t* d = (*k); - int skill_level = Units::getEffectiveSkill(d->dwarf, skill); - - if (skill_level > best_skill_level) - { - bestdwarf = k; - best_skill_level = skill_level; - } - } - } - - if (print_debug) - out.print("assign \"%s\" labor %d\n", (*bestdwarf)->dwarf->name.first_name.c_str(), labor); - (*bestdwarf)->set_labor(labor); - - idle_dwarfs.erase(bestdwarf); - } - public: void process() { @@ -1196,6 +1169,8 @@ public: count_tools(); + // create job entries for designation + // collect current job list collect_job_list(); @@ -1204,82 +1179,76 @@ public: collect_dwarf_list(); - // assign jobs requiring skill to idle dwarfs + // match idle dwarfs to need list - if an idle dwarf is assigned to that labor, then yay, decrement the need count + // and remove the idle dwarf from the idle list - int jobs_to_assign = jobs.size(); - if (jobs_to_assign > idle_dwarfs.size()) - jobs_to_assign = idle_dwarfs.size(); - - if (print_debug) - out.print ("Assign idle (skilled): %d\n", jobs_to_assign); - - std::vector jobs2; - - for (int i = 0; i < jobs_to_assign; ++i) + for (auto i = idle_dwarfs.begin(); i != idle_dwarfs.end(); i++) { - df::job* j = jobs[i]; - - df::job_skill skill; - df::unit_labor labor; - - find_job_skill_labor(j, skill, labor); - - if(print_debug) - out.print("Job skill = %d labor = %d\n", skill, labor); - - if (labor == -1) - out.print("Invalid labor for job (%d)\n", j->job_type); - - if (skill == df::job_skill::NONE) - jobs2.push_back(j); - else - assign_one_dwarf(skill, labor); + FOR_ENUM_ITEMS(unit_labor, l) + { + if ((*i)->dwarf->status.labors[l]) + if (labor_needed[l] > 0) + { + if (print_debug) + out.print("assign \"%s\" labor %d (carried through)\n", (*i)->dwarf->name.first_name.c_str(), l); + labor_needed[l]--; + idle_dwarfs.erase(i); // remove from idle list + break; + } else { + (*i)->dwarf->status.labors[l] = false; + } + } } - // assign mining jobs to idle dwarfs - - int dig_max = dig_count; - if (dig_max > pick_count) - dig_max = pick_count; - - jobs_to_assign = dig_max - jobs2.size(); - if (jobs_to_assign > idle_dwarfs.size()) - jobs_to_assign = idle_dwarfs.size(); - - if (print_debug) - out.print ("Assign idle (mining): %d\n", jobs_to_assign); - - for (int i = 0; i < jobs_to_assign; ++i) + priority_queue> pq; + + for (auto i = labor_needed.begin(); i != labor_needed.end(); i++) { - df::job_skill skill = df::job_skill::MINING; - df::unit_labor labor = df::unit_labor::MINE; - - assign_one_dwarf(skill, labor); + if (i->second > 0) + pq.push(make_pair(i->second, i->first)); } + + while (!idle_dwarfs.empty() && !pq.empty()) + { + df::unit_labor labor = pq.top().second; + int remaining = pq.top().first; + df::job_skill skill = labor_to_skill[labor]; - // now assign unskilled jobs to idle dwarfs + if (print_debug) + out.print("labor %d skill %d remaining %d\n", labor, skill, remaining); - jobs_to_assign = jobs2.size(); - if (jobs_to_assign > idle_dwarfs.size()) - jobs_to_assign = idle_dwarfs.size(); + std::deque::iterator bestdwarf = idle_dwarfs.begin(); - if (print_debug) - out.print ("Assign idle (unskilled): %d\n", jobs_to_assign); + if (skill != df::job_skill::NONE) + { + int best_skill_level = -1; - for (int i = 0; i < jobs_to_assign; ++i) - { - df::job* j = jobs2[i]; + for (std::deque::iterator k = idle_dwarfs.begin(); k != idle_dwarfs.end(); k++) + { + dwarf_info_t* d = (*k); + int skill_level = Units::getEffectiveSkill(d->dwarf, skill); - df::job_skill skill; - df::unit_labor labor; + if (skill_level > best_skill_level) + { + bestdwarf = k; + best_skill_level = skill_level; + } + } + } - find_job_skill_labor(j, skill, labor); - assign_one_dwarf(skill, labor); + if (print_debug) + out.print("assign \"%s\" labor %d\n", (*bestdwarf)->dwarf->name.first_name.c_str(), labor); + (*bestdwarf)->set_labor(labor); + + idle_dwarfs.erase(bestdwarf); + pq.pop(); + if (--remaining) + pq.push(make_pair(remaining, labor)); } print_debug = 0; - } + } };