Add a way to only count locally-made items in workflow.

develop
Alexander Gavrilov 2012-11-11 10:58:05 +04:00
parent 0e4df55364
commit d5c31942b5
6 changed files with 550 additions and 333 deletions

File diff suppressed because it is too large Load Diff

@ -58,9 +58,35 @@ The stonesense plugin might require some additional libraries on Linux.
If any of the plugins or dfhack itself refuses to load, check the stderr.log
file created in your DF folder.
Getting started
===============
If DFHack is installed correctly, it will automatically pop up a console
window once DF is started as usual on windows. Linux and Mac OS X require
running the dfhack script from the terminal, and will use that terminal for
the console.
**NOTE**: The dfhack-run executable is there for calling DFHack commands in
an already running DF+DFHack instance from external OS scripts and programs,
and is *not* the way how you use DFHack normally.
DFHack has a lot of features, which can be accessed by typing commands in the
console, or by mapping them to keyboard shortcuts. Most of the newer and more
user-friendly tools are designed to be at least partially used via the latter
way.
In order to set keybindings, you have to create a text configuration file
called ``dfhack.init``; the installation comes with an example version called
``dfhack.init-example``, which is fully functional, covers all of the recent
features and can be simply renamed to ``dfhack.init``. You are encouraged to look
through it to learn which features it makes available under which key combinations.
For more information, refer to the rest of this document.
============
Using DFHack
============
DFHack basically extends what DF can do with something similar to the drop-down
console found in Quake engine games. On Windows, this is a separate command line
window. On linux, the terminal used to launch the dfhack script is taken over
@ -1258,10 +1284,18 @@ Usage:
List workflow-controlled jobs (if in a workshop, filtered by it).
``workflow list``
List active constraints, and their job counts.
``workflow count <constraint-spec> <cnt-limit> [cnt-gap], workflow amount <constraint-spec> <cnt-limit> [cnt-gap]``
Set a constraint. The first form counts each stack as only 1 item.
``workflow list-commands``
List active constraints as workflow commands that re-create them;
this list can be copied to a file, and then reloaded using the
``script`` built-in command.
``workflow count <constraint-spec> <cnt-limit> [cnt-gap]``
Set a constraint, counting every stack as 1 item.
``workflow amount <constraint-spec> <cnt-limit> [cnt-gap]``
Set a constraint, counting all items within stacks.
``workflow unlimit <constraint-spec>``
Delete a constraint.
``workflow unlimit-all``
Delete all constraints.
Function
........
@ -1279,6 +1313,34 @@ the frequency of jobs being toggled.
Check out the ``gui/workflow`` script below for a simple front-end integrated
in the game UI.
Constraint format
.................
The contstraint spec consists of 4 parts, separated with '/' characters::
ITEM[:SUBTYPE]/[GENERIC_MAT,...]/[SPECIFIC_MAT:...]/[LOCAL,<quality>]
The first part is mandatory and specifies the item type and subtype,
using the raw tokens for items, in the same syntax you would e.g. use
for a custom reaction input. See this list for more info: http://dwarffortresswiki.org/index.php/Item_token
The subsequent parts are optional:
- A generic material spec constrains the item material to one of
the hard-coded generic classes, which currently include::
PLANT WOOD CLOTH SILK LEATHER BONE SHELL SOAP TOOTH HORN PEARL YARN
METAL STONE SAND GLASS CLAY MILK
- A specific material spec chooses the material exactly, using the
raw syntax for reaction input materials, e.g. INORGANIC:IRON,
although for convenience it also allows just IRON, or ACACIA:WOOD etc.
See this page for more details on the unabbreviated raw syntax:
http://dwarffortresswiki.org/index.php/Material_token
- A comma-separated list of miscellaneous flags, which currently can
be used to ignore imported items or items below a certain quality.
Constraint examples
...................
@ -1304,10 +1366,15 @@ Make sure there are always 25-30 empty bins/barrels/bags.
Make sure there are always 15-20 coal and 25-30 copper bars.
::
workflow count BAR//COAL 20
workflow count BAR//COPPER 30
Produce 15-20 gold crafts.
::
workflow count CRAFTS//GOLD 20
Collect 15-20 sand bags and clay boulders.
::
@ -1319,9 +1386,16 @@ Make sure there are always 80-100 units of dimple dye.
workflow amount POWDER_MISC//MUSHROOM_CUP_DIMPLE:MILL 100 20
.. note::
In order for this to work, you have to set the material of the PLANT input
on the Mill Plants job to MUSHROOM_CUP_DIMPLE using the 'job item-material'
command.
command. Otherwise the plugin won't be able to deduce the output material.
Maintain 10-100 locally-made crafts of exceptional quality.
::
workflow count CRAFTS///LOCAL,EXCEPTIONAL 100 90
Fortress activity management

@ -2,21 +2,32 @@
# Generic dwarfmode bindings #
##############################
# toggle the display of water level as 1-7 tiles
keybinding add Ctrl-W twaterlvl
# with cursor:
# designate the whole vein for digging
keybinding add Ctrl-V digv
keybinding add Ctrl-Shift-V "digv x"
# clean the selected tile of blood etc
keybinding add Ctrl-C spotclean
# destroy items designated for dump in the selected tile
keybinding add Ctrl-Shift-K autodump-destroy-here
# any item:
# with an item selected:
# destroy the selected item
keybinding add Ctrl-K autodump-destroy-item
# scripts:
# quicksave, only in main dwarfmode screen and menu page
keybinding add Ctrl-Alt-S@dwarfmode/Default quicksave
# gui/rename script
# gui/rename script - rename units and buildings
keybinding add Ctrl-Shift-N gui/rename
keybinding add Ctrl-Shift-T "gui/rename unit-profession"
@ -31,10 +42,10 @@ keybinding add Ctrl-Shift-B "adv-bodyswap force"
# Context-specific bindings #
#############################
# q->stockpile; p
# q->stockpile; p - copy & paste stockpiles
keybinding add Alt-P copystock
# q->workshop
# q->workshop - duplicate the selected job
keybinding add Ctrl-D job-duplicate
# materials: q->workshop; b->select items
@ -48,7 +59,7 @@ keybinding add Shift-O "job-material OBSIDIAN"
keybinding add Shift-T "job-material ORTHOCLASE"
keybinding add Shift-G "job-material GLASS_GREEN"
# sort units and items
# sort units and items in the on-screen list
keybinding add Alt-Shift-N "sort-units name" "sort-items description"
keybinding add Alt-Shift-R "sort-units arrival"
keybinding add Alt-Shift-T "sort-units profession" "sort-items type material"
@ -60,7 +71,7 @@ keybinding add Ctrl-M@dwarfmode/QueryBuilding/Some gui/mechanisms
# browse rooms of same owner
keybinding add Alt-R@dwarfmode/QueryBuilding/Some gui/room-list
# interface for the liquids plugin
# interface for the liquids plugin - spawn water/magma/obsidian
keybinding add Alt-L@dwarfmode/LookAround gui/liquids
# machine power sensitive pressure plate construction

@ -266,9 +266,16 @@ function constraintToToken(cspec)
error('invalid material: '..cspec.mat_type..':'..(cspec.mat_index or -1))
end
end
local qpart
local qlist = {}
if cspec.is_local then
table.insert(qlist, "LOCAL")
end
if cspec.quality and cspec.quality > 0 then
qpart = df.item_quality[cspec.quality] or error('invalid quality: '..cspec.quality)
table.insert(qlist, df.item_quality[cspec.quality] or error('invalid quality: '..cspec.quality))
end
local qpart
if #qlist > 0 then
qpart = table.concat(qlist, ',')
end
if mask_part or mat_part or qpart then

@ -100,6 +100,19 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" as the item amount goes above or below the limit. The gap specifies how\n"
" much below the limit the amount has to drop before jobs are resumed;\n"
" this is intended to reduce the frequency of jobs being toggled.\n"
"Constraint format:\n"
" The contstraint spec consists of 4 parts, separated with '/' characters:\n"
" ITEM[:SUBTYPE]/[GENERIC_MAT,...]/[SPECIFIC_MAT:...]/[LOCAL,<quality>]\n"
" The first part is mandatory and specifies the item type and subtype,\n"
" using the raw tokens for items, in the same syntax you would e.g. use\n"
" for a custom reaction input. The subsequent parts are optional:\n"
" - A generic material spec constrains the item material to one of\n"
" the hard-coded generic classes, like WOOD, METAL, YARN or MILK.\n"
" - A specific material spec chooses the material exactly, using the\n"
" raw syntax for reaction input materials, e.g. INORGANIC:IRON,\n"
" although for convenience it also allows just IRON, or ACACIA:WOOD.\n"
" - A comma-separated list of miscellaneous flags, which currently can\n"
" be used to ignore imported items or items below a certain quality.\n"
"Constraint examples:\n"
" workflow amount AMMO:ITEM_AMMO_BOLTS/METAL 1000 100\n"
" workflow amount AMMO:ITEM_AMMO_BOLTS/WOOD,BONE 200 50\n"
@ -124,6 +137,8 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" In order for this to work, you have to set the material of\n"
" the PLANT input on the Mill Plants job to MUSHROOM_CUP_DIMPLE\n"
" using the 'job item-material' command.\n"
" workflow count CRAFTS///LOCAL,EXCEPTIONAL 100 90\n"
" Maintain 10-100 locally-made crafts of exceptional quality.\n"
)
);
}
@ -279,17 +294,20 @@ typedef std::map<std::pair<int,int>, bool> TMaterialCache;
struct ItemConstraint {
PersistentDataItem config;
// Fixed key parsed into fields
bool is_craft;
ItemTypeInfo item;
MaterialInfo material;
df::dfhack_material_category mat_mask;
item_quality::item_quality min_quality;
bool is_local;
// Tracking data
int weight;
std::vector<ProtectedJob*> jobs;
item_quality::item_quality min_quality;
int item_amount, item_count, item_inuse;
bool request_suspend, request_resume;
@ -299,8 +317,9 @@ struct ItemConstraint {
public:
ItemConstraint()
: is_craft(false), weight(0), min_quality(item_quality::Ordinary),item_amount(0),
item_count(0), item_inuse(0), is_active(false), cant_resume_reported(false)
: is_craft(false), min_quality(item_quality::Ordinary), is_local(false),
weight(0), item_amount(0), item_count(0), item_inuse(0),
is_active(false), cant_resume_reported(false)
{}
int goalCount() { return config.ival(0); }
@ -673,7 +692,7 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
if (mat_mask.whole != 0)
weight += 100;
MaterialInfo material;
std::string matstr = vector_get(tokens,2);
if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) {
@ -681,21 +700,6 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
return NULL;
}
item_quality::item_quality minqual = item_quality::Ordinary;
std::string qualstr = vector_get(tokens, 3);
if(!qualstr.empty()) {
if(qualstr == "ordinary") minqual = item_quality::Ordinary;
else if(qualstr == "wellcrafted") minqual = item_quality::WellCrafted;
else if(qualstr == "finelycrafted") minqual = item_quality::FinelyCrafted;
else if(qualstr == "superior") minqual = item_quality::Superior;
else if(qualstr == "exceptional") minqual = item_quality::Exceptional;
else if(qualstr == "masterful") minqual = item_quality::Masterful;
else {
out.printerr("Cannot find quality: %s\nKnown qualities: ordinary, wellcrafted, finelycrafted, superior, exceptional, masterful\n", qualstr.c_str());
return NULL;
}
}
if (material.type >= 0)
weight += (material.index >= 0 ? 5000 : 1000);
@ -704,13 +708,52 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
return NULL;
}
item_quality::item_quality minqual = item_quality::Ordinary;
bool is_local = false;
std::string qualstr = vector_get(tokens, 3);
if(!qualstr.empty())
{
std::vector<std::string> qtokens;
split_string(&qtokens, qualstr, ",");
for (size_t i = 0; i < qtokens.size(); i++)
{
auto token = toLower(qtokens[i]);
if (token == "local")
is_local = true;
else
{
bool found = false;
FOR_ENUM_ITEMS(item_quality, qv)
{
if (toLower(ENUM_KEY_STR(item_quality, qv)) != token)
continue;
minqual = qv;
found = true;
}
if (!found)
{
out.printerr("Cannot parse token: %s\n", token.c_str());
return NULL;
}
}
}
}
if (is_local || minqual > item_quality::Ordinary)
weight += 10;
for (size_t i = 0; i < constraints.size(); i++)
{
ItemConstraint *ct = constraints[i];
if (ct->is_craft == is_craft &&
ct->item == item && ct->material == material &&
ct->mat_mask.whole == mat_mask.whole &&
ct->min_quality == minqual)
ct->min_quality == minqual &&
ct->is_local == is_local)
return ct;
}
@ -720,6 +763,7 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
nct->material = material;
nct->mat_mask = mat_mask;
nct->min_quality = minqual;
nct->is_local = is_local;
nct->weight = weight;
if (cfg)
@ -1099,9 +1143,11 @@ static void map_job_items(color_ostream &out)
(cv->item.subtype != -1 && cv->item.subtype != isubtype))
continue;
}
if(item->getQuality() < cv->min_quality) {
continue;
}
if (cv->is_local && item->flags.bits.foreign)
continue;
if (item->getQuality() < cv->min_quality)
continue;
TMaterialCache::iterator it = cv->material_cache.find(matkey);
@ -1307,6 +1353,7 @@ static void push_constraint(lua_State *L, ItemConstraint *cv)
Lua::SetField(L, cv->material.index, ctable, "mat_index");
Lua::SetField(L, (int)cv->min_quality, ctable, "min_quality");
Lua::SetField(L, (bool)cv->is_local, ctable, "is_local");
// Constraint value

@ -191,8 +191,15 @@ function JobConstraints:initListChoices(clist, sel_token)
order_pen = COLOR_BLUE
end
local itemstr = describe_item_type(cons)
if cons.min_quality > 0 then
itemstr = itemstr .. ' ('..df.item_quality[cons.min_quality]..')'
if cons.min_quality > 0 or cons.is_local then
local lst = {}
if cons.is_local then
table.insert(lst, 'local')
end
if cons.min_quality > 0 then
table.insert(lst, string.lower(df.item_quality[cons.min_quality]))
end
itemstr = itemstr .. ' ('..table.concat(lst,',')..')'
end
local matstr = describe_material(cons)
local matflagstr = ''