overhaul quickfort alias documentation

- move the alias syntax and usage docs from dfhack-config/quickfort/aliases.txt to a proper guide written in RST. Add examples and more details.
- move the alias library docs from data/quickfort/aliases-common.txt to the new guide
- reorder aliases in aliases-common to match the order in the docs
- factor out the character used to enter the stockpile config screen so we can use the same aliases for stockpiles and hauling routes (use 's' for stockpiles and '{Enter}' for hauling routes)
- reference the new guide in the quickfort user guide
- do an editorial pass of the quickfort user guide
  - change name to "Quickfort Blueprint Guide", but only in the text, not the filename, so we don't change the URL
  - add `quickfort-blueprint-guide` as a label, in addition to the existing `quickfort-user-guide`
  - changed table-like lists to actual tables
  - changed "grid" tables into "simple" tables where possible
  - used ':kbd:' markers whenever we refer to a single character
  - turned Meta blueprints and Notes blueprints sections into subsections of a new "Other blueprint modes" section, in preparation for a few new modes coming in -r5.
  - updated out-of date caveat about bookcases, display furniture, and offering places not being supported
develop
myk002 2020-12-05 18:36:15 -08:00
parent 855ce84eca
commit 025c9ff758
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
4 changed files with 1244 additions and 493 deletions

@ -1,32 +1,61 @@
# Common baseline for aliases for quickfort query mode blueprints. # Standard library of aliases for quickfort query mode blueprints.
# #
# Please DO NOT EDIT this file directly. It will get overwritten when DFHack # Please DO NOT EDIT this file directly. It will get overwritten when DFHack
# is updated. Instead, custom aliases should be added to # is updated. Instead, custom aliases should be added to
# dfhack-config/quickfort/aliases.txt. See that file for syntax documentation. # dfhack-config/quickfort/aliases.txt
# Custom alias definitions will take precedence over aliases in this file.
# #
# The aliases in this file were tested in DF 0.47.04 on 2020 Jul 18. # Please see
# # https://docs.dfhack.org/en/latest/docs/guides/quickfort-alias-guide.html
# The aliases are generally split into three categories: # or
# 1) The aliases that name a type disable everything else for that stockpile # hack/docs/docs/guides/quickfort-alias-guide.html
# category and enable only that type. For example, "preparedfood" enables # in your DF installation directory for alias syntax documentation and
# prepared food and disables all other types of food. # documentation for the aliases in this file.
# 2) The aliases that start with "forbid" only forbid (or toggle) the named type
# and leave the rest of the stockpile untouched. ##################################
# 3) The aliases that start with "permit" only permit (or toggle) the named type # naming aliases
# and leave the rest of the stockpile untouched. ##################################
#
# Aliases that don't fit into those two categories have comments explaining givename: !n{name}&
# their usage. namezone: ^i{givename}^q
##################################
# quantum stockpile aliases
##################################
# Allows the standard stockpile config aliases to also be used to configure
# hauling routes.
enter_sp_config: {enter_sp_config_default}
enter_sp_config_default: s
enter_sp_config_hauling: &
quantum_enable: {enableanimals}{enablefood}{enablefurniture}{enablestone}{enableammo}{enablecoins}{enablebars}{enablegems}{enablefinishedgoods}{enableleather}{enablecloth}{enablewood}{enableweapons}{enablearmor}{enablesheet}
quantum: {linksonly}{nocontainers}{quantum_enable}{givename}
route_enable: {quantum_enable}{enablecorpses}{enablerefuse}
quantumstop: ^hrn{name}&sn{stop_name}&&xxx{route_enable enter_sp_config={enter_sp_config_hauling}}s{move}p^{move_back}^q
quantumstopfromeast: {quantumstop move={Right} move_back={Left}}
quantumstopfromsouth: {quantumstop move={Down} move_back={Up}}
quantumstopfromwest: {quantumstop move={Left} move_back={Right}}
quantumstopfromnorth: {quantumstop move={Up} move_back={Down}}
##################################
# farm plots
##################################
growlastcropall: a/&b/&c/&d/&
growfirstcropall: a&b&c&d&
######################################## ########################################
# general purpose stockpile adjustments # stockpile utility aliases
######################################## ########################################
linksonly: a linksonly: a
nocontainers: CE nocontainers: CE
# for configuring stockpiles to give to other nearby stockpiles/workshops
give: g{move}& give: g{move}&
give2up: {give move={Up 2}} give2up: {give move={Up 2}}
give2down: {give move={Down 2}} give2down: {give move={Down 2}}
@ -37,69 +66,15 @@ give10down: {give move={Down 10}}
give10left: {give move={Left 10}} give10left: {give move={Left 10}}
give10right: {give move={Right 10}} give10right: {give move={Right 10}}
# Keep in mind that building, stockpile, and zone names have a maximum length
# of 20 characters. usage example: {givename name="myname"}
givename: {Ctrl}n{name}&
# use to toggle a sequence of stockpile options. for example: {togglesequence 5}
togglesequence: &{Down} togglesequence: &{Down}
togglesequence2: &{Down 2} togglesequence2: &{Down 2}
enablesequence: e{Down}
# Enables everything but corpses and refuse. Refuse is excluded since otherwise
# clothes and armor in this quantum stockpile will rot away. If you want bones
# in your quantum stockpile, apply this alias to a refuse stockpile (but don't
# put useful clothes or armor in there!)
# Optionally set a name for the stockpile by specifying the 'name' parameter,
# for example: {quantum name="my name"}
quantum: {linksonly}{nocontainers}{enableanimals}{enablefood}{enablefurniture}{enablestone}{enableammo}{enablecoins}{enablebars}{enablegems}{enablefinishedgoods}{enableleather}{enablecloth}{enablewood}{enableweapons}{enablearmor}{enablesheet}{givename}
##################################
# hauling aliases
##################################
# Run one of the quantumstopfrom* aliases over a track stop that is set to dump
# into a quantum stockpile. The alias will set up the stop to accept all types
# (the actual types stored in the quantum stockpile should be controlled by the
# feeder stockpile) and link the indicated adjacent feeder stockpile. For
# example, the quantumstopfromsouth alias should be used over a track stop set
# to dump to the North and take items from a feeder stockpile one tile to the
# South. All you need to do afterwards is assign a vehicle to the stop. The
# track stop does not need to be constructed yet, but the feeder stockpile needs
# to exist so we can link to it.
#
# Be sure to define the optional 'name' parameter if you want to give your
# quantum hauling routes custom names. Keep in mind that names have a maximum
# length of 22 characters. For example:
# {quantumstopfromsouth name="Trash Dump"}
#
# For several examples of these aliases, see
# https://docs.google.com/spreadsheets/d/1gvTJxxRxZ5V4vXkqwhL-qlr_lXCNt8176TK14m4kSOU
namelastrouteprefix: ^h--n
namelastroutesuffix: &^q
namelastroute: {namelastrouteprefix}{name}{namelastroutesuffix}
quantumstopprefix: ^hrs&xxx&{enablesequence 17}^
quantumstopsuffix: ^q{namelastroute}
quantumstopfromeast: {quantumstopprefix}s{Right}p^{Left}{quantumstopsuffix}
quantumstopfromsouth: {quantumstopprefix}s{Down}p^{Up}{quantumstopsuffix}
quantumstopfromwest: {quantumstopprefix}s{Left}p^{Right}{quantumstopsuffix}
quantumstopfromnorth: {quantumstopprefix}s{Up}p^{Down}{quantumstopsuffix}
##################################
# zone aliases
##################################
# usage example: {namezone name="my zone name"}
namezone: ^i{givename}^q
################################## ##################################
# animal stockpile adjustments # animal stockpile adjustments
################################## ##################################
animalsprefix: s animalsprefix: {enter_sp_config}
enableanimals: {animalsprefix}e^ enableanimals: {animalsprefix}e^
disableanimals: {animalsprefix}d^ disableanimals: {animalsprefix}d^
@ -117,7 +92,7 @@ permittraps: {forbidtraps}
# food stockpile adjustments # food stockpile adjustments
################################## ##################################
foodprefix: s{Down} foodprefix: {enter_sp_config}{Down}
enablefood: {foodprefix}e^ enablefood: {foodprefix}e^
disablefood: {foodprefix}d^ disablefood: {foodprefix}d^
@ -148,9 +123,10 @@ permitdye: {forbiddye}
permittallow: {forbidtallow} permittallow: {forbidtallow}
permitmiscliquid: {foodprefix}{Right}{Down 18}p^ permitmiscliquid: {foodprefix}{Right}{Down 18}p^
# the next two aliases are for compatibility with previous implementations of
# Quickfort and are not documented.
# enables everything but seeds # enables everything but seeds
noseeds: {disablefood}{enablefood}{forbidseeds} noseeds: {disablefood}{enablefood}{forbidseeds}
# enables all food except for the types listed above # enables all food except for the types listed above
food: {noseeds}{forbidpreparedfood}{forbidunpreparedfish}{forbidplants}{forbidbooze}{forbiddye}{forbidtallow}{forbidmiscliquid} food: {noseeds}{forbidpreparedfood}{forbidunpreparedfish}{forbidplants}{forbidbooze}{forbiddye}{forbidtallow}{forbidmiscliquid}
@ -159,7 +135,7 @@ food: {noseeds}{forbidpreparedfood}{forbidunpreparedfish}{forbidplants}{forbidbo
# furniture stockpile adjustments # furniture stockpile adjustments
################################## ##################################
furnitureprefix: s{Down 2} furnitureprefix: {enter_sp_config}{Down 2}
enablefurniture: {furnitureprefix}e^ enablefurniture: {furnitureprefix}e^
disablefurniture: {furnitureprefix}d^ disablefurniture: {furnitureprefix}d^
@ -173,11 +149,11 @@ sand: {furnitureprefix}de{Right}f{Right}{Up}&^
# corpses and refuse stockpile adjustments # corpses and refuse stockpile adjustments
########################################### ###########################################
corpsesprefix: s{Down 3} corpsesprefix: {enter_sp_config}{Down 3}
enablecorpses: {corpsesprefix}e^ enablecorpses: {corpsesprefix}e^
disablecorpses: {corpsesprefix}d{Up}d^ disablecorpses: {corpsesprefix}d{Up}d^
refuseprefix: s{Down 4} refuseprefix: {enter_sp_config}{Down 4}
enablerefuse: {refuseprefix}e^ enablerefuse: {refuseprefix}e^
disablerefuse: {refuseprefix}d^ disablerefuse: {refuseprefix}d^
@ -220,7 +196,7 @@ permitcraftrefuse: {permitskulls}{permitbones}{permitshells}{permitteeth}{permit
# stone stockpile adjustments # stone stockpile adjustments
################################## ##################################
stoneprefix: s{Down 5} stoneprefix: {enter_sp_config}{Down 5}
enablestone: {stoneprefix}e^ enablestone: {stoneprefix}e^
disablestone: {stoneprefix}d^ disablestone: {stoneprefix}d^
@ -259,7 +235,7 @@ permitclay: {stoneprefix}{Right}{Down 3}p^
# ammo stockpile adjustments # ammo stockpile adjustments
################################## ##################################
ammoprefix: s{Down 6} ammoprefix: {enter_sp_config}{Down 6}
enableammo: {ammoprefix}e^ enableammo: {ammoprefix}e^
disableammo: {ammoprefix}d^ disableammo: {ammoprefix}d^
@ -274,7 +250,7 @@ forbidbonebolts: {ammoprefix}{Right}{Down 2}{Right}{Down}&^
# bar stockpile adjustments # bar stockpile adjustments
################################## ##################################
barsprefix: s{Down 8} barsprefix: {enter_sp_config}{Down 8}
enablebars: {barsprefix}e^ enablebars: {barsprefix}e^
disablebars: {barsprefix}d^ disablebars: {barsprefix}d^
@ -309,7 +285,7 @@ forbidblocks: {barsprefix}{Down 2}f{Down}f{Down}f^
# gem stockpile adjustments # gem stockpile adjustments
################################## ##################################
gemsprefix: s{Down 9} gemsprefix: {enter_sp_config}{Down 9}
enablegems: {gemsprefix}e^ enablegems: {gemsprefix}e^
disablegems: {gemsprefix}d^ disablegems: {gemsprefix}d^
@ -330,7 +306,7 @@ forbidcutstone: {gemsprefix}{Right}{Down 4}f^
# finished goods stockpile adjustments # finished goods stockpile adjustments
####################################### #######################################
finishedgoodsprefix: s{Down 10} finishedgoodsprefix: {enter_sp_config}{Down 10}
enablefinishedgoods: {finishedgoodsprefix}e^ enablefinishedgoods: {finishedgoodsprefix}e^
disablefinishedgoods: {finishedgoodsprefix}d^ disablefinishedgoods: {finishedgoodsprefix}d^
@ -341,7 +317,7 @@ jugs: {finishedgoodsprefix}{Right}f{Right}{Up 2}&{Left}{Down 2}f{Down}f{Down}f^
# cloth # cloth
################################## ##################################
clothprefix: s{Down 12} clothprefix: {enter_sp_config}{Down 12}
enablecloth: {clothprefix}e^ enablecloth: {clothprefix}e^
disablecloth: {clothprefix}d^ disablecloth: {clothprefix}d^
@ -355,7 +331,7 @@ adamantinecloth: {clothprefix}b{Right}{Up}p^
# weapon stockpile adjustments # weapon stockpile adjustments
################################## ##################################
weaponsprefix: s{Down 14} weaponsprefix: {enter_sp_config}{Down 14}
enableweapons: {weaponsprefix}e^ enableweapons: {weaponsprefix}e^
disableweapons: {weaponsprefix}d^ disableweapons: {weaponsprefix}d^
@ -396,7 +372,7 @@ permitartifactweapons: {forbidartifactweapons}
# armor stockpile adjustments # armor stockpile adjustments
################################## ##################################
armorprefix: s{Down 15} armorprefix: {enter_sp_config}{Down 15}
enablearmor: {armorprefix}e^ enablearmor: {armorprefix}e^
disablearmor: {armorprefix}d^ disablearmor: {armorprefix}d^
@ -432,32 +408,18 @@ permitartifactarmor: {forbidartifactarmor}
# others # others
################################## ##################################
coinsprefix: s{Down 7} coinsprefix: {enter_sp_config}{Down 7}
enablecoins: {coinsprefix}e^ enablecoins: {coinsprefix}e^
disablecoins: {coinsprefix}d^ disablecoins: {coinsprefix}d^
leatherprefix: s{Down 11} leatherprefix: {enter_sp_config}{Down 11}
enableleather: {leatherprefix}e^ enableleather: {leatherprefix}e^
disableleather: {leatherprefix}d^ disableleather: {leatherprefix}d^
woodprefix: s{Down 13} woodprefix: {enter_sp_config}{Down 13}
enablewood: {woodprefix}e^ enablewood: {woodprefix}e^
disablewood: {woodprefix}d^ disablewood: {woodprefix}d^
sheetprefix: s{Down 16} sheetprefix: {enter_sp_config}{Down 16}
enablesheet: {sheetprefix}e^ enablesheet: {sheetprefix}e^
disablesheet: {sheetprefix}d^ disablesheet: {sheetprefix}d^
##################################
# farm plots
##################################
# Sets a farm plot to grow the LAST type of seed in the list of available seeds
# for all 4 seasons. The last seed is used because it's usually Plump helmet
# spawn, suitable for post-embark. If you only have 1 seed type, that'll be
# grown.
growlastcropall: a/&b/&c/&d/&
# Like growlastcropall but grows the first one in the list instead.
growfirstcropall: a&b&c&d&

@ -1,106 +1,17 @@
# Aliases for quickfort #query mode blueprints # Custom aliases for quickfort query mode blueprints
# #
# This file defines custom keycode shortcuts for #query mode blueprints. # This file defines custom key sequence shortcuts for query mode blueprints.
# Definitions in this file take precedence over any definitions in the baseline # Definitions in this file take precedence over any definitions in the
# aliases configuration file at hack/data/quickfort/aliases-common.txt. See that # baseline aliases configuration file in
# file for the many useful aliases that are already defined. # hack/data/quickfort/aliases-common.txt
# #
# If possible, build on the baseline aliases when defining your own aliases. If # Please see
# the DF UI screens change, updated baseline aliases may allow your aliases to # https://docs.dfhack.org/en/latest/docs/guides/quickfort-alias-guide.html
# automatically adapt to the new UI. For example, if you create an alias to # or
# modify particular furniture stockpile settings, start your alias with # hack/docs/docs/guides/quickfort-alias-guide.html
# "{furnitureprefix}" instead of manually writing "s{Down 2}". Then, if the # in your DF installation directory for alias syntax documentation and an
# location of the furniture setting changes, your alias will automatically # overview of the DFHack alias standard library.
# inherit the updated position when DFHack is updated.
# #
# Aliases simplify repetitive tasks, such as configuring workshop profiles or
# adjusting a food stockpile to accept only seeds. Making new aliases is just a
# matter of mimicking the keys used to navigate through the menus and select
# options. Use the aliases in your blueprint spreadsheets by writing an alias by
# itself in a cell, like "nocontainers", or reference an alias in a larger
# sequence by enclosing it in curly brackets, like "{nocontainers}{linksonly}"
# #
# For example, say you have the following build and place blueprints: # Add your custom aliases here. Example:
# # food_stash: {foodprefix}b{Right}{Down 11}p^{permitplants}
# #build masonry workshop
# ~, ~,~,`,`,`
# ~,wm,~,`,`,`
# ~, ~,~,`,`,`
#
# #place stockpile for mason
# ~,~,~,s,s,s
# ~,~,~,s,s,s
# ~,~,~,s,s,s
#
# and you want to configure the stockpile to hold only non-economic ("other")
# stone and to give to the adjacent mason workshop. You could write the
# keystrokes directly:
#
# #query start(4;1;upper left corner of stockpile) configure mason
# ~,~,~,s{Down 5}deb{Right}{Down 2}p^,`,`
# ~,~,~,g{Left 2}&, `,`
# ~,~,~,`, `,`
#
# or you could use alias names:
#
# #query start(4;1;upper left corner of stockpile) configure mason
# ~,~,~,otherstone,`,`
# ~,~,~,give2left, `,`
# ~,~,~,`, `,`
#
# you can combine the two aliases above into a single cell as well, if desired:
#
# #query start(4;1;upper left corner of stockpile) configure mason
# ~,~,~,{otherstone}{give2left},`,`
# ~,~,~,`, `,`
# ~,~,~,`, `,`
#
# The syntax for defining aliases is:
# aliasname: keystrokes
#
# Where aliasname is at least two letters or digits long (including dashes and
# underscores) and keystrokes are whatever you would type into the DF UI. A
# keystroke can also be a named keycode from the DF interface definition file
# (data/init/interface.txt), enclosed in curly brackets like an alias, like:
# "{Right}" or "{Enter}". In # order to avoid naming conflicts between aliases
# and keycodes, the convention is to start aliases with a lowercase letter.
#
# Anything enclosed within curly brackets can also have a number after it,
# indicating how many times that alias or keycode should be repeated. For
# example: "{togglesequence 9}" or "{Down 5}".
#
# Finally, you can specify sub-aliases that will only be defined while the
# current alias is being resolved by adding them after the alias name (but
# before the repetition number, if it is specified), for example:
# {quantumstopfromeast name="Trash Dump"}
# The value of the sub-alias 'name' is used by quantumstopfromeast (or one of
# the aliases it calls) to give a useful name to your quantum dump hauling
# route. You can also use this format to temporarily override the value of an
# existing regularly-defined alias.
#
# Sub-aliases must be in one of the following formats:
# subaliasname=valwithnospaces
# subaliasname="val with spaces"
# subaliasname={someotheralias repetitions}
#
# Ctrl, Alt, and Shift modifiers can be specified for the next keycode by adding
# them into the key sequence. For example, Alt-h is written as "{Alt}h".
#
# Some frequently-used keystrokes are assigned shorthand characters. Think of
# them as single-character aliases that don't need to be surrounded in curly
# brackets:
# & expands to {Enter}
# @ expands to {Shift}{Enter}
# ~ expands to {Alt}
# ! expands to {Ctrl}
# ^ expands to {ESC}
#
# There is also a non-standard alias built into the code for the common
# shorthand for "make room":
# r+ expands to r+&
#
# If you need literal verisons of the shorthand characters, surround them in
# curly brackets, for example: "{!}"
#
#
# Add your custom aliases here:

@ -0,0 +1,850 @@
.. _quickfort-alias-guide:
Quickfort Alias Guide
=====================
Aliases allow you to use simple words to represent complicated key sequences
when configuring buildings and stockpiles in quickfort ``#query`` blueprints.
For example, say you have the following ``#build`` and ``#place`` blueprints:
::
#build masonry workshop
~, ~,~,`,`,`
~,wm,~,`,`,`
~, ~,~,`,`,`
#place stockpile for mason
~,~,~,s,s,s
~,~,~,s,s,s
~,~,~,s,s,s
and you want to configure the stockpile to hold only non-economic ("other")
stone and to give to the adjacent mason workshop. You could write the
key sequences directly:
::
#query configure stockpile with expanded key sequences
~,~,~,s{Down 5}deb{Right}{Down 2}p^,`,`
~,~,~,g{Left 2}&, `,`
~,~,~,`, `,`
or you could use aliases:
::
#query configure stockpile with aliases
~,~,~,otherstone,`,`
~,~,~,give2left, `,`
~,~,~,`, `,`
If the stockpile had only a single tile, you could also replay both aliases in
a single cell:
::
#query configure mason with multiple aliases in one cell
~,~,~,{otherstone}{give2left},`,`
~,~,~,`, `,`
~,~,~,`, `,`
With aliases, blueprints are much easier to read and understand. They also
save you from having to copy the same long key sequences everywhere.
Alias definition files
----------------------
DFHack comes with a library of aliases for you to use that are always
available when you run a ``#query`` blueprint. Many blueprints can be built
with just those aliases. This "standard alias library" is stored in
:source:`data/quickfort/aliases-common.txt`. The aliases in that file are
described at the `bottom of this document <quickfort-alias-library>`.
Please do not edit the aliases in the standard library directly. The file will
get overwritten when DFHack is updated and you'll lose your changes. Instead,
add your custom aliases to :source:`dfhack-config/quickfort/aliases.txt`.
Definitions in this file take precedence over any definitions in the standard
library.
Alias syntax and usage
----------------------
The syntax for defining aliases is:
::
aliasname: expansion
Where ``aliasname`` is at least two letters or digits long (dashes and
underscores are also allowed) and ``expansion`` is whatever you would type
into the DF UI.
You use an alias by typing its name into a ``#query`` blueprint cell where you
want it to be applied. You can use an alias by itself or as part of a larger
sequence, potentially with other aliases. If the alias is the only text in the
cell, the alias name is matched and its expansion is used. If the alias has
other keys before or after it, the alias name must be surrounded in curly
brackets (:kbd:`{` and :kbd:`}`). An alias can be surrounded in curly brackets
even if it is the only text in the cell, it just isn't necesary. For example,
the following blueprint uses the ``aliasname`` alias by itself in the first
two rows and uses it as part of a longer sequence in the third row:
::
#query apply alias 'aliasname' in three different ways
aliasname
{aliasname}
literaltext{aliasname}literaltext
For a more concrete example of an alias definition, a simple alias that
configures a stockpile to have no bins (:kbd:`C`) and no barrels (:kbd:`E`)
assigned to it would look like this:
::
nocontainers: CE
The alias definition can also contain references to other aliases by including
the alias names in curly brackets. For example, ``nocontainers`` could be
equivalently defined like this:
::
nobins: C
nobarrels: E
nocontainers: {nobins}{nobarrels}
Aliases used in alias definitions *must* be surrounded by curly brackets, even
if they are the only text in the definition:
::
alias1: text1
alias2: alias1
alias3: {alias1}
Here, ``alias1`` and ``alias3`` expand to ``text1``, but ``alias2`` expands to
the literal text ``alias1``.
Keycodes
~~~~~~~~
Non-printable characters, like the arrow keys, are represented by their
keycode name and are also surrounded by curly brackets, like ``{Right}`` or
``{Enter}``. Keycodes are used exactly like aliases -- they just have special
expansions that you wouldn't be able to write yourself. In order to avoid
naming conflicts between aliases and keycodes, the convention is to start
aliases with a lowercase letter.
Any keycode name from the DF interface definition file
(data/init/interface.txt) is valid, but only a few keycodes are actually
useful for blueprints:
::
Up
Down
Left
Right
Enter
ESC
Backspace
Space
Tab
Repetitions
~~~~~~~~~~~
Anything enclosed within curly brackets can also have a number, indicating how
many times that alias or keycode should be repeated. For example:
``{togglesequence 9}`` or ``{Down 5}`` will repeat the ``togglesequence``
alias nine times and the ``Down`` keycode five times, respectively.
Modifier keys
~~~~~~~~~~~~~
Ctrl, Alt, and Shift modifiers can be specified for the next key by adding
them into the key sequence. For example, Alt-h is written as ``{Alt}h``.
Note that DF does not handle keys that have more than a single modifier, so
sequences like ``{Ctrl}{Alt}a`` will result in an error.
Shorthand characters
~~~~~~~~~~~~~~~~~~~~
Some frequently-used keycodes are assigned shorthand characters. Think of them
as single-character aliases that don't need to be surrounded in curly
brackets:
::
& expands to {Enter}
@ expands to {Shift}{Enter}
~ expands to {Alt}
! expands to {Ctrl}
^ expands to {ESC}
If you need literal versions of the shorthand characters, surround them in
curly brackets, for example: use ``{!}`` for a literal exclamation point.
Built-in aliases
~~~~~~~~~~~~~~~~
Most aliases that come with DFHack are in ``aliases-common.txt``, but there is
one alias built into the code for the common shorthand for "make room":
::
r+ expands to r+{Enter}
This needs special code support since ``+`` can't normally be used in alias
names. You can use it just like any other alias, either by itself in a cell
(``r+``) or surrounded in curly brackets (``{r+}``).
Sub-aliases
~~~~~~~~~~~
You can specify sub-aliases that will only be defined while the current alias
is being resolved. This is useful for "injecting" custom behavior into the
middle of a larger alias. For example:
::
{quantumstopfromeast name="Trash Dump"}
The value of the sub-alias ``name`` is used in the middle of the definition of
``quantumstopfromeast`` to give a useful name to your quantum dump hauling
route. Without sub-aliases, we'd have to write something like:
::
{quantumstopfromeastprefix}Trash Dump{quantumstopfromeastsuffix}
which is more difficult to write and more difficult to understand.
A handy technique is to define an alias with some sort of default
behavior and then use sub-aliases to override that behavior as necessary. For
example, here is a simplified version of the standard ``quantum`` alias that
sets up quantum stockpiles:
::
quantum_enable: {enableanimals}{enablefood}{enablefurniture}...
quantum: {linksonly}{nocontainers}{quantum_enable}
You can use the default behavior of ``quantum_enable`` by just using the
``quantum`` alias by itself. But you can override ``quantum_enable`` to just
enable furniture for some specific stockpile like this:
::
{quantum quantum_enable={enablefurniture}}
Sub-aliases must be in one of the following formats:
::
subaliasname=keyswithnospaces
subaliasname="keys with spaces or {aliases}"
subaliasname={singlealias}
If you specify both a sub-alias and a number of repetitions, the number for
repetitions goes last, right before the :kbd:`}`:
::
{alias subaliasname=value repetitions}
Beyond query mode
-----------------
``#query`` blueprints normally do things in DF :kbd:`q`\uery mode, but nobody
said that we have to *stay* in query mode. ``#query`` blueprints send
arbitrary key sequences to Dwarf Fortress. Anything you can do by typing keys
into DF, you can do in a ``#query`` blueprint. It is absolutely fine to
temporarily exit out of query mode, go into, say, hauling or zone or hotkey
mode, and do whatever needs to be done.
You just have to make certain to exit out of that alternate mode and get back
into :kbd:`q`\uery mode at the end of the key sequence. That way quickfort can
continue on configuring the next tile -- a tile configuration that assumes the
game is still in query mode.
For example, here is the standard library alias for giving a name to a zone:
::
namezone: ^i{givename}^q
The first :kbd:`\^` exits out of query mode. Then :kbd:`i` enters zones mode.
We then reuse the standard alias for giving something a name. Finally, we exit
out of zones mode with another :kbd:`\^` and return to :kbd:`q`\uery mode.
.. _quickfort-alias-library:
The DFHack standard alias library
---------------------------------
DFHack comes with many useful aliases for you to use in your blueprints. Many
blueprints can be built with just these aliases alone, with no custom aliases
required.
This section goes through all aliases provided by the DFHack standard alias
library, discussing their intended usage and detailing sub-aliases that you
can define to customize their behavior.
If you do define your own custom aliases in
``dfhack-config/quickfort/aliases.txt``, try to build on the library aliases.
For example, if you create an alias to modify particular furniture stockpile
settings, start your alias with ``{furnitureprefix}`` instead of
``s{Down 2}``. Using library prefixes will allow sub-aliases to work with your
aliases just like they do with library aliases. In this case, using
``{furnitureprefix}`` will allow your stockpile customization alias to work
with both stockpiles and hauling routes.
Naming aliases
~~~~~~~~~~~~~~
These aliases give descriptive names to workshops, levers, stockpiles, zones,
etc. Dwarf Fortress building, stockpile, and zone names have a maximum length
of 20 characters.
======== ===========
Alias Sub-aliases
======== ===========
givename name
namezone name
======== ===========
``givename`` works anywhere you can hit Ctrl-n to customize a name, like when
the cursor is over buildings and stockpiles. Example:
::
#place
f(10x2)
#query
{booze}{givename name="booze"}
``namezone`` is intended to be used when over an activity zone. It includes
commands to get into zones mode, set the zone name, and get back to query
mode. Example:
::
#zone
n(2x2)
#query
{namezone name="guard dog pen"}
Quantum stockpile aliases
~~~~~~~~~~~~~~~~~~~~~~~~~
These aliases make it easy to create :wiki:`minecart stop-based quantum stockpiles <Quantum_stockpile#The_Minecart_Stop>`.
+----------------------+------------------+
| Alias | Sub-aliases |
+======================+==================+
| quantum | | name |
| | | quantum_enable |
+----------------------+------------------+
| quantumstopfromnorth | | name |
+----------------------+ | stop_name |
| quantumstopfromsouth | | route_enable |
+----------------------+ |
| quantumstopfromeast | |
+----------------------+ |
| quantumstopfromwest | |
+----------------------+------------------+
| quantumstop | | name |
| | | stop_name |
| | | route_enable |
| | | move |
| | | move_back |
+----------------------+------------------+
The idea is to use a minecart on a track stop to dump an infinite number of
items into a receiving "quantum" stockpile, which significantly simplifies
stockpile management. These aliases configure the quantum stockpile and
hauling route that make it all work. Here is a complete example for quantum
stockpiling weapons, armor, and ammunition. It has a 3x1 feeder stockpile on
the bottom (South), the trackstop in the center, and the quantum stockpile on
the top (North). Note that the feeder stockpile is the only stockpile that
needs to be configured to control which types of items end up in the quantum
stockpile. By default, the hauling route and quantum stockpile itself simply
accept whatever is put into them.
::
#place
,c
,
pdz(3x1)
#build
,
,trackstopN
#query message(remember to assign a minecart to the new route)
,quantum
,quantumstopfromsouth
nocontainers
The ``quantum`` alias configures a 1x1 stockpile to be a quantum stockpile. It
bans all containers and prevents the stockpile from being manually filled. By
default, it also enables storage of all item categories (except corpses and
refuse), so it doesn't really matter what letter you use to place the
stockpile. :wiki:`Refuse` is excluded by default since otherwise clothes and
armor in the quantum stockpile would rot away. If you want corpses or bones in
your quantum stockpile, use :kbd:`y` and/or :kbd:`r` to place the stockpile
and the ``quantum`` alias will just enable the remaining types. If you *do*
enable refuse in your quantum stockpile, be sure you avoid putting useful
clothes or armor in there!
The ``quantumstopfromsouth`` alias is run over the track stop and configures
the hauling route, again, allowing all item categories into the minecart by
default so any item that can go into the feeder stockpile can then be placed
in the minecart. It also links the hauling route with the feeder stockpile to
the South.The track stop does not need to be fully constructed before the
``#query`` blueprint is run, but the feeder stockpile needs to exist so we can
link to it. This means that the three blueprints above can be run one right
after another, without any dwarven labor in between them, and the quantum
stockpile will work properly.
Finally, the ``nocontainers`` alias simply configures the feeder stockpile to
not have any containers (which would just get in the way here). If we wanted
to be more specific about what item types we want in the quantum stockpile, we
could configure the feeder stockpile further, for example with standard
`stockpile adjustment aliases <quickfort-stockpile-aliases>`.
After the blueprints are run, the last step is to manually assign a minecart
to the newly-defined hauling route.
You can define sub-aliases to customize how these aliases work, for example to
have fine-grained control over what item types are enabled for the route and
quantum stockpile. We'll go over those options below, but first, here is an
example for how to just give names to everything:
::
#query message(remember to assign a minecart to the new route)
,{quantum name="armory quantum"}
,{quantumstopfromsouth name="Armory quantum" stop_name="Armory quantum stop"}{givename name="armory dumper"} `
{givename name="armory feeder"}
All ``name`` sub-aliases are completely optional, of course. Keep in mind that
hauling route names have a maximum length of 22 characters, hauling route stop
names have a maximum length of 21 characters, and all other names have a
maximum length of 20 characters.
If you want to be absolutely certain that nothing ends up in your quantum
stockpile other than what you've configured in the feeder stockpile, you can
set the ``quantum_enable`` sub-alias for the ``quantum`` alias. This can
prevent, for example, somebody's knocked-out tooth from being considered part
of your furniture quantum stockpile when it happened to land on it during a
fistfight:
::
#query
{quantum name="furniture quantum" quantum_enable={enablefurniture}}
You can have similar control over the hauling route if you need to be more
selective about what item types are allowed into the minecart. If you have
multiple specialized quantum stockpiles that use a common feeder pile, for
example, you can set the ``route_enable`` sub-alias:
::
#query
{quantumstopfromsouth name="Armory quantum" route_enable="{enableweapons}{enablearmor}{enableammo}"}
Any of the `stockpile configuration aliases <quickfort-stockpile-aliases>` can
be used for either the ``quantum_enable`` or ``route_enable`` sub-aliases.
Experienced Dwarf Fortress players may be wondering how the same aliases can
work in both contexts since the keys for entering the configuration screen
differ. Fear not! There is some sub-alias magic at work here. If you define
your own stockpile configuraiton aliases, you can use the magic yourself by
building your aliases on the ``*prefix`` aliases described later in this
guide.
Finally, the ``quantumstop`` alias is a more general version of the
``quantumstopfrom*`` aliases. The ``quantumstopfrom*`` aliases assume that the
feeder stockpile is orthogonally adjacent to your track stop (which is how
most people set them up). If your feeder stockpile is somewhere further away,
you can use the ``quantumstop`` alias directly. In addition to the
``quantumstopfrom*`` sub-aliases, you can also define the ``move`` and
``move_back`` sub-aliases, which let you specify the cursor keys required to
move from the track stop to the feeder stockpile and back again, respectively:
::
#query
{quantumstop move="{Right 2}{Up}" move_back="{Down}{Left 2}"}
Farm plots
~~~~~~~~~~
Sets a farm plot to grow the first or last type of seed in the list of
available seeds for all four seasons. The last seed is usually Plump helmet
spawn, suitable for post-embark. But if you only have one seed type, that'll
be grown instead.
+------------------+
| Alias |
+==================+
| growlastcropall |
+------------------+
| growfirstcropall |
+------------------+
Instead of these aliases, though, it might be more useful to use the DFHack
`autofarm` plugin.
Stockpile configuration utility aliases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=============== ===========
Alias Sub-aliases
=============== ===========
linksonly
nocontainers
give2up
give2down
give2left
give2right
give10up
give10down
give10left
give10right
give move
togglesequence
togglesequence2
=============== ===========
``linksonly`` and ``nocontainers`` set the named basic properties on
stockpiles. ``nocontainers`` sets bins and barrels to 0, but does not affect
wheelbarrows since the hotkeys for changing the number of wheelbarrows depend
on whether you have the DFHack `stockpiles` plugin active. It is better to set
the number of wheelbarrows via the `quickfort` ``stockpiles_max_wheelbarrows``
setting. It is set to ``0`` by default.
The ``give*`` aliases set a stockpile to give to a workshop or another
stockpile located at the indicated number of tiles in the indicated direction
from the current tile. For example, here we use the ``give2down`` alias to
connect an ``otherstone`` stockpile with a mason workshop:
::
#place
s,s,s,s,s
s, , , ,s
s, , , ,s
s, , , ,s
s,s,s,s,s
#build
`,`,`,`,`
`, , , ,`
`, ,wm,,`
`, , , ,`
`,`,`,`,`
#query
, ,give2down
otherstone
and here is a generic stone stockpile that gives to a stockpile that only
takes flux:
::
#place
s(10x1)
s(10x10)
#query
flux
,
give2up
If you want to give to some other tile that is not already covered by the
``give2*`` or ``give10*`` aliases, you can use the generic ``give`` alias and
specify the movement keys yourself in the ``move`` sub-alias. Here is how to
give to a stockpile or workshop one z-level above, 9 tiles to the left, and 14
tiles down:
::
#query
{give move="<{Left 9}{Down 14}"}
``togglesequence`` and ``togglesequence2`` send ``{Down}{Enter}`` or
``{Down 2}{Enter}`` to toggle adjacent (or alternating) items in a list. This
is useful when toggling a bunch of related item types in the stockpile config.
For example, the ``dye`` and ``tallow`` aliases in the standard alias library
need to select specific items from long lists:
::
dye: {foodprefix}b{Right}{Down 11}{Right}{Down 28}{togglesequence 4}^
tallow: {foodprefix}b{Right}{Down 13}{Right}{Down}{togglesequence2 811}^
.. _quickfort-stockpile-aliases:
Stockpile adjustment aliases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For each stockpile item category, there are three standard aliases:
* ``*prefix`` aliases enter the stockpile configuration screen and position
the cursor at a particular item category in the left-most column, ready for
further keys that configure the elements within that category. All other
stockpile adjustment aliases are built on these prefixes. You can use them
yourself to create stockpile adjustment aliases that aren't already covered
by the standard library aliases. Using the library prefix instead of
creating your own also allows your stockpile configuration aliases to be
used for both stockpiles and hauling routes. For example, here is the
library definition for ``booze``:
::
booze: {foodprefix}b{Right}{Down 5}p{Down}p^
* ``enable*`` aliases enter the stockpile configuration screen, enable all
subtypes of the named category, and exit the stockpile configuration screen
* ``disable*`` aliases enter the stockpile configuration screen, disable all
subtypes of the named category, and exit the stockpile configuration screen
==================== ==================== =====================
Prefix Enable Disable
==================== ==================== =====================
animalsprefix enableanimals disableanimals
foodprefix enablefood disablefood
furnitureprefix enablefurniture disablefurniture
corpsesprefix enablecorpses disablecorpses
refuseprefix enablerefuse disablerefuse
stoneprefix enablestone disablestone
ammoprefix enableammo disableammo
coinsprefix enablecoins disablecoins
barsprefix enablebars disablebars
gemsprefix enablegems disablegems
finishedgoodsprefix enablefinishedgoods disablefinishedgoods
leatherprefix enableleather disableleather
clothprefix enablecloth disablecloth
woodprefix enablewood disablewood
weaponsprefix enableweapons disableweapons
armorprefix enablearmor disablearmor
sheetprefix enablesheet disablesheet
==================== ==================== =====================
Then, for each item category, there are aliases that manipulate interesting
subsets of that category:
* Exclusive aliases forbid everthing within a category and then enable only
the named item type (or named class of items)
* ``forbid*`` aliases forbid the named type and leave the rest of the
stockpile untouched.
* ``permit*`` aliases permit the named type and leave the rest of the
stockpile untouched.
Note that for specific item types (items in the third stockpile configuration
column), you can only toggle the item type on and off. Aliases can't know
whether sending the ``{Enter}`` key will enable or disable the type. The
``forbid*`` aliases that affect these item types assume the item type was
enabled and toggle it off. Likewise, the ``permit*`` aliases assume the item
type was disabled and toggle it on. If the item type is not in the expected
enabled/disabled state when the alias is run, the aliases will not behave
properly.
Animal stockpile adjustments
````````````````````````````
=========== =========== ============
Exclusive Forbid Permit
=========== =========== ============
cages forbidcages permitcages
traps forbidtraps permittraps
=========== =========== ============
Food stockpile adjustments
``````````````````````````
=============== ==================== ====================
Exclusive Forbid Permit
=============== ==================== ====================
preparedfood forbidpreparedfood permitpreparedfood
unpreparedfish forbidunpreparedfish permitunpreparedfish
plants forbidplants permitplants
booze forbidbooze permitbooze
seeds forbidseeds permitseeds
dye forbiddye permitdye
tallow forbidtallow permittallow
miscliquid forbidmiscliquid permitmiscliquid
=============== ==================== ====================
Furniture stockpile adjustments
```````````````````````````````
+-----------+
| Exclusive |
+===========+
| pots |
+-----------+
| bags |
+-----------+
| buckets |
+-----------+
| sand |
+-----------+
Notes:
* Because of the limitations of Dwarf Fortress, ``bags`` cannot distinguish
between empty and filled bags
Refuse stockpile adjustments
````````````````````````````
=========== ================== ==================
Exclusive Forbid Permit
=========== ================== ==================
bodyparts forbidbodyparts permitbodyparts
rawhides forbidrawhides permitrawhides
tannedhides forbidtannedhides permittannedhides
skulls forbidskulls permitskulls
bones forbidbones permitbones
shells forbidshells permitshells
teeth forbidteeth permitteeth
horns forbidhorns permithorns
hair forbidhair permithair
craftrefuse forbidcraftrefuse permitcraftrefuse
=========== ================== ==================
Notes:
* ``bodyparts`` includes remains/corpses and rotten rawhdes.
* ``craftrefuse`` includes everything a craftsdwarf can use: skulls, bones,
shells, teeth, horns, and hair.
Stone stockpile adjustments
```````````````````````````
============= ==================== ====================
Exclusive Forbid Permit
============= ==================== ====================
metal forbidmetal permitmetal
iron forbidiron permitiron
economic forbideconomic permiteconomic
flux forbidflux permitflux
plaster forbidplaster permitplaster
coalproducing forbidcoalproducing permitcoalproducing
otherstone forbidotherstone permitotherstone
bauxite forbidbauxite permitbauxite
clay forbidclay permitclay
============= ==================== ====================
Ammo stockpile adjustments
``````````````````````````
=============== ====================
Exclusive Forbid
=============== ====================
bolts
\ forbidmetalbolts
\ forbidwoodenbolts
\ forbidbonebolts
=============== ====================
Bar stockpile adjustments
`````````````````````````
=========== ==================
Exclusive Forbid
=========== ==================
bars forbidbars
metalbars forbidmetalbars
ironbars forbidironbars
steelbars forbidsteelbars
pigironbars forbidpigironbars
otherbars forbidotherbars
coal forbidcoal
potash forbidpotash
ash forbidash
pearlash forbidpearlash
soap forbidsoap
blocks forbidblocks
=========== ==================
Gem stockpile adjustments
`````````````````````````
=========== ================
Exclusive Forbid
=========== ================
roughgems forbidroughgems
roughglass forbidroughglass
cutgems forbidcutgems
cutglass forbidcutglass
cutstone forbidcutstone
=========== ================
Finished goods stockpile adjustments
````````````````````````````````````
+-----------+
| Exclusive |
+===========+
| jugs |
+-----------+
Cloth stockpile adjustments
```````````````````````````
+------------------+
| Exclusive |
+==================+
| thread |
+------------------+
| adamantinethread |
+------------------+
| cloth |
+------------------+
| adamantinecloth |
+------------------+
Weapon stockpile adjustments
````````````````````````````
================= ======================== ====================
Exclusive Forbid Permit
================= ======================== ====================
\ forbidweapons permitweapons
\ forbidtrapcomponents permittrapcomponents
metalweapons forbidmetalweapons permitmetalweapons
\ forbidstoneweapons permitstoneweapons
\ forbidotherweapons permitotherweapons
ironweapons forbidironweapons permitironweapons
copperweapons forbidcopperweapons permitcopperweapons
steelweapons forbidsteelweapons permitsteelweapons
masterworkweapons forbidmasterworkweapons permitmasterworkweapons
artifactweapons forbidartifactweapons permitartifactweapons
================= ======================== ====================
Armor stockpile adjustments
```````````````````````````
=============== ====================== ====================
Exclusive Forbid Permit
=============== ====================== ====================
metalarmor forbidmetalarmor permitmetalarmor
otherarmor forbidotherarmor permitotherarmor
ironarmor forbidironarmor permitironarmor
copperarmor forbidcopperarmor permitcopperarmor
steelarmor forbidsteelarmor permitsteelarmor
masterworkarmor forbidmasterworkarmor permitmasterworkarmor
artifactarmor forbidartifactarmor permitartifactarmor
=============== ====================== ====================

@ -1,7 +1,8 @@
.. _quickfort-user-guide: .. _quickfort-user-guide:
.. _quickfort-blueprint-guide:
Quickfort User Guide Quickfort Blueprint Guide
==================== =========================
`Quickfort <quickfort>` is a DFHack script that helps you build fortresses from `Quickfort <quickfort>` is a DFHack script that helps you build fortresses from
"blueprint" .csv and .xlsx files. Many applications exist to edit these files, "blueprint" .csv and .xlsx files. Many applications exist to edit these files,
@ -15,12 +16,12 @@ macro. Joel Thornton reimplemented the core logic in Python and extended its
functionality with `Quickfort 2.0 <https://github.com/joelpt/quickfort>`__. This functionality with `Quickfort 2.0 <https://github.com/joelpt/quickfort>`__. This
DFHack-native implementation, called "DFHack Quickfort" or just "quickfort", DFHack-native implementation, called "DFHack Quickfort" or just "quickfort",
builds upon Quickfort 2.0's formats and features. Any blueprint that worked in builds upon Quickfort 2.0's formats and features. Any blueprint that worked in
Python Quickfort 2.0 should work with DFHack Quickfort. DFHack Quickfort is Python Quickfort 2.0 should work with DFHack Quickfort. DFHack Quickfort
written in Lua and interacts with Dwarf Fortress memory structures directly, interacts with Dwarf Fortress memory structures directly, allowing for
allowing for instantaneous blueprint application, error checking and recovery, instantaneous blueprint application, error checking and recovery, and many other
and many other advanced features. advanced features.
This document focuses on DFHack Quickfort's capabilities and teaches players how This guide focuses on DFHack Quickfort's capabilities and teaches players how
to understand and create blueprint files. Some of the text was originally to understand and create blueprint files. Some of the text was originally
written by Joel Thornton, reused here with his permission. written by Joel Thornton, reused here with his permission.
@ -55,14 +56,15 @@ Features
- Supports .csv and multi-worksheet .xlsx blueprint files - Supports .csv and multi-worksheet .xlsx blueprint files
- Near-instant application, even for very large and complex blueprints - Near-instant application, even for very large and complex blueprints
- Blueprints can span multiple z-levels - Blueprints can span multiple z-levels
- Supports multiple blueprints per .csv file/spreadsheet sheet - You can package all blueprints and aliases needed for an entire fortress
- "meta" blueprints that automate the application of sequences of blueprints in a single file for easy sharing
- "meta" blueprints that simplify the application of sequences of blueprints
- Undo functionality for dig, build, place, and zone blueprints - Undo functionality for dig, build, place, and zone blueprints
- Automatic cropping of blueprints so you don't get errors if the blueprint - Automatic cropping of blueprints so you don't get errors if the blueprint
extends off the map extends off the map
- Can generate manager orders for everything required by a build blueprint - Can generate manager orders for everything required by a build blueprint
- Library of ready-to-use blueprints included - Includes a library of ready-to-use blueprints
- Verbose output mode for debugging - Verbose output mode for blueprint debugging
- Dig mode - Dig mode
@ -75,53 +77,55 @@ Features
- Build mode - Build mode
- DFHack buildingplan integration, so you can place buildings before - Fully integrated with DFHack buildingplan: you can place buildings before
manufacturing all required source materials manufacturing building materials and you can use the buildingplan UI for
- Designate complete constructions at once, without having to wait for each setting materials preferences
tile to become supported before you can build it - Designate entire constructions in mid-air without having to wait for each
tile to become supported
- Automatic expansion of building footprints to their minimum dimensions, so - 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 only the center tile of a multi-tile building needs to be recorded in the
blueprint blueprint
- Tile occupancy and validity checking so, for example, buildings that - Tile occupancy and validity checking so, for example, buildings that
cannot be placed on a certain tile will simply be skipped instead of the cannot be placed on a target tile will be skipped instead of messing up
blueprint failing to apply. Blueprints that are only partially applied for the blueprint. Blueprints that are only partially applied for any reason
any reason (for example, you need to dig out some more tiles) can be (e.g. you need to dig out some more tiles) can be safely reapplied to
safely reapplied to build the remaining buildings. build the remaining buildings.
- Relaxed rules for farm plot and road placement: you can still place the - 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 building even if an invalid tile (e.g. stone tiles for farm plots) splits
the designated area into two parts the designated area into two disconnected parts
- Intelligent boundary detection for adjacent buildings of the same type - 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 (e.g. a 6x6 block of ``wj`` cells will be correctly split into 4 jeweler's
workshops) workshops)
- Place and zone modes - Place and zone modes
- Define stockpiles and zones in any continguous shape, not just rectangular - Define stockpiles and zones of shape, not just rectangles
blocks - Configurable numbers of bins, barrels and wheelbarrows assigned to created
- Configurable maximums for bins, barrels and wheelbarrows assigned to stockpiles
created stockpiles
- Automatic splitting of stockpiles and zones that exceed maximum dimension - Automatic splitting of stockpiles and zones that exceed maximum dimension
limits limits
- Full access to all zone settings, such as hospital supply counts - Fully configurable zone settings, such as pit/pond and hospital supply
counts
- Query mode - Query mode
- Send arbitrary keystroke sequences to the UI -- *anything* you can do - Send arbitrary keystroke sequences to the UI -- *anything* you can do
through the UI is supported through the UI is supported
- Supports aliases to automate frequent keystroke combos - Supports aliases to simplify frequent keystroke combos
- Includes a library of pre-made and tested aliases to automate most common - Includes a library of pre-made and tested aliases to simplify most common
tasks, such as configuring stockpiles for important item types or creating tasks, such as configuring stockpiles for important item types or creating
named hauling routes for quantum stockpiles. named hauling routes for quantum stockpiles.
- Supports including aliases in other aliases, and repeating key sequences a - Supports including aliases in other aliases for easy management of common
specified number of times subsequences
- Skips sending key sequences when the cursor is over a tile that does not - Supports repeating key sequences a specified number of times
have a stockpile or building, so missing buildings won't desynchronize - Skips sending keys when the cursor is over a tile that does not have a
your blueprint stockpile or building, so missing buildings won't desynchronize your
blueprint
- Instant halting of query blueprint application when keystroke errors are - Instant halting of query blueprint application when keystroke errors are
detected, such as when a key sequence leaves us stuck in a submenu, to detected, such as when a mistake in a key sequence leaves us stuck in a
make blueprint misconfigurations easier to debug submenu, to make query blueprints easier to debug
Editing Blueprints Editing blueprints
------------------ ------------------
We recommend using a spreadsheet editor such as Excel, `Google We recommend using a spreadsheet editor such as Excel, `Google
@ -133,32 +137,39 @@ line (or upper-left cell) of the spreadsheet should look like this:
:: ::
#dig This is a decription. #dig
The keyword "dig" tells Quickfort we are going to be using the Designations menu The keyword ``dig`` tells Quickfort we are going to be using the Designations
in DF. The following "mode" keywords are understood: menu in DF. The following "mode" keywords are understood:
:: ============== ===========
Blueprint mode Description
============== ===========
dig Designations menu (:kbd:`d`)
build Build menu (:kbd:`b`)
place Place stockpiles menu (:kbd:`p`)
zone Activity zones menu (:kbd:`i`)
query Set building tasks/prefs menu (:kbd:`q`)
============== ===========
dig Designations menu (d) If no modeline appears in the first cell, Quickfort assumes that it's looking at
build Build menu (b) a ``#dig`` blueprint.
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 There are also other modes that don't directly correspond to Dwarf Fortress
``#dig`` blueprint. menus, but we'll talk about those `later <quickfort-other-modes>`.
There are also "meta" and "notes" blueprints, but we'll talk about If you like, you may enter a comment after the mode keyword. This comment will
`those <quickfort-meta>` `later <quickfort-notes>`. appear in the output of ``quickfort list`` when run from the ``DFHack#`` prompt.
You can use this space for explanations, attribution, etc.
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, #dig grand dining room
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): Below this line begin entering keys in each spreadsheet cell that represent what
you want designated in the corresponding game map tile. For example, we could
dig out a 4x4 room like so (spaces are used as column separators here for
readability, but a real .csv file would have commas):
:: ::
@ -169,9 +180,9 @@ for clarity, but a real .csv file would have commas):
d d d d # d d d d #
# # # # # # # # # #
Note the # symbols at the right end of each row and below the last row. These Note the :kbd:`#` symbols at the right end of each row and below the last row.
are completely optional, but can be helpful to make the row and column positions These are completely optional, but can be helpful to make the row and column
clear. positions clear.
Once the dwarves have that dug out, let's build a walled-in bedroom within our Once the dwarves have that dug out, let's build a walled-in bedroom within our
dug-out area: dug-out area:
@ -185,10 +196,10 @@ dug-out area:
Cw Cw Cw # Cw Cw Cw #
# # # # # # # # # #
Note my generosity - in addition to the bed (b) I've built a chest (h) here for Note my generosity - in addition to the bed (:kbd:`b`) I've built a chest
the dwarf as well. You must use the full series of keys needed to build (:kbd:`c`) here for the dwarf as well. You must use the full series of keys
something in each cell, e.g. 'Cw' enters DF's constructions submenu (C) and needed to build something in each cell, e.g. :kbd:`C`:kbd:`w` indicates we
selects walls (w). should enter DF's constructions submenu (:kbd:`C`) and select walls (:kbd:`w`).
I'd also like to place a booze stockpile in the 2 unoccupied tiles in the room. I'd also like to place a booze stockpile in the 2 unoccupied tiles in the room.
@ -196,34 +207,21 @@ I'd also like to place a booze stockpile in the 2 unoccupied tiles in the room.
#place Place a food stockpile #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 ` # ` f f ` #
` ` ` ` # ` ` ` #
# # # # # # # # # #
This illustration may be a little hard to understand. The two :kbd:`f`
characters are in row 3, columns 2 and 3. All the other cells are empty. QF
considers both :kbd:`\`` (backtick -- the character under the tilde) and
:kbd:`~` (tilde) characters within cells to be empty cells; this can help with
multilayer or fortress-wide blueprint layouts as "chalk lines".
QF is smart enough to recognize this as a 2x1 food stockpile, and creates it as 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 such rather than as two 1x1 food stockpiles. Quickfort treats any connected
region of identical designations as a single stockpile. The tiles can be region of identical designations as a single entity. The tiles can be connected
connected orthogonally or diagonally, just as long as they are touching somehow. orthogonally or diagonally, just as long as they are touching.
Lastly, let's turn the bed into a bedroom and set the food stockpile to hold Lastly, let's turn the bed into a bedroom and set the food stockpile to hold
only booze. only booze.
@ -237,22 +235,30 @@ only booze.
` ` ` ` # ` ` ` ` #
# # # # # # # # # #
In column 2, row 2 we have "r&". This sends the "r" key to DF when the cursor is In row 2, column 2 we have ``r&``. This sends the :kbd:`r` key to DF when the
over the bed, causing us to 'make room' and "&", which is a special symbol that cursor is over the bed, causing us to "make room" and :kbd:`Enter`, represented
expands to "{Enter}", to indicate that we're done. by special ``&`` alias, to indicate that we're done setting the size (the
default room size is fine here).
In column 2, row 3 we have "booze". This is one of many alias keywords defined
in the included :source:`baseline aliases file <data/quickfort/aliases-common.txt>`. In column 2, row 3 we have ``booze``. This is one of many alias keywords defined
This particular alias sets a food stockpile to carry booze only. It sends the in the included :source:`aliases library <data/quickfort/aliases-common.txt>`.
keys needed to navigate DF's stockpile settings menu, and then sends an Escape This particular alias sets a food stockpile to accept only booze. It sends the
character ("^" or "{ESC}") to exit back to the map. It is important to exit out keys needed to navigate DF's stockpile settings menu, and then it sends an
of any menus that you enter while in query mode so that the cursor can move to Escape character to exit back to the map. It is important to exit out of any
the next tile when it is done configuring the current tile. menus that you enter while in query mode so that the cursor can move to the next
tile when it is done with the current tile.
Check out the included :source:`blueprint library <data/blueprints/library>`
to see many more examples. Read the baseline aliases file for helpful If there weren't an alias named ``booze`` then the literal characters
pre-packaged aliases, or create your own in :kbd:`b`:kbd:`o`:kbd:`o`:kbd:`z`:kbd:`e` would have been sent, so be sure to
:source:`dfhack-config/quickfort/aliases.txt` in your DFHack installation. spell those aliases correctly!
You can save a lot of time and effort by using aliases instead of adding all
key seqences directly to your blueprints. For more details, check out the
`Quickfort Alias Guide <quickfort-alias-guide>`. You can also see examples of
aliases being used in the query blueprints in the
:source:`DFHack blueprint library <data/blueprints/library>`. You can create
your own aliases by adding them to :source:`dfhack-config/quickfort/aliases.txt`
in your DFHack folder.
Area expansion syntax Area expansion syntax
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -280,13 +286,9 @@ form:
keys(WxH) keys(WxH)
In Quickfort the above two examples of specifying a contiguous 3x3 area produce Note that area expansion syntax can only specify rectangular areas. If you want
identical output: a single 3x3 designation will be performed, rather than nine to create extent-based structures (e.g. farm plots or stockpiles) in different
1x1 designations as the first example might suggest. shapes, use the first format above. For example:
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:
:: ::
@ -309,8 +311,8 @@ adjacent, but separate, stockpiles of the same type:
~ ~ ~ ~ # ~ ~ ~ ~ #
# # # # # # # # # #
As mentioned previously, "~" characters are ignored as comment characters and As mentioned previously, :kbd:`~` characters are ignored as comment characters
can be used for visualizing the blueprint layout. The blueprint can be and can be used for visualizing the blueprint layout. This blueprint can be
equivalently written as: equivalently written as:
:: ::
@ -386,7 +388,7 @@ If you are building a large-scale block factory, for example, this will create
:: ::
#build line of 20 mason workshops #build line of 20 mason workshops
wm(60x3) # wm(60x3)
Quickfort will intelligently break large areas of the same designation into Quickfort will intelligently break large areas of the same designation into
appropriately-sized chunks. appropriately-sized chunks.
@ -453,7 +455,7 @@ Marker mode
~~~~~~~~~~~ ~~~~~~~~~~~
Marker mode is useful for when you want to plan out your digging, but you don't 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 want to dig everything just yet. In ``#dig`` mode, you can add a :kbd:`m` before
any other designation letter to indicate that the tile should be designated in 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 marker mode. For example, to dig out the perimeter of a room, but leave the
center of the room marked for digging later: center of the room marked for digging later:
@ -468,15 +470,15 @@ center of the room marked for digging later:
d d d d d # d d d d d #
# # # # # # # # # # # #
Then you can use "Toggle Standard/Marking" (``d-M``) to convert the center tiles Then you can use "Toggle Standard/Marking" (:kbd:`d`:kbd:`M`) to convert the
to regular designations at your leisure. center tiles to regular designations at your leisure.
To apply an entire dig blueprint in marker mode, regardless of what the To apply an entire dig blueprint in marker mode, regardless of what the
blueprint itself says, you can set the global quickfort setting blueprint itself says, you can set the global quickfort setting
``force_marker_mode`` to ``true`` before you apply the blueprint. ``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 Note that the in-game UI setting "Standard/Marker Only" (:kbd:`d`:kbd:`m`) does
any effect on quickfort. not have any effect on quickfort.
Stockpiles and zones Stockpiles and zones
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
@ -484,7 +486,7 @@ Stockpiles and zones
It is very common to have stockpiles that accept multiple categories of items or 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 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`` 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 blueprint, quickfort also supports directly declaring all the types in the
``#place`` and ``#zone`` blueprints. For example, to declare a 20x10 stockpile ``#place`` and ``#zone`` blueprints. For example, to declare a 20x10 stockpile
that accepts both corpses and refuse, you could write: that accepts both corpses and refuse, you could write:
@ -493,7 +495,6 @@ that accepts both corpses and refuse, you could write:
#place refuse heap #place refuse heap
yr(20x10) yr(20x10)
And similarly, to declare a zone that is a pasture, a fruit picking area, and a And similarly, to declare a zone that is a pasture, a fruit picking area, and a
meeting area all at once: meeting area all at once:
@ -505,14 +506,15 @@ meeting area all at once:
The order of the individual letters doesn't matter. If you want to configure the The order of the individual letters doesn't matter. If you want to configure the
stockpile from scratch in a ``#query`` blueprint, you can place unconfigured stockpile from scratch in a ``#query`` blueprint, you can place unconfigured
"custom" stockpiles with (:kbd:`c`). It is more efficient, though, to place "custom" stockpiles with (:kbd:`c`). It is more efficient, though, to place
stockpiles using the keys that represent the types you want to store, and stockpiles using the keys that represent the categories of items that you want
then only use a ``#query`` blueprint if you need fine-grained customization. to store, and then only use a ``#query`` blueprint if you need fine-grained
customization.
Detailed configuration for zones, such as the pit/pond toggle, can also be set Detailed configuration for zones, such as the pit/pond toggle, can also be set
by mimicking the hotkeys used to set them. Note that gather flags default to by mimicking the hotkeys used to set them. Note that gather flags default to
true, so specifying them in a blueprint will turn the toggles off. If you need true, so specifying them in a blueprint will turn the toggles off. If you need
to set configuration from multiple zone subscreens, separate the key sections to set configuration from multiple zone subscreens, separate the key sections
with ``^``. Note the special syntax for setting hospital supply levels, which with :kbd:`^`. Note the special syntax for setting hospital supply levels, which
have no in-game hotkeys: have no in-game hotkeys:
:: ::
@ -532,8 +534,8 @@ The valid hospital settings (and their maximum values) are:
buckets (100) buckets (100)
soap (15000) soap (15000)
To toggle the ``active`` flag for zones, add an ``a`` character to the string. To toggle the ``active`` flag for zones, add an :kbd:`a` character to the
For example, to create a *disabled* pond zone (that you later intend to string. For example, to create a *disabled* pond zone (that you later intend to
carefully fill with 3-depth water for a dwarven bathtub): carefully fill with 3-depth water for a dwarven bathtub):
:: ::
@ -552,14 +554,13 @@ simpler, so we'll start with them.
Constructed tracks Constructed tracks
`````````````````` ``````````````````
Quickfort supports the designation of track stops and rollers through the normal Quickfort supports the designation of track stops and rollers in ``#build``
mechanisms: a ``#build`` blueprint with ``CS`` and some number of ``d`` and blueprints. You can build a track stop with :kbd:`C`:kbd:`S` and some number of
``a`` characters (for selecting dump direction and friction) in a cell :kbd:`d` and :kbd:`a` characters for selecting dump direction and friction. You
designates a track stop and a ``#build`` blueprint with ``Mr`` and some number can build a roller with :kbd:`M`:kbd:`r` and some number of :kbd:`s` and
of ``s`` and ``q`` characters (for direction and speed) designates a roller. :kbd:`q` characters for direction and speed. However, this can get confusing
This can get confusing very quickly and is very difficult to read in a very quickly and is very difficult to read in a blueprint. Moreover, constructed
blueprint. Constructed track segments don't even have keys associated with them track segments don't even have keys associated with them at all!
at all!
To solve this problem, Quickfort provides the following keywords for use in To solve this problem, Quickfort provides the following keywords for use in
build blueprints: build blueprints:
@ -632,19 +633,20 @@ their outside directions with the following blueprint:
trackstopW trackEW trackEW trackEW trackstopE trackstopW trackEW trackEW trackEW trackstopE
Note that the **only** way to build track and track/ramp segments is with the 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 keywords. The UI method of using :kbd:`+` and :kbd:`-` keys to select the track
a list does not work since DFHack Quickfort doesn't actually send keys to the UI type from a list does not work since DFHack Quickfort doesn't actually send keys
to build buildings. The text in your spreadsheet cells is mapped directly into to the UI to build buildings. The text in your spreadsheet cells is mapped
DFHack API calls. Only ``#query`` blueprints still send actual keycodes to the directly onto DFHack API calls. Only ``#query`` blueprints send actual keycodes
UI. to the UI.
Carved tracks Carved tracks
````````````` `````````````
In the game, you carve a minecart track by specifying a beginning and ending 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 tile and the game "adds" the designation to the tiles in between. You cannot
single tiles. For example to carve two track segments that cross each other, you designate single tiles. For example to carve two track segments that cross each
might use the cursor to designate a line of three vertical tiles like this: other, you might use the cursor to designate a line of three vertical tiles like
this:
:: ::
@ -722,7 +724,7 @@ about yet. You can:
- register a message to be displayed after the blueprint is successfully - register a message to be displayed after the blueprint is successfully
applied applied
The full modeline syntax, when everything is specified, is: The full modeline syntax, when all optional elements are specified, is:
:: ::
@ -778,10 +780,10 @@ will build the workshop *centered* on the cursor, not down and to the right of
the cursor. the cursor.
The two numbers specify the column and row (or X and Y offset) where 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 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 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 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 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 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 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 fully-specified ``start()`` markers. For example, a meta blueprint that refers
@ -810,15 +812,19 @@ Messages
A blueprint with a ``message()`` marker will display a message after the A blueprint with a ``message()`` marker will display a message after the
blueprint is applied with ``quickfort run``. This is useful for reminding blueprint is applied with ``quickfort run``. This is useful for reminding
players to take manual steps that cannot be automated, like assigning animals to players to take manual steps that cannot be automated, like assigning minecarts
a pasture or assigning minecarts to a route, or listing the next step in a to a route, or listing the next step in a series of blueprints. For long or
series of blueprints. For long or multi-part messages, you can embed newlines: multi-part messages, you can embed newlines:
:: ::
"#meta label(surface1) message(This would be a good time to start digging the industry level. "#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" Once the area is clear, continue with /surface2.) clear the embark site and set up pastures"
The quotes surrounding the cell text are only necessary if you are writing a
.csv file by hand. Spreadsheet applications will surround multi-line text with
quotes automatically when they save/export the file.
.. _quickfort-packaging: .. _quickfort-packaging:
Packaging a set of blueprints Packaging a set of blueprints
@ -826,7 +832,7 @@ Packaging a set of blueprints
A complete specification for a section of your fortress may contain 5 or more 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 separate blueprints, one for each "phase" of construction (dig, build, place
stockpiles, designate zones, query building adjustments). stockpiles, designate zones, and query adjustments).
To manage all the separate blueprints, it is often convenient to keep related 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 blueprints in a single file. For .xlsx spreadsheets, you can keep each blueprint
@ -838,7 +844,9 @@ sizes and coloring.
For both .csv files and .xlsx spreadsheets you can also add as many blueprints 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 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 to indicate the start of a new blueprint. Instead of multiple .csv files, you
can concatenate them into one single file. can concatenate them into one single file. This is especially useful when you
are sharing your blueprints with others. A single file is much easier to manage
than a directory of files.
For example, you can store multiple blueprints together like this: For example, you can store multiple blueprints together like this:
@ -886,15 +894,33 @@ files and just give related blueprints similar names:
bedroom.4.query.csv bedroom.4.query.csv
bedroom.5.query2.csv bedroom.5.query2.csv
But the naming and organization is completely up to you. The naming and organization is completely up to you.
.. _quickfort-other-modes:
Other blueprint modes
~~~~~~~~~~~~~~~~~~~~~
There are a few additional blueprint modes that become useful when you are
sharing your blueprints with others or managing complex blueprint sets. Instead
of mapping tile positions to keystroke sequences like the basic modes do, these
"blueprints" have specialized, higher-level uses:
============== ===========
Blueprint mode Description
============== ===========
meta Link sequences of blueprints together
notes Display long messages, such as help text or blueprint
walkthroughs
============== ===========
.. _quickfort-meta: .. _quickfort-meta:
Meta blueprints Meta blueprints
~~~~~~~~~~~~~~~ ```````````````
Meta blueprints are blueprints that script a series of other blueprints. Many Meta blueprints are blueprints that script a series of other blueprints. For
blueprint packages follow this pattern: example, many blueprint sets follow this pattern:
1. Apply dig blueprint to designate dig areas 1. Apply dig blueprint to designate dig areas
#. Wait for miners to dig #. Wait for miners to dig
@ -905,11 +931,12 @@ blueprint packages follow this pattern:
#. Apply a different query blueprint to configure rooms #. Apply a different query blueprint to configure rooms
Those three "apply"s in the middle might as well get done in one command instead 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 of three. A ``#meta`` blueprint can encode that sequence. A meta blueprint
other blueprints by their label (see the `Modeline markers`_ section above) in refers to other blueprints in the same file by their label (see the
the same format used by the `quickfort` command: ``<sheet name>/<label>``, or `Modeline markers`_ section above) in the same format used by the `quickfort`
just ``/<label>`` for blueprints in .csv files or blueprints in the same command: ``<sheet name>/<label>``, or just ``/<label>`` for blueprints in .csv
spreadsheet sheet as the ``#meta`` blueprint that references them. 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" A few examples might make this clearer. Say you have a .csv file with the "bed"
blueprints in the previous section: blueprints in the previous section:
@ -960,23 +987,17 @@ 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 your entire fortress for digging at once. For example, say you have a
spreadsheet with the following layout: spreadsheet with the following layout:
+-------------------------------------------+----------------------------------+ ============= ========
| Sheet name | contents | Sheet name Contents
+===========================================+==================================+ ============= ========
| dig_farming | one #dig blueprint, no label | dig_farming one #dig blueprint, no label
+-------------------------------------------+----------------------------------+ dig_industry 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_dining | four #dig blueprints, with | dig_guildhall one #dig blueprint, no label
| | labels "main", "basement", | dig_suites one #dig blueprint, no label
| | "waterway", and "cistern" | dig_bedrooms one #dig blueprint, no label
+-------------------------------------------+----------------------------------+ ============= ========
| 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 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): a big fort, so we're planning for a lot of bedrooms):
@ -1014,30 +1035,31 @@ a big fort, so we're planning for a lot of bedrooms):
Note that for blueprints without an explicit label, we still need to address Note that for blueprints without an explicit label, we still need to address
them by their auto-generated numerical label. them by their auto-generated numerical label.
It's worth calling out that ``#meta`` blueprints can only refer to blueprints It's worth repeating that ``#meta`` blueprints can only refer to blueprints that
that are defined in the same file. This means that all blueprints that a are defined in the same file. This means that all blueprints that a meta
``#meta`` blueprint needs to script must be in sheets within the same blueprint needs to run must be in sheets within the same .xlsx spreadsheet or
.xlsx spreadsheet or concatenated into the same .csv file. concatenated into the same .csv file.
You can then hide the blueprints that you now manage with the ``#meta``-mode You can then hide the blueprints that you now manage with the meta blueprint
blueprint from ``quickfort list`` by adding a ``hidden()`` marker to their from ``quickfort list`` by adding a ``hidden()`` marker to their modelines. That
modelines. That way the output of ``quickfort list`` won't be cluttered by way the output of ``quickfort list`` won't be cluttered by blueprints that you
blueprints that you don't need to run directly. If you ever *do* need to access don't need to run directly. If you ever *do* need to access the managed
the managed blueprints individually, you can still see them with blueprints individually, you can still see them with
``quickfort list --hidden``. ``quickfort list --hidden``.
.. _quickfort-notes: .. _quickfort-notes:
Notes blueprints Notes blueprints
~~~~~~~~~~~~~~~~ ````````````````
Sometimes you just want to record some information about your blueprints, such 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 as when to apply them, what preparations you need to make, or what the
blueprints contain. The `message() <quickfort-message>` modeline marker is blueprints contain. The `message() <quickfort-message>` modeline marker is
useful for small, single-line messages, but a ``#notes`` blueprint is more 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 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()`` ``#notes`` blueprint are output as if they were contained within one large
marker. For example, the following two blueprints result in the same output: multi-line ``message()`` marker. For example, the following two blueprints
result in the same output:
:: ::
@ -1067,22 +1089,22 @@ job but can't find the materials.
As long as the `buildingplan` plugin is enabled, quickfort will use it to manage As long as the `buildingplan` plugin is enabled, quickfort will use it to manage
construction. The buildingplan plugin also has an "enabled" setting for each construction. The buildingplan plugin also has an "enabled" setting for each
building type, but that setting only applies to the buildingplan user interface; building type, but that setting only applies to the buildingplan user interface;
quickfort will always use buildingplan to manage everything designated in a quickfort will use buildingplan to manage everything designated in a ``#build``
``#build`` blueprint. blueprint regardless of the buildingplan UI settings.
However, quickfort *does* use buildingplan's filters for each building type. For However, quickfort *does* use buildingplan's filters for each building type. For
example, you can use the buildingplan UI to set the stone you want your walls example, you can use the buildingplan UI to set the type of stone you want your
made out of. Or you can specify that all buildingplan-managed tables must be of walls made out of. Or you can specify that all buildingplan-managed tables must
Masterful quality. The current filter settings are saved with planned buildings be of Masterful quality. The current filter settings are saved with planned
when the ``#build`` blueprint is run. This means you can set the filters the way buildings when the ``#build`` blueprint is run. This means you can set the
you want for one blueprint, run the blueprint, and then freely change them again filters the way you want for one blueprint, run the blueprint, and then freely
for the next blueprint, even if the first set of buildings haven't been built change them again for the next blueprint, even if the first set of buildings
yet. haven't been built yet.
Note that buildings are still constructed immediately if you already have the Note that buildings are still constructed immediately if you already have the
materials. However, with the buildingplan integration you now have the freedom materials. However, with buildingplan you now have the freedom to apply
to apply ``#build`` blueprints before you manufacture the resources. The ``#build`` blueprints before you manufacture the resources. The construction
construction jobs will be fulfilled as the materials become available. jobs will be fulfilled whenever the materials become available.
Since it can be difficult to figure out exactly what source materials you need Since it can be difficult to figure out exactly what source materials you need
for a ``#build`` blueprint, quickfort supplies the ``orders`` command. It for a ``#build`` blueprint, quickfort supplies the ``orders`` command. It
@ -1095,7 +1117,8 @@ are needed.
If the buildingplan plugin is not enabled, run ``quickfort orders`` first and If the buildingplan plugin is not enabled, run ``quickfort orders`` first and
make sure all manager orders are fulfilled before applying a ``#build`` make sure all manager orders are fulfilled before applying a ``#build``
blueprint. blueprint. Otherwise you will get job cancellation spam when the buildings can't
be built with available materials.
Generating manager orders Generating manager orders
------------------------- -------------------------
@ -1118,9 +1141,9 @@ few extra blocks, but not too many.
If you want your constructions to be in a consistent color, be sure to choose a 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 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 hitting :kbd:`d`. You might want to set the rock type for other non-block orders
something different if you fear running out of the type of rock that you want to to something different if you fear running out of the type of rock that you want
use for blocks. You should also set the `buildingplan` material filter for to use for blocks. You should also set the `buildingplan` material filter for
construction building types to that type of rock as well so other random blocks construction building types to that type of rock as well so other random blocks
you might have lying around aren't used. you might have lying around aren't used.
@ -1152,11 +1175,11 @@ Tips and tricks
concentrate on one level at a time. You just have to remember to "unmark" a 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. 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 - As of DF 0.34.x, it is no longer possible to build doors (:kbd:`d`) at the
that you build adjacent walls (Cw). Doors must now be built *after* walls are same time that you build adjacent walls (:kbd:`C`:kbd:`w`). Doors must now be
constructed for them to be next to. This does not affect the more common case built *after* adjacent walls are constructed. This does not affect the more
where walls exist as a side-effect of having dug-out a room in a #dig common case where walls exist as a side-effect of having dug-out a room in a
blueprint. ``#dig`` blueprint.
Caveats and limitations Caveats and limitations
----------------------- -----------------------
@ -1177,11 +1200,10 @@ Caveats and limitations
- Pressure plates can be built, but they cannot be usefully configured yet. - Pressure plates can be built, but they cannot be usefully configured yet.
- Building instruments, bookcases, display furniture, and offering places are - Building instruments is not yet supported.
not yet supported by DFHack.
- This script is relatively new, and there are bound to be bugs! Please report - DFHack Quickfort is relatively new, and there are bound to be bugs! Please
them at the :issue:`DFHack issue tracker <>` so they can be addressed. report them at the :issue:`DFHack issue tracker <>` so they can be addressed.
Dreamfort case study: a practical guide to advanced blueprint design Dreamfort case study: a practical guide to advanced blueprint design
-------------------------------------------------------------------- --------------------------------------------------------------------
@ -1224,7 +1246,7 @@ obvious just from looking at them.
The surface_ level: how to manage complexity The surface_ level: how to manage complexity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _surface: https://docs.google.com/spreadsheets/d/1vlxOuDOTsjsZ5W45Ri1kJKgp3waFo8r505LfZVg5wkU/edit?usp=sharing .. _surface: https://docs.google.com/spreadsheets/d/1vlxOuDOTsjsZ5W45Ri1kJKgp3waFo8r505LfZVg5wkU
For smaller blueprints, packaging and usability are not really that important - 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 just write it, run it, and you're done. However, as your blueprints become
@ -1270,11 +1292,11 @@ view of your entire plan in one sheet.
Keep the blueprint list uncluttered with hidden() markers. Keep the blueprint list uncluttered with hidden() markers.
If a blueprint is bundled into a meta blueprint, it does not need to appear in 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 the quickfort list output since you won't be running it directly. Add a
`hidden() marker <quickfort-hidden>` to those blueprints to keep the list `hidden() marker <quickfort-hidden>` to those blueprints to keep the list
output tidy. You can still access hidden blueprints with ``quickfort 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 --hidden`` if you need to -- for example to reapply a partially completed
blueprint -- but now they wont clutter up the normal blueprint list. ``#build`` blueprint -- but now they wont clutter up the normal blueprint list.
.. topic:: Tip .. topic:: Tip
@ -1309,14 +1331,15 @@ sheet, like in surface's meta sheet.
things to include in messages are: things to include in messages are:
* The name of the next blueprint to apply and when to run it * The name of the next blueprint to apply and when to run it
* Whether quickfort orders could be run for an upcoming step * Whether ``quickfort orders`` should be run for an upcoming step
* Any manual actions that have to happen, like assigning minecarts to hauling * Any actions that you have to perform manually after running the blueprint,
routes or pasturing animals after creating zones 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 These things are just too easy to forget. Adding a ``message()`` can save you
hidden() blueprints, and they'll still get shown when the blueprint is run via from time-wasting mistakes. Note that message() markers can still appear on the
the ``#meta`` blueprint. For an example of this, check out the `zones sheet ``hidden()`` blueprints, and they'll still get shown when the blueprint is run
via a ``#meta`` blueprint. For an example of this, check out the `zones sheet
<https://docs.google.com/spreadsheets/d/ <https://docs.google.com/spreadsheets/d/
1vlxOuDOTsjsZ5W45Ri1kJKgp3waFo8r505LfZVg5wkU/edit#gid=1226136256>`__ where the 1vlxOuDOTsjsZ5W45Ri1kJKgp3waFo8r505LfZVg5wkU/edit#gid=1226136256>`__ where the
pastures are defined. pastures are defined.
@ -1324,20 +1347,20 @@ pastures are defined.
The farming_ level: fun with stockpiles The farming_ level: fun with stockpiles
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _farming: https://docs.google.com/spreadsheets/d/1iuj807iGVk6vsfYY4j52v9_-wsszA1AnFqoxeoehByg/edit?usp=sharing .. _farming: https://docs.google.com/spreadsheets/d/1iuj807iGVk6vsfYY4j52v9_-wsszA1AnFqoxeoehByg
It is usually convenient to store closely associated blueprints in the same 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 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 miasma vents have to perfectly line up with where they are needed. However,
and, more importantly, already has many many blueprints, so farming is split surface is a separate z-level and, more importantly, already has many many
into a separate file. blueprints, so farming is split into a separate file.
.. topic:: Tip .. topic:: Tip
Automate stockpile chains when you can, and write message() reminders when Automate stockpile chains when you can, and write message() reminders when
you can't. you can't.
The farming level starts doing interesting things with query blueprints and The farming level starts doing interesting things with ``#query`` blueprints and
stockpiles. Note the `careful customization stockpiles. Note the `careful customization
<https://docs.google.com/spreadsheets/d/1iuj807iGVk6vsfYY4j52v9_- <https://docs.google.com/spreadsheets/d/1iuj807iGVk6vsfYY4j52v9_-
wsszA1AnFqoxeoehByg/edit#gid=486506218>`__ of the food stockpiles and the wsszA1AnFqoxeoehByg/edit#gid=486506218>`__ of the food stockpiles and the
@ -1347,7 +1370,7 @@ 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 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 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 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(). we call that out in the ``#query`` blueprint's ``message()``.
.. topic:: Tip .. topic:: Tip
@ -1355,12 +1378,13 @@ we call that out in the query blueprint's message().
Hauling routes are notoriously fiddly to set up, but they can be automated with 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. Check out the Southern area of the ``#place`` and ``#query``
blueprints for how the quantum garbage dump is configured. blueprints for how the quantum garbage dump is configured with simple aliases
from the alias library.
The industry_ level: when not to use aliases The industry_ level: when not to use aliases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _industry: https://docs.google.com/spreadsheets/d/1gvTJxxRxZ5V4vXkqwhL-qlr_lXCNt8176TK14m4kSOU/edit?usp=sharing .. _industry: https://docs.google.com/spreadsheets/d/1gvTJxxRxZ5V4vXkqwhL-qlr_lXCNt8176TK14m4kSOU
The industry level is densely packed and has more complicated examples of 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 stockpile configurations and quantum dumps. However, what I'd like to call out
@ -1381,10 +1405,10 @@ 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 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 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 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 the stockpile link right there in the blueprint instead of editing a separate
aliases.txt file. alias definition.
There are also good examples in the query blueprint for how to use the There are also good examples in the ``#query`` blueprint for how to use the
``permit`` and ``forbid`` stockpile aliases. ``permit`` and ``forbid`` stockpile aliases.
.. topic:: Tip .. topic:: Tip
@ -1402,31 +1426,35 @@ categories:
If you have a stockpile that covers multiple tiles, it might seem natural to put If you have a stockpile that covers multiple tiles, it might seem natural to put
one alias per spreadsheet cell. The aliases still all get applied to the one alias per spreadsheet cell. The aliases still all get applied to the
stockpile, and with only one alias per cell, you can just type the alias name stockpile, and with only one alias per cell, you can just type the alias name
and avoid having to use the messier-looking ``{alias1}{alias2}`` syntax: and avoid having to use the messier-looking ``{aliasname}`` syntax:
:: ::
#query Incorrectly configure a 3x3 food stockpile to accept tallow and dye #place Declare a food stockpile
f(3x3)
#query Incorrectly configure a food stockpile to accept tallow and dye
tallow tallow
permitdye permitdye
However, in quickfort there are no guarantees about which cell will be However, in quickfort there are no guarantees about which cell will be
processed first. In the example above, we obviously intend for the food processed first. In the example above, we obviously intend for the food
stockpile to have everything forbidden, then tallow permitted, then dye stockpile to have tallow exclusively permitted, then to add dye. It could happen
permitted. The algorithm could happen to apply them in the opposite order, that the two aliases are applied in the opposite order, though, and we'd end up
though, and we'd end up with dye being permitted, then everything being with dye being permitted, then everything being forbidden and tallow being
forbidden and tallow being enabled. To make sure you always get what you want, enabled. To make sure you always get what you want, write order-sensitive
write order-sensitive aliases on the same line: aliases on the same line:
:: ::
#query Properly configure a 3x3 food stockpile to accept tallow and dye #place Declare a food stockpile
f(3x3)
#query Properly configure a food stockpile to accept tallow and dye
{tallow}{permitdye} {tallow}{permitdye}
The services_ level: handling multi-level dig blueprints The services_ level: handling multi-level dig blueprints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _services: https://docs.google.com/spreadsheets/d/1IBy6_pGEe6WSBCLukDz_5I-4vi_mpHuJJyOp2j6SJlY/edit?usp=sharing .. _services: https://docs.google.com/spreadsheets/d/1IBy6_pGEe6WSBCLukDz_5I-4vi_mpHuJJyOp2j6SJlY
Services is a multi-level blueprint that includes a well cistern beneath the 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 main level. Unwanted ramps caused by channeling are an annoyance, but we can
@ -1441,21 +1469,18 @@ We can `ensure <https://docs.google.com/spreadsheets/d/1IBy6_pGEe6WSBCLukDz_5I-
4vi_mpHuJJyOp2j6SJlY/edit#gid=962076234>`__ the bottom level is carved out 4vi_mpHuJJyOp2j6SJlY/edit#gid=962076234>`__ the bottom level is carved out
before the layer above is channelled by assigning the channel designations lower 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 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 there is no chance of cave-in.
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 An alternative is to have a follow-up blueprint that removes any undesired
ramps. Using dig priorities to avoid the issue in the first place can be ramps. We did this on the surface and farming levels with the miasma vents to
cleaner, though. avoid the complication of setting detailed dig priorities over such large areas.
The guildhall_ level: avoiding smoothing issues The guildhall_ level: avoiding smoothing issues
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _guildhall: https://docs.google.com/spreadsheets/d/1wwKcOpEW-v_kyEnFyXS0FTjvLwJsyWbCUmEGaXWxJyU/edit?usp=sharing .. _guildhall: https://docs.google.com/spreadsheets/d/1wwKcOpEW-v_kyEnFyXS0FTjvLwJsyWbCUmEGaXWxJyU
The goal of this level is to provide rooms for locations like guildhalls, 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 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 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 dwarf has to be adjacent to it, and since some furniture, like statues, block
@ -1466,15 +1491,15 @@ dwarves from entering a tile, where you put them affects what you can access.
Don't put statues in corners unless you want to smooth everything first. 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 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 corners. This gives the player freedom for choosing when to smooth. If a statue
block wall segments, it forces the player to smooth before building the statues, blocks a corner, or if a line of statues blocks a wall segment, it forces the
or else they have to mess with temporarily removing statues to smooth the walls player to smooth before building the statues. Otherwise they have to mess with
behind them. temporarily removing statues to smooth the walls behind them.
The beds_ levels: multi level meta blueprints The beds_ levels: multi level meta blueprints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _beds: https://docs.google.com/spreadsheets/d/1QNHORq6YmYfuVVMP5yGAFCQluary_JbgZ-UXACqKs9g/edit?usp=sharing .. _beds: https://docs.google.com/spreadsheets/d/1QNHORq6YmYfuVVMP5yGAFCQluary_JbgZ-UXACqKs9g
The suites and apartments blueprints are straightforward. The only fancy bit The suites and apartments blueprints are straightforward. The only fancy bit
here is the meta blueprint, which brings us to our final tip: here is the meta blueprint, which brings us to our final tip:
@ -1486,9 +1511,10 @@ here is the meta blueprint, which brings us to our final tip:
We couldn't use this technique for the entire fortress since there is often an 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 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 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 useful shortcut of designating all apartment levels at once. See the
blueprint for how it applies the apartments on six z-levels using ``#>`` between `#meta <https://docs.google.com/spreadsheets/d/1QNHORq6YmYfuVVMP5yGAFCQluary_JbgZ-UXACqKs9g/edit#gid=1980526014>`__
apartment blueprint references. 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 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 forums if you have ideas on how this guide (or the dreamfort blueprints) can be
@ -1500,8 +1526,8 @@ Links
**Quickfort links:** **Quickfort links:**
- `Quickfort command reference <quickfort>` - `Quickfort command reference <quickfort>`
- `Quickfort alias guide <quickfort-alias-guide>`
- :forums:`Quickfort forum thread <176889>` - :forums:`Quickfort forum thread <176889>`
- :source:`Quickfort blueprints library <data/blueprints/library>`
- :issue:`DFHack issue tracker <>` - :issue:`DFHack issue tracker <>`
- :source:scripts:`Quickfort source code <internal/quickfort>` - :source:scripts:`Quickfort source code <internal/quickfort>`
@ -1509,5 +1535,7 @@ Links
- DFHack's `blueprint plugin <blueprint>` can generate blueprints from actual - DFHack's `blueprint plugin <blueprint>` can generate blueprints from actual
DF maps. DF maps.
- DFHack's `buildingplan plugin <buildingplan>` sets material and quality
constraints for quickfort-placed buildings.
- `Python Quickfort <http://joelpt.net/quickfort>`__ is the previous, - `Python Quickfort <http://joelpt.net/quickfort>`__ is the previous,
Python-based implementation that DFHack's quickfort script was inspired by. Python-based implementation that DFHack's quickfort script was inspired by.