WoS Quest Script
The QUEST scripting language of Well of Souls - Dan Samuel's freeware multiplayer RPG - a label-and-GOTO scene language where every quest in the game is a numbered script of actor commands, token tests and string variables called cookies
Created by Dan Samuel (Synthetic Reality Co.)
WoS Quest Script - called simply QUEST by its author - is the scripting language built into Well of Souls, the freeware multiplayer role-playing game written by Dan Samuel of Synthetic Reality Co. It is a small, blunt, unapologetically procedural language of numbered scenes, @labels and GOTOs, in which every conversation, every shop, every plot twist and every boss fight in a Well of Souls world is a short program. It has no types, no scoping and exactly one data structure - a string variable the author calls a cookie. It also has something most game-scripting languages of its era did not: a clearly specified answer to what happens when several players run the same script at once.
History and Origins
Synthetic Reality was, in Samuel’s own words on the company’s history page, “pretty much just me, Dan Samuel” - a working programmer who wrote games in the evenings, at Mpath Interactive (which, as the same page records, changed its name to HearMe in 1999), before going full-time on the games “sometime around May 2000”. Well of Souls was the project that followed his earlier Warpath games, and from the beginning it was conceived less as a game than as an engine: the demo page describes it as “a script-driven, multi-player Role Playing Game (RPG)” whose “idea is to make the design open enough that you can generate your own worlds and quests, share them with friends”.
The oldest surviving release note on the Synthetic Reality site is dated 5 April 1998, and the reference section attached to that same page already sets out the shape of the language:
Each World has a script file “quest.txt” which contains the overall information about that world. […] Then you define scenes, with optional characters who can deliver dialog and take action based upon your responses. The format of the script language is pretty basic, hopefully simple (though tedious) and don’t expect any great documentation soon.
That candour about documentation is worth noting, because it explains a common dating error. Many catalogues record QUEST as a 2000 language. But 2000 is the date of Alpha 30 (14 January 2000), the release in which Samuel, by his own account, got round to “finally writing some documentation for the individual script commands”. The language itself is a 1998 artefact; Well of Souls carries a 1998 copyright, and the engine’s scripted scenes predate the public Open Alpha, which was announced on 1 January 1999 - in a news item that opens by conceding the site announces “news items months after the fact”.
From there the language grew one release note at a time for a decade, through 97 numbered alpha releases, and then stopped. Alpha 97 - the last - was posted in December 2008.
Design Philosophy
QUEST is designed around a single unit of composition: the scene. A scene is a background image with sprite actors drawn on top of it, and a scene script is the program that stages what happens there. Everything else in the language exists to serve that: commands to place and move actors, commands to set mood (MUSIC, THEME, WEATHER, FX, BKGND), commands to hand the player items and take them away again, and a conditional apparatus for deciding which of those to do.
Three decisions give the language its character.
Tokens, not variables, carry the plot. A TOKEN is a numbered flag with a human-readable description, permanently attached to a character: “You have stolen the secret poker chip!” Because tokens are persistent and cheap, a world’s whole non-linear plot can be encoded as a set of token tests, with no need for any script to know what any other script did. The documentation is explicit that a cookie should not “do the job of a TOKEN”.
Conditions are written as signed algebra over IDs. Rather than boolean operators, IF takes a list of typed IDs joined with + and -:
IF T12+I15-S22, @label
which reads “if the host has token 12 and item 15 but not spell 22”. The ID letters cover most of the game’s state - T token, I item, S spell, C character class, E equipped item, G gold, H character age in hours, F map flag, J mission, plus bare words like ALIVE, DEAD and GS (Golden Soul). Disjunction arrived much later, in version A84, as a | separator between whole clauses; the dictionary describes evaluation as proceeding left to right and stopping at the first clause that comes up true.
The host runs the script. In multiplayer, when more than one player stands in a scene, the scene commands execute on the machine of the player hosting it, and - as the dictionary states plainly - “all IF conditionals are based on that player”. Objects that are given or taken in the scene affect everyone present. That single rule is what makes a language with no concurrency primitives usable in a shared world, and it is visible in the command set: GIVE versus HOST_GIVE versus PARTY_GIVE exist precisely to let an author choose the blast radius of an effect.
Key Features
| Feature | Form |
|---|---|
| Scene declaration | SCENE <id>, "<background>", SCENE, "<title>", 0, 0 … END |
| Labels and jumps | @label, GOTO @label, GOTO EXIT, GOTO LINK, GOTO SCENE |
| Subroutines (A89+) | CALL 200@foo arg, arg / RETURN val, val, arguments in arg0-arg9 |
| Actors | ACTOR <id>.<layer>, <name>, <skin>, <pose>, <x>, <y>, then SEL, MOVE, FACE, POSE |
| Dialogue | 1: Hello, my name is %0. Your name is %2. - the actor number, a colon, the line |
| Variables (“cookies”) | SET name, "value" to write, #<name> to read; de-referencing via SET #<a>, "v" |
| Integer math | ADD, SUB, MUL, DIV, MOD (all mutate a cookie in place) |
| Floating-point math | F_ADD, F_SUB, F_MUL, F_DIV, F_MOD (A90+) |
| Comparison | COMPARE a, b then IF=, IF>, IF<, IF<=, IF>=, IF<>, IFEVEN, IFODD |
| Strings | SET_LEN, SET_SUBSTR, STRCMP, STRSTR; STRLWR and NTH_TOKEN (A96+) |
| Stack | PUSH <cookie>, POP <cookie> |
| Bitwise | AND, OR, XOR, NOT (A91+) |
| Player input | ASK <seconds> sets yes/no flags and #<lastAsk>; Qword conditions scan the reply |
| Persistence beyond the player | GET_SERVER_VAR, SET_SERVER_VAR |
Dialogue lines use a percent-code vocabulary rather than string interpolation: %0 is the speaking character’s name, %1 the scene host, %2 the reading client’s own name, %3 a randomly generated insult, %Rn a random number from 1 to n, %Mn the name of monster n, %L the host’s level title, and so on, with %% for a literal percent sign. Cookies are expanded before the line is parsed, which is what makes constructs like %I#<itemNumber> work - and, as the documentation warns, what makes cookies “quite powerful, and hence dangerous and confusing”.
Each world lives in its own folder with a quest.txt at the root and subfolders for MIDI, MAPS, ART, MONSTERS, SCENES and SFX. Large worlds split their scripts across files and pull them together with #include. Scenes live in a +SCENES table; the language has no imports, no namespaces, and a flat global numbering of scenes, tokens, items and spells.
A Worked Example
This is the casino script from Samuel’s own dictionary, reproduced as published:
SCENE 45, "casino", SCENE, "Casino Room", 0, 0
; Set up the mood
THEME 3
MUSIC "waltz2.mid"
ACTOR 1, "Barker", joshRoyalty, 2, 25, 90
; Check if he has already stolen the chip
IF T23, @hasStolenChip
; No, be friendly
MOVE 1, 15, 80
SEL 1
POSE 2, 3, 4
1: Try your luck, %1!
1: Our slots pay the most!
GAME 1
END
@hasStolenChip
; The player is a thief, sound the alarm!
1: Thief! %3!
SOUND "alarm.wav"
BKGND "closed.jpg"
1: Guards, come kill the interloper!
WAIT 2.3
WEATHER 9
; Bring in 3 monsters to fight the player
FIGHT 15, 15, 15
IF ALIVE, @wonFight
1: Ha! My guards made short work of you!
1: Now, get out of here!
WAIT 1.5
; Boot the player back out to the map
GOTO EXIT
END
@wonFight
1: Well, OK, I guess you're stronger than my guards.
GIVE T34
END
TOKEN 23, "You have stolen the secret poker chip!"
TOKEN 34, "You have beaten the three guards."
Everything characteristic of the language is here in thirty-eight lines: the numbered scene, the semicolon comments, the actor declared with a skin file and screen coordinates given as percentages of the window, the token test that forks the whole scene, the 1: dialogue lines with %1 and %3 substitutions, the FIGHT that hands control to the combat engine and reports back through the ALIVE condition, and the token definitions parked at the bottom of the table where the author found them convenient.
Evolution
QUEST grew by accretion, and the release notes read like a diary of a language finding out what it needs. It began with actors and dialogue. Scene decoration (BKGND, FX, WEATHER) came in January 2000. Variables did not arrive until July 2001 - three years in - when Alpha 57 introduced cookies together with arithmetic and comparison in a single release, turning a branching dialogue notation into something that could count. Indirection through cookies followed in October 2002, subroutines and a call stack in October 2005, floating point a week after that, and bitwise operators and parity tests in February 2006.
Samuel narrated the additions with a running commentary on his own design. Of the boolean operators: “Not sure if anyone would ever really NEED these.” Of IFEVEN and IFODD: “I can’t believe I added this. How lazy can a world developer be, hmm?” Of the cross-scene CALL that let a function fall through into unrelated code: “Of course, thinking like that gave us perl!”
The arc is unusual. Most game-scripting DSLs start by embedding an existing language; QUEST instead rediscovered variables, then functions, then a stack, in public, over seven years, each addition justified by a specific world author who had asked for it.
Current Relevance
Well of Souls is dormant. Alpha 97 is the final release: the download page records it as updated 5 December 2008, and a request for the installer in September 2026 still returns the same 9,855,503-byte file with a Last-Modified date of 6 December 2008. The news page stops in May 2008. Samuel had by then moved on to his day job at There Inc. - later Makena Technologies - and to the Arcadia family of smaller multiplayer toys.
What is remarkable is that the site is still up and still serving. synthetic-reality.com remains live over HTTP, the Quest Language Dictionary is still at wosquest.htm, the complete dated release notes from April 1998 forward are still split across three pages, and the installer and its patches still download. The game’s own official requirements - Windows 95 through XP “etc”, a Pentium 90, 16 MB of RAM, DirectX 3 or higher and Internet Explorer for the embedded web features - date it precisely, and no port to any other platform appears to have been published.
For a language whose only implementation is inside a Windows game binary, the documentation has aged far better than the runtime.
Why It Matters
QUEST is a good specimen of a category that is enormous in practice and almost invisible in language history: the one-game scripting language, written by the game’s author, documented in a single HTML page, and used seriously by a community of world authors to build things its designer never anticipated. There were dozens of such languages in the late 1990s shareware world, and almost none of them left a record. This one did, because Samuel wrote down every change he made for ten years and never took the pages down.
Two things about it are genuinely instructive. The first is the token model: by making plot state a flat, persistent, numbered set of flags with human-readable descriptions, Samuel gave amateur authors a way to write non-linear stories without writing a state machine. The second is the host-executes rule, which is a real answer to a real distributed-systems problem - who decides what happened? - expressed in one sentence of documentation and a handful of HOST_/PARTY_ command variants, so that a world author never has to think about it at all.
It is also a reminder of how much of the design of a small language is determined by the questions its users ask. Read the release notes in order and the shape of QUEST is legible as a decade of requests: someone wanted to change the background mid-scene, someone wanted to count monsters, someone wanted to reuse a snippet of dialogue, someone wanted a card game. Each got a command. The result is a language that is not elegant, but is exactly the size of the problem it was asked to solve.
Timeline
Notable Uses & Legacy
Evergreen
The world that ships with Well of Souls, written by Dan Samuel with monster and hero art by Josh Worts. The developer documentation points authors at wos/worlds/evergreen as the worked reference implementation of the language, and its quest.txt is where most world builders learned QUEST.
Monkey Town
A downloadable world by Ben Samuel - the author's son, whose ideas Synthetic Reality credits throughout its games - distributed through the game's built-in "Check On Line For New Worlds" menu.
Narretidem Islands
A third-party world by James Gregory, listed on Synthetic Reality's Other Worlds page and distributed in-game; an example of the player-authored worlds the scripting language existed to enable.
Furtopia
A player-built world by the community member Lord FireFox, who also ran one of the WoS fan sites linked from the official download page.
Aerianell
A world by Lady Gryphon, credited on Synthetic Reality's Other Worlds page as contributing their own monster artwork alongside Josh Worts' shared skins - the full stack of custom content the world format allows.