diff options
| author | Alexander Gavrilov | 2012-05-05 19:26:56 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-05-05 19:26:56 +0400 |
| commit | 1b5ce7b7170223f5f6303cd04ba7e1fb80c4ca70 (patch) | |
| tree | c2cf8a0d14e6335da76b1440d24cc701e4c91deb /plugins/autolabor.cpp | |
| parent | 7e01b004e9675fec417bee0eead7d3d0702395e6 (diff) | |
| parent | 6903f3877fb7f3b8aa1f1062e342f0bc2b6001ae (diff) | |
| download | dfhack-1b5ce7b7170223f5f6303cd04ba7e1fb80c4ca70.tar.gz dfhack-1b5ce7b7170223f5f6303cd04ba7e1fb80c4ca70.tar.bz2 dfhack-1b5ce7b7170223f5f6303cd04ba7e1fb80c4ca70.tar.xz | |
Merge remote-tracking branch 'ab9rf/master'
Diffstat (limited to 'plugins/autolabor.cpp')
| -rw-r--r-- | plugins/autolabor.cpp | 142 |
1 files changed, 95 insertions, 47 deletions
diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp index 797bd746..81c89000 100644 --- a/plugins/autolabor.cpp +++ b/plugins/autolabor.cpp @@ -23,6 +23,16 @@ #include <df/building.h> #include <df/workshop_type.h> #include <df/unit_misc_trait.h> +#include <df/entity_position_responsibility.h> +#include <df/historical_figure.h> +#include <df/historical_entity.h> +#include <df/histfig_entity_link.h> +#include <df/histfig_entity_link_positionst.h> +#include <df/entity_position_assignment.h> +#include <df/entity_position.h> +#include <df/building_tradedepotst.h> + +#include <MiscUtils.h> using std::string; using std::endl; @@ -446,21 +456,45 @@ static const struct labor_default default_labor_infos[] = { /* WAX_WORKING */ {AUTOMATIC, false, 1, 200, 0}, }; -static const df::job_skill noble_skills[] = { - df::enums::job_skill::APPRAISAL, - df::enums::job_skill::ORGANIZATION, - df::enums::job_skill::RECORD_KEEPING, +static const int responsibility_penalties[] = { + 0, /* LAW_MAKING */ + 0, /* LAW_ENFORCEMENT */ + 3000, /* RECEIVE_DIPLOMATS */ + 0, /* MEET_WORKERS */ + 1000, /* MANAGE_PRODUCTION */ + 3000, /* TRADE */ + 1000, /* ACCOUNTING */ + 0, /* ESTABLISH_COLONY_TRADE_AGREEMENTS */ + 0, /* MAKE_INTRODUCTIONS */ + 0, /* MAKE_PEACE_AGREEMENTS */ + 0, /* MAKE_TOPIC_AGREEMENTS */ + 0, /* COLLECT_TAXES */ + 0, /* ESCORT_TAX_COLLECTOR */ + 0, /* EXECUTIONS */ + 0, /* TAME_EXOTICS */ + 0, /* RELIGION */ + 0, /* ATTACK_ENEMIES */ + 0, /* PATROL_TERRITORY */ + 0, /* MILITARY_GOALS */ + 0, /* MILITARY_STRATEGY */ + 0, /* UPGRADE_SQUAD_EQUIPMENT */ + 0, /* EQUIPMENT_MANIFESTS */ + 0, /* SORT_AMMUNITION */ + 0, /* BUILD_MORALE */ + 5000 /* HEALTH_MANAGEMENT */ }; struct dwarf_info_t { int highest_skill; int total_skill; - bool is_best_noble; int mastery_penalty; int assigned_jobs; dwarf_state state; bool has_exclusive_labor; + int noble_penalty; // penalty for assignment due to noble status + bool medical; // this dwarf has medical responsibility + bool trader; // this dwarf has trade responsibility }; static bool isOptionEnabled(unsigned flag) @@ -683,6 +717,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) bool has_butchers = false; bool has_fishery = false; + bool trader_requested = false; for (int i = 0; i < world->buildings.all.size(); ++i) { @@ -695,7 +730,14 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) has_butchers = true; if (df::enums::workshop_type::Fishery == subType) has_fishery = true; - } + } + else if (df::enums::building_type::TradeDepot == type) + { + df::building_tradedepotst* depot = (df::building_tradedepotst*) build; + trader_requested = depot->flags.bits.trader_requested; + if (print_debug) + out.print("Trade depot found and trader requested, trader will be excluded from all labors.\n"); + } } for (int i = 0; i < world->units.all.size(); ++i) @@ -714,15 +756,49 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) std::vector<dwarf_info_t> dwarf_info(n_dwarfs); - std::vector<int> best_noble(ARRAY_COUNT(noble_skills)); - std::vector<int> highest_noble_skill(ARRAY_COUNT(noble_skills)); - std::vector<int> highest_noble_experience(ARRAY_COUNT(noble_skills)); - // Find total skill and highest skill for each dwarf. More skilled dwarves shouldn't be used for minor tasks. for (int dwarf = 0; dwarf < n_dwarfs; dwarf++) { - assert(dwarfs[dwarf]->status.souls.size() > 0); +// assert(dwarfs[dwarf]->status.souls.size() > 0); +// assert fails can cause DF to crash, so don't do that + + if (dwarfs[dwarf]->status.souls.size() <= 0) + continue; + + // compute noble penalty + + int noble_penalty = 0; + + df::historical_figure* hf = df::historical_figure::find(dwarfs[dwarf]->hist_figure_id); + for (int i = 0; i < hf->entity_links.size(); i++) { + df::histfig_entity_link* hfelink = hf->entity_links.at(i); + if (hfelink->getType() == df::histfig_entity_link_type::POSITION) { + df::histfig_entity_link_positionst *epos = + (df::histfig_entity_link_positionst*) hfelink; + df::historical_entity* entity = df::historical_entity::find(epos->entity_id); + if (!entity) + continue; + df::entity_position_assignment* assignment = binsearch_in_vector(entity->positions.assignments, epos->assignment_id); + if (!assignment) + continue; + df::entity_position* position = binsearch_in_vector(entity->positions.own, assignment->position_id); + if (!position) + continue; + + for (int n = 0; n < 25; n++) + if (position->responsibilities[n]) + noble_penalty += responsibility_penalties[n]; + + if (position->responsibilities[df::entity_position_responsibility::HEALTH_MANAGEMENT]) + dwarf_info[dwarf].medical = true; + + if (position->responsibilities[df::entity_position_responsibility::TRADE]) + dwarf_info[dwarf].trader = true; + + } + dwarf_info[dwarf].noble_penalty = noble_penalty; + } for (auto s = dwarfs[dwarf]->status.souls[0]->skills.begin(); s != dwarfs[dwarf]->status.souls[0]->skills.end(); s++) { @@ -733,30 +809,6 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) int skill_level = (*s)->rating; int skill_experience = (*s)->experience; - // Track the dwarfs with the best Appraisal, Organization, and Record Keeping skills. - // They are likely to have appointed noble positions, so should be kept free where possible. - - int noble_skill_id = -1; - for (int i = 0; i < ARRAY_COUNT(noble_skills); i++) - { - if (skill == noble_skills[i]) - noble_skill_id = i; - } - - if (noble_skill_id >= 0) - { - assert(noble_skill_id < ARRAY_COUNT(noble_skills)); - - if (highest_noble_skill[noble_skill_id] < skill_level || - (highest_noble_skill[noble_skill_id] == skill_level && - highest_noble_experience[noble_skill_id] < skill_experience)) - { - highest_noble_skill[noble_skill_id] = skill_level; - highest_noble_experience[noble_skill_id] = skill_experience; - best_noble[noble_skill_id] = dwarf; - } - } - // Track total & highest skill among normal/medical skills. (We don't care about personal or social skills.) if (skill_class != df::enums::job_skill_class::Normal && skill_class != df::enums::job_skill_class::Medical) @@ -768,24 +820,13 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) } } - // Mark the best nobles, so we try to keep them non-busy. (It would be better to find the actual assigned nobles.) - - for (int i = 0; i < ARRAY_COUNT(noble_skills); i++) - { - assert(best_noble[i] >= 0); - assert(best_noble[i] < n_dwarfs); - - dwarf_info[best_noble[i]].is_best_noble = true; - } - // Calculate a base penalty for using each dwarf for a task he isn't good at. for (int dwarf = 0; dwarf < n_dwarfs; dwarf++) { dwarf_info[dwarf].mastery_penalty -= 40 * dwarf_info[dwarf].highest_skill; dwarf_info[dwarf].mastery_penalty -= 10 * dwarf_info[dwarf].total_skill; - if (dwarf_info[dwarf].is_best_noble) - dwarf_info[dwarf].mastery_penalty -= 250; + dwarf_info[dwarf].mastery_penalty -= dwarf_info[dwarf].noble_penalty; for (int labor = ENUM_FIRST_ITEM(unit_labor); labor <= ENUM_LAST_ITEM(unit_labor); labor++) { @@ -1032,6 +1073,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) * Note that only idle and busy dwarfs count towards the number of dwarfs. "Other" dwarfs * (sleeping, eating, on break, etc.) will have labors assigned, but will not be counted. * Military and children/nobles will not have labors assigned. + * Dwarfs with the "health management" responsibility are always assigned DIAGNOSIS. */ for (int i = 0; i < candidates.size() && labor_infos[labor].active_dwarfs < max_dwarfs; i++) { @@ -1047,6 +1089,10 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) preferred_dwarf = true; if (previously_enabled[dwarf] && labor_infos[labor].is_exclusive) preferred_dwarf = true; + if (dwarf_info[dwarf].medical && labor == df::unit_labor::DIAGNOSE) + preferred_dwarf = true; + if (dwarf_info[dwarf].trader && trader_requested) + continue; if (labor_infos[labor].active_dwarfs >= min_dwarfs && !preferred_dwarf) continue; @@ -1084,6 +1130,8 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) std::vector<int> hauler_ids; for (int dwarf = 0; dwarf < n_dwarfs; dwarf++) { + if (dwarf_info[dwarf].trader && trader_requested) + continue; if (dwarf_info[dwarf].state == IDLE || dwarf_info[dwarf].state == BUSY) hauler_ids.push_back(dwarf); } |
