Go to menu

Customising Dwarf Fortress on Nix

2024-09-27

A few days back I wanted to play Dwarf Fortress, and I was happy to find that NixOS didn’t just package Dwarf Fortress, but that it included a whole framework for building the game, with DFHack, TWBT and various themes. The recommended setup is pretty easy and installs the game, the above-mentioned mods, and some extra utilities:

dwarf-fortress-packages.dwarf-fortress-full.override {
  dfVersion = "0.47.05";
  theme = "cla";
  enableIntro = false;
  enableFPS = true;
}

I, however, wanted more customization. I wanted a different font than the one that came with the theme, to tweak some game settings, and to fix theme installation (the contents of twbt_art should be copied directly to art, the stock package copies the folder directly).

This proved easy enough, but definitely non-intuitive. Here’s a simple skeleton:

dwarf-fortress-packages.dwarf-fortress_0_47_05.override {
  enableDFHack = true;
  extraPackages = [ font-cooz-curses ];
  settings = {
    d_init.AUTOSAVE = "SEASONAL";
    d_init.AUTOBACKUP = true;
  };
}

The dwarf-fortress_0_47_05 derivation is actually made by wrapper/default.nix, which lists its arguments at the start. Most are intuitive, settings modifies keys in *.txt files in the init directory and extraPackages lists packages whose contents will be copied into the game directory.

Please note that the raw directory (which themes (“graphics sets” in DF parlance) generally change) is copied into each savegame. When you change themes you need to make those changes there too. This might break the save though, so beware, and make backups!

Here’s my own configuration, which installs the Mayday theme and a different font (tileset):

let
  themeInstallScript = ''
    mkdir -p $out/data/art $out/data/init $out/raw/graphics $out/raw/objects
    cp data/art/* $out/data/art/
    cp data/twbt_art/* $out/data/art/
    cp data/init/* $out/data/init/
    cp data/twbt_init/* $out/data/init/
    cp -r raw/graphics/* $out/raw/graphics/
    cp -r raw/twbt_graphics/* $out/raw/graphics/
    cp -r raw/objects/* $out/raw/objects/
    cp -r raw/twbt_objects/* $out/raw/objects/
    cp raw/*.init $out/raw/
  '';
  theme-mayday = stdenv.mkDerivation {
    name = "dwarf-fortress-mayday-theme";
    src = fetchFromGitHub {
      owner = "DFgraphics";
      repo = "Mayday";
      rev = "caa936fac3bc02b35e754b18cc41eca7360da853";
      hash = "sha256-JN4aF4YPv4iudBPy6k6SVwHJIgUWIvMvex/UshU6Yj8=";
    };
    installPhase = themeInstallScript;
  };
  font-cooz-curses = stdenv.mkDerivation rec {
    name = "dwarf-fortress-font-cooz-curses";
    src = fetchurl {
      url = "https://dwarffortresswiki.org/images/2/2c/Cooz_curses_14x16.png";
      hash = "sha256-WXXfcph6dl+j15hADvuGKWNs6ITLmD6SbdHtu4p7fQg=";
    };
    unpackPhase = ":"; # Don't try to unpack the png
    installPhase = ''
      mkdir -p $out/data/art
      cp ${src} $out/data/art/Cooz_curses_14x16.png
    '';
  };
in
dwarf-fortress-packages.dwarf-fortress_0_47_05.override {
  enableDFHack = true;
  enableTWBT = true;
  enableSoundSense = true;
  enableStoneSense = true;
  enableIntro = false;
  enableTruetype = true;
  enableFPS = true;
  enableSound = false;
  theme = theme-mayday;
  extraPackages = [ font-cooz-curses ];
  settings = {
    d_init.AUTOSAVE = "SEASONAL";
    d_init.AUTOBACKUP = true;
    d_init.AUTOSAVE_PAUSE = true;

    init.FONT = "Cooz_curses_14x16.png";
    init.FULLFONT = "Cooz_curses_14x16.png";
  };
}

In the end I feel that Dwarf Fortress repeats a common scenario in Nix(OS): The initial setup is easy. Figuring out how to customise beyond the provided options is suddenly harder, but you end up with a much more robust install than if you’d done it manually.