Merge pull request #2575 from myk002/myk_autochop

Update and validate autochop
develop
Myk 2023-01-09 23:51:56 -08:00 committed by GitHub
commit c33274ef11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 876 additions and 769 deletions

@ -4,9 +4,18 @@ autochop
.. dfhack-tool:: .. dfhack-tool::
:summary: Auto-harvest trees when low on stockpiled logs. :summary: Auto-harvest trees when low on stockpiled logs.
:tags: fort auto plants :tags: fort auto plants
:no-command:
This plugin can designate trees for chopping when your stocks are low on logs. This plugin can automatically designate trees for chopping when your stocks are
low on logs. It can also ensure specified burrows are kept clear of trees, so,
for example, caravans always have a path to your depot and trees won't grow
close to your walls, giving invaders an unexpected path into your fort.
Autochop checks your stock of logs and designates appropriate trees for chopping
once every in-game day. Logs that are forbidden or inaccessible (e.g. in hidden
parts of the map, under water, etc.) are not counted towards your target. Trees
that are inaccessible are likewise never designated.
Please see `gui/autochop` for the interactive configuration dialog.
Usage Usage
----- -----
@ -14,14 +23,64 @@ Usage
:: ::
enable autochop enable autochop
autochop [status]
autochop (designate|undesignate)
autochop target <max> [<min>]
autochop (chop|nochop) <burrow>[,<burrow>...]
autochop (clearcut|noclearcut) <burrow>[,<burrow>...]
autochop (protect|unprotect) <type>[,<type>...] <burrow>[,<burrow>...]
Examples
--------
Ensure we always have about 200 logs in stock, harvested from accessible trees
anywhere on the map::
enable autochop
Ensure we always have about 500 logs in stock, harvested from a burrow named
"TreeFarm". Also ensure the caravan pathway and the area around the outer wall
("CaravanPath" and "OuterWall") are always clear::
enable autochop
autochop target 500
autochop chop TreeFarm
autochop clearcut CaravanPath,OuterWall
Clear all non-food-producing trees out of a burrow ("PicnicArea") intended to
contain only food-producing trees::
autochop clearcut PicnicArea
autochop protect brewable,edible,cookable PicnicArea
autochop designate
Commands
--------
``status``
Show current configuration and relevant statistics.
``designate``
Designate trees for chopping right now according to the current
configuration. This works even if ``autochop`` is not currently enabled.
``undesignate``
Undesignates all trees.
Then, open the settings menu with :kbd:`c` from the designations menu (the ``target <max> [<min>]``
option appears when you have "Chop Down Trees" selected with :kbd:`d`-:kbd:`t`). Set the target range for the number of logs you want to have in stock. If a
minimum amount is not specified, it defaults to 20% less than the maximum.
The default target is ``200`` (with a corresponding minimum of ``160``).
Set your desired thresholds and enable autochopping with :kbd:`a`. ``(no)chop <burrow>[,<burrow>...]``
Instead of choosing trees across the whole game map, restrict tree cutting
to the given burrows. Burrows can be specified by name or internal ID.
You can also restrict autochopping to specific burrows. Highlight a burrow name ``(no)clearcut <burrow>[,<burrow>...]``
with the Up/Down arrow keys and hit :kbd:`Enter` to mark it as the autochop Ensure the given burrows are always clear of trees. As soon as a tree
burrrow. appears in any of these burrows, it is designated for chopping at priority
2.
Autochop checks your stock of logs and designates trees once every in game day. ``(un)protect <type>[,<type>...] <burrow>[,<burrow>...]``
Choose whether to exclude trees from chopping that produce any of the given
types of food. Valid types are: ``brewable``, ``edible``, and ``cookable``.

@ -81,7 +81,7 @@ set_source_files_properties( Brushes.h PROPERTIES HEADER_FILE_ONLY TRUE )
#dfhack_plugin(3dveins 3dveins.cpp) #dfhack_plugin(3dveins 3dveins.cpp)
#dfhack_plugin(add-spatter add-spatter.cpp) #dfhack_plugin(add-spatter add-spatter.cpp)
dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua) dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua)
#dfhack_plugin(autochop autochop.cpp) dfhack_plugin(autochop autochop.cpp LINK_LIBRARIES lua)
#dfhack_plugin(autoclothing autoclothing.cpp) #dfhack_plugin(autoclothing autoclothing.cpp)
#dfhack_plugin(autodump autodump.cpp) #dfhack_plugin(autodump autodump.cpp)
dfhack_plugin(autofarm autofarm.cpp) dfhack_plugin(autofarm autofarm.cpp)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,111 @@
local _ENV = mkmodule('plugins.autochop')
local argparse = require('argparse')
local function process_args(opts, args)
if args[1] == 'help' then
opts.help = true
return
end
return argparse.processArgsGetopt(args, {
{'h', 'help', handler=function() opts.help = true end},
})
end
function setTargets(max, min)
max = tonumber(max)
max = max and math.floor(max) or nil
if not max or max < 0 then
qerror('target maximum must be a non-negative integer')
end
min = tonumber(min)
min = min and math.floor(min) or nil
if min and (min < 0 or min > max) then
qerror('target minimum must be between 0 and the maximum, inclusive')
end
if not min then
min = math.floor(max * 0.8)
end
autochop_setTargets(max, min)
end
local function do_set_burrow_config(var_name, val, burrows)
for _,bspec in ipairs(argparse.stringList(burrows)) do
local config = autochop_getBurrowConfig(bspec)
config[var_name] = val
autochop_setBurrowConfig(config.id, config.chop, config.clearcut,
config.protect_brewable, config.protect_edible,
config.protect_cookable)
end
end
local function do_set_burrow_protect_config(types, val, burrows)
for _,tname in ipairs(argparse.stringList(types)) do
do_set_burrow_config('protect_'..tname, val, burrows)
end
end
function parse_commandline(...)
local args, opts = {...}, {}
local positionals = process_args(opts, args)
if opts.help then
return false
end
local command = positionals[1]
if not command or command == 'status' then
autochop_printStatus()
elseif command == 'designate' then
autochop_designate()
elseif command == 'undesignate' then
autochop_undesignate()
elseif command == 'target' then
setTarget(args[2], args[3])
elseif command == 'chop' then
do_set_burrow_config('chop', true, args[2])
elseif command == 'nochop' then
do_set_burrow_config('chop', false, args[2])
elseif command == 'clearcut' or command == 'clear' then
do_set_burrow_config('clearcut', true, args[2])
elseif command == 'noclearcut' or command == 'noclear' then
do_set_burrow_config('clearcut', false, args[2])
elseif command == 'protect' then
do_set_burrow_protect_config(args[2], true, args[3])
elseif command == 'unprotect' or command == 'noprotect' then
do_set_burrow_protect_config(args[2], false, args[3])
else
return false
end
return true
end
-- used by gui/autochop
function setBurrowConfig(config)
autochop_setBurrowConfig(config.id, config.chop, config.clearcut,
config.protect_brewable, config.protect_edible,
config.protect_cookable)
end
function getTreeCountsAndBurrowConfigs()
local data = {autochop_getTreeCountsAndBurrowConfigs()}
local ret = {}
ret.summary = table.remove(data, 1)
ret.tree_counts = table.remove(data, 1)
ret.designated_tree_counts = table.remove(data, 1)
ret.burrow_configs = data
for _,c in ipairs(ret.burrow_configs) do
c.name = df.burrow.find(c.id).name
c.chop = c.chop ~= 0
c.clearcut = c.clearcut ~= 0
c.protect_brewable = c.protect_brewable ~= 0
c.protect_edible = c.protect_edible ~= 0
c.protect_cookable = c.protect_cookable ~= 0
end
return ret
end
return _ENV