Autolabor: rework tool management to try to reduce tool litter

develop
Kelly Martin 2012-12-12 14:28:11 -06:00
parent 3b9f21a1ea
commit 82031092a9
1 changed files with 136 additions and 108 deletions

@ -385,89 +385,96 @@ struct labor_info
}; };
enum tools_enum {
TOOL_NONE, TOOL_PICK, TOOL_AXE, TOOL_CROSSBOW,
TOOLS_MAX
};
struct labor_default struct labor_default
{ {
int priority; int priority;
int maximum_dwarfs; int maximum_dwarfs;
tools_enum tool;
}; };
static std::vector<struct labor_info> labor_infos; static std::vector<struct labor_info> labor_infos;
static const struct labor_default default_labor_infos[] = { static const struct labor_default default_labor_infos[] = {
/* MINE */ {200, 0}, /* MINE */ {200, 0, TOOL_PICK},
/* HAUL_STONE */ {100, 0}, /* HAUL_STONE */ {100, 0, TOOL_NONE},
/* HAUL_WOOD */ {100, 0}, /* HAUL_WOOD */ {100, 0, TOOL_NONE},
/* HAUL_BODY */ {200, 0}, /* HAUL_BODY */ {200, 0, TOOL_NONE},
/* HAUL_FOOD */ {300, 0}, /* HAUL_FOOD */ {300, 0, TOOL_NONE},
/* HAUL_REFUSE */ {100, 0}, /* HAUL_REFUSE */ {100, 0, TOOL_NONE},
/* HAUL_ITEM */ {100, 0}, /* HAUL_ITEM */ {100, 0, TOOL_NONE},
/* HAUL_FURNITURE */ {100, 0}, /* HAUL_FURNITURE */ {100, 0, TOOL_NONE},
/* HAUL_ANIMAL */ {100, 0}, /* HAUL_ANIMAL */ {100, 0, TOOL_NONE},
/* CLEAN */ {200, 0}, /* CLEAN */ {200, 0, TOOL_NONE},
/* CUTWOOD */ {200, 0}, /* CUTWOOD */ {200, 0, TOOL_AXE},
/* CARPENTER */ {200, 0}, /* CARPENTER */ {200, 0, TOOL_NONE},
/* DETAIL */ {200, 0}, /* DETAIL */ {200, 0, TOOL_NONE},
/* MASON */ {200, 0}, /* MASON */ {200, 0, TOOL_NONE},
/* ARCHITECT */ {400, 0}, /* ARCHITECT */ {400, 0, TOOL_NONE},
/* ANIMALTRAIN */ {200, 0}, /* ANIMALTRAIN */ {200, 0, TOOL_NONE},
/* ANIMALCARE */ {200, 0}, /* ANIMALCARE */ {200, 0, TOOL_NONE},
/* DIAGNOSE */ {1000, 0}, /* DIAGNOSE */ {1000, 0, TOOL_NONE},
/* SURGERY */ {1000, 0}, /* SURGERY */ {1000, 0, TOOL_NONE},
/* BONE_SETTING */ {1000, 0}, /* BONE_SETTING */ {1000, 0, TOOL_NONE},
/* SUTURING */ {1000, 0}, /* SUTURING */ {1000, 0, TOOL_NONE},
/* DRESSING_WOUNDS */ {1000, 0}, /* DRESSING_WOUNDS */ {1000, 0, TOOL_NONE},
/* FEED_WATER_CIVILIANS */ {1000, 0}, /* FEED_WATER_CIVILIANS */ {1000, 0, TOOL_NONE},
/* RECOVER_WOUNDED */ {200, 0}, /* RECOVER_WOUNDED */ {200, 0, TOOL_NONE},
/* BUTCHER */ {200, 0}, /* BUTCHER */ {200, 0, TOOL_NONE},
/* TRAPPER */ {200, 0}, /* TRAPPER */ {200, 0, TOOL_NONE},
/* DISSECT_VERMIN */ {200, 0}, /* DISSECT_VERMIN */ {200, 0, TOOL_NONE},
/* LEATHER */ {200, 0}, /* LEATHER */ {200, 0, TOOL_NONE},
/* TANNER */ {200, 0}, /* TANNER */ {200, 0, TOOL_NONE},
/* BREWER */ {200, 0}, /* BREWER */ {200, 0, TOOL_NONE},
/* ALCHEMIST */ {200, 0}, /* ALCHEMIST */ {200, 0, TOOL_NONE},
/* SOAP_MAKER */ {200, 0}, /* SOAP_MAKER */ {200, 0, TOOL_NONE},
/* WEAVER */ {200, 0}, /* WEAVER */ {200, 0, TOOL_NONE},
/* CLOTHESMAKER */ {200, 0}, /* CLOTHESMAKER */ {200, 0, TOOL_NONE},
/* MILLER */ {200, 0}, /* MILLER */ {200, 0, TOOL_NONE},
/* PROCESS_PLANT */ {200, 0}, /* PROCESS_PLANT */ {200, 0, TOOL_NONE},
/* MAKE_CHEESE */ {200, 0}, /* MAKE_CHEESE */ {200, 0, TOOL_NONE},
/* MILK */ {200, 0}, /* MILK */ {200, 0, TOOL_NONE},
/* COOK */ {200, 0}, /* COOK */ {200, 0, TOOL_NONE},
/* PLANT */ {200, 0}, /* PLANT */ {200, 0, TOOL_NONE},
/* HERBALIST */ {200, 0}, /* HERBALIST */ {200, 0, TOOL_NONE},
/* FISH */ {100, 0}, /* FISH */ {100, 0, TOOL_NONE},
/* CLEAN_FISH */ {200, 0}, /* CLEAN_FISH */ {200, 0, TOOL_NONE},
/* DISSECT_FISH */ {200, 0}, /* DISSECT_FISH */ {200, 0, TOOL_NONE},
/* HUNT */ {100, 0}, /* HUNT */ {100, 0, TOOL_CROSSBOW},
/* SMELT */ {200, 0}, /* SMELT */ {200, 0, TOOL_NONE},
/* FORGE_WEAPON */ {200, 0}, /* FORGE_WEAPON */ {200, 0, TOOL_NONE},
/* FORGE_ARMOR */ {200, 0}, /* FORGE_ARMOR */ {200, 0, TOOL_NONE},
/* FORGE_FURNITURE */ {200, 0}, /* FORGE_FURNITURE */ {200, 0, TOOL_NONE},
/* METAL_CRAFT */ {200, 0}, /* METAL_CRAFT */ {200, 0, TOOL_NONE},
/* CUT_GEM */ {200, 0}, /* CUT_GEM */ {200, 0, TOOL_NONE},
/* ENCRUST_GEM */ {200, 0}, /* ENCRUST_GEM */ {200, 0, TOOL_NONE},
/* WOOD_CRAFT */ {200, 0}, /* WOOD_CRAFT */ {200, 0, TOOL_NONE},
/* STONE_CRAFT */ {200, 0}, /* STONE_CRAFT */ {200, 0, TOOL_NONE},
/* BONE_CARVE */ {200, 0}, /* BONE_CARVE */ {200, 0, TOOL_NONE},
/* GLASSMAKER */ {200, 0}, /* GLASSMAKER */ {200, 0, TOOL_NONE},
/* EXTRACT_STRAND */ {200, 0}, /* EXTRACT_STRAND */ {200, 0, TOOL_NONE},
/* SIEGECRAFT */ {200, 0}, /* SIEGECRAFT */ {200, 0, TOOL_NONE},
/* SIEGEOPERATE */ {200, 0}, /* SIEGEOPERATE */ {200, 0, TOOL_NONE},
/* BOWYER */ {200, 0}, /* BOWYER */ {200, 0, TOOL_NONE},
/* MECHANIC */ {200, 0}, /* MECHANIC */ {200, 0, TOOL_NONE},
/* POTASH_MAKING */ {200, 0}, /* POTASH_MAKING */ {200, 0, TOOL_NONE},
/* LYE_MAKING */ {200, 0}, /* LYE_MAKING */ {200, 0, TOOL_NONE},
/* DYER */ {200, 0}, /* DYER */ {200, 0, TOOL_NONE},
/* BURN_WOOD */ {200, 0}, /* BURN_WOOD */ {200, 0, TOOL_NONE},
/* OPERATE_PUMP */ {200, 0}, /* OPERATE_PUMP */ {200, 0, TOOL_NONE},
/* SHEARER */ {200, 0}, /* SHEARER */ {200, 0, TOOL_NONE},
/* SPINNER */ {200, 0}, /* SPINNER */ {200, 0, TOOL_NONE},
/* POTTERY */ {200, 0}, /* POTTERY */ {200, 0, TOOL_NONE},
/* GLAZING */ {200, 0}, /* GLAZING */ {200, 0, TOOL_NONE},
/* PRESSING */ {200, 0}, /* PRESSING */ {200, 0, TOOL_NONE},
/* BEEKEEPING */ {200, 1}, // reduce risk of stuck beekeepers (see http://www.bay12games.com/dwarves/mantisbt/view.php?id=3981) /* BEEKEEPING */ {200, 0, TOOL_NONE},
/* WAX_WORKING */ {200, 0}, /* WAX_WORKING */ {200, 0, TOOL_NONE},
/* PUSH_HAUL_VEHICLES */ {200, 0} /* PUSH_HAUL_VEHICLES */ {200, 0, TOOL_NONE}
}; };
struct dwarf_info_t struct dwarf_info_t
@ -477,9 +484,7 @@ struct dwarf_info_t
bool clear_all; bool clear_all;
bool has_axe; bool has_tool[TOOLS_MAX];
bool has_pick;
bool has_crossbow;
int high_skill; int high_skill;
@ -488,9 +493,11 @@ struct dwarf_info_t
df::unit_labor using_labor; df::unit_labor using_labor;
dwarf_info_t(df::unit* dw) : dwarf(dw), clear_all(false), has_axe(false), has_pick(false), has_crossbow(false), dwarf_info_t(df::unit* dw) : dwarf(dw), clear_all(false),
state(OTHER), high_skill(0), has_children(false), armed(false) state(OTHER), high_skill(0), has_children(false), armed(false)
{ {
for (int e = TOOL_NONE; e < TOOLS_MAX; e++)
has_tool[e] = false;
} }
void set_labor(df::unit_labor labor) void set_labor(df::unit_labor labor)
@ -498,10 +505,6 @@ struct dwarf_info_t
if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor)) if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor))
{ {
dwarf->status.labors[labor] = true; dwarf->status.labors[labor] = true;
if ((labor == df::unit_labor::MINE && !has_pick) ||
(labor == df::unit_labor::CUTWOOD && !has_axe) ||
(labor == df::unit_labor::HUNT && !has_crossbow))
dwarf->military.pickup_flags.bits.update = 1;
} }
} }
@ -510,10 +513,6 @@ struct dwarf_info_t
if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor)) if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor))
{ {
dwarf->status.labors[labor] = false; dwarf->status.labors[labor] = false;
if ((labor == df::unit_labor::MINE && has_pick) ||
(labor == df::unit_labor::CUTWOOD && has_axe) ||
(labor == df::unit_labor::HUNT && has_crossbow))
dwarf->military.pickup_flags.bits.update = 1;
} }
} }
@ -1472,8 +1471,9 @@ private:
int tree_count; int tree_count;
int plant_count; int plant_count;
int detail_count; int detail_count;
int pick_count;
int axe_count; int tool_count[TOOLS_MAX];
bool reequip_needed[TOOLS_MAX];
int cnt_recover_wounded; int cnt_recover_wounded;
int cnt_diagnosis; int cnt_diagnosis;
@ -1542,7 +1542,7 @@ private:
{ {
if (bl->designation[x][y].bits.hidden) if (bl->designation[x][y].bits.hidden)
continue; continue;
df::tile_dig_designation dig = bl->designation[x][y].bits.dig; df::tile_dig_designation dig = bl->designation[x][y].bits.dig;
if (dig != df::enums::tile_dig_designation::No) if (dig != df::enums::tile_dig_designation::No)
{ {
@ -1570,8 +1570,8 @@ private:
void count_tools() void count_tools()
{ {
pick_count = 0; for (int e = TOOL_NONE; e < TOOLS_MAX; e++)
axe_count = 0; tool_count[e] = 0;
df::item_flags bad_flags; df::item_flags bad_flags;
bad_flags.whole = 0; bad_flags.whole = 0;
@ -1598,15 +1598,15 @@ private:
df::itemdef_weaponst* weapondef = ((df::item_weaponst*)item)->subtype; df::itemdef_weaponst* weapondef = ((df::item_weaponst*)item)->subtype;
df::job_skill weaponsk = (df::job_skill) weapondef->skill_melee; df::job_skill weaponsk = (df::job_skill) weapondef->skill_melee;
df::job_skill weaponsk2 = (df::job_skill) weapondef->skill_ranged;
if (weaponsk == df::job_skill::AXE) if (weaponsk == df::job_skill::AXE)
axe_count++; tool_count[TOOL_AXE]++;
else if (weaponsk == df::job_skill::MINING) else if (weaponsk == df::job_skill::MINING)
pick_count++; tool_count[TOOL_PICK]++;
else if (weaponsk2 = df::job_skill::CROSSBOW)
tool_count[TOOL_CROSSBOW]++;
} }
if (print_debug)
out.print("Axes = %d, picks = %d\n", axe_count, pick_count);
} }
void collect_job_list() void collect_job_list()
@ -1866,19 +1866,21 @@ private:
df::job_skill rangesk = (df::job_skill) weapondef->skill_ranged; df::job_skill rangesk = (df::job_skill) weapondef->skill_ranged;
if (weaponsk == df::job_skill::AXE) if (weaponsk == df::job_skill::AXE)
{ {
dwarf->has_axe = 1; dwarf->has_tool[TOOL_AXE] = true;
if (state != IDLE) if (state != IDLE)
axe_count--; tool_count[TOOL_AXE]--;
} }
else if (weaponsk == df::job_skill::MINING) else if (weaponsk == df::job_skill::MINING)
{ {
dwarf->has_pick = 1; dwarf->has_tool[TOOL_PICK] = 1;
if (state != IDLE) if (state != IDLE)
pick_count--; tool_count[TOOL_PICK]--;
} }
else if (rangesk == df::job_skill::CROSSBOW) else if (rangesk == df::job_skill::CROSSBOW)
{ {
dwarf->has_crossbow = 1; dwarf->has_tool[TOOL_CROSSBOW] = 1;
if (state != IDLE)
tool_count[TOOL_CROSSBOW]--;
} }
} }
} }
@ -1908,11 +1910,14 @@ public:
{ {
dwarf_info.clear(); dwarf_info.clear();
dig_count = tree_count = plant_count = detail_count = pick_count = axe_count = 0; dig_count = tree_count = plant_count = detail_count = 0;
cnt_recover_wounded = cnt_diagnosis = cnt_immobilize = cnt_dressing = cnt_cleaning = cnt_surgery = cnt_suture = cnt_recover_wounded = cnt_diagnosis = cnt_immobilize = cnt_dressing = cnt_cleaning = cnt_surgery = cnt_suture =
cnt_setting = cnt_traction = cnt_crutch = 0; cnt_setting = cnt_traction = cnt_crutch = 0;
need_food_water = 0; need_food_water = 0;
for (int e = 0; e < TOOLS_MAX; e++)
tool_count[e] = 0;
trader_requested = false; trader_requested = false;
FOR_ENUM_ITEMS(unit_labor, l) FOR_ENUM_ITEMS(unit_labor, l)
@ -1945,8 +1950,8 @@ public:
// add job entries for designation-related jobs // add job entries for designation-related jobs
labor_needed[df::unit_labor::MINE] += std::min(pick_count, dig_count); labor_needed[df::unit_labor::MINE] += std::min(tool_count[TOOL_PICK], dig_count);
labor_needed[df::unit_labor::CUTWOOD] += std::min(axe_count, tree_count); labor_needed[df::unit_labor::CUTWOOD] += std::min(tool_count[TOOL_AXE], tree_count);
labor_needed[df::unit_labor::DETAIL] += detail_count; labor_needed[df::unit_labor::DETAIL] += detail_count;
labor_needed[df::unit_labor::HERBALIST] += plant_count; labor_needed[df::unit_labor::HERBALIST] += plant_count;
@ -2089,9 +2094,8 @@ public:
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);
if (d->dwarf->status.labors[labor]) if (d->dwarf->status.labors[labor])
score += 500; score += 500;
if ((labor == df::unit_labor::MINE && d->has_pick) || if (default_labor_infos[labor].tool != TOOL_NONE &&
(labor == df::unit_labor::CUTWOOD && d->has_axe) || d->has_tool[default_labor_infos[labor].tool])
(labor == df::unit_labor::HUNT && d->has_crossbow))
score += 3000; score += 3000;
if (d->has_children && labor_outside[labor]) if (d->has_children && labor_outside[labor])
score -= 10000; score -= 10000;
@ -2120,8 +2124,17 @@ public:
continue; continue;
if (l == best_labor) if (l == best_labor)
{
(*bestdwarf)->set_labor(l); (*bestdwarf)->set_labor(l);
else tools_enum t = default_labor_infos[l].tool;
if (t != TOOL_NONE)
{
tool_count[t]--;
if (!(*bestdwarf)->has_tool[t])
(*bestdwarf)->dwarf->military.pickup_flags.bits.update = true;
}
}
else
(*bestdwarf)->clear_labor(l); (*bestdwarf)->clear_labor(l);
} }
@ -2150,6 +2163,21 @@ public:
out.print ("Setting %s as the hauling canary\n", d->dwarf->name.first_name.c_str()); out.print ("Setting %s as the hauling canary\n", d->dwarf->name.first_name.c_str());
} }
/* set reequip on any dwarfs who are carrying tools needed by others */
for (auto d = dwarf_info.begin(); d != dwarf_info.end(); d++)
{
FOR_ENUM_ITEMS (unit_labor, l)
{
tools_enum t = default_labor_infos[l].tool;
if (t != TOOL_NONE && tool_count[t] < 0 && (*d)->has_tool[t] && !(*d)->dwarf->status.labors[l])
{
tool_count[t]++;
(*d)->dwarf->military.pickup_flags.bits.update = 1;
}
}
}
print_debug = 0; print_debug = 0;
} }