Merge remote-tracking branch 'myk002/quickfort_skeleton' into develop

develop
lethosor 2020-07-24 22:08:24 -04:00
commit fddda1818e
No known key found for this signature in database
GPG Key ID: 76A269552F4F58C1
16 changed files with 284 additions and 22 deletions

1
.gitignore vendored

@ -24,6 +24,7 @@ build/Makefile
build/CMakeCache.txt
build/cmake_install.cmake
build/CMakeFiles
build/data
build/doc
build/lua
build/bin

@ -429,6 +429,7 @@ if(BUILD_PLUGINS)
add_subdirectory(plugins)
endif()
add_subdirectory(data)
add_subdirectory(scripts)
find_package(Sphinx QUIET)

@ -0,0 +1,2 @@
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/blueprints/ DESTINATION blueprints)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/quickfort/ DESTINATION "${DFHACK_DATA_DESTINATION}/data/quickfort")

@ -0,0 +1,14 @@
This directory is for quickfort blueprints. You can apply them to your fortress
map with the DFHack quickfort plugin. See
https://docs.dfhack.org/en/stable/docs/Scripts.html#quickfort for details.
You can create blueprints by hand or by using any spreadsheet application,
saving them as .xlsx or .csv files. You can also build your plan "for real" in
Dwarf Fortress, and then export your map using the DFHack blueprint for later
replay in a different fort. See
https://docs.dfhack.org/en/stable/docs/Plugins.html#blueprint for more info.
DFHack blueprints follow the original Quickfort 2.0 syntax. See
https://github.com/joelpt/quickfort for joelpt's excellent documentation.
There are many ready-to-use examples of blueprints in the library subfolder.

@ -0,0 +1,4 @@
#dig start(2;2) This is a library placeholder for use during quickfort development
d,d,d
d, ,d
d,d,d
1 #dig start(2;2) This is a library placeholder for use during quickfort development
2 d,d,d
3 d, ,d
4 d,d,d

@ -0,0 +1,135 @@
# quickfort aliases common baseline configuration file
#
# Defines custom keycode shortcuts for blueprints. Please DO NOT EDIT this file
# directly. Instead, custom aliases should be added to
# dfhack-config/quickfort/aliases.txt.
#
# Syntax:
# aliasname: keystrokes
#
# Special keys:
# {Right}, {Left}, {Up}, {Down}, >, < move the DF cursor
# {/}, {*}, {+}, {-} can be used to navigate some DF menus
# {Enter}, +{Enter}, {ExitMenu} - Enter, Shift+Enter, and Escape, respectively
# {Wait} pauses playback briefly
#
# Special keys can be repeated by adding a number inside the curly braces, for
# example: {Down 5}
#
# Some shorthand:
# & expands to {Enter}
# @ expands to +{Enter}
# ^ expands to {ExitMenu}
# % expands to {Wait}
#
# The aliases in this file were tested in DF 0.47.04 on 2020 Jul 18.
##################################
# food stockpile adjustments
##################################
seeds: s{Down}deb{Right}{Down 9}p^
noseeds: s{Down}dea{Right}{Down 9}f^
booze: s{Down}deb{Right}{Down 5}p{Down}p^
food: s{Down}dea{Right}{Down 5}f{Down}f{Down 3}f^
plants: s{Down}deb{Right}{Down 4}p^
##################################
# refuse stockpile adjustments
##################################
corpses: s{Down 4}deb{Right 2}&{Down 2}&{Left}{Down}p{Down}p^
bones: s{Down 4}deb{Right}{Down 3}p{Down}p^
rawhides: s{Down 4}deb{Right 2}{Down}&^
tannedhides: s{Down 4}deb{Right 2}{Down 53}&^
##################################
# stone stockpile adjustments
##################################
metal: s{Down 5}deb{Right}p^
nometal: s{Down 5}dea{Right}f^
bauxite: s{Down 5}deb{Right}{Down 2}{Right}{Down 42}&^
# Only use nobauxite on stone piles that you want to accept all "Other Stone" on.
# This alias works by permitting all "Other Stone",then forbidding just bauxite.
# Thus you wouldn't want to use this on a metal-only pile, for example.
nobauxite: s{Down 5}{Right}{Down 2}p{Right}{Down 42}&^
##################################
# misc stockpile adjustments
##################################
# Artifacts-only stockpile, usable on any type of existing pile.
artifacts: sd{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down}d{Down 4}deu{Right}{Up}f{Right}{Up}&{Left 2}{Down 4}e{Right}{Up}f{Right}{Up}&{Left 2}{Down 4}e{Right}{Up}f{Right}{Up}&{Left 2}{Down 4}e{Right}{Up}f{Right}{Up}&{Left 2}{Down}e{Right}{Up}f{Right}{Up}&{Left 2}^
# Bans artifacts on any pile (or rather, allows items of any quality except Artifact quality).
# This should be safe to run on any type of pile.
noartifacts: sd{Down 2}{Right}{Up}fp{Right}{Up}&{Down 2}{Left 2}{Down 4}{Right}{Up}fp{Right}{Up}&{Down 2}{Left 2}{Down 4}{Right}{Up}fp{Right}{Up}&{Down 2}{Left 2}{Down 4}{Right}{Up}fp{Right}{Up}&{Down 2}{Left 2}{Down}{Right}{Up}fp{Right}{Up}&{Down 2}{Left 2}^
# Set a finished goods stockpile to crappy low-quality trade goods only.
# Position such a stockpile near fort entrances to (hopefully) let thieves steal low quality junk.
junkgoods: s{Down 10}de{Right 2}&{Down 5}&{Down}&{Down}&{Down}&{Down 8}&{Down 2}&{Down}&{Down}&{Down}&{Down}&{Down}&{Left}{Down}f{Right}{Down}&{Down}&{Left}{Down}f{Down 2}f{Right}&{Down}&^
##################################
# 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&
##################################
# mining tracks
##################################
# The following aliases make it more convenient to build the various types of mine tracks.
# For example, to build a north/south track 'Track (NS)', you would put trackNS in a cell(s).
trackN: CT{Enter}
trackS: CT{+ 1}{Enter}
trackE: CT{+ 2}{Enter}
trackW: CT{+ 3}{Enter}
trackNS: CT{+ 4}{Enter}
trackNE: CT{+ 5}{Enter}
trackNW: CT{+ 6}{Enter}
trackSE: CT{+ 7}{Enter}
trackSW: CT{+ 8}{Enter}
trackEW: CT{+ 9}{Enter}
trackNSE: CT{+ 10}{Enter}
trackNSW: CT{+ 11}{Enter}
trackNEW: CT{+ 12}{Enter}
trackSEW: CT{+ 13}{Enter}
trackNSEW: CT{+ 14}{Enter}
trackrampN: CT{+ 15}{Enter}
trackrampS: CT{+ 15}{+ 1}{Enter}
trackrampE: CT{+ 15}{+ 2}{Enter}
trackrampW: CT{+ 15}{+ 3}{Enter}
trackrampNS: CT{+ 15}{+ 4}{Enter}
trackrampNE: CT{+ 15}{+ 5}{Enter}
trackrampNW: CT{+ 15}{+ 6}{Enter}
trackrampSE: CT{+ 15}{+ 7}{Enter}
trackrampSW: CT{+ 15}{+ 8}{Enter}
trackrampEW: CT{+ 15}{+ 9}{Enter}
trackrampNSE: CT{+ 15}{+ 10}{Enter}
trackrampNSW: CT{+ 15}{+ 11}{Enter}
trackrampNEW: CT{+ 15}{+ 12}{Enter}
trackrampSEW: CT{+ 15}{+ 13}{Enter}
trackrampNSEW: CT{+ 15}{+ 14}{Enter}
# Aliases for building track rollers; use e.g. rollerHqqq to make a low-speed horizontal roller
rollerH: Mrs
rollerV: Mr
rollerNS: Mr
rollerSN: Mrss
rollerEW: Mrs
rollerWE: Mrsss
# Aliases for building track stops that dump in each of the four directions
trackstopN: CSd
trackstopS: CSdd
trackstopE: CSddd
trackstopW: CSdddd

@ -0,0 +1,8 @@
# quickfort materials common baseline configuration file
#
# Defines forbidden materials and material preferences for build blueprints.
# Please DO NOT EDIT this file directly. Instead, custom materials preferences
# should be added to dfhack-config/quickfort/materials.txt.
#
# Syntax TBD

@ -0,0 +1,30 @@
# quickfort aliases configuration file
#
# Defines custom keycode shortcuts for blueprints. Definitions in this file take
# precedence over any definitions in the baseline aliases configuration file at
# hack/data/quickfort/aliases-common.txt. See that file for aliases that are
# already defined.
#
# This file can be used to simplify repetitive tasks, such as building minecart
# tracks or adjusting a food stockpile to accept seeds only. Making new aliases
# is just a matter of mimicking the keys used to navigate through the menus and
# select options.
#
# Syntax:
# aliasname: keystrokes
#
# Special keys:
# {Right}, {Left}, {Up}, {Down}, >, < move the DF cursor
# {/}, {*}, {+}, {-} can be used to navigate some DF menus
# {Enter}, +{Enter}, {ExitMenu} - Enter, Shift+Enter, and Escape, respectively
# {Wait} pauses playback briefly
#
# Special keys can be repeated by adding a number inside the curly braces, for
# example: {Down 5}
#
# Some shorthand:
# & expands to {Enter}
# @ expands to +{Enter}
# ^ expands to {ExitMenu}
# % expands to {Wait}

@ -0,0 +1,9 @@
# quickfort materials preference configuration file
#
# Defines forbidden materials and material preferences for build blueprints.
# Settings in this file take precedence over any settings in the baseline
# materials configuration file at hack/data/quickfort/materials-common.txt. See
# that file to view the global defaults.
#
# Syntax TBD

@ -0,0 +1,20 @@
# quickfort main configuration file
#
# Set startup defaults for the quickfort script in this file. Settings can be
# dynamically overridden in the active session with the `quickfort set` command.
# Directory to search for blueprints. Can be set to an absolute or relative
# path. If set to a relative path, resolves to a directory under the DF folder.
blueprints_dir=blueprints
# Set to "true" or "false". If true, will designate dig blueprints in marker
# mode. If false, only cells with dig codes prefixed with ``m`` will be
# designated in marker mode.
force_marker_mode=false
# Allows you to manually select building materials for each
# building/construction when running (or creating orders for) build blueprints.
# Materials in selection dialogs are ordered according to preferences in
# materials.txt. If false, will only prompt for materials that have :labels.
# See https://github.com/joelpt/quickfort#manual-material-selection for details.
force_interactive_build=false

@ -2116,8 +2116,10 @@ unless otherwise noted.
* ``dfhack.filesystem.listdir(path)``
Lists files/directories in a directory. Returns ``{}`` if ``path`` does not exist.
Set include_prefix to false if you don't want the ``path`` string prepended to the
returned filenames.
* ``dfhack.filesystem.listdir_recursive(path [, depth = 10])``
* ``dfhack.filesystem.listdir_recursive(path [, depth = 10[, include_prefix = true]])``
Lists all files/directories in a directory and its subdirectories. All directories
are listed before their contents. Returns a table with subtables of the format::

@ -52,6 +52,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## API
- Added ``Filesystem::mkdir_recursive``
- Extended ``Filesystem::listdir_recursive`` to optionally make returned filenames relative to the start directory
## Lua
- Added a ``ref_target`` field to primitive field references, corresponding to the ``ref-target`` XML attribute

@ -1737,18 +1737,35 @@ bool Core::Init()
virtual_identity::Init(this);
// copy over default config files if necessary
std::vector<std::string> config_files;
std::vector<std::string> default_config_files;
if (Filesystem::listdir("dfhack-config", config_files) != 0)
std::map<std::string, bool> config_files;
std::map<std::string, bool> default_config_files;
if (Filesystem::listdir_recursive("dfhack-config", config_files, 10, false) != 0)
con.printerr("Failed to list directory: dfhack-config");
else if (Filesystem::listdir("dfhack-config/default", default_config_files) != 0)
else if (Filesystem::listdir_recursive("dfhack-config/default", default_config_files, 10, false) != 0)
con.printerr("Failed to list directory: dfhack-config/default");
else
{
// ensure all config file directories exist before we start copying files
for (auto it = default_config_files.begin(); it != default_config_files.end(); ++it)
{
std::string filename = *it;
if (std::find(config_files.begin(), config_files.end(), filename) == config_files.end())
// skip over files
if (!it->second)
continue;
std::string dirname = "dfhack-config/" + it->first;
if (!Filesystem::mkdir_recursive(dirname))
{
con.printerr("Failed to create config directory: '%s'\n", dirname.c_str());
}
}
// copy files from the default tree that don't already exist in the config tree
for (auto it = default_config_files.begin(); it != default_config_files.end(); ++it)
{
// skip over directories
if (it->second)
continue;
std::string filename = it->first;
if (config_files.find(filename) == config_files.end())
{
std::string src_file = std::string("dfhack-config/default/") + filename;
if (!Filesystem::isfile(src_file))

@ -2406,8 +2406,11 @@ static int filesystem_listdir_recursive(lua_State *L)
int depth = 10;
if (lua_type(L, 2) == LUA_TNUMBER)
depth = lua_tounsigned(L, 2);
bool include_prefix = true;
if (lua_type(L, 3) == LUA_TBOOLEAN)
include_prefix = lua_toboolean(L, 3);
std::map<std::string, bool> files;
int err = DFHack::Filesystem::listdir_recursive(dir, files, depth);
int err = DFHack::Filesystem::listdir_recursive(dir, files, depth, include_prefix);
if (err)
{
lua_pushnil(L);

@ -149,6 +149,7 @@ namespace DFHack {
DFHACK_EXPORT bool chdir (std::string path);
DFHACK_EXPORT std::string getcwd ();
DFHACK_EXPORT bool mkdir (std::string path);
// returns true on success or if directory already exists
DFHACK_EXPORT bool mkdir_recursive (std::string path);
DFHACK_EXPORT bool rmdir (std::string path);
DFHACK_EXPORT bool stat (std::string path, STAT_STRUCT &info);
@ -160,7 +161,9 @@ namespace DFHack {
DFHACK_EXPORT int64_t ctime (std::string path);
DFHACK_EXPORT int64_t mtime (std::string path);
DFHACK_EXPORT int listdir (std::string dir, std::vector<std::string> &files);
// set include_prefix to false to prevent dir from being prepended to
// paths returned in files
DFHACK_EXPORT int listdir_recursive (std::string dir, std::map<std::string, bool> &files,
int depth = 10, std::string prefix = "");
int depth = 10, bool include_prefix = true);
}
}

@ -205,34 +205,46 @@ int Filesystem::listdir (std::string dir, std::vector<std::string> &files)
return 0;
}
int Filesystem::listdir_recursive (std::string dir, std::map<std::string, bool> &files,
int depth /* = 10 */, std::string prefix /* = "" */)
// prefix is the top-level dir where we started recursing
// path is the relative path under the prefix; must be empty or end in a '/'
// files is the output list of files and directories (bool == true for dir)
// depth is the remaining dir depth to recurse into. function returns -1 if
// we haven't finished recursing when we run out of depth.
// include_prefix controls whether the directory where we started recursing is
// included in the filenames returned in files.
static int listdir_recursive_impl (std::string prefix, std::string path,
std::map<std::string, bool> &files, int depth, bool include_prefix)
{
int err;
if (depth < 0)
return -1;
if (prefix == "")
prefix = dir;
std::vector<std::string> tmp;
err = listdir(dir, tmp);
std::string prefixed_path = prefix + "/" + path;
std::vector<std::string> curdir_files;
int err = Filesystem::listdir(prefixed_path, curdir_files);
if (err)
return err;
for (auto file = tmp.begin(); file != tmp.end(); ++file)
for (auto file = curdir_files.begin(); file != curdir_files.end(); ++file)
{
if (*file == "." || *file == "..")
continue;
std::string rel_path = prefix + "/" + *file;
if (isdir(rel_path))
std::string prefixed_file = prefixed_path + *file;
std::string path_file = path + *file;
if (Filesystem::isdir(prefixed_file))
{
files.insert(std::pair<std::string, bool>(rel_path, true));
err = listdir_recursive(dir + "/" + *file, files, depth - 1, rel_path);
files.insert(std::pair<std::string, bool>(include_prefix ? prefixed_file : path_file, true));
err = listdir_recursive_impl(prefix, path_file + "/", files, depth - 1, include_prefix);
if (err)
return err;
}
else
{
files.insert(std::pair<std::string, bool>(rel_path, false));
files.insert(std::pair<std::string, bool>(include_prefix ? prefixed_file : path_file, false));
}
}
return 0;
}
int Filesystem::listdir_recursive (std::string dir, std::map<std::string, bool> &files,
int depth /* = 10 */, bool include_prefix /* = true */)
{
return listdir_recursive_impl(dir, "", files, depth, include_prefix);
}