Ok, I wrote up a guide for advanced blueprints. It's a little longer than I expected it would be, and the audience is probably smaller than the rest of the user guide, but I'm hoping it will be useful to the "serious blueprinters" out there!
I'm planning on getting it properly reviewed and merged into the user guide once lethosor migrates it to RST format, but here's a first draft:
Dreamfort case study: a practical guide to advanced blueprint design
While syntax definitions and toy examples will certainly get you started with your blueprints, it may not be clear how all the quickfort features fit together or what the best practices are, especially for large and complex blueprint sets. This section walks through the "Dreamfort" blueprints found in the DFHack blueprint library, highlighting design choices and showcasing practical techniques that can help you create better blueprints. Note that this is not a guide for how to design the best forts (there is plenty about that on the wiki). This is essentially an extended tips and tricks section focused on how to make usable and useful quickfort blueprints that will save you time and energy.
The Dreamfort blueprints we'll be discussing are available in the library as one large .csv file or online as individual spreadsheets. Either can be read and applied by quickfort, but for us humans, the online spreadsheets are much easier to work with. Check them out here. Each spreadsheet has a "Notes" sheet with some useful details. Flip through some of the spreadsheets and read the help text to get oriented. Also, if you haven't built Dreamfort before, try an embark in a flat area and take it for a spin!
Almost every quickfort feature is used somewhere in Dreamfort, so the blueprints as a whole are useful as practical examples. You can copy the blueprints and use them as starting points for your own, or just refer to them when you create something similar.
In this case study, we'll start by discussing the high level organization of the Dreamfort blueprint set, using the "surface" blueprints as an example. Then we'll walk through the blueprints for each of the remaining fort levels in turn, explaining the parts that might not be obvious just from looking at them.
The surface level: how to manage complexity
For smaller blueprints, packaging and usability are not a big deal - just write it, run it, and you're done. However, as your blueprints become larger and more detailed, there are some best practices that can help you deal with the added complexity. Dreamfort's surface level is many steps long since there are trees to be cleared, holes to be dug, flooring to be laid, and furniture to be built, and each step requires the previous step to be completely finished before it can begin. Therefore, a lot of thought went into minimizing the toil associated with applying so many blueprints.
Tip: Use meta blueprints to reduce the number of quickfort commands you have to run
The single most effective way to make your blueprint sets easier to use is to group them with meta blueprints to minimize the number of quickfort run commands that you have to execute. For the Dreamfort set of blueprints, each logical "step" generally takes more than one blueprint. For example, setting up pastures with a #zone blueprint, placing starting stockpiles with a #place blueprint, building starting workshops with a #build blueprint, and configuring the stockpiles with a #query blueprint can all be done at once. Bundling blueprints like this reduced the number of steps in Dreamfort from 47 to 24, and it also made it much clearer to see which blueprints can be applied at once without unpausing the game. Check out dreamfort_surface's "meta" sheet to see how much meta blueprints can simplify your life.
Note that one of the meta blueprints just has one line. In this case, the meta blueprint isn't strictly necessary. The referenced blueprint could just be applied directly. However, quickfort lists blueprints in the order that it reads them, and we chose to make a one-blueprint meta blueprint to ensure all the steps appear in order in the quickfort list output.
By the way, you can define as many blueprints as you want on one sheet, but multi-blueprint sheets are especially useful when writing a bunch of meta blueprints. It's like having a bird's eye view of your entire blueprint set in one sheet.
Tip: Keep the blueprint list uncluttered with hidden() markers
If a blueprint is bundled into a meta blueprint, it does not need to appear in the quickfort list output, since you won't be running it directly. Add a hidden() marker to those blueprints to keep the list output tidy. You can still access hidden blueprints if you need to, say to reapply a partially completed #build blueprint, but now they won’t clutter up the blueprint list.
Tip: Name your blueprints with a common prefix so you can find them easily
This goes for both the file name and the modeline label(). Searching and filtering is implemented for both the quickfort list command and the quickfort gui. If you give related blueprints a common prefix, it makes it easy to set the filters to display just the blueprints that you're interested in. If you have a lot of blueprints, this can save you a lot of time. Dreamfort, of course, uses the "dreamfort" prefix for the files and sequence names for the labels, like "surface1", "surface2", "farming1", etc.
Tip: Add descriptive comments that remind you what the blueprint contains
If you've been away from Dwarf Fortress for a while, it's easy to forget what your blueprints actually do. Make use of modeline comments so your descriptions are visible in the blueprint list. If you use meta blueprints, all your comments can be conveniently edited on one sheet, like in surface's meta sheet.
Tip: Use message() markers to remind yourself what to do next
Messages are displayed after a blueprint is applied. Good things to include in messages are:
The name of the next blueprint to apply and when to run it
Whether quickfort orders should be run for an upcoming step
Any manual actions that have to happen, like assigning minecarts to hauling routes or pasturing animals after creating zones
These things are just too easy to forget. Adding a message() can save you from time-wasting mistakes. Note that message() markers can still appear on the hidden() blueprints, and they'll still get shown when the blueprint is run through the meta blueprint. For an example of this, check out the zone sheet where the pastures are defined.
The farming level: fun with stockpiles
It is usually convenient to store closely associated blueprints in the same spreadsheet. The farming level is very closely tied to the surface because the miasma vents have to perfectly line up. However, surface is a separate z-level and, more importantly, already has far too many blueprints as it was, so farming is split into a separate file.
Tip: Automate stockpile chains when you can, and write message() reminders when you can't
The farming level starts doing interesting things with query blueprints and stockpiles. Note the careful customization of the food stockpiles and the stockpile chains set up with the give* aliases. This is so when multiple stockpiles can hold the same item, the largest can keep the smaller ones filled. If you have multiple stockpiles holding the same type on different z-levels, though, this can be tricky to set up with a blueprint. Here, the jugs and pots stockpiles must be manually linked to the quantum stockpile on the industry level, since we can't know beforehand how many z-levels away that is. Note how we call that out in the query blueprint's message().
Tip: Use aliases to set up hauling routes and quantum stockpiles
Hauling routes are notoriously fiddly to set up, but they can be automated with blueprints. Check out the Southern area of the #place and #query blueprints for how the quantum garbage dump is configured.
Note that aliases that must be applied in a particular order must appear in the same cell. Otherwise there are no guarantees for which cell will be processed first. For example, look at the track stop cells in the #query blueprint for how the hauling routes are given names.
The industry level: when not to use aliases
The industry level is densely packed and has more complicated examples of stockpile configurations and quantum dumps. However, what I'd like to call out are the key sequences that are *not* in aliases.
Tip: Don't use aliases for ad-hoc cursor movements
It may be tempting to put all query blueprint key sequences into aliases to make them easier to edit, keep them all in one place, and make them reusable, but some let sequences just aren't very valuable as aliases.
Check out the Eastern (goods) and Northern (stone and gems) quantum stockpiles. They give to the jeweler's workshop to prevent the jeweler from using the gems held in reserve for strange moods. The keys are not aliases since they're dependent on the relative positions of the tiles where they are interpreted, which is easiest to see in the blueprint itself. Also, if you move the workshop, it's easier to fix the stockpile link right there in the blueprint instead of editing the separate aliases.txt file.
The services level: handling multi level dig blueprints
Services is a multi-level blueprint that includes a well cistern beneath the main level. Unwanted ramps caused by channeling are an annoyance, but we can avoid getting a ramp at the bottom of the cistern with careful use of dig priorities.
Tip: Use dig priorities to control ramp creation
We can ensure the bottom level is carved out before the layer above is channelled. This is easy to do here because it's just one tile and there is no chance of cave-in. We could have used this technique on the farming level for the miasma vents instead of requiring that the channels be dug before the farming level is dug, but that would have been much more fiddly for the larger areas.
The alternative is just to have a follow-up blueprint that removes any undesired ramps. Using dig priorities to avoid the issue in the first place can be cleaner, though.
The guildhall level: avoiding smoothing issues
The goal of this level is to provide rooms for locations like guildhalls, libraries, and temples. The value of these rooms is very important, so we are likely to smooth and engrave everything. To smooth or engrave a wall tile, a dwarf has to be adjacent to it, and since some furniture, like statues, block dwarves from entering a tile, where you put them affects what you can access.
Tip: Don't put statues in corners unless you want to smooth everything first
In the guildhall level, the statues are placed so as not to block any wall corners. This gives the player freedom for choosing when to smooth. If statues block wall segments, it forces the player to smooth before building the statues, or else they have to mess with temporarily removing statues to smooth the walls behind them.
The suites and apartments levels: multi level meta blueprints
The suites and apartments blueprints are straightforward. The only fancy bit here is the meta blueprint, which brings us to our final tip:
Tip: Use meta blueprints to lay out multiple adjacent levels
We couldn't use this technique for the entire fortress since there is often an aquifer between the farming and industry levels, and we can't know beforehand how many z-levels we need to skip. Here, though, we can at least provide the useful shortcut of designating all apartment levels at once. See the meta blueprint for how it applies the apartments on six z-levels using #> between apartment blueprint references.
That's it! I hope this guide was useful to you. Please leave feedback on the forums if you have ideas on how this guide (or the dreamfort blueprints) can be improved!