From 1806f0da1beceb7e16e89f9de179d7d89be53ce9 Mon Sep 17 00:00:00 2001 From: unboundlopez Date: Wed, 25 Jun 2025 22:18:44 -0500 Subject: [PATCH 1/3] Add z_instrument_all script and documentation --- docs/z_instrument_all.rst | 27 ++++++++++++++ z_instrument_all.lua | 75 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 docs/z_instrument_all.rst create mode 100644 z_instrument_all.lua diff --git a/docs/z_instrument_all.rst b/docs/z_instrument_all.rst new file mode 100644 index 000000000..9ae78ee24 --- /dev/null +++ b/docs/z_instrument_all.rst @@ -0,0 +1,27 @@ +z_instrument_all.lua +===================== + +**Automatically queue work orders for all discovered instruments in Dwarf Fortress using DFHack.** + +Features +-------- + +- Detects all valid, craftable instruments via `instruments` command +- Normalizes and filters instrument names for compatibility +- Automatically places a work order for each instrument without having to manually input order and name + +Usage +----- + +Run with a number to place **that many** orders per instrument (defaults to 1 if omitted): + +:: + + z_instrument_all 5 + +This example queues 5 of each discovered instrument. + +Acknowledgments +--------------- + +This script utilizes the DFHack `instruments` command to retrieve and process instrument definitions. \ No newline at end of file diff --git a/z_instrument_all.lua b/z_instrument_all.lua new file mode 100644 index 000000000..9f338e745 --- /dev/null +++ b/z_instrument_all.lua @@ -0,0 +1,75 @@ +-- ztest.lua +-- Automatically places work orders for all discovered instruments using: 'instruments order ' +-- Accepts an optional numeric argument to control how many of each to order (default is 1) + +-- Retrieves and returns a list of unique instrument names from the DFHack 'instruments' command. +-- Strips parenthetical info and filters out crafting steps like 'make' or 'forge'. +local function collect_unique_instrument_names() + local success, raw_output = pcall(function() + return dfhack.run_command_silent("instruments") + end) + + if not success or not raw_output then + qerror("Failed to run 'instruments': " .. tostring(raw_output)) + end + + local instrument_names = {} + local seen_names = {} + + for line in raw_output:gmatch("[^\r\n]+") do + local normalized_line = dfhack.toSearchNormalized(line) + + -- Skip crafting steps + if not normalized_line:match("^%s*make") and not normalized_line:match("^%s*forge") then + -- Remove content in parentheses and trim whitespace + local name = normalized_line:gsub("%s*%b()", ""):gsub("^%s+", ""):gsub("%s+$", "") + if name ~= "" and not seen_names[name] then + seen_names[name] = true + table.insert(instrument_names, name) + end + end + end + + return instrument_names +end + +-- Submits DFHack instrument work orders using the list of instrument names and specified count. +local function place_instrument_work_orders(order_count) + local names = collect_unique_instrument_names() + + for _, instrument in ipairs(names) do + print("------------------------------\n") + + print("Placed order for: " .. instrument .. " (x" .. order_count .. ")\n") + local success, err = pcall(function() + dfhack.run_command("instruments", "order", instrument, tostring(order_count)) + end) + + if not success then + dfhack.printerr("Failed to place order for '" .. instrument .. "': " .. tostring(err)) + end + print("------------------------------\n") + end +end + +-- Main entry point: processes optional count argument and triggers order placement. +local args = {...} +local quantity = 1 -- Default number of orders per instrument + +if #args == 1 then + local parsed = tonumber(args[1]) + if parsed and parsed > 0 then + quantity = math.floor(parsed) + else + qerror("Invalid argument. Usage: ztest [number_of_orders_per_instrument]") + end +elseif #args > 1 then + qerror("Too many arguments. Usage: ztest [number_of_orders_per_instrument]") +end + +local ok, err = pcall(function() + place_instrument_work_orders(quantity) +end) +if not ok then + qerror("Script failed: " .. tostring(err)) +end From e161965fc6223ecf757643c250cf19a00fefc1e0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 26 Jun 2025 03:20:07 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/z_instrument_all.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/z_instrument_all.rst b/docs/z_instrument_all.rst index 9ae78ee24..a0021a0d5 100644 --- a/docs/z_instrument_all.rst +++ b/docs/z_instrument_all.rst @@ -24,4 +24,4 @@ This example queues 5 of each discovered instrument. Acknowledgments --------------- -This script utilizes the DFHack `instruments` command to retrieve and process instrument definitions. \ No newline at end of file +This script utilizes the DFHack `instruments` command to retrieve and process instrument definitions. From 04664ee7ac02c6f0664bd0fadb3aef6f76cfd375 Mon Sep 17 00:00:00 2001 From: unboundlopez <47876628+unboundlopez@users.noreply.github.com> Date: Thu, 26 Jun 2025 21:47:50 -0500 Subject: [PATCH 3/3] Update z_instrument_all.lua --- z_instrument_all.lua | 67 +++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/z_instrument_all.lua b/z_instrument_all.lua index 9f338e745..fbb53e88c 100644 --- a/z_instrument_all.lua +++ b/z_instrument_all.lua @@ -1,9 +1,7 @@ --- ztest.lua +-- z_instrument_all.lua -- Automatically places work orders for all discovered instruments using: 'instruments order ' --- Accepts an optional numeric argument to control how many of each to order (default is 1) +-- Optionally accepts a numeric argument to specify the number of each instrument to order (default is 1) --- Retrieves and returns a list of unique instrument names from the DFHack 'instruments' command. --- Strips parenthetical info and filters out crafting steps like 'make' or 'forge'. local function collect_unique_instrument_names() local success, raw_output = pcall(function() return dfhack.run_command_silent("instruments") @@ -17,15 +15,13 @@ local function collect_unique_instrument_names() local seen_names = {} for line in raw_output:gmatch("[^\r\n]+") do - local normalized_line = dfhack.toSearchNormalized(line) - - -- Skip crafting steps - if not normalized_line:match("^%s*make") and not normalized_line:match("^%s*forge") then - -- Remove content in parentheses and trim whitespace - local name = normalized_line:gsub("%s*%b()", ""):gsub("^%s+", ""):gsub("%s+$", "") - if name ~= "" and not seen_names[name] then - seen_names[name] = true - table.insert(instrument_names, name) + local normalized = dfhack.toSearchNormalized(line) + if not normalized:match("^%s*make") and not normalized:match("^%s*forge") then + local raw_name = line:gsub("%s*%b()", ""):gsub("^%s+", ""):gsub("%s+$", "") + local normalized_name = dfhack.toSearchNormalized(raw_name) + if raw_name ~= "" and not seen_names[normalized_name] then + seen_names[normalized_name] = true + table.insert(instrument_names, { name = raw_name, original_line = line }) end end end @@ -33,38 +29,59 @@ local function collect_unique_instrument_names() return instrument_names end --- Submits DFHack instrument work orders using the list of instrument names and specified count. local function place_instrument_work_orders(order_count) - local names = collect_unique_instrument_names() + local instruments = collect_unique_instrument_names() + local counts = { building = 0, handheld = 0, total = 0 } + + for _, instrument in ipairs(instruments) do + local name = instrument.name + local type = "unknown" - for _, instrument in ipairs(names) do - print("------------------------------\n") + -- Determine type based on line description + local line_lower = instrument.original_line:lower() + if line_lower:find("building") then + type = "building" + elseif line_lower:find("handheld") then + type = "handheld" + end + + print("------------------------------") + print("Placed order for: " .. name .. " (x" .. order_count .. ") [" .. type .. "]") + print("------------------------------") - print("Placed order for: " .. instrument .. " (x" .. order_count .. ")\n") local success, err = pcall(function() - dfhack.run_command("instruments", "order", instrument, tostring(order_count)) + dfhack.run_command("instruments", "order", name, tostring(order_count)) end) if not success then - dfhack.printerr("Failed to place order for '" .. instrument .. "': " .. tostring(err)) + dfhack.printerr("Failed to place order for '" .. name .. "': " .. tostring(err)) + else + counts[type] = counts[type] + order_count + counts.total = counts.total + order_count end - print("------------------------------\n") end + + -- Summary + print("\n==== Instrument Order Summary ====") + print("Total instruments ordered: " .. counts.total) + print(" Handheld: " .. counts.handheld) + print(" Building: " .. counts.building) + print("==================================\n") end --- Main entry point: processes optional count argument and triggers order placement. +-- Main execution local args = {...} -local quantity = 1 -- Default number of orders per instrument +local quantity = 1 if #args == 1 then local parsed = tonumber(args[1]) if parsed and parsed > 0 then quantity = math.floor(parsed) else - qerror("Invalid argument. Usage: ztest [number_of_orders_per_instrument]") + qerror("Invalid argument. Usage: z_instrument_all [number_of_orders_per_instrument]") end elseif #args > 1 then - qerror("Too many arguments. Usage: ztest [number_of_orders_per_instrument]") + qerror("Too many arguments. Usage: z_instrument_all [number_of_orders_per_instrument]") end local ok, err = pcall(function()