PWMAngband and Tangaria are not just a great games in its own right, they are 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.
The data files
This file contains game values such as carried item capacity, visual range and dungeon level and town dimensions.
This file contains the names and common properties of the basic object classes – scroll, sword, ring, and so on. All objects have an object base. Each object base is assigned a ‘tval’ – a numeric index. The tvals are defined in list-tvals.h. While adding new object bases is possible, it is unlikely to do much without deeper changes to the game.
This file contains the names, properties and description of all the object types that appear in PWMAngband. New object kinds can easily be added to this file, or existing ones edited. Each object defined by this file has an object base, and is also allocated another numeric index called an ‘sval’. A tval-sval pair completely identifies an object – since the tval and sval are saved to savefiles, removing or adding objects is likely to render existing save files unusable.
This file contains the names, properties and description of ego items, which are magically enhanced weapons and armour. New ego items can be added or removed at will, although removing or changing one with an instance currently in the game might cause problems.
This file contains the names, properties and description of artifacts, which are unique items – only one of each will ever be generated. If you are considering major changes, new artifacts are one of the most visible signs of a change of theme. Regardless, new artifacts are easy and fun to design.
This file contains lists of words which are used to generate names for random character names, random artifacts and scrolls. Again, in the case of a change of theme, this is a good way of displaying the new theme.
Activations are used for artifacts and some regular objects, and could be used for ego items (see Cloaks of Lordly Resistance). Some standard artifacts from artifact.txt have activations, and random artifacts may have any activation from this file chosen for them. Activations can be made up of any effects (see effects.c and list-effects.h).
Items such as potions and wands are assigned a flavor per object kind, different in each game. There need to be at least as many flavors for each flavored object base as objects with that base.
Monster bases are the monster equivalent of object bases – classes of monster like orc, troll or vampire. This file contains the properties common across all monsters in each of these classes.
This contains the detail of all monster races, each of which will have its monster base properties plus additional ones. Some monsters are unique, and once killed will never reappear.
All the spells that can be cast by monsters (and are referred to in the ‘spells:’ lines in monster.txt) are defined in this file. As with activations, monster spells are built up from effects.
This file contains the various messages that are given to describe how a monster responds to attack.
Dungeon levels can contain pits – rooms full of a particular selection of monsters. This file defines these selections. They can also be used, for example, to generate partial or complete dungeon levels with themed monsters.
This file completely defines how player classes work, including all details of castable spells. There are some class-specific properties hard-coded, which are referred to via the ‘flags:’ lines, and appear in list-player-flags.h.
This file defines all player race characteristics. Race-specific code is handled as for classes.
Every player race has a body, which defines what equipment they can use. Currently there is only one body, which all races use, but this is easily changeable for significant effect.
This file is for creating the player background found on the character screen. If a new race is introduced, a selection of background information for it will need to be added.
This is simply a list of general pieces of advice that shopkeepers will give to their customers.
This file defines the quest monsters (Sauron and Morgoth) and where they appear. This currently can’t easily be changed, as there are still hard-coded aspects of the quests.
This file defines the kind of terrain which can appear in PWMAngband, and its properties. Current terrain can be changed (with possibly large effects), but removing it without code changes is likely to break the game. Adding new terrain will have no effect by itself, because there is no mechanism for it to appear.
This defines all traps, door locks and runes. Actual trap effects appear in effects.c and list-effects.h.
This is a list of templates for interesting-shaped rooms which appear in the dungeon. These can easily be changed and new ones added.
Similar to room_template.txt, this handles vaults, which are very dangerous and lucrative rooms.
This file contains fairly technical details about the different types of dungeon level which can be generated. The actual generation routines are in gen-cave.c; the information here consists of parameters for generating individual levels, and for how often given level types appear.
This details the shop owners and their relative generosity.
This defines effects to the player caused by monster attacks. The simplest monster attacks just deal damage, but others can affect the player’s status, stats or inventory.
This details the different ways monsters can attack (hit, claw, etc.). It affects the messages the player gets, and also whether the blow can stun or cut the player.
This details how weapon brands work.
This details how weapons can be more effective against certain monsters.
This file contains all the different curses that can be applied to objects. It includes what type of object they can be applied to, random effects they can cause, and how they change an object’s properties.
This file gives details about what properties an object can have (apart from basic combat and armor class). Every property has a code which is used in the game to refer to that property in some way. This means it is not possible to add new properties to this file and expect to have any effect, but it is possible to change how existing properties work.
This file contains formulas for calculating power of objects (used in determining prices and generating random artifacts). You should only change this file if you understand the way they are used (defined in obj-power.c).
This file defines some of the properties of timed effects (such as haste and confusion) that can apply to the player. It chiefly contains the messages on changes in these effects, and player attributes which prevent the effects. To add new timed effects or change the way existing ones operate, you will have to alter list-player-timed.h and probably other files, and re-compile the game.
This file contains a lot of the defining information about projections – effects which can be produced at a distance by player or monsters, and affecting player, monsters, objects, and/or terrain. In particular, this file defines details of the effects of elemental attacks (such as fire or shards) and the effectiveness of corresponding player resistance. New projections have to be included in list-projections.h, and the code to implement their effects put in other source files – project-obj.c for effects on objects, and other similarly-named files.
This contains a small amount of information about the current magic realms.
This contains definitions for the types of monsters that can be summoned. Adding a new summon type is not yet possible, because the summon spells are hard-coded in list-mon-spells.h
This file contains the list of dungeons.
This file contains the list of simple role-playing messages.
This file contains the list of towns and their coordinates on the metamap.
This file contains the layout for the town of Bree.
This file contains the layout for the town of Gondolin.
This file contains the layout for the town of Lothlorien.
This file contains the layout for the town of Minas Anor.
This file contains the layout for the town of Umbar.
This file contains the symbols used to describe the layout for the above towns.
This file contains the list of available terrain types in the wilderness. Order must match entries in list-wild-feats.h.
This file contains the layout for the metamap.
This file contains information about dragon breeds.
Making Graphical Tilesets
You can make new graphical tilesets for PWMAngband 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/foo)
- Register the tileset in lib/tiles/list.txt
- Create an empty bitmap image large enough to hold your tileset
- Store the empty bitmap image in your tileset folder
- Author one or more .prf files to inform Angband how to use your tileset
- Create 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, Shockbolt’s tileset uses 64×64 pixel tiles. It also uses the special alpha blending flag so it can use double-height tiles (64×128) for large or tall monsters. Its dimensions are 8192×2048 but the tileset is not completely full. More tiles can be added without increasing the size of the image as new objects are added to future releases of PWMAngband. This should be kept in mind as packing your tileset into the smallest possible image size may not be the most maintainable solution. Be sure to name the image file after the tile size, for example 64×64.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. 64×64), 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 PWMAngband how to interpret your tileset image. You need to map each tile in your image to a specific element in the game so that PWMAngband knows which tiles to show for which ASCII characters. This process can be done incrementally because PWMAngband 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.
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:
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):
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 64×64 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:closed door:quartz vein: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:
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. Shockbolt’s tiles make great use of this and define a well organized set of mappings using three files with comments for each logical section of objects to be mapped:
# This is a comment %:other-stuff.prf # Load another preference file
Once you have a working tileset and functional understanding of how tilesets are managed and organized, it would be a good idea to study Shockbolt’s tileset and follow the examples there in order to produce a high-quality tileset that you will be proud to share with others.
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:
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. Should you get to this point, the best thing to do is to discuss your ideas on the Angband forums at http://angband.oook.cz. The people there are typically keen to hear new ideas and ways to play.