Modifying ZangbandTK#
ZangbandTK, like the Angband it is built on, is really easy to modify. Much of the detail of the game is contained in text data files. These can be changed using nothing more than a text editor for an immediate change to how the game works.
These data files are in lib/gamedata.
Each file has a header which describes the lines which make up entries of the file, and for the most part this will make it clear what needs to be done to make changes to the files. Below is brief description of each of the files.
Those who want to change the game more than is allowed just by varying the data files will need the source code. Below the data file descriptions is a brief discussion of where to start on such an endeavour.
ZangbandTK’s own data files#
Everything above is Angband’s. These are this game’s, and they are where its character lives.
The imported content is in files named *.zangband.txt, kept apart from
Angband’s so that the provenance of any given monster or object is obvious from
the file it is in. They are generated by tools/zconv and must not be
hand-edited: a change made in one is lost the next time the converter runs.
Hand-tuned values belong in tools/zconv/overrides.toml.
- monster.zangband.txt, object.zangband.txt, artifact.zangband.txt, ego_item.zangband.txt
The imported bestiary and treasure – 387 monsters, 86 object kinds, 51 artifacts and 16 ego types. Same formats as the Angband files they sit beside.
- flavor.zangband.txt
Ring and amulet flavours that 4.2 does not have. The imported kinds need them: 4.2 assigns one flavour per kind and quits if it runs out.
- monster.zangbandtk.txt
Monsters that are neither Angband’s nor Zangband’s but this game’s own. Hand-edited, unlike the two files it sits between.
- dungeon.txt
The dungeons of the world: the range of depths each covers, what lives in it, what treasure it favours, what its floors are made of, and what country its entrance is found in. This is what replaces “the dungeon” as a single place; see Exploring the Dungeon.
- town.txt
The names the world’s towns are drawn from, by size band. Curated rather than generated, because a name generator here would generate the wrong setting.
- quality.txt
The quality ladder a shop is drawn from – a plain Weapon Smiths against an Advanced, Expert or Arcane one. The tiers live here once and apply to any trade; which tier a town’s shop gets is scored from the country around it.
- mutation.txt
The ninety-six mutations: what each does, what it costs to use if it is activatable, and what it cannot coexist with. Generated by
tools/zconv. See Mutations.- patron.txt
The nine Lords of the Courts of Chaos a Chaos-Warrior can be sworn to, and the rewards and punishments each hands out. Two kinds of record:
reward:defines what a favour or a punishment does, andpatron:names a Lord and lists twenty rewards worst-first. See Creating a Character.- monster_speech.txt
What a monster with the
CAN_SPEAKflag says – in a fight, when afraid, and when it dies.- rename.txt
Things this game used to call something else. A savefile records what it holds by name, so a rename would silently cost a character the item; this file is consulted when a lookup fails and makes the rename free instead. Add an entry whenever you rename or remove an object, monster, artifact or ego type.
Making Graphical Tilesets#
You can make new graphical tilesets for Angband or customize existing ones. In this section we’ll dive into how tilesets are defined and describe how to set one up from scratch. First, we’ll enumerate the steps required and then we’ll break down each step in detail.
Create a directory to contain the tileset’s files: (ex.
lib/tiles/mytileset)Register the tileset in
lib/tiles/list.txtCreate an empty bitmap image large enough to hold your tileset
Store the empty bitmap image in your tileset folder
Author one or more
.prffiles to inform Angband how to use your tilesetCreate a Makefile in your tileset folder
First you need to create a directory to contain your tileset’s files. Put the directory in lib/tiles and choose a name for the directory that is lower-case and generally matches the naming convention of the other tilesets you see there. Once the directory has been created, the next step is to decide how big the tiles will be in pixels and then create a blank PNG image large enough to hold all of the tiles (be sure to enable alpha transparency). As an example, David Gervais’ tileset uses 32x32 pixel tiles and its dimensions are 4096x960, but the tileset is not completely full – roughly two thirds of its cells are unmapped, and a good many of those hold art nobody has wired up. More tiles can be added without increasing the size of the image as new objects are added, so packing your tileset into the smallest possible image size may not be the most maintainable solution.
The extra line also carries an alpha-blending flag that allows double-height
tiles for large or tall monsters. No tileset shipped with this game uses it –
the one that did, Shockbolt’s, is not distributed here (see Copying and licence information) –
but the support is intact and a new tileset may ask for it. Be sure to name the image file after the tile size, for
example 64x64.png. Use the base size even if you are enabling double-height
tiles.
The only file you’ll need to edit outside of your tileset’s directory is lib/tiles/list.txt. list.txt contains a registry of which tilesets to load as well as some information about the size of the tiles and any special flags to set. The format of the file is documented in list.txt’s header. Specifically, you will be defining the name of the tileset, which directory contains the tileset’s files, how big the tiles are in pixels (i.e. 64x64), the name of the main preference file for the tileset and some additional flags which have to do with alpha blending. Not all tilesets need to set extra flags.
Now that the basic setup is complete you need to tell Angband how to interpret your tileset image. You need to map each tile in your image to a specific element in the game so that Angband knows which tiles to show for which ASCII characters. This process can be done incrementally because Angband will continue to show the default character symbols in-game for objects that have not yet been mapped. This is especially helpful for verifying that your tileset has been setup correctly before beginning to map things out in earnest. It also means that if new objects are added to the game that you have not mapped into your tileset, the game will still be playable with your tileset, albeit the displayed ASCII character may appear incongruous with your styling. Mapping tiles to game elements is done in text files called preference files which have the extension ‘.prf’.
The first thing to understand about mapping game elements in preference files is that everything that can be displayed in the game has a name, or in the case of flavors, an ID number. The names for each type of thing can be referenced from the data files as mentioned above. The table below is a quick reference for where to find names of things and how to form IDs correctly to reference them.
Type |
Data File |
Example |
|---|---|---|
Terrain |
terrain.txt |
|
Trap |
trap.txt |
|
Object |
object.txt |
|
Monster |
monster.txt |
|
Spell Effect |
monster_spell.txt |
|
Player |
<see below> |
|
Player pictures are referenced differently than other types of objects. They use a special query syntax that checks to see what kind class the player is as well as the gender in order to determine which picture to show. The query to select which tile to show for a female elf ranger would be:
?:[AND [EQU $CLASS Ranger] [EQU $RACE Elf] [EQU $GENDER Female] ]
Here, the query is checking to see if the player is a female Half-Elf and would use the assignment on the next line of the preference file only if this is true.
Some types of objects such as terrain can use different tiles based on their state. In the case of terrain, the terrain can have different images for when it is lit by a torch, or dark. these are selected by appending another colon and a specifier to the name. For example, this would be the name of a torch-lit up staircase:
feat:LESS:torch
It is possible to specify the same tile be used for all possible states of a terrain feature by using an asterisk. This example identifies any unknown terrain tile (a tile the player hasn’t lit or otherwise seen yet):
feat:NONE:*
Given the full name of an object the last thing to do is to specify which tile from the tileset to use. Tile locations are given in a coordinate system using pairs of hexadecimal numbers. The coordinates start from 0x80:0x80 and increment from there. The pairs translate directly to the top and left most pixel of the corresponding tile from the graphics file, so the top left pixel of the first tile on the top left of the graphics file would be specified as 0x80:0x80 (the pixel at x:0 y:0). The next tile immediately to the right of the that one would be 0x80:0x81. The tilesheet is sliced into rows and columns based on the tile size you specified in list.txt. So given a tile size of 64x64 pixels, the tile at 0x80:0x81 would be located in the graphics file at pixel x:64 y:0. Remember, the coordinates in the preference files are in hexadecimal, so the next number after 0x89 would be 0x8A. The next number after 0x8F would be 0x90 and so on. To map an object to your tileset you will add one complete line to the file per object. This example maps the tile at 0x81:0x81 to the terrain feature ‘quartz vein’ when the quartz vein is lit by torch light:
feat:QUARTZ:torch:0x81:0x81
Before going any further, it is advisable to map a single object in your preference file, then start the game up, select your tileset and make sure you see your mapped tile in game. If this worked, then you are ready to design and map the rest of your tiles. A quick example would be to map a tile for your home in the town to the first tile position in your graphics file:
feat:HOME:*:0x80:0x80
It’s possible to have more than one preference file by using a sort of include
syntax that causes other preference files referenced from your main preference
file to also be read. It is also possible to place comments in your preference
files to help you keep track of where different kinds of objects are
mapped. Any text on a line after a # symbol is ignored. The shipped tilesets
make great use of this and define a well organized set of mappings using several
files with comments for each logical section of objects to be mapped:
# This is a comment
%:other-stuff.prf # Load another preference file
The last step to take is to make sure your tileset will be packaged with Angband when it is compiled for distribution and that it can be installed alongside the other tilesets. to do this you will need to add a file called ‘Makefile’ to your tileset directory. Copy and paste an existing Makefile from one of the other tileset directories and update the DATA and PACKAGE lines to match the filenames you chose for your tileset.
Once you have a working tileset and functional understanding of how tilesets are managed and organized, it would be a good idea to study David Gervais’ set – the largest one shipped here – and follow the examples there in order to produce a high-quality tileset that you will be proud to share with others.
Larger changes#
If changing data files is not enough for you, you will need to change actual game code and recompile it. The first place to look is in the compiled data files, some of which have already been mentioned:
list-dun-profiles.h |
list-mon-temp-flags.h |
list-rooms.h |
list-effects.h |
list-mon-timed.h |
list-room-flags.h |
list-elements.h |
list-object-flags.h |
list-square-flags.h |
list-equip-slots.h |
list-object-modifiers.h |
list-stats.h |
list-history-types.h |
list-options.h |
list-terrain.h |
list-ignore-types.h |
list-origins.h |
list-terrain-flags.h |
list-kind-flags.h |
list-parser-errors.h |
list-trap-flags.h |
list-message.h |
list-player-flags.h |
list-tvals.h |
list-mon-message.h |
list-player-timed.h |
list-ui-entry-renderers.h |
list-mon-race-flags.h |
list-projections.h |
|
list-mon-spells.h |
list-randart-properties.h |
Beyond this, you will have to have some knowledge of the C programming language, and can start making changes to the way the game runs or appears. Many people have done this - there are over 100 variants of Angband: https://nickmcconnell.github.io/AngbandPlus/ Should you get to this point, the best thing to do is to discuss your ideas on the Angband forums at https://angband.live/forums/. The people there are typically keen to hear new ideas and ways to play.