Quickfort User Guide

Quickfort is a DFHack script that helps you build fortresses from “blueprint” .csv and .xlsx files. Many applications exist to edit these files, such as MS Excel and Google Sheets. You can also build your plan “for real” in Dwarf Fortress, and then export your map using the blueprint plugin. Most layout and building-oriented DF commands are supported through the use of multiple files or spreadsheets, each describing a different phase of DF construction: designation, building, placing stockpiles/zones, and setting configuration.

The original idea and 1.0 codebase came from Valdemar’s auto-designation macro. Joel Thornton (joelpt) reimplemented the core logic in Python and extended its functionality with Quickfort 2.0. This DFHack-native implementation, called “DFHack Quickfort” or just “quickfort”, builds upon Quickfort 2.0’s formats and features. DFHack Quickfort is written in Lua and interacts with Dwarf Fortress memory structures directly, allowing for instantaneous blueprint application, error checking and recovery, and many other advanced features.

This document focuses on DFHack Quickfort’s capabilities and teaches players how to understand and build blueprint files. Some of the text was originally written by Joel Thornton, reused here with his permission.

For those just looking to apply blueprints, check out the quickfort command’s documentation for syntax. There are also many ready-to-use blueprints available in the blueprints/library subfolder in your DFHack installation. Browse them on your computer or online, or run quickfort list -l at the [DFHack]# prompt to list them, and then quickfort run to apply them to your fort!

See the Links section for more information and online resources.

Features

  • General
    • Manages blueprints to handle all phases of DF construction
    • Supports .csv and multi-worksheet .xlsx blueprint files
    • Near-instant application, even for very large and complex blueprints
    • Blueprints can span multiple z-levels
    • Supports multiple blueprints per .csv file/spreadsheet sheet
    • “meta” blueprints that automate the application of sequences of blueprints
    • Undo functionality for dig, build, place, and zone blueprints
    • Automatic cropping of blueprints so you don’t get errors if the blueprint extends off the map
    • Can generate manager orders for everything required by a build blueprint
    • Library of ready-to-use blueprints included
    • Verbose output mode for debugging
  • Dig mode
    • Supports all types of designations, including dumping/forbidding items and setting traffic settings
    • Supports setting dig priorities
    • Supports applying dig blueprints in marker mode
    • Handles carving arbitrarily complex minecart tracks, including tracks that cross other tracks
  • Build mode
    • DFHack buildingplan integration
    • Designate complete constructions at once, without having to wait for each tile to become supported before you can build it
    • Automatic expansion of building footprints to their minimum dimensions, so only the center tile of a multi-tile building needs to be recorded in the blueprint
    • Tile occupancy and validity checking so, for example, buildings that cannot be placed on a certain tile will simply be skipped instead of the blueprint failing to apply. Blueprints that are only partially applied for any reason (for example, you need to dig out some more tiles) can be safely reapplied to build the remaining buildings.
    • Relaxed rules for farm plot and road placement: you can still place the building even if an invalid tile (e.g. stone tiles for farm plots) splits the designated area into two parts
    • Intelligent boundary detection for adjacent buildings of the same type (e.g. a 6x6 block of wj cells will be correctly split into 4 jeweler’s workshops)
  • Place and zone modes
    • Define stockpiles and zones in any continguous shape, not just rectangular blocks
    • Configurable maximums for bins, barrels and wheelbarrows assigned to created stockpiles
    • Automatic splitting of stockpiles and zones that exceed maximum dimension limits
  • Query mode
    • Send arbitrary keystroke sequences to the UI – anything you can do through the UI is supported
    • Supports aliases to automate frequent keystroke combos
    • Includes a library of pre-made and tested aliases to automate most common tasks, such as configuring stockpiles for important item types or creating named hauling routes for quantum stockpiles.
    • Supports including aliases in other aliases, and repeating key sequences a specified number of times
    • Skips sending key sequences when the cursor is over a tile that does not have a stockpile or building, so missing buildings won’t desynchronize your blueprint
    • Instant halting of query blueprint application when keystroke errors are detected, such as when a key sequence leaves us stuck in a submenu, to make blueprint misconfigurations easier to debug

Editing Blueprints

We recommend using a spreadsheet editor such as Excel, Google Sheets, or LibreOffice to edit blueprint files, but any text editor will do.

The format of Quickfort-compatible blueprint files is straightforward. The first line (or upper-left cell) of the spreadsheet should look like this:

#dig This is a decription.

The keyword “dig” tells Quickfort we are going to be using the Designations menu in DF. The following “mode” keywords are understood:

dig     Designations menu (d)
build   Build menu (b)
place   Place stockpiles menu (p)
zone    Activity zones menu (i)
query   Set building tasks/prefs menu (q)

If no modeline appears in the first cell, the file or sheet is interpreted as a #dig blueprint.

There are also “meta” and “notes” blueprints, but we’ll talk about those later.

Optionally following this keyword and a space, you may enter a comment. This comment will appear in the output of quickfort list when run from the DFHack# prompt. You can use this space for explanations, attribution, etc.

Below this line begin entering the keys you want sent in each cell. For example, we could dig out a 4x4 room like so (spaces are used as column separators here for clarity, but a real .csv file would have commas):

#dig
d d d d #
d d d d #
d d d d #
d d d d #
# # # # #

Note the # symbols at the right end of each row and below the last row. These are completely optional, but can be helpful to make the row and column positions clear.

Once the dwarves have that dug out, let’s build a walled-in bedroom within our dug-out area:

#build
Cw Cw Cw Cw #
Cw b  h  Cw #
Cw       Cw #
Cw Cw    Cw #
#  #  #  #  #

Note my generosity - in addition to the bed (b) I’ve built a chest (h) here for the dwarf as well. You must use the full series of keys needed to build something in each cell, e.g. ‘Cw’ enters DF’s constructions submenu (C) and selects walls (w).

I’d also like to place a booze stockpile in the 2 unoccupied tiles in the room.

#place Place a food stockpile
` ` ` ` #
` ` ` ` #
` f(2x1)#
` ` ` ` #
# # # # #

This illustration may be a little hard to understand. The f(2x1) is in column 2, row 3. All the other cells are empty. QF considers both “`” (backtick – the character under the tilde) and “~” (tilde) characters within cells to be empty cells; this can help with multilayer or fortress-wide blueprint layouts as ‘chalk lines’.

With f(2x1), we’ve asked QF to place a food stockpile 2 units wide by 1 high unit. Note that the f(2x1) syntax isn’t actually necessary here; we could have just used:

#place Place a food stockpile
` ` ` ` #
` ` ` ` #
` f f ` #
` ` ` ` #
# # # # #

QF is smart enough to recognize this as a 2x1 food stockpile, and creates it as such rather than as two 1x1 food stockpiles. Quickfort recognizes any connected region of identical designations as a single stockpile. The tiles can be connected orthogonally or diagonally, just as long as they are touching somehow.

Lastly, let’s turn the bed into a bedroom and set the food stockpile to hold only booze.

#query
` ` ` ` #
` r&  ` #
` booze #
` ` ` ` #
# # # # #

In column 2, row 2 we have “r&”. This sends the “r” key to DF when the cursor is over the bed, causing us to ‘make room’ and “&”, which is a special symbol that expands to “{Enter}”, to indicate that we’re done.

In column 2, row 3 we have “booze”. This is one of many alias keywords defined in the included baseline aliases file. This particular alias sets a food stockpile to carry booze only. It sends the keys needed to navigate DF’s stockpile settings menu, and then sends an Escape character (“^” or “{ESC}”) to exit back to the map. It is important to exit out of any menus that you enter while in query mode so that the cursor can move to the next tile when it is done configuring the current tile.

Check out the included blueprint library to see many more examples. Read the baseline aliases file for helpful pre-packaged aliases, or create your own in dfhack-config/quickfort/aliases.txt in your DFHack installation.

Area expansion syntax

In Quickfort, the following blueprints are equivalent:

#dig a 3x3 area
d d d #
d d d #
d d d #
# # # #

#dig the same area with d(3x3) specified in row 1, col 1
d(3x3)#
` ` ` #
` ` ` #
# # # #

The second example uses Quickfort’s “area expansion syntax”, which takes the form:

keys(WxH)

In Quickfort the above two examples of specifying a contiguous 3x3 area produce identical output: a single 3x3 designation will be performed, rather than nine 1x1 designations as the first example might suggest.

Area expansion syntax can only specify rectangular areas. If you want to create extent-based structures (e.g. farm plots or stockpiles) in different shapes, use the first format above. For example:

#place L shaped food stockpile
f f ` ` #
f f ` ` #
f f f f #
f f f f #
# # # # #

Area expansion syntax also sets boundaries, which can be useful if you want adjacent, but separate, stockpiles of the same type:

#place Two touching but separate food stockpiles
f(4x2)  #
~ ~ ~ ~ #
f(4x2)  #
~ ~ ~ ~ #
# # # # #

As mentioned previously, “~” characters are ignored as comment characters and can be used for visualizing the blueprint layout. The blueprint can be equivalently written as:

#place Two touching but separate food stockpiles
f(4x2)  #
~ ~ ~ ~ #
f f f f #
f f f f #
# # # # #

since the area expansion syntax of the upper stockpile prevents it from combining with the lower, freeform syntax stockpile.

Area expansion syntax can also be used for buildings which have an adjustable size, like bridges. The following blueprints are equivalent:

#build a 4x2 bridge from row 1, col 1
ga(4x2)  `  #
`  `  `  `  #
#  #  #  #  #

#build a 4x2 bridge from row 1, col 1
ga ga ga ga #
ga ga ga ga #
#  #  #  #  #

Automatic area expansion

Buildings larger than 1x1, like workshops, can be represented in any of three ways. You can designate just their center tile with empty cells around it to leave room for the footprint, like this:

#build a mason workshop in row 2, col 2 that will occupy the 3x3 area
`  `  `  #
`  wm `  #
`  `  `  #
#  #  #  #

Or you can fill out the entire footprint like this:

#build a mason workshop
wm wm wm #
wm wm wm #
wm wm wm #
#  #  #  #

This format may be verbose for regular workshops, but it can be very helpful for laying out structures like screw pump towers and waterwheels, whose “center point” can be non-obvious.

Finally, you can use area expansion syntax to represent the workshop:

#build a mason workshop
wm(3x3)  #
`  `  `  #
`  `  `  #
#  #  #  #

This style can be convenient for laying out multiple buildings of the same type. If you are building a large-scale block factory, for example, this will create 20 mason workshops all in a row:

#build line of 20 mason workshops
wm(60x3) #

Quickfort will intelligently break large areas of the same designation into appropriately-sized chunks.

Multilevel blueprints

Multilevel blueprints are accommodated by separating Z-levels of the blueprint with #> (go down one z-level) or #< (go up one z-level) at the end of each floor.

#dig Stairs leading down to a small room below
j  `  `  #
`  `  `  #
`  `  `  #
#> #  #  #
u  d  d  #
d  d  d  #
d  d  d  #
#  #  #  #

The marker must appear in the first column of the row to be recognized, just like a modeline.

Dig priorities

DF designation priorities are supported for #dig blueprints. The full syntax is [letter][number][expansion], where if the letter is not specified, d is assumed, and if number is not specified, 4 is assumed (the default priority). So each of these blueprints is equivalent:

#dig dig the interior of the room at high priority
d  d  d  d  d  #
d  d1 d1 d1 d  #
d  d1 d1 d1 d  #
d  d1 d1 d1 d  #
d  d  d  d  d  #
#  #  #  #  #  #

#dig dig the interior of the room at high priority
d  d  d  d  d  #
d  d1(3x3)  d  #
d  `  `  `  d  #
d  `  `  `  d  #
d  d  d  d  d  #
#  #  #  #  #  #

#dig dig the interior of the room at high priority
4  4  4  4  4  #
4  1  1  1  4  #
4  1  1  1  4  #
4  1  1  1  4  #
4  4  4  4  4  #
#  #  #  #  #  #

Marker mode

Marker mode is useful for when you want to plan out your digging, but you don’t want to dig everything just yet. In #dig mode, you can add a m before any other designation letter to indicate that the tile should be designated in marker mode. For example, to dig out the perimeter of a room, but leave the center of the room marked for digging later:

#dig
d  d  d  d d #
d md md md d #
d md md md d #
d md md md d #
d  d  d  d d #
#  #  #  # # #

Then you can use “Toggle Standard/Marking” (d-M) to convert the center tiles to regular designations at your leisure.

To apply an entire dig blueprint in marker mode, regardless of what the blueprint itself says, you can set the global quickfort setting force_marker_mode to true before you apply the blueprint.

Note that the in-game UI setting “Standard/Marker Only” (d-m) does not have any effect on quickfort.

Stockpiles and zones

It is very common to have stockpiles that accept multiple categories of items or zones that permit more than one activity. Although it is perfectly valid to declare a single-purpose stockpile or zone and then modify it with a #query blueprint, quickfort also supports directly declaring all the types on the #place and #zone blueprints. For example, to declare a 10x10 area that is a pasture, a fruit picking area, and a meeting area all at once, you could write:

#zone main pasture and picnic area
nmg(10x10)

And similarly, to declare a stockpile that accepts both corpses and refuse, you could write:

#place refuse heap
yr(20x10)

The order of the individual letters doesn’t matter.

To toggle the active flag for zones, add an a character to the string. For example, to create a disabled pit zone (that you later intend to turn into a pond and carefully fill to 3-depth water):

#zone disabled future pond zone
pa(1x3)

Note that while this notation covers most use cases, tweaking low-level zone parameters, like hospital supply levels or converting between pits and ponds, must still be done manually or with a #query blueprint.

Minecart tracks

There are two ways to produce minecart tracks, and they are handled very differently by the game. You can carve them into hard natural floors or you can construct them out of building materials. Constructed tracks are conceptually simpler, so we’ll start with them.

Constructed tracks

Quickfort supports the designation of track stops and rollers through the normal mechanisms: a #build blueprint with CS and some number of d and a characters (for selecting dump direction and friction) in a cell designates a track stop and a #build blueprint with Mr and some number of s and q characters (for direction and speed) designates a roller. This can get confusing very quickly and is very difficult to read in a blueprint. Constructed track segments don’t even have keys associated with them at all!

To solve this problem, Quickfort provides the following keywords for use in build blueprints:

-- Track segments --
trackN
trackS
trackE
trackW
trackNS
trackNE
trackNW
trackSE
trackSW
trackEW
trackNSE
trackNSW
trackNEW
trackSEW
trackNSEW

-- Track/ramp segments --
trackrampN
trackrampS
trackrampE
trackrampW
trackrampNS
trackrampNE
trackrampNW
trackrampSE
trackrampSW
trackrampEW
trackrampNSE
trackrampNSW
trackrampNEW
trackrampSEW
trackrampNSEW

-- Horizontal and vertical roller segments --
rollerH
rollerV
rollerNS
rollerSN
rollerEW
rollerWE

Note: append up to four 'q' characters to roller keywords to set roller
speed. E.g. a roller that propels from East to West at the slowest speed can
be specified with 'rollerEWqqqq'.

-- Track stops that (optionally) dump to the N/S/E/W --
trackstop
trackstopN
trackstopS
trackstopE
trackstopW

Note: append up to four 'a' characters to trackstop keywords to set friction
amount. E.g. a stop that applies the smallest amount of friction can be
specified with 'trackstopaaaa'.

As an example, you can create an E-W track with stops at each end that dump to their outside directions with the following blueprint:

#build Example track
trackstopW trackEW trackEW trackEW trackstopE

Note that the only way to build track and track/ramp segments is with the keywords. The UI method of using “+” and “-” keys to select the track type from a list does not work since DFHack Quickfort doesn’t actually send keys to the UI to build buildings. The text in your spreadsheet cells is mapped directly into DFHack API calls. Only #query blueprints still send actual keycodes to the UI.

Carved tracks

In the game, you carve a minecart track by specifying a beginning and ending tile and the game “adds” the designation to the tiles. You cannot designate single tiles. For example to carve two track segments that cross each other, you might use the cursor to designate a line of three vertical tiles like this:

`  start here  `  #
`  `           `  #
`  end here    `  #
#  #           #  #

Then to carve the cross, you’d do a horizonal segment:

`           `  `         #
start here  `  end here  #
`           `  `         #
#           #  #         #

This will result in a carved track that would be equivalent to a constructed track of the form:

#build
`       trackS     `       #
trackE  trackNSEW  trackW  #
`       trackN     `       #
#       #          #       #

To carve this same track with a #dig blueprint, you’d use area expansion syntax with a height or width of 1 to indicate the segments to designate:

#dig
`       T(1x3)  `  #
T(3x1)  `       `  #
`       `       `  #
#       #       #  #

“But wait!”, I can hear you say, “How do you designate a track corner that opens to the South and East? You can’t put both T(1xH) and T(Wx1) in the same cell!” This is true, but you can specify both width and height, and for tracks, QF interprets it as an upper-left corner extending to the right W tiles and down H tiles. For example, to carve a track in a closed ring, you’d write:

#dig
T(3x3)  `  T(1x3)  #
`       `  `       #
T(3x1)  `  `       #
#       #  #       #

Which would result in a carved track simliar to a constructed track of the form:

#build
trackSE  trackEW  trackSW  #
trackNS  `        trackNS  #
trackNE  trackEW  trackNW  #
#        #        #        #

Modeline markers

The modeline has some additional optional components that we haven’t talked about yet. You can:

  • give a blueprint a label by adding a label() marker
  • set a cursor offset and/or start hint by adding a start() marker
  • hide a blueprint from being listed with a hidden() marker
  • register a message to be displayed after the blueprint is successfully applied

The full modeline syntax, when everything is specified, is:

#mode label(mylabel) start(X;Y;STARTCOMMENT) hidden() message(mymessage) comment

Note that all elements are optional except for the initial #mode (though, as mentioned in the first section, if a modeline doesn’t appear at all in the first cell of a spreadsheet, the blueprint is interpreted as a #dig blueprint with no optional markers). Here are a few examples of modelines with optional elements before we discuss them in more detail:

#dig start(3; 3; Center tile of a 5-tile square) Regular blueprint comment
#build label(noblebedroom) start(10;15)
#query label(configstockpiles) No explicit start() means cursor is at upper left corner
#meta label(digwholefort) start(center of stairs on surface)
#dig label(digdining) hidden() managed by the digwholefort meta blueprint
#zone label(pastures) message(remember to assign animals to the new pastures)

Blueprint labels

Labels are displayed in the quickfort list output and are used for addressing specific blueprints when there are multiple blueprints in a single file or spreadsheet sheet (see Packaging a set of blueprints below). If a blueprint has no label, the label becomes the ordinal of the blueprint’s position in the file or sheet. For example, the label of the first blueprint will be “1” if it is not otherwise set, the label of the second blueprint will be “2” if it is not otherwise set, etc. Labels that are explicitly defined must start with a letter to ensure the auto-generated labels don’t conflict with user-defined labels.

Start positions

Start positions specify a cursor offset for a particular blueprint, simplifying the task of blueprint alignment. This is very helpful for blueprints that are based on a central staircase, but it helps whenever a blueprint has an obvious “center”. For example:

#build start(2;2;center of workshop) label(masonw) a mason workshop
wm wm wm #
wm wm wm #
wm wm wm #
#  #  #  #

will build the workshop centered on the cursor, not down and to the right of the cursor.

The two numbers specify the column and row (or X and Y offset) where the cursor is expected to be when you apply the blueprint. Position 1;1 is the top left cell. The optional comment will show up in the quickfort list output and should contain information about where to position the cursor. If the start position is 1;1, you can omit the numbers and just add a comment describing where to put the cursor. This is also useful for meta blueprints that don’t actually care where the cursor is, but that refer to other blueprints that have fully-specified start() markers. For example, a meta blueprint that refers to the masonw blueprint above could look like this:

#meta start(center of workshop) a mason workshop
/masonw

Hiding blueprints

A blueprint with a hidden() marker won’t appear in quickfort list output unless the --hidden flag is specified. The primary reason for hiding a blueprint (rather than, say, deleting it or moving it out of the blueprints/ folder) is if a blueprint is intended to be run as part of a larger sequence managed by a meta blueprint.

Messages

A blueprint with a message() marker will display a message after the blueprint is applied with quickfort run. This is useful for reminding players to take manual steps that cannot be automated, like assigning animals to a pasture or assigning minecarts to a route, or listing the next step in a series of blueprints. For long or multi-part messages, you can embed newlines:

"#meta label(surface1) message(This would be a good time to start digging the industry level.
Once the area is clear, continue with /surface2.) clear the embark site and set up pastures"

Packaging a set of blueprints

A complete specification for a section of your fortress may contain 5 or more separate blueprints, one for each “phase” of construction (dig, build, place stockpiles, designate zones, query building adjustments).

To manage all the separate blueprints, it is often convenient to keep related blueprints in a single file. For .xlsx spreadsheets, you can keep each blueprint in a separate sheet. Online spreadsheet applications like Google Sheets make it easy to work with multiple related blueprints, and, as a bonus, they retain any formatting you’ve set, like column sizes and coloring.

For both .csv files and .xlsx spreadsheets you can also add as many blueprints as you want in a single file or sheet. Just add a modeline in the first column to indicate the start of a new blueprint. Instead of multiple .csv files, you can concatenate them into one single file.

For example, you can store multiple blueprints together like this:

#dig label(bed1)
d d d d #
d d d d #
d d d d #
d d d d #
# # # # #
#build label(bed2)
b   f h #
        #
        #
n       #
# # # # #
#place label(bed3)
        #
f(2x2)  #
        #
        #
# # # # #
#query label(bed4)
        #
booze   #
        #
        #
# # # # #
#query label(bed5)
r{+ 3}& #
        #
        #
        #
# # # # #

Of course, you could still choose to keep your blueprints in single-sheet .csv files and just give related blueprints similar names:

bedroom.1.dig.csv
bedroom.2.build.csv
bedroom.3.place.csv
bedroom.4.query.csv
bedroom.5.query2.csv

But the naming and organization is completely up to you.

Meta blueprints

Meta blueprints are blueprints that script a series of other blueprints. Many blueprint packages follow this pattern:

  • Apply dig blueprint to designate dig areas
  • Wait for miners to dig
  • Apply build buildprint to designate buildings
  • Apply place buildprint to designate stockpiles
  • Apply query blueprint to configure stockpiles
  • Wait for buildings to get built
  • Apply a different query blueprint to configure rooms

Those three “apply”s in the middle might as well get done in one command instead of three. A meta blueprint can encode that sequence. A meta blueprint refers to other blueprints by their label (see the Modeline markers section above) in the same format used by the quickfort command: <sheet name>/<label>, or just /<label> for blueprints in .csv files or blueprints in the same spreadsheet sheet as the #meta blueprint that references them.

A few examples might make this clearer. Say you have a .csv file with the “bed” blueprints in the previous section:

#dig label(bed1)
...
#build label(bed2)
...
#place label(bed3)
...
#query label(bed4)
...
#query label(bed5)
...

Note how I’ve given them all labels so we can address them safely. If I hadn’t given them labels, they would receive default labels of “1”, “2”, “3”, etc, but those labels would change if I ever add more blueprints at the top. This is not a problem if we’re just running the blueprints individually from the quickfort list command, but meta blueprints need a label name that isn’t going to change over time.

So let’s add a meta blueprint to this file that will combine the middle three blueprints into one:

"#meta plan bedroom: combines build, place, and stockpile config blueprints"
/bed2
/bed3
/bed4

Now your sequence is shortened to:

  • Apply dig blueprint to designate dig areas
  • Wait for miners to dig
  • Apply meta buildprint to build buildings and designate/configure stockpiles
  • Wait for buildings to get built
  • Apply the final query blueprint to configure the room

You can use meta blueprints to lay out your fortress at a larger scale as well. The #< and #> notation is valid in meta blueprints, so you can, for example, store the dig blueprints for all the levels of your fortress in different sheets in a spreadsheet, and then use a meta blueprint to designate your entire fortress for digging at once. For example, say you have a spreadsheet with the following layout:

Sheet name contents
dig_farming one #dig blueprint, no label
dig_industry one #dig blueprint, no label
dig_dining four #dig blueprints, with labels “main”, “basement”, “waterway”, and “cistern”
dig_guildhall one #dig blueprint, no label
dig_suites one #dig blueprint, no label
dig_bedrooms one #dig blueprint, no label

We can add a sheet named “dig_all” with the following contents (we’re expecting a big fort, so we’re planning for a lot of bedrooms):

#meta dig the whole fortress (remember to set force_marker_mode to true)
dig_farming/1
#>
dig_industry/1
#>
#>
dig_dining/main
#>
dig_dining/basement
#>
dig_dining/waterway
#>
dig_dining/cistern
#>
dig_guildhall/1
#>
dig_suites/1
#>
dig_bedrooms/1
#>
dig_bedrooms/1
#>
dig_bedrooms/1
#>
dig_bedrooms/1
#>
dig_bedrooms/1

Note that for blueprints without an explicit label, we still need to address them by their auto-generated numerical label.

You can then hide the blueprints that you now manage with the #meta-mode blueprint from quickfort list by adding a hidden() marker to their modelines. That way the output of quickfort list won’t be cluttered by blueprints that you don’t need to run directly. If you ever do need to access the managed blueprints individually, you can still see them with quickfort list --hidden.

Notes blueprints

Sometimes you just want to record some information about your blueprints, such as when to apply them, what preparations you need to make, or what the blueprints contain. The message() modeline marker is useful for small, single-line messages, but a #notes blueprint is more convenient for long messages or messages that span many lines. The lines in a #notes blueprint are output as if they were contained within a message() marker. For example, the following two blueprints result in the same output:

"#meta label(help) message(This is the help text for the blueprint set
contained in this file.

More info here...) blueprint set walkthough"

#notes label(help) blueprint set walkthrough
This is the help text for the blueprint set
contained in this file

More info here...

The quotes around the #meta modeline allow newlines in a single cell’s text. Each line of the #notes “blueprint”, however, is in a separate cell, allowing for much easier viewing and editing.

Buildingplan integration

Buildingplan is a DFHack plugin that keeps jobs in a suspended state until the materials required for the job are available. This prevents a building designation from being canceled when a dwarf picks up the job but can’t find the materials.

For all types that buildingplan supports, quickfort using buildingplan to manage construction. Buildings are still constructed immediately if you have the materials, but you now have the freedom to apply build blueprints before you manufacture all required materials, and the jobs will be fulfilled as the materials become available.

If a #build blueprint only refers to supported types, the buildingplan integration pairs well with the workflow plugin, which can build items a few at a time continuously as long as they are needed. For building types that are not yet supported by buildingplan, a good pattern to follow is to first run quickfort orders on the #build blueprint to manufacture all the required items, then apply the blueprint itself.

See the buildingplan documentation for more information. As of this writing, buildingplan only supports basic furniture.

Generating manager orders

Quickfort can generate manager orders to make sure you have the proper items in stock to apply a #build blueprint.

Many items can be manufactured from different source materials. Orders will always choose rock when it can, then wood, then cloth, then iron. You can always remove orders that don’t make sense for your fort and manually enqueue a similar order more to your liking. For example, if you want silk ropes instead of cloth ropes, make a new manager order for an appropriate quantity of silk ropes, and then remove the generated cloth rope order.

Anything that requires generic building materials (workshops, constructions, etc.) will result in an order for a rock block. One “Make rock blocks” job produces four blocks per boulder, so the number of jobs ordered will be the number of blocks you need divided by four (rounded up). You might end up with a few extra blocks, but not too many.

If you want your constructions to be in a consistent color, be sure to choose a rock type for all of your ‘Make rock blocks’ orders by selecting the order and hitting d. You might want to set the rock type for other non-block orders to something different if you fear running out of the type of rock that you want to use for blocks.

There are a few building types that will generate extra manager orders for related materials:

  • Track stops will generate an order for a minecart
  • Traction benches will generate orders for a table, mechanism, and rope
  • Levers will generate an order for an extra two mechanisms for connecting the lever to a target
  • Cage traps will generate an order for a cage

Tips and tricks

  • During blueprint application, especially query blueprints, don’t click the mouse on the DF window or type any keys. They can change the state of the game while the blueprint is being applied, resulting in strange errors.
  • After digging out an area, you may wish to smooth and/or engrave the area before starting the build phase, as dwarves may be unable to access walls or floors that are behind/under built objects.
  • If you are designating more than one level for digging at a time, you can make your miners more efficient by using marker mode on all levels but one. This prevents your miners from digging out a few tiles on one level, then running down/up the stairs to do a few tiles on an adjacent level. With only one level “live” and all other levels in marker mode, your miners can concentrate on one level at a time. You just have to remember to “unmark” a new level when your miners are done with their current one.
  • As of DF 0.34.x, it is no longer possible to build doors (d) at the same time that you build adjacent walls (Cw). Doors must now be built after walls are constructed for them to be next to. This does not affect the more common case where walls exist as a side-effect of having dug-out a room in a #dig blueprint.

Caveats and limitations

  • Buildings will be designated regardless of whether you have the required materials, but if materials are not available when the construction job is picked up by a dwarf, the buildings will be canceled and the designations will disappear. Until the buildingplan plugin can be extended to support all building types, you should use quickfort orders to pre-manufacture all the materials you need for a #build blueprint before you apply it.
  • If you use the jugs alias in your #query-mode blueprints, be aware that there is no way to differentiate jugs from other types of tools in the game. Therefore, jugs stockpiles will also take nest boxes and other tools. The only workaround is not to have other tools lying around in your fort.
  • Likewise for bags. The game does not differentiate between empty and full bags, so you’ll get bags of gypsum power and sand in your bags stockpile unless you avoid collecting sand and are careful to assign all your gypsum to your hospital.
  • Weapon traps and upright spear/spike traps can currently only be built with a single weapon.
  • Pressure plates can be built, but they cannot be usefully configured yet.
  • Building instruments, bookcases, display furniture, and offering places are not yet supported by DFHack.
  • This script is relatively new, and there are bound to be bugs! Please report them at the DFHack issue tracker so they can be addressed.

Dreamfort case study: a practical guide to advanced blueprint design

While syntax definitions and toy examples will certainly get you started with your blueprints, it may not be clear how all the quickfort features fit together or what the best practices are, especially for large and complex blueprint sets. This section walks through the “Dreamfort” blueprints found in the DFHack blueprint library, highlighting design choices and showcasing practical techniques that can help you create better blueprints. Note that this is not a guide for how to design the best forts (there is plenty about that on the wiki). This is essentially an extended tips and tricks section focused on how to make usable and useful quickfort blueprints that will save you time and energy.

The Dreamfort blueprints we’ll be discussing are available in the library as one large .csv file or online as individual spreadsheets. Either can be read and applied by quickfort, but for us humans, the online spreadsheets are much easier to work with. Each spreadsheet has a “Notes” sheet with some useful details. Flip through some of the spreadsheets and read the walkthrough to get oriented. Also, if you haven’t built Dreamfort before, try an embark in a flat area and take it for a spin!

Almost every quickfort feature is used somewhere in Dreamfort, so the blueprints as a whole are useful as practical examples. You can copy the blueprints and use them as starting points for your own, or just refer to them when you create something similar.

In this case study, we’ll start by discussing the high level organization of the Dreamfort blueprint set, using the “surface” blueprints as an example. Then we’ll walk through the blueprints for each of the remaining fort levels in turn, calling out feature usage examples and explaining the parts that might not be obvious just from looking at them.

The surface level: how to manage complexity

For smaller blueprints, packaging and usability are not really that important - just write it, run it, and you’re done. However, as your blueprints become larger and more detailed, there are some best practices that can help you deal with the added complexity. Dreamfort’s surface level is many steps long since there are trees to be cleared, holes to be dug, flooring to be laid, and furniture to be built, and each step requires the previous step to be completely finished before it can begin. Therefore, a lot of thought went into minimizing the toil associated with applying so many blueprints.

Tip

Use meta blueprints to script blueprint sequences and reduce the number of quickfort commands you have to run.

The single most effective way to make your blueprint sets easier to use is to group them with meta blueprints. For the Dreamfort set of blueprints, each logical “step” generally takes more than one blueprint. For example, setting up pastures with a #zone blueprint, placing starting stockpiles with a #place blueprint, building starting workshops with a #build blueprint, and configuring the stockpiles with a #query blueprint can all be done at once. Bundling blueprints like this reduced the number of steps in Dreamfort from 47 to 24, and it also made it much clearer to see which blueprints can be applied at once without unpausing the game. Check out dreamfort_surface’s “meta” sheet to see how much meta blueprints can simplify your life.

Note that one of the #meta blueprints just has one line. In this case, the #meta blueprint isn’t strictly necessary. The referenced blueprint could just be applied directly. However, quickfort lists blueprints in the order that it reads them, and we chose to make a one-blueprint meta blueprint to ensure all the steps appear in order in the quickfort list output.

By the way, you can define as many blueprints as you want on one sheet, but multi-blueprint sheets are especially useful when writing meta blueprints. It’s like having a bird’s eye view of your entire plan in one sheet.

Tip

Keep the blueprint list uncluttered with hidden() markers.

If a blueprint is bundled into a meta blueprint, it does not need to appear in the quickfort list output, since you won’t be running it directly. Add a hidden() marker to those blueprints to keep the list output tidy. You can still access hidden blueprints with quickfort list --hidden if you need to – for example to reapply a partially completed #build blueprint – but now they won’t clutter up the normal blueprint list.

Tip

Name your blueprints with a common prefix so you can find them easily.

This goes for both the file name and the modeline label(). Searching and filtering is implemented for both the quickfort list command and the quickfort interactive dialog. If you give related blueprints a common prefix, it makes it easy to set the filters to display just the blueprints that you’re interested in. If you have a lot of blueprints, this can save you a lot of time. Dreamfort, of course, uses the “dreamfort” prefix for the files and sequence names for the labels, like “surface1”, “surface2”, “farming1”, etc. So if I’m in the middle of applying the surface blueprints, I’d set the filter to dreamfort surface to just display the relevant blueprints.

Tip

Add descriptive comments that remind you what the blueprint contains.

If you’ve been away from Dwarf Fortress for a while, it’s easy to forget what your blueprints actually do. Make use of modeline comments so your descriptions are visible in the blueprint list. If you use meta blueprints, all your comments can be conveniently edited on one sheet, like in surface’s meta sheet.

Tip

Use message() markers to remind yourself what to do next.

Messages are displayed after a blueprint is applied. Good things to include in messages are:

  • The name of the next blueprint to apply and when to run it
  • Whether quickfort orders should be run for an upcoming step
  • Any manual actions that have to happen, like assigning minecarts to hauling routes or pasturing animals after creating zones

These things are just too easy to forget. Adding a message() can save you from time-wasting mistakes. Note that message() markers can still appear on the hidden() blueprints, and they’ll still get shown when the blueprint is run via the #meta blueprint. For an example of this, check out the zones sheet where the pastures are defined.

The farming level: fun with stockpiles

It is usually convenient to store closely associated blueprints in the same spreadsheet. The farming level is very closely tied to the surface because the miasma vents have to perfectly line up. However, surface is a separate z-level and, more importantly, already has many many blueprints, so farming is split into a separate file.

Tip

Automate stockpile chains when you can, and write message() reminders when you can’t.

The farming level starts doing interesting things with query blueprints and stockpiles. Note the careful customization of the food stockpiles and the stockpile chains set up with the give* aliases. This is so when multiple stockpiles can hold the same item, the largest can keep the smaller ones filled. If you have multiple stockpiles holding the same type on different z-levels, though, this can be tricky to set up with a blueprint. Here, the jugs and pots stockpiles must be manually linked to the quantum stockpile on the industry level, since we can’t know beforehand how many z-levels away that is. Note how we call that out in the query blueprint’s message().

Tip

Use aliases to set up hauling routes and quantum stockpiles.

Hauling routes are notoriously fiddly to set up, but they can be automated with blueprints. Check out the Southern area of the #place and #query blueprints for how the quantum garbage dump is configured.

Note that aliases that must be applied in a particular order must appear in the same cell. Otherwise there are no guarantees for which cell will be processed first. For example, look at the track stop cells in the #query blueprint for how the hauling routes are given names.

The industry level: when not to use aliases

The industry level is densely packed and has more complicated examples of stockpile configurations and quantum dumps. However, what I’d like to call out are the key sequences that are not in aliases.

Tip

Don’t use aliases for ad-hoc cursor movements.

It may be tempting to put all query blueprint key sequences into aliases to make them easier to edit, keep them all in one place, and make them reusable, but some key sequences just aren’t very valuable as aliases.

Check out the Eastern (goods) and Northern (stone and gems) quantum stockpiles – cells I19 and R10. They give to the jeweler’s workshop to prevent the jeweler from using the gems held in reserve for strange moods. The keys are not aliased since they’re dependent on the relative positions of the tiles where they are interpreted, which is easiest to see in the blueprint itself. Also, if you move the workshop, it’s easier to fix the stockpile link right there in the blueprint instead of editing the separate aliases.txt file.

The services level: handling multi-level dig blueprints

Services is a multi-level blueprint that includes a well cistern beneath the main level. Unwanted ramps caused by channeling are an annoyance, but we can avoid getting a ramp at the bottom of the cistern with careful use of dig priorities.

Tip

Use dig priorities to control ramp creation.

We can ensure the bottom level is carved out before the layer above is channelled by assigning the channel designations lower priorities (row 76). This is easy to do here because it’s just one tile and there is no chance of cave-in. We could have used this technique on the farming level for the miasma vents instead of requiring that the channels be dug before the farming level is dug, but that would have been much more fiddly for the larger areas.

The alternative is just to have a follow-up blueprint that removes any undesired ramps. Using dig priorities to avoid the issue in the first place can be cleaner, though.

The guildhall level: avoiding smoothing issues

The goal of this level is to provide rooms for locations like guildhalls, libraries, and temples. The value of these rooms is very important, so we are likely to smooth and engrave everything. To smooth or engrave a wall tile, a dwarf has to be adjacent to it, and since some furniture, like statues, block dwarves from entering a tile, where you put them affects what you can access.

Tip

Don’t put statues in corners unless you want to smooth everything first.

In the guildhall level, the statues are placed so as not to block any wall corners. This gives the player freedom for choosing when to smooth. If statues block wall segments, it forces the player to smooth before building the statues, or else they have to mess with temporarily removing statues to smooth the walls behind them.

The beds levels: multi level meta blueprints

The suites and apartments blueprints are straightforward. The only fancy bit here is the meta blueprint, which brings us to our final tip:

Tip

Use meta blueprints to lay out multiple adjacent levels.

We couldn’t use this technique for the entire fortress since there is often an aquifer between the farming and industry levels, and we can’t know beforehand how many z-levels we need to skip. Here, though, we can at least provide the useful shortcut of designating all apartment levels at once. See the meta blueprint for how it applies the apartments on six z-levels using #> between apartment blueprint references.

That’s it! I hope this guide was useful to you. Please leave feedback on the forums if you have ideas on how this guide (or the dreamfort blueprints) can be improved!