Skip to content

Wheelbarrow Assignment for Stockpiles #1462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/zAutowheelbarrow.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
zAutowheelbarrow
================

Automatically manages wheelbarrow assignments for your fortress stockpiles.

This script evaluates all stockpiles and assigns wheelbarrows to those that
would benefit the most (e.g., stone, furniture, or corpse stockpiles) based on
their size. It also clears stale or invalid wheelbarrow assignments.

Overview
--------

This script performs the following tasks:

1. **Scans all stockpiles** in the fortress.
2. **Calculates desired wheelbarrows** for each applicable stockpile (one per 3 tiles).
3. **Assigns wheelbarrows** only to stone, furniture, or corpse stockpiles.
4. **Clears existing wheelbarrow assignments** if they are no longer valid.
5. **Provides a summary** of total stockpiles, total wheelbarrows, and how many more are needed or excess.

Usage
-----

Run the script from the DFHack console:
92 changes: 92 additions & 0 deletions zAutowheelbarrow.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
local stockpiles = df.global.world.buildings.other.STOCKPILE
local tool_items = df.global.world.items.other.TOOL

local function get_total_stockpiles()
local count = 0
for _ in ipairs(stockpiles) do
count = count + 1
end
return count
end

local function get_total_wheelbarrows()
local count = 0
for _, item in ipairs(tool_items) do
if df.item_toolst:is_instance(item) and item.subtype and item.subtype.id == "ITEM_TOOL_WHEELBARROW" then
count = count + 1
end
end
return count
end

local function log_summary(total_stockpiles, total_wheelbarrows, needed_wheelbarrows)
print(string.format("Total stockpiles in fortress: %d", total_stockpiles))
print(string.format("Total wheelbarrows in fortress: %d", total_wheelbarrows))

if needed_wheelbarrows > total_wheelbarrows then
print(string.format("You need to craft %d more wheelbarrows.", needed_wheelbarrows - total_wheelbarrows))
elseif needed_wheelbarrows < total_wheelbarrows then
print(string.format("You have %d excess wheelbarrows.", total_wheelbarrows - needed_wheelbarrows))
else
print("You have exactly the number of wheelbarrows needed.")
end
end

local function assign_wheelbarrows_to_stockpiles()
local total_needed = 0

print("\n--- Stockpiles Assigned Wheelbarrows ---")
for _, bld in ipairs(stockpiles) do
local width = bld.x2 - bld.x1 + 1
local height = bld.y2 - bld.y1 + 1
local area = width * height
local desired_wheelbarrows = math.floor(area / 3)

local flags = bld.settings and bld.settings.flags
if flags and (flags.stone or flags.furniture or flags.corpses) then
bld.storage.max_wheelbarrows = desired_wheelbarrows
total_needed = total_needed + desired_wheelbarrows
print(string.format("Stockpile #%d: size %d x %d = %d tiles, needs %d wheelbarrows", bld.id, width, height, area, desired_wheelbarrows))
end
end

local skipped_count = 0
for _, bld in ipairs(stockpiles) do
local flags = bld.settings and bld.settings.flags
if not (flags and (flags.stone or flags.furniture or flags.corpses)) then
bld.storage.max_wheelbarrows = 0
skipped_count = skipped_count + 1
end
end
print("\n--- Skipped Stockpiles ---")
print(string.format("Skipped %d stockpiles (not stone, furniture, or corpses) \n", skipped_count))

return total_needed
end

local function clear_wheelbarrow_assignments()
for _, item in ipairs(tool_items) do
if df.item_toolst:is_instance(item)
and item.subtype
and item.subtype.id == "ITEM_TOOL_WHEELBARROW" then

if #item.specific_refs > 0 or #item.general_refs > 0 then
print(string.format("Wheelbarrow ID %d in use, skipping", item.id))
elseif item.stockpile then
item.stockpile.id = -1
item.stockpile.x = -30000
item.stockpile.y = -30000
end
end
end
end

local total_stockpiles = get_total_stockpiles()
local total_wheelbarrows = get_total_wheelbarrows()
local needed_wheelbarrows = assign_wheelbarrows_to_stockpiles()

log_summary(total_stockpiles, total_wheelbarrows, needed_wheelbarrows)

print("\n> zAutowheelbarrow\n")

clear_wheelbarrow_assignments()