From cbcb148182b0491283d0840d36b8dcadc941f8d0 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Tue, 8 Nov 2016 12:01:24 -0600 Subject: [PATCH 1/5] Better job assignment algorithm for labormanager. --- plugins/labormanager.cpp | 266 ++++++++++++++++++++++----------------- 1 file changed, 149 insertions(+), 117 deletions(-) diff --git a/plugins/labormanager.cpp b/plugins/labormanager.cpp index 5a2774cd2..298568a41 100644 --- a/plugins/labormanager.cpp +++ b/plugins/labormanager.cpp @@ -414,23 +414,23 @@ struct labor_default static std::vector labor_infos; static const struct labor_default default_labor_infos[] = { - /* MINEa */ {200, 0, TOOL_PICK}, + /* MINE */ {100, 0, TOOL_PICK}, /* HAUL_STONE */ {100, 0, TOOL_NONE}, /* HAUL_WOOD */ {100, 0, TOOL_NONE}, - /* HAUL_BODY */ {200, 0, TOOL_NONE}, - /* HAUL_FOOD */ {300, 0, TOOL_NONE}, - /* HAUL_REFUSE */ {100, 0, TOOL_NONE}, + /* HAUL_BODY */ {1000, 0, TOOL_NONE}, + /* HAUL_FOOD */ {500, 0, TOOL_NONE}, + /* HAUL_REFUSE */ {200, 0, TOOL_NONE}, /* HAUL_ITEM */ {100, 0, TOOL_NONE}, /* HAUL_FURNITURE */ {100, 0, TOOL_NONE}, /* HAUL_ANIMAL */ {100, 0, TOOL_NONE}, - /* CLEAN */ {200, 0, TOOL_NONE}, - /* CUTWOOD */ {200, 0, TOOL_AXE}, - /* CARPENTER */ {200, 0, TOOL_NONE}, - /* DETAIL */ {200, 0, TOOL_NONE}, - /* MASON */ {200, 0, TOOL_NONE}, - /* ARCHITECT */ {400, 0, TOOL_NONE}, - /* ANIMALTRAIN */ {200, 0, TOOL_NONE}, - /* ANIMALCARE */ {200, 0, TOOL_NONE}, + /* CLEAN */ {100, 0, TOOL_NONE}, + /* CUTWOOD */ {100, 0, TOOL_AXE}, + /* CARPENTER */ {100, 0, TOOL_NONE}, + /* DETAIL */ {100, 0, TOOL_NONE}, + /* MASON */ {100, 0, TOOL_NONE}, + /* ARCHITECT */ {100, 0, TOOL_NONE}, + /* ANIMALTRAIN */ {100, 0, TOOL_NONE}, + /* ANIMALCARE */ {100, 0, TOOL_NONE}, /* DIAGNOSE */ {1000, 0, TOOL_NONE}, /* SURGERY */ {1000, 0, TOOL_NONE}, /* BONE_SETTING */ {1000, 0, TOOL_NONE}, @@ -438,65 +438,65 @@ static const struct labor_default default_labor_infos[] = { /* DRESSING_WOUNDS */ {1000, 0, TOOL_NONE}, /* FEED_WATER_CIVILIANS */ {1000, 0, TOOL_NONE}, /* RECOVER_WOUNDED */ {200, 0, TOOL_NONE}, - /* BUTCHER */ {200, 0, TOOL_NONE}, - /* TRAPPER */ {200, 0, TOOL_NONE}, - /* DISSECT_VERMIN */ {200, 0, TOOL_NONE}, - /* LEATHER */ {200, 0, TOOL_NONE}, - /* TANNER */ {200, 0, TOOL_NONE}, - /* BREWER */ {200, 0, TOOL_NONE}, - /* ALCHEMIST */ {200, 0, TOOL_NONE}, - /* SOAP_MAKER */ {200, 0, TOOL_NONE}, - /* WEAVER */ {200, 0, TOOL_NONE}, - /* CLOTHESMAKER */ {200, 0, TOOL_NONE}, - /* MILLER */ {200, 0, TOOL_NONE}, - /* PROCESS_PLANT */ {200, 0, TOOL_NONE}, - /* MAKE_CHEESE */ {200, 0, TOOL_NONE}, - /* MILK */ {200, 0, TOOL_NONE}, - /* COOK */ {200, 0, TOOL_NONE}, - /* PLANT */ {200, 0, TOOL_NONE}, - /* HERBALIST */ {200, 0, TOOL_NONE}, + /* BUTCHER */ {500, 0, TOOL_NONE}, + /* TRAPPER */ {100, 0, TOOL_NONE}, + /* DISSECT_VERMIN */ {100, 0, TOOL_NONE}, + /* LEATHER */ {100, 0, TOOL_NONE}, + /* TANNER */ {100, 0, TOOL_NONE}, + /* BREWER */ {100, 0, TOOL_NONE}, + /* ALCHEMIST */ {100, 0, TOOL_NONE}, + /* SOAP_MAKER */ {100, 0, TOOL_NONE}, + /* WEAVER */ {100, 0, TOOL_NONE}, + /* CLOTHESMAKER */ {100, 0, TOOL_NONE}, + /* MILLER */ {100, 0, TOOL_NONE}, + /* PROCESS_PLANT */ {100, 0, TOOL_NONE}, + /* MAKE_CHEESE */ {100, 0, TOOL_NONE}, + /* MILK */ {100, 0, TOOL_NONE}, + /* COOK */ {100, 0, TOOL_NONE}, + /* PLANT */ {100, 0, TOOL_NONE}, + /* HERBALIST */ {100, 0, TOOL_NONE}, /* FISH */ {100, 0, TOOL_NONE}, - /* CLEAN_FISH */ {200, 0, TOOL_NONE}, - /* DISSECT_FISH */ {200, 0, TOOL_NONE}, + /* CLEAN_FISH */ {100, 0, TOOL_NONE}, + /* DISSECT_FISH */ {100, 0, TOOL_NONE}, /* HUNT */ {100, 0, TOOL_CROSSBOW}, - /* SMELT */ {200, 0, TOOL_NONE}, - /* FORGE_WEAPON */ {200, 0, TOOL_NONE}, - /* FORGE_ARMOR */ {200, 0, TOOL_NONE}, - /* FORGE_FURNITURE */ {200, 0, TOOL_NONE}, - /* METAL_CRAFT */ {200, 0, TOOL_NONE}, - /* CUT_GEM */ {200, 0, TOOL_NONE}, - /* ENCRUST_GEM */ {200, 0, TOOL_NONE}, - /* WOOD_CRAFT */ {200, 0, TOOL_NONE}, - /* STONE_CRAFT */ {200, 0, TOOL_NONE}, - /* BONE_CARVE */ {200, 0, TOOL_NONE}, - /* GLASSMAKER */ {200, 0, TOOL_NONE}, - /* EXTRACT_STRAND */ {200, 0, TOOL_NONE}, - /* SIEGECRAFT */ {200, 0, TOOL_NONE}, - /* SIEGEOPERATE */ {200, 0, TOOL_NONE}, - /* BOWYER */ {200, 0, TOOL_NONE}, - /* MECHANIC */ {200, 0, TOOL_NONE}, - /* POTASH_MAKING */ {200, 0, TOOL_NONE}, - /* LYE_MAKING */ {200, 0, TOOL_NONE}, - /* DYER */ {200, 0, TOOL_NONE}, - /* BURN_WOOD */ {200, 0, TOOL_NONE}, - /* OPERATE_PUMP */ {200, 0, TOOL_NONE}, - /* SHEARER */ {200, 0, TOOL_NONE}, - /* SPINNER */ {200, 0, TOOL_NONE}, - /* POTTERY */ {200, 0, TOOL_NONE}, - /* GLAZING */ {200, 0, TOOL_NONE}, - /* PRESSING */ {200, 0, TOOL_NONE}, - /* BEEKEEPING */ {200, 0, TOOL_NONE}, - /* WAX_WORKING */ {200, 0, TOOL_NONE}, - /* PUSH_HAUL_VEHICLES */ {200, 0, TOOL_NONE}, - /* HAUL_TRADE */ {200, 0, TOOL_NONE}, - /* PULL_LEVER */ {200, 0, TOOL_NONE}, - /* REMOVE_CONSTRUCTION */ {200, 0, TOOL_NONE}, - /* HAUL_WATER */ {200, 0, TOOL_NONE}, - /* GELD */ {200, 0, TOOL_NONE}, - /* BUILD_ROAD */ {200, 0, TOOL_NONE}, - /* BUILD_CONSTRUCTION */ {200, 0, TOOL_NONE}, - /* PAPERMAKING */ {200, 0, TOOL_NONE}, - /* BOOKBINDING */ {200, 0, TOOL_NONE} + /* SMELT */ {100, 0, TOOL_NONE}, + /* FORGE_WEAPON */ {100, 0, TOOL_NONE}, + /* FORGE_ARMOR */ {100, 0, TOOL_NONE}, + /* FORGE_FURNITURE */ {100, 0, TOOL_NONE}, + /* METAL_CRAFT */ {100, 0, TOOL_NONE}, + /* CUT_GEM */ {100, 0, TOOL_NONE}, + /* ENCRUST_GEM */ {100, 0, TOOL_NONE}, + /* WOOD_CRAFT */ {100, 0, TOOL_NONE}, + /* STONE_CRAFT */ {100, 0, TOOL_NONE}, + /* BONE_CARVE */ {100, 0, TOOL_NONE}, + /* GLASSMAKER */ {100, 0, TOOL_NONE}, + /* EXTRACT_STRAND */ {100, 0, TOOL_NONE}, + /* SIEGECRAFT */ {100, 0, TOOL_NONE}, + /* SIEGEOPERATE */ {100, 0, TOOL_NONE}, + /* BOWYER */ {100, 0, TOOL_NONE}, + /* MECHANIC */ {100, 0, TOOL_NONE}, + /* POTASH_MAKING */ {100, 0, TOOL_NONE}, + /* LYE_MAKING */ {100, 0, TOOL_NONE}, + /* DYER */ {100, 0, TOOL_NONE}, + /* BURN_WOOD */ {100, 0, TOOL_NONE}, + /* OPERATE_PUMP */ {100, 0, TOOL_NONE}, + /* SHEARER */ {100, 0, TOOL_NONE}, + /* SPINNER */ {100, 0, TOOL_NONE}, + /* POTTERY */ {100, 0, TOOL_NONE}, + /* GLAZING */ {100, 0, TOOL_NONE}, + /* PRESSING */ {100, 0, TOOL_NONE}, + /* BEEKEEPING */ {100, 0, TOOL_NONE}, + /* WAX_WORKING */ {100, 0, TOOL_NONE}, + /* PUSH_HAUL_VEHICLES */ {100, 0, TOOL_NONE}, + /* HAUL_TRADE */ {1000, 0, TOOL_NONE}, + /* PULL_LEVER */ {1000, 0, TOOL_NONE}, + /* REMOVE_CONSTRUCTION */ {100, 0, TOOL_NONE}, + /* HAUL_WATER */ {100, 0, TOOL_NONE}, + /* GELD */ {100, 0, TOOL_NONE}, + /* BUILD_ROAD */ {100, 0, TOOL_NONE}, + /* BUILD_CONSTRUCTION */ {100, 0, TOOL_NONE}, + /* PAPERMAKING */ {100, 0, TOOL_NONE}, + /* BOOKBINDING */ {100, 0, TOOL_NONE} }; void debug (char* fmt, ...); @@ -852,12 +852,13 @@ private: return df::unit_labor::TRAPPER; case df::building_type::Civzone: case df::building_type::Nest: - case df::building_type::RoadDirt: case df::building_type::Stockpile: case df::building_type::Weapon: return df::unit_labor::NONE; case df::building_type::SiegeEngine: return df::unit_labor::SIEGECRAFT; + case df::building_type::RoadDirt: + return df::unit_labor::BUILD_ROAD; } debug ("LABORMANAGER: Cannot deduce labor for construct building job of type %s\n", @@ -1167,13 +1168,13 @@ public: job_to_labor_table[df::job_type::CheckChest] = jlf_no_labor; job_to_labor_table[df::job_type::StoreOwnedItem] = jlf_no_labor; job_to_labor_table[df::job_type::PlaceItemInTomb] = jlf_const(df::unit_labor::HAUL_BODY); - job_to_labor_table[df::job_type::StoreItemInStockpile] = jlf_no_labor; // Can arise from many different labors, but will never appear in a pending job list - job_to_labor_table[df::job_type::StoreItemInBag] = jlf_no_labor; // Can arise from many different labors, but will never appear in a pending job list + job_to_labor_table[df::job_type::StoreItemInStockpile] = jlf_hauling; + job_to_labor_table[df::job_type::StoreItemInBag] = jlf_hauling; job_to_labor_table[df::job_type::StoreItemInHospital] = jlf_hauling; job_to_labor_table[df::job_type::StoreWeapon] = jlf_hauling; job_to_labor_table[df::job_type::StoreArmor] = jlf_hauling; - job_to_labor_table[df::job_type::StoreItemInBarrel] = jlf_no_labor; // Can arise from many different labors, but will never appear in a pending job list - job_to_labor_table[df::job_type::StoreItemInBin] = jlf_no_labor; // Can arise from many different labors, but will never appear in a pending job list + job_to_labor_table[df::job_type::StoreItemInBarrel] = jlf_hauling; + job_to_labor_table[df::job_type::StoreItemInBin] = jlf_hauling; job_to_labor_table[df::job_type::SeekArtifact] = jlf_no_labor; job_to_labor_table[df::job_type::SeekInfant] = jlf_no_labor; job_to_labor_table[df::job_type::AttendParty] = jlf_no_labor; @@ -1676,20 +1677,24 @@ private: if (bld != -1) { df::building* b = binsearch_in_vector(world->buildings.all, bld); - int fjid = -1; - for (int jn = 0; jn < b->jobs.size(); jn++) - { - if (b->jobs[jn]->flags.bits.suspend) - continue; - fjid = b->jobs[jn]->id; - break; - } + // check if this job is the first nonsuspended job on this building; if not, ignore it // (except for farms and trade depots) - if (fjid != j->id && - b->getType() != df::building_type::FarmPlot && - b->getType() != df::building_type::TradeDepot) - return; + + if (b->getType() != df::building_type::FarmPlot && + b->getType() != df::building_type::TradeDepot) + { + int fjid = -1; + for (int jn = 0; jn < b->jobs.size(); jn++) + { + if (b->jobs[jn]->flags.bits.suspend) + continue; + fjid = b->jobs[jn]->id; + break; + } + if (fjid != j->id) + return; + } } df::unit_labor labor = labor_mapper->find_job_labor (j); @@ -2056,7 +2061,8 @@ private: out.print("Dwarf \"%s\": state %s %d\n", dwarf->dwarf->name.first_name.c_str(), state_names[dwarf->state], dwarf->clear_all); // determine if dwarf has medical needs - if (dwarf->dwarf->health) + // babies cannot currently receive health care even if they need it + if (dwarf->dwarf->profession != profession::BABY && dwarf->dwarf->health) { if (dwarf->dwarf->health->flags.bits.needs_recovery) cnt_recover_wounded++; @@ -2160,13 +2166,10 @@ private: if (labor == df::unit_labor::OPERATE_PUMP) score += 50000; else - score += 1000; + score += 25000; if (default_labor_infos[labor].tool != TOOL_NONE && d->has_tool[default_labor_infos[labor].tool]) - score += 30000; - if (default_labor_infos[labor].tool != TOOL_NONE && - !d->has_tool[default_labor_infos[labor].tool]) - score -= 30000; + score += 10000000; if (d->has_children && labor_outside[labor]) score -= 15000; if (d->armed && labor_outside[labor]) @@ -2361,8 +2364,6 @@ public: } - labor_needed[df::unit_labor::CLEAN] = 1; - if (print_debug) { for (auto i = labor_needed.begin(); i != labor_needed.end(); i++) @@ -2372,7 +2373,9 @@ public: } } + std::map base_priority; priority_queue> pq; + priority_queue> pq2; for (auto i = labor_needed.begin(); i != labor_needed.end(); i++) { @@ -2383,15 +2386,16 @@ public: if (labor_infos[l].maximum_dwarfs() > 0 && i->second > labor_infos[l].maximum_dwarfs()) i->second = labor_infos[l].maximum_dwarfs(); - if (i->second > 0) - { - int priority = labor_infos[l].priority(); - if (l < df::unit_labor::HAUL_STONE || l > df::unit_labor::HAUL_ANIMALS) - priority += labor_infos[l].time_since_last_assigned()/12; + int priority = labor_infos[l].priority(); + + priority += labor_infos[l].time_since_last_assigned()/12; + priority -= labor_infos[l].busy_dwarfs; + + base_priority[l] = priority; - for (int n = 0; n < labor_infos[l].busy_dwarfs; n++) - priority /= 2; + if (i->second > 0) + { pq.push(make_pair(priority, l)); } } @@ -2418,9 +2422,22 @@ public: if (--labor_needed[labor] > 0) { - priority /= 2; - pq.push(make_pair(priority, labor)); + priority-=10; + pq2.push(make_pair(priority, labor)); } + + if (pq.empty()) + while(!pq2.empty()) + { + pq.push(pq2.top()); + pq2.pop(); + } + } + + while (!pq2.empty()) + { + pq.push(pq2.top()); + pq2.pop(); } int canary = (1 << df::unit_labor::HAUL_STONE) | @@ -2475,7 +2492,7 @@ public: if (l == best_labor && ( t == TOOL_NONE || tool_in_use[t] < tool_count[t]) ) { set_labor(*bestdwarf, l, true); - if (t != TOOL_NONE && (*bestdwarf)->has_tool[t]) + if (t != TOOL_NONE && !((*bestdwarf)->has_tool[t])) { df::job_type j; j = df::job_type::NONE; @@ -2526,8 +2543,7 @@ public: continue; int score = score_labor (*d, l); - if (l < df::unit_labor::HAUL_STONE || l > df::unit_labor::HAUL_ANIMALS) - score += labor_infos[l].time_since_last_assigned()/12; + if (l == df::unit_labor::HAUL_FOOD && priority_food > 0) score += 1000000; @@ -2538,7 +2554,9 @@ public: { set_labor(*d, l, true); } - if ((*d)->using_labor != df::unit_labor::NONE && score > current_score + 5000 && default_labor_infos[(*d)->using_labor].tool == TOOL_NONE) + if ((*d)->using_labor != df::unit_labor::NONE && + (score > current_score + 5000 || base_priority[(*d)->using_labor] < base_priority[l]) && + default_labor_infos[(*d)->using_labor].tool == TOOL_NONE) set_labor(*d, (*d)->using_labor, false); } } @@ -2579,18 +2597,23 @@ public: /* Assign any leftover dwarfs to "standard" labors */ + if (print_debug) + out.print ("After assignment, %d dwarfs left over\n", available_dwarfs.size()); + for (auto d = available_dwarfs.begin(); d != available_dwarfs.end(); d++) { FOR_ENUM_ITEMS (unit_labor, l) { - if (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS && - canary & (1 << l)) - set_labor(*d, l, true); - else if (l == df::unit_labor::CLEAN || l == df::unit_labor::REMOVE_CONSTRUCTION || l == df::unit_labor::PULL_LEVER) - set_labor(*d, l, true); - else - set_labor(*d, l, false); - } + if (l == df::unit_labor::NONE) + continue; + + set_labor(*d, l, + (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS) || + l == df::unit_labor::CLEAN || + l == df::unit_labor::REMOVE_CONSTRUCTION || + l == df::unit_labor::PULL_LEVER || + l == df::unit_labor::HAUL_TRADE); + } } /* check for dwarfs assigned no labors and assign them the bucket list if there are */ @@ -2648,7 +2671,8 @@ public: bool has_tool = (*d)->has_tool[t]; bool needs_tool = (*d)->dwarf->status.labors[l]; - if (has_tool != needs_tool) + if ((needs_tool && !has_tool) || + (has_tool && !needs_tool && tool_in_use[t] >= tool_count[t])) { df::job_type j = df::job_type::NONE; @@ -2675,6 +2699,10 @@ public: *df::global::process_jobs = true; } + if (print_debug) { + *df::global::pause_state = true; + } + print_debug = 0; } @@ -2709,8 +2737,12 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) return CR_OK; } - if (++step_count < 60) +// if (++step_count < 60) +// return CR_OK; + + if (*df::global::process_jobs) return CR_OK; + step_count = 0; debug_stream = &out; From 61baaa0c374d252bc72645af01dd527c91c8fd7b Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Tue, 25 Oct 2016 18:02:07 -0500 Subject: [PATCH 2/5] Docs for labormanager --- docs/Plugins.rst | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/docs/Plugins.rst b/docs/Plugins.rst index ba502c38e..adf4d1206 100644 --- a/docs/Plugins.rst +++ b/docs/Plugins.rst @@ -810,6 +810,110 @@ Examples: ``autolabor CUTWOOD disable`` Turn off autolabor for wood cutting. +.. _labormanager: + +labormanager +============ +Automatically manage dwarf labors to efficiently complete jobs. +Labormanager is derived from autolabor (above) but uses a completely +different approach to assigning jobs to dwarves. While autolabor tries +to keep as many dwarves busy as possible, labormanager instead strives +to get jobs done as quickly as possible. + +Labormanager frequently scans the current job list, current list of +dwarfs, and the map to determine how many dwarves need to be assigned to +what labors in order to meet all current labor needs without starving +any particular type of job. + +.. warning:: + + *As with autolabor, labormanager will override any manual changes you + make to labors while it is enabled, including through other tools such + as Dwarf Therapist* + +Simple usage: + +:enable labormanager: Enables the plugin with default settings. +(Persistent per fortress) :disable labormanager: Disables the plugin. + +Anything beyond this is optional - autolabor works fairly well on the +default settings. + +The default priorities for each labor vary (some labors are higher +priority by default than others). The way the plugin works is that, once +it determines how many of each labor is needed, it then sorts them by +adjusted priority. (Labors other than hauling have a bias added to them +based on how long it's been since they were last used, to prevent job +starvation.) The labor with the highest priority is selected, the "best +fit" dwarf for that labor is assigned to that labor, and then its +priority is *halved*. This process is repeated until either dwarfs or +labors run out. + +Because there is no easy way to detect how many haulers are actually +needed at any moment, the plugin always ensures that at least one dwarf +is assigned to each of the hauling labors, even if no hauling jobs are +detected. At least one dwarf is always assigned to construction removing +and cleaning because these jobs also cannot be easily detected. Lever +pulling is always assigned to everyone. Any dwarfs for which there are +no jobs will be assigned hauling, lever pulling, and cleaning labors. If +you use animal trainers, note that labormanager + +Labormanager also sometimes assigns extra labors to currently busy +dwarfs so that when they finish their current job, they will go off and +do something useful instead of standing around waiting for a job. + +There is special handling to ensure that at least one dwarf is assigned +to haul food whenever food is detected left in a place where it will rot +if not stored. This will cause a dwarf to go idle if you have no +storepiles to haul food to. + +Dwarfs who are unable to work (child, in the military, wounded, +handless, asleep, in a meeting) are entirely excluded from labor +assignment. Any dwarf explicitly assigned to a burrow will also be +completely ignored by labormanager. + +The fitness algorithm for assigning jobs to dwarfs generally attempts to +favor dwarfs who are more skilled over those who are less skilled. It +also tries to avoid assigning female dwarfs with children to jobs that +are "outside", favors assigning "outside" jobs to dwarfs who are +carrying a tool that could be used as a weapon, and tries to minimize +how often dwarfs have to reequip. + +Labormanager automatically determines medical needs and reserves health +care providers as needed. Note that this may cause idling if you have +injured dwarfs but no or inadequate hospital facilities. + +Hunting is never assigned without a butchery, and fishing is never +assigned without a fishery, and neither of these labors is assigned +unless specifically enabled. + +The method by which labormanager determines what labor is needed for a +particular job is complicated and, in places, incomplete. In some +situations, labormanager will detect that it cannot determine what labor +is required. It will, by default, pause and print an error message on +the dfhack console, followed by the message "LABORMANAGER: Game paused +so you can investigate the above message.". If this happens, please open +an issue on github, reporting the lines that immediately preceded this +message. You can tell labormanager to ignore this error and carry on by +typing "autolabor pause-on-error no", but be warned that some job may go +undone in this situation. + +Advanced usage: + +:autolabor enable: Turn plugin on. +:autolabor disable: Turn plugin off. +:autolabor priority : Set the priority value (see above) for labor to . +:autolabor reset : Reset the priority value of labor to its default. +:autolabor reset-all: Reset all priority values to their defaults. +:autolabor allow-fishing: Allow dwarfs to fish. *Warning* This tends to result in most of the fort going fishing. +:autolabor forbid-fishing: Forbid dwarfs from fishing. Default behavior. +:autolabor allow-hunting: Allow dwarfs to hunt. *Warning* This tends to result in as many dwarfs going hunting as you have crossbows. +:autolabor forbid-hunting: Forbid dwarfs from hunting. Default behavior. +:autolabor list: Show current priorities and current allocation stats. +:autolabor pause-on-error yes: Make labormanager pause if the labor inference engine fails. See above. +:autolabor pause-on-error no: Allow labormanager to continue past a labor inference engine failure. + + .. _autohauler: autohauler From a28c4db69ae8441d9e6d38a080dea8673e0a7a4a Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Tue, 25 Oct 2016 18:10:29 -0500 Subject: [PATCH 3/5] Finish clipped sentence. (erk.) --- docs/Plugins.rst | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/Plugins.rst b/docs/Plugins.rst index adf4d1206..c82d68389 100644 --- a/docs/Plugins.rst +++ b/docs/Plugins.rst @@ -856,7 +856,10 @@ detected. At least one dwarf is always assigned to construction removing and cleaning because these jobs also cannot be easily detected. Lever pulling is always assigned to everyone. Any dwarfs for which there are no jobs will be assigned hauling, lever pulling, and cleaning labors. If -you use animal trainers, note that labormanager +you use animal trainers, note that labormanager will misbehave if you +assign specific trainers to specific animals; results are only guaranteed +if you use "any trainer", and animal trainers will probably be +overallocated in any case. Labormanager also sometimes assigns extra labors to currently busy dwarfs so that when they finish their current job, they will go off and @@ -900,18 +903,18 @@ undone in this situation. Advanced usage: -:autolabor enable: Turn plugin on. -:autolabor disable: Turn plugin off. -:autolabor priority : Set the priority value (see above) for labor to . -:autolabor reset : Reset the priority value of labor to its default. -:autolabor reset-all: Reset all priority values to their defaults. -:autolabor allow-fishing: Allow dwarfs to fish. *Warning* This tends to result in most of the fort going fishing. -:autolabor forbid-fishing: Forbid dwarfs from fishing. Default behavior. -:autolabor allow-hunting: Allow dwarfs to hunt. *Warning* This tends to result in as many dwarfs going hunting as you have crossbows. -:autolabor forbid-hunting: Forbid dwarfs from hunting. Default behavior. -:autolabor list: Show current priorities and current allocation stats. -:autolabor pause-on-error yes: Make labormanager pause if the labor inference engine fails. See above. -:autolabor pause-on-error no: Allow labormanager to continue past a labor inference engine failure. +:labormanager enable: Turn plugin on. +:labormanager disable: Turn plugin off. +:labormanager priority : Set the priority value (see above) for labor to . +:labormanager reset : Reset the priority value of labor to its default. +:labormanager reset-all: Reset all priority values to their defaults. +:labormanager allow-fishing: Allow dwarfs to fish. *Warning* This tends to result in most of the fort going fishing. +:labormanager forbid-fishing: Forbid dwarfs from fishing. Default behavior. +:labormanager allow-hunting: Allow dwarfs to hunt. *Warning* This tends to result in as many dwarfs going hunting as you have crossbows. +:labormanager forbid-hunting: Forbid dwarfs from hunting. Default behavior. +:labormanager list: Show current priorities and current allocation stats. +:labormanager pause-on-error yes: Make labormanager pause if the labor inference engine fails. See above. +:labormanager pause-on-error no: Allow labormanager to continue past a labor inference engine failure. .. _autohauler: From 47426e3e002356980f632c91ade9ded5073656f3 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Sat, 26 Nov 2016 17:37:26 -0600 Subject: [PATCH 4/5] Use attributes in calculating assignment weight --- plugins/labormanager.cpp | 156 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 2 deletions(-) diff --git a/plugins/labormanager.cpp b/plugins/labormanager.cpp index 298568a41..eedcffe7e 100644 --- a/plugins/labormanager.cpp +++ b/plugins/labormanager.cpp @@ -1504,9 +1504,152 @@ static void generate_labor_to_skill_map() labor_to_skill[labor] = skill; } } - } +struct skill_attr_weight { + int phys_attr_weights [6]; + int mental_attr_weights [13]; +}; + +static struct skill_attr_weight skill_attr_weights[ENUM_LAST_ITEM(job_skill) + 1] = +{ + // S A T E R D AA F W C I P M LA SS M KS E SA + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* MINING */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* WOODCUTTING */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* CARPENTRY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* DETAILSTONE */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MASONRY */, + { { 0, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 } } /* ANIMALTRAIN */, + { { 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 } } /* ANIMALCARE */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* DISSECT_FISH */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* DISSECT_VERMIN */, + { { 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PROCESSFISH */, + { { 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* BUTCHER */, + { { 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* TRAPPING */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* TANNER */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* WEAVING */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* BREWING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* ALCHEMY */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* CLOTHESMAKING */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MILLING */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PROCESSPLANTS */, + { { 1, 1, 0, 1, 0, 0 }, { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* CHEESEMAKING */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MILK */, + { { 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* COOK */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PLANT */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } } /* HERBALISM */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } } /* FISH */, + { { 1, 0, 1, 1, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* SMELT */, + { { 1, 1, 0, 1, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* EXTRACT_STRAND */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* FORGE_WEAPON */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* FORGE_ARMOR */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* FORGE_FURNITURE */, + { { 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* CUTGEM */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* ENCRUSTGEM */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* WOODCRAFT */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* STONECRAFT */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* METALCRAFT */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* GLASSMAKER */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* LEATHERWORK */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* BONECARVE */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* AXE */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SWORD */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* DAGGER */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* MACE */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* HAMMER */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SPEAR */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* CROSSBOW */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SHIELD */, + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* ARMOR */, + { { 1, 1, 0, 1, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* SIEGECRAFT */, + { { 1, 0, 1, 1, 0, 0 }, { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SIEGEOPERATE */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* BOWYER */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* PIKE */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* WHIP */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* BOW */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* BLOWGUN */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* THROW */, + { { 1, 1, 0, 1, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MECHANICS */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MAGIC_NATURE */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SNEAK */, + { { 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* DESIGNBUILDING */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 } } /* DRESS_WOUNDS */, + { { 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 } } /* DIAGNOSE */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SURGERY */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SET_BONE */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SUTURE */, + { { 0, 1, 0, 1, 0, 0 }, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* CRUTCH_WALK */, + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* WOOD_BURNING */, + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* LYE_MAKING */, + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* SOAP_MAKING */, + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* POTASH_MAKING */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* DYER */, + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* OPERATE_PUMP */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SWIMMING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 } } /* PERSUASION */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 } } /* NEGOTIATION */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1 } } /* JUDGING_INTENT */, + { { 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 } } /* APPRAISAL */, + { { 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 } } /* ORGANIZATION */, + { { 0, 0, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } } /* RECORD_KEEPING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 } } /* LYING */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 } } /* INTIMIDATION */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 } } /* CONVERSATION */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 } } /* COMEDY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 } } /* FLATTERY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0 } } /* CONSOLE */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 } } /* PACIFY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* TRACKING */, + { { 0, 1, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } } /* KNOWLEDGE_ACQUISITION */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } } /* CONCENTRATION */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* DISCIPLINE */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SITUATIONAL_AWARENESS */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* WRITING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PROSE */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* POETRY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* READING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* SPEAKING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* COORDINATION */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* BALANCE */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 } } /* LEADERSHIP */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 } } /* TEACHING */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* MELEE_COMBAT */, + { { 1, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* RANGED_COMBAT */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* WRESTLING */, + { { 1, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* BITE */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* GRASP_STRIKE */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* STANCE_STRIKE */, + { { 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* DODGING */, + { { 1, 1, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* MISC_WEAPON */, + { { 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* KNAPPING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MILITARY_TACTICS */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* SHEARING */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* SPINNING */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* POTTERY */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* GLAZING */, + { { 1, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PRESSING */, + { { 1, 1, 0, 1, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* BEEKEEPING */, + { { 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 } } /* WAX_WORKING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* CLIMBING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* GELD */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* DANCE */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MAKE_MUSIC */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* SING_MUSIC */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PLAY_KEYBOARD_INSTRUMENT */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PLAY_STRINGED_INSTRUMENT */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PLAY_WIND_INSTRUMENT */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PLAY_PERCUSSION_INSTRUMENT */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* CRITICAL_THINKING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* LOGIC */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* MATHEMATICS */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* ASTRONOMY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* CHEMISTRY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* GEOGRAPHY */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* OPTICS_ENGINEER */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* FLUID_ENGINEER */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* PAPERMAKING */, + { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } /* BOOKBINDING */ +}; static void enable_plugin(color_ostream &out) { @@ -2147,6 +2290,7 @@ private: { int skill_level = 0; int xp = 0; + int attr_weight = 0; if (labor != df::unit_labor::NONE) { @@ -2155,10 +2299,16 @@ private: { skill_level = Units::getEffectiveSkill(d->dwarf, skill); xp = Units::getExperience(d->dwarf, skill, false); + + for (int pa = 0; pa < 6; pa++) + attr_weight += (skill_attr_weights[skill].phys_attr_weights[pa]) * (d->dwarf->body.physical_attrs[pa].value - 1000); + + for (int ma = 0; ma < 13; ma++) + attr_weight += (skill_attr_weights[skill].mental_attr_weights[ma]) * (d->dwarf->status.current_soul->mental_attrs[ma].value - 1000); } } - int score = skill_level * 1000 - (d->high_skill - skill_level) * 2000 + (xp / (skill_level + 5) * 10); + int score = skill_level * 1000 - (d->high_skill - skill_level) * 2000 + (xp / (skill_level + 5) * 10) + attr_weight; if (labor != df::unit_labor::NONE) { @@ -2176,6 +2326,8 @@ private: score += 5000; } + score -= Units::computeMovementSpeed(d->dwarf); + return score; } From ad84217687fa84ef9e0375a705a14b35290c2cf9 Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Sat, 26 Nov 2016 18:08:48 -0600 Subject: [PATCH 5/5] fix white space to make travis happy --- plugins/labormanager.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/labormanager.cpp b/plugins/labormanager.cpp index eedcffe7e..e0c26bb61 100644 --- a/plugins/labormanager.cpp +++ b/plugins/labormanager.cpp @@ -1825,7 +1825,7 @@ private: // (except for farms and trade depots) if (b->getType() != df::building_type::FarmPlot && - b->getType() != df::building_type::TradeDepot) + b->getType() != df::building_type::TradeDepot) { int fjid = -1; for (int jn = 0; jn < b->jobs.size(); jn++) @@ -2300,10 +2300,10 @@ private: skill_level = Units::getEffectiveSkill(d->dwarf, skill); xp = Units::getExperience(d->dwarf, skill, false); - for (int pa = 0; pa < 6; pa++) + for (int pa = 0; pa < 6; pa++) attr_weight += (skill_attr_weights[skill].phys_attr_weights[pa]) * (d->dwarf->body.physical_attrs[pa].value - 1000); - for (int ma = 0; ma < 13; ma++) + for (int ma = 0; ma < 13; ma++) attr_weight += (skill_attr_weights[skill].mental_attr_weights[ma]) * (d->dwarf->status.current_soul->mental_attrs[ma].value - 1000); } } @@ -2540,10 +2540,10 @@ public: i->second = labor_infos[l].maximum_dwarfs(); int priority = labor_infos[l].priority(); - + priority += labor_infos[l].time_since_last_assigned()/12; priority -= labor_infos[l].busy_dwarfs; - + base_priority[l] = priority; if (i->second > 0) @@ -2578,8 +2578,8 @@ public: pq2.push(make_pair(priority, labor)); } - if (pq.empty()) - while(!pq2.empty()) + if (pq.empty()) + while(!pq2.empty()) { pq.push(pq2.top()); pq2.pop(); @@ -2706,8 +2706,8 @@ public: { set_labor(*d, l, true); } - if ((*d)->using_labor != df::unit_labor::NONE && - (score > current_score + 5000 || base_priority[(*d)->using_labor] < base_priority[l]) && + if ((*d)->using_labor != df::unit_labor::NONE && + (score > current_score + 5000 || base_priority[(*d)->using_labor] < base_priority[l]) && default_labor_infos[(*d)->using_labor].tool == TOOL_NONE) set_labor(*d, (*d)->using_labor, false); } @@ -2759,10 +2759,10 @@ public: if (l == df::unit_labor::NONE) continue; - set_labor(*d, l, - (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS) || - l == df::unit_labor::CLEAN || - l == df::unit_labor::REMOVE_CONSTRUCTION || + set_labor(*d, l, + (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS) || + l == df::unit_labor::CLEAN || + l == df::unit_labor::REMOVE_CONSTRUCTION || l == df::unit_labor::PULL_LEVER || l == df::unit_labor::HAUL_TRADE); } @@ -2892,7 +2892,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) // if (++step_count < 60) // return CR_OK; - if (*df::global::process_jobs) + if (*df::global::process_jobs) return CR_OK; step_count = 0;