What Can You Develop?
At the moment, you are limited to developing quests, NPCs, and monsters for The Clans. In the future, items, mine events, classes, races, and possibly game strings may be available — but a system must first exist to prevent cheat packs. It would be far too easy to hand out the item creator and have BBSes build up super items.
Quests are what players go on via the G option in the mines. They're event files (scripts) plus optional NPCs and monster files. Modify your QUESTS.INI and sometimes CLANS.INI and you're set.
NPCs are characters encountered on the street or in other locales. They're made up of stats (for joining clans) and quotes (for conversation).
How Does The System Work?
The Clans uses two INI files for add-on modules:
CLANS.INI — the general INI. Lets the sysop add NPCs, races, classes, items, and spells (only NPCs can be developed by 3rd parties). Also allows changing the language file.
QUESTS.INI — tells the game which quests are available and where to find them.
When distributing an add-on, you must provide installation instructions. Currently, lines must be added to the INI files manually. (An add-on installer may be created in a future version.)
CLANS /M), and logging in and out constantly. A slap upside the head is in order if you don't!
Writing Source Files in UTF-8
All devkit source files (event scripts, monster definitions, NPC quotes, spell and item data, etc.) have traditionally been written in CP437 encoding — the IBM PC character set used by BBS terminals. CP437 is the encoding the game uses internally for box-drawing characters, block elements, shading, and accented letters.
If your text editor does not support CP437 (most modern editors default to UTF-8), you can write source files in UTF-8 instead. The devkit compilers automatically detect UTF-8 files and convert them to CP437 at compile time. The compiled output is byte-identical to what a CP437 source file would produce.
How to Use It
Name your source file with .u8. before the final extension:
myquest.u8.evt instead of myquest.evt npcquote.u8.txt instead of npcquote.txt spells.u8.txt instead of spells.txt
Then compile as usual:
ecomp myquest.u8.evt myquest.e makenpc npcquote.u8.txt npcquote.npc mspells spells.u8.txt spells.spl
The compiler detects the .u8. in the filename and converts each line from UTF-8 to CP437. If the filename does not contain .u8., the file is read as raw CP437 with no conversion — fully backward compatible.
Commonly Used CP437 Graphics
In a UTF-8 source file, type the Unicode equivalent of any CP437 character and the compiler will convert it. Here are the most commonly used ones:
| CP437 | Unicode | Description |
|---|---|---|
| 0xB0 | U+2591 | LIGHT SHADE |
| 0xB1 | U+2592 | MEDIUM SHADE |
| 0xB2 | U+2593 | DARK SHADE |
| 0xB3 | U+2502 | BOX DRAWINGS LIGHT VERTICAL |
| 0xC4 | U+2500 | BOX DRAWINGS LIGHT HORIZONTAL |
| 0xC5 | U+253C | BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL |
| 0xCD | U+2550 | BOX DRAWINGS DOUBLE HORIZONTAL |
| 0xDB | U+2588 | FULL BLOCK |
| 0xDC | U+2584 | LOWER HALF BLOCK |
| 0xDD | U+258C | LEFT HALF BLOCK |
| 0xDE | U+2590 | RIGHT HALF BLOCK |
| 0xDF | U+2580 | UPPER HALF BLOCK |
| 0xFE | U+25A0 | BLACK SQUARE |
All 128 CP437 high bytes (0x80–0xFF) and 32 control-character glyphs (0x01–0x1F) are supported — a total of 168 canonical mappings plus 8 alternative Unicode codepoints. For the complete table, see utf8.txt (included with the devkit).
Characters That Are Not Allowed
Certain Unicode characters that look similar to ASCII punctuation are blocked because they would break the game's pipe-code (|NN) and backtick-code (`XY) colour formatting:
| Character | Use instead |
|---|---|
| Smart single quotes | ASCII apostrophe ' |
| Smart double quotes | ASCII quotation mark " |
| Em dash | -- (double hyphen) |
| En dash | - (hyphen) |
These typically appear when text is copied from word processors. The compiler prints an error with the line number and a suggestion.
Any Unicode character that has no CP437 equivalent also produces an error: the compiler prints the codepoint (e.g., U+1F600) along with the filename and line number.
Which Tools Support It
All devkit compilers and the PAK builder support UTF-8 input:
| Tool | Purpose |
|---|---|
ecomp | Event compiler (.evt -> .e/.q) |
langcomp | Language strings (.txt -> .xl) |
mcomp | Monster compiler (.txt -> .mon) |
makenpc | NPC compiler (.txt -> .npc) |
mclass | Class/race compiler (.txt -> .cls) |
mitems | Item compiler (.txt -> .itm) |
mspells | Spell compiler (.txt -> .spl) |
makepak | PAK builder (text files in pak.lst) |
For makepak, list the .u8. filename in pak.lst and leave the alias unchanged:
menus.u8.hlp /n/menus.hlp
makepak converts the UTF-8 content to CP437 before packing, so the PAK contents are identical regardless of whether the source was CP437 or UTF-8.
What Are Event Files?
Event files are simple scripts used to construct "events" encountered through quests and mine events (e.g. meeting the spirit knights). They are small programs run by the game using its own compiled language.
Workflow: write a text script → compile it with ECOMP.EXE → test it in The Clans.
Making Event Files
Example 1 — Getting Started
The simplest event file you'll ever see. Lines beginning with # are comments. Event starts a named block; End stops execution. Text outputs a string to the player's screen.
EVENT1.EVT# Example Event File No.1 Event SimpleEvent Text "Hello World! End
Compile it:
ECOMP EVENT1.EVT EVENT1.E
Register it as a quest in QUESTS.INI:
Name Event1 Test File EVENT1.E Index SimpleEvent Known
Go into the game and run the quest. After running it, you won't be able to run it again until you force maintenance with CLANS /M.
Example 2 — Blocks & Jumps
A file can contain multiple blocks. Event blocks can be started directly as quests. Result blocks are jump targets — they're not started on their own. Use Jump to move between blocks. Multiple quests can share one file — just use different Index values.
EVENT2.EVTEvent FirstEvent Text "This is the 1st event Jump FirstEvent.Result End Result FirstEvent.Result Text "This is a result of the first event! End Event SecondEvent Text "This is the 2nd event! End
End at the end of each block. Without it, execution "falls through" into the next block — which you usually don't want.
The Known keyword in QUESTS.INI makes a quest available without the player needing to be "told" about it by an NPC first.
Example 3 — Getting Options
Prompt is like Text but without a newline at the end. Option captures a single keypress and jumps to a named block. Input captures a full-line response.
EVENT3.EVTEvent Block1 Text "This is example #3! Text Prompt "Press A,B,C, or D > Option A PressA Option B ILikeB Option C C Option D NextLine Text "You pressed D! Jump Block2 End Result PressA Text "You pressed A! Jump Block2 End Result Block2 Text "Now let's chat: Input TFC1 1. This is Option 1 Input TFC2 2. This is Option 2 Input TFC3 3. This is Option 3 End
Option D NextLine — using NextLine as the target causes execution to continue at the line immediately after all the Option keywords.
Example 4 — Fighting
Use AddEnemy to load monsters into the fight buffer, then Fight to trigger combat. DoneQuest marks the quest permanently completed for that player.
EVENT4.EVTEvent FightExample Text "You will now experience a battle! Pause AddEnemy /m/Output 1 AddEnemy /m/Output 1 AddEnemy /m/Output 1 AddEnemy /m/Output 1 Fight YouWin YouLose NextLine Text "aw, you ran away! End Result YouWin Text "Good job, you won! DoneQuest End Result YouLose Text "You suck! How could you lose!? End
Special Fight labels: NextLine continues after the Fight line, STOP halts execution, NoRun prevents the player from fleeing.
# Most common usage pattern: Fight NextLine STOP NoRun
Example 5 — Flags & ACS
Flags are boolean variables (TRUE/FALSE) used to track state across an event. They are tested using {} syntax before any command.
| Flag Type | Description |
|---|---|
| G0–G63 | Global flags — shared by all users, never cleared |
| H0–H63 | Daily global flags — cleared once a day during maintenance |
| D0–D63 | Daily player flags — per-user, cleared each maintenance |
| P0–P63 | Player flags — per-user, never cleared |
| T0–T63 | Temporary flags — cleared each time an event or quote file runs |
EVENT5.EVTEvent FlagExample SetFlag T1 # executed only if T1 is set {T1}Text "T1 was set! # this line will NEVER execute {!T1}Text "T1 was NOT set! SetFlag T3 Jump NextPart End Result NextPart {T3}Text "T3 is set! ClearFlag T1 {!T1}Text "T1 has been cleared. {!T1 & T3}Text "T3 was set but T1 was not. # these three sometimes appear and sometimes don't {R50}Text "Random display 1 # ^ = always TRUE, % = always FALSE {^}Text "This should ALWAYS be seen {%}Text "This should NEVER be seen End
ACS expressions support & (AND), | (OR), ! (NOT), and grouping with ( ):
# true if G12 AND T2 are set, OR if H9 is set AND D1 is NOT set:
{ (G12 & T2) | (H9 & !D1) }
Additional ACS conditions:
| ACS | Meaning |
|---|---|
| $xxx | True if player has xxx gold or more in pocket |
| Qaa | True if player has completed quest #aa |
| ^ | Always true |
| % | Always false |
| Ryy | True if roll of 1–100 is ≥ yy (e.g. R50 = 50% chance) |
| Lyy | True if player is exactly at mine level yy |
| Kyy | True if player is at mine level yy or higher |
| Cyy | True if the clan leader's Charisma is yy or higher |
Event File Command Reference
| Command | Description |
|---|---|
| Event <name> | Start an event block. Can be referenced as a quest Index. |
| Result <name> | Start a result block. Used as a jump target; not started directly as a quest. |
| End | Stop execution of the current script. Always place at the end of each block. |
| Jump <label> | Jump to another Event or Result block. |
| Text "<string> | Display text to the player followed by a newline. Text alone outputs a blank line. |
| Prompt "<string> | Display text without a trailing newline (for prompts). |
| Pause | Display <pause> and wait for any keypress. |
| Option <key> <label> | Accept a single keypress. Groups of Options are scanned together. Use NextLine as label to continue after the Option group, or STOP to halt. |
| Input <label> <text> | Present a menu line and jump to label when selected. |
| AddEnemy <file> <index> | Add monster #index from a monster file to the fight queue. Monsters are 0-indexed. |
| Fight <Win> <Lose> <Run> | Trigger combat with queued enemies. Labels: block name, NextLine, STOP, or NoRun for Run. |
| Chat <NPCIndex> | Initiate a chat with the NPC matching NPCIndex. |
| TellQuest <index> | Inform the player about quest #index, making it accessible in their quest menu. |
| DoneQuest | Mark the quest as permanently completed for this player. They cannot replay it. |
| AddNews "<string> | Add a string to the news file. |
| Display "<filename> | Display an ANSI or ASCII file. |
| SetFlag @X | Set flag @X (e.g. SetFlag T5, SetFlag G60). |
| ClearFlag @X | Clear flag @X (e.g. ClearFlag P13). |
| Heal [SP] | Heal all living clan members. Heal restores HP; Heal SP restores skill points. |
| TakeGold <amount> | Remove gold from player's pocket. Does NOT check for negatives — use {$xxx} first. |
| GiveGold <amount> | Give the player gold. Recommended range: 300–1000. |
| GiveXP <amount> | Give XP to all living clan members. Recommended range: 1–10. |
| GiveItem <name> | Give an item to the clan. See Item Index for valid names. |
| GiveFight X | Give X additional monster fights to the clan. |
| GiveFollowers X | Give X additional followers to the clan. |
| GivePoints X | Give X points to the clan. Do not give more than 75 at a time. |
.E extension. Inside PAKfiles, they're stored under a /e/ path. Quote files use .Q or /q/ in PAKfiles.
Multi-line Comments
Use >> delimiters for block comments spanning multiple lines:
>> Everything in here is a comment. Can span many lines. >>
Monsters
Monsters are the creatures players fight in combat. They're created from a text file and compiled using MCOMP.EXE.
Making Monsters
Create a text file (e.g. MONSTERS.TXT or MYMON.TXT) and compile it:
MCOMP MONSTERS.TXT OUTPUT.MON MCOMP MYMON.TXT MYMON.MON
See the included MONSTERS.TXT for a full example. The output file extension is just a convention — it can be any valid filename.
Monster Field Reference
| Field | Description |
|---|---|
| Name | Monster name, max 19 characters |
| HP | Hit points |
| SP | Skill points |
| Difficulty | Monster level (1 = lowest) |
| Agility | Agility stat |
| Dexterity | Dexterity stat |
| Strength | Strength stat |
| Wisdom | Wisdom stat |
| ArmorStr | Armor strength |
| Spell | Spell known by monster (numeric index). Multiple Spell lines are allowed. See Spell Index for values. |
NPCs
NPCs are characters encountered by pressing / in game menus, in random mine encounters, and in quests. Players can chat with them and sometimes recruit them to join their clan.
Making NPCs
Create a text file similar to NPCS.TXT and compile it using MakeNPC:
MakeNPC infile.txt outfile.npc
Add the NPC file to the game in CLANS.INI:
NpcFile MYNPCS.NPC
If using a PAKfile:
NpcFile @MYPAK.PAK/npc/Mine
CLANS.NPC — that's already used. Choose a unique name.
Example NPC — The Knight
Every NPC block starts with the Index line — a unique tagword used to reference the NPC in event files (via Chat <index>). It MUST come first and MUST be globally unique.
_Knight1). Another option is your initials (AUKnight). Without a convention, two add-ons with the same index name will conflict.
After Index, the order of remaining fields doesn't matter. Key fields:
- — QuoteFile: the compiled quote file for this NPC's dialogue
- — NPCDAT: which monster index in the MonFile holds the NPC's stats (0 = first)
- — MonFile: the .MON file containing the NPC's stats
- — Loyalty: 0–10. Higher = less likely to reveal clan info. 10 = never, 0 = always
- — Topic: an unknown topic revealed via TellTopic in a quote file
- — KnownTopic: a topic the player can chat about from the start
- — IntroTopic: the first topic shown when the player starts chatting
Quote Files
Quote files (QFs) are compiled exactly like event files using ECOMP.EXE, but use the keyword Topic instead of Event or Result. Each topic corresponds to a topic listed in the NPC's data file.
Three extra commands are available in QFs:
| Command | Description |
|---|---|
| TellTopic <name> | Reveal a previously unknown topic to the player so they can select it in future chats. |
| EndChat | End the conversation and return the player to the chatting menu. |
| JoinClan | The NPC joins the player's clan using NPCDAT/MonFile stats. Declines if already in a clan. |
Using Monster Files for NPC Stats
Create a file similar to NPC-MON.TXT and compile it with MCOMP.EXE as you would a normal monster file. Reference it using the MonFile keyword and the specific monster within it using NPCDAT.
MCOMP NPC-MON.TXT NPC.MON
NPC Field Reference
Index MUST always come first. All other fields can appear in any order.| Field | Description |
|---|---|
| Index | Unique tagword, one word, max 19 chars. Used with the Chat command. MUST be unique across all add-ons. |
| Name | Display name, max 19 chars |
| QuoteFile | Compiled quote filename, max 12 chars (e.g. NPCQUOTE.Q) |
| MonFile | The .MON file holding this NPC's stats. Do NOT use NPC.MON — that's taken. Use your own (e.g. JOE.MON). |
| NPCDat | Index of the monster in MonFile to use for stats. 0 = first monster. |
| Loyalty | 0–10. How loyal the NPC is to their current clan when asked about it. 10 = never discloses. |
| OddsOfSeeing | 0–100. Chance (%) the NPC appears in their wander location each day. |
| Wander | Where the NPC can be found. Valid values: Street, Church, Market, Town Hall, Training Hall, Mine |
| IntroTopic | Name of the Topic shown first when a player starts chatting. |
| Topic [name] [display] | Add an unknown topic. Must be revealed via TellTopic. |
| KnownTopic [name] [display] | Add a topic already known to the player. |
| MaxTopics N | Optional. Maximum number of topics a user can chat about. |
| HereNews [string] | Optional. Adds a news entry when this NPC appears in the village that day. |
Installing Add-On NPCs
Tell the sysop to add one line to CLANS.INI:
NpcFile MYNPCS.NPC
# Or if using a PAKfile:
NpcFile @MYPAK.PAK/npc/Mine
Installing Add-On Quests
Ask the sysop to add entries like these to QUESTS.INI:
Name Bathtub o' Blood
File BLOOD.E
Index Blood
Known
# Or with a PAKfile:
Name Bathtub o' Blood
File @BOB.PAK/e/Bob
Index Blood
Known
To avoid the "Help not found!" message, also provide a quest description block for the sysop to append to QUESTS.HLP. Format:
^Bathtub o' Blood |12Bathtub o' Blood |06---------------- |04Go on a rampage killing everything in sight. |12Difficulty: Hard and BLOODY! ^END
The first line (with ^) must exactly match the Name in QUESTS.INI. All text between that line and ^END is displayed to the player.
Testing Quest Packs with qtest
qtest is a standalone debugger for quest packs and NPC scripts. It runs all your quest event scripts and NPC chat files in a safe, sandboxed environment: no game data is read from or written to disk, all changes live only in memory for the duration of the session, and you can manipulate every flag and resource freely to drive your scripts into any state you want.
Use qtest whenever you are developing a new quest pack or making changes to an existing one. It lets you walk through every branch of your event scripts and NPC dialogues without touching a live game installation.
Running qtest
qtest resolves all file paths relative to the directory it is run from. To test a pack without touching your live game directory, create a subdirectory inside the game directory, copy the required files into it, and run qtest from there:
mkdir mypack-test cd mypack-test ../qtest
The following files must be present in the test subdirectory:
| File | Description |
|---|---|
clans.pak | Base game data. Required for language strings and for AddEnemy commands referencing standard monsters. Copy or symlink from the game directory. |
clans.ini | Your pack's version, listing NpcFile entries pointing to your compiled NPC files. |
quests.ini | Your pack's quest registry. |
mypak.pak | Your pack's compiled PAK file. If not using a PAK, place individual compiled files (.npc, .evt, .q, .mon) here instead. |
quests.hlp is optional. When present, the D) action in the Quest Runner lets you read a quest's description without running it.
qtest starts with a simulated clan called "DebugClan" with four level-1 members, 5000 gold, and mine level 1. All quests marked Known in quests.ini are automatically known for the debug clan.
The Main Screen
From the main screen you can choose:
| Option | Description |
|---|---|
| F) Edit Flags | Open the flag editor to set/clear any flag group |
| G) Edit Gold / Mine Level | Change the debug clan's gold and mine level |
| N) Chat with NPCs | Open the full chat interface for any registered NPC |
| Q) Run Quests | Browse and run quest event scripts |
| X) Exit | Quit qtest |
Testing Workflow
mkdir mypack-test cd mypack-test cp ../clans.pak . # or: ln -s ../clans.pak . cp /path/to/mypak.pak . cp /path/to/clans.ini . cp /path/to/quests.ini . ../qtest
Script Mode
qtest also supports a non-interactive script mode (-s) for automated regression testing. In script mode, every prompt the event engine raises (choices, fight outcomes, NPC topics, numeric and string inputs) is answered by a line in a plain text script file rather than by keyboard input. After the event or chat completes, qtest prints a full Key=Value state summary to stderr so you can assert exact flag, gold, and HP values from a shell test.
Script mode is the recommended approach for building a repeatable test suite around a quest pack. Full documentation is in qtest-scripting.txt (included with the devkit).
Tool Overview
The devkit includes several command-line tools for compiling data files. Here's a quick reference — see the section on genall.bat below for how they all fit together.
genall.bat — Building Everything
The included genall.bat shows how all tools are used together to regenerate all the game's data files from source. Useful as a starting template for your own build script.
GENALL.BATlangcomp strings.txt > TMP.FIL
mcomp eventmon.txt event.mon >> TMP.FIL
mcomp monsters.txt output.mon >> TMP.FIL
mspells spells.txt spells.dat >> TMP.FIL
mitems items.txt items.dat >> TMP.FIL
mclass classes.txt classes.cls >> TMP.FIL
mclass races.txt races.cls >> TMP.FIL
makenpc npcs.txt clans.npc >> TMP.FIL
ecomp pray.evt pray.e >> TMP.FIL
ecomp eva.txt eva.e >> TMP.FIL
ecomp quests.evt quests.e >> TMP.FIL
ecomp church.evt church.e >> TMP.FIL
ecomp secret.evt secret.e >> TMP.FIL
makepak clans.pak pak.lst >> TMP.FIL
MAKEPAK.EXE and PAKfiles
PAKfiles bundle multiple files into one archive to reduce clutter when distributing an add-on. The game reads from PAK archives transparently.
Creating a PAK File
-
Step 1. Create a file listing (e.g.
PAK.LST) with two columns: the real filename on the left, the PAKfile internal name on the right. PAKfile names MUST begin with/and cannot exceed 29 characters.PAK.LSTmenus.hlp /hlp/menus combat.hlp /hlp/combat items.dat /dat/items spells.dat /dat/spells strings.xl /dat/Language dumbfile.txt /dumbstuff/dumbfile.text important.doc /This.Is.Important -
Step 2. Run MAKEPAK:
MAKEPAK AI.PAK PAK.LST
Accessing PAK Files
Files inside PAKs are accessed using the @ prefix and PAK filename:
# Access /Event.E in ADDON.PAK: @ADDON.PAK/Event.E # Access /Event.E in CLANS.PAK (explicit): @CLANS.PAK/Event.E # Access /Event.E in CLANS.PAK (shorthand -- omitting @ uses CLANS.PAK by default): /Event.E
@YOURPAK.PAK/filename form when accessing files in your own PAK. If you omit the @YOURPAK.PAK prefix, the game searches CLANS.PAK instead and won't find your file.
Example — if you PAK an ANSI into DRAGON.PAK as /ans/Welcome:
# CORRECT: Display "@DRAGON.PAK/ans/Welcome # WRONG -- searches CLANS.PAK, not DRAGON.PAK: Display "/ans/Welcome
CHEW.EXE and INSTALL.EXE
For distributing add-ons, you can use the included installation system. Since every Clans installation already has INSTALL.EXE, you don't need to include it in your archive.
Creating a .GUM Archive with CHEW
A .GUM file is a compressed archive (similar to ZIP or ARJ). Create a file list called FILES.LST (one filename per line), then run CHEW:
FILES.LSTMYQUEST.TXT
MYQUEST.PAK
SYSOP.DOC
CHEW MYQUEST.GUM
If no GUM filename is given, ARCHIVE.GUM is created by default. Compression uses the sixpack algorithm by Philip G. Gage.
chew [dest.gum] [file-list] to specify both the GUM filename and a custom file list. You must provide either both parameters or neither.
The INI File
INSTALL.EXE is driven by an INI file. See EXAMPLE.INI for a full template. Key sections:
EXAMPLE.INI (STRUCTURE)# First line beginning with ! specifies the GUM file to use: !MYQUEST.GUM # Sections begin with : and end when the next : section starts. # :title is shown as a header, :goodbye on exit. :title |17 My Quest Installer |16 :welcome |15Welcome to My Quest! :install |07This will install My Quest files. :install.files # o = overwrite, s = skip if exists, q = query user o MYQUEST.PAK o MYQUEST.DOC s readme.txt :installdone Done! Please read MYQUEST.DOC. :upgrade Upgrade message here. :upgrade.files o MYQUEST.PAK s readme.txt
Run the installer using the INI filename (without extension):
INSTALL MYQUEST
:install.files or :upgrade.files sections. The |xx codes are pipe colour codes for ANSI colouring.
Frequently Asked Questions
Distributing Add-Ons
Once you've created an add-on, open a ticket on SourceForge first so it can be tested (though that's not strictly required any more). If you have a webpage with your add-ons, mention it and we'll link it from the project page.
Web: http://theclans.sourceforge.net
Spell Index
Use these numeric values with the Spell field in monster files.
Item Index
Use these exact names with the GiveItem command in event files.
Monster Index
Event Monsters — @CLANS.PAK/m/Eva
Use these with AddEnemy /m/Eva <index> for quest encounters.
Mine Monsters — @CLANS.PAK/m/Output
Use these with AddEnemy /m/Output <index> for standard mine fights (0–183).
This document and its accompanying files are by no means complete. More work is required — feedback and emails are welcome.