Skip to content

File format

GameScript

The stack language the whole game is written in — and the 1,906 engine operators it calls into.

.gs

In short

Nearly all of Lords of Magic's rules live in plain-text scripts inside the game's archives, in a stack-oriented language derived from PostScript. That is why the community's balance mods exist at all, and it is the single largest modding surface the game has.

Every script in all three studied installs tokenises with a small parser. An experimental interpreter loads the game's own utility library and runs it correctly. Where a script reaches something only the game engine can do, the interpreter stops and names it rather than guessing an answer.

What was found

The engine's whole vocabulary is recoverable

Measured

The game's executable contains a dispatch table naming all 1,906 operators the scripts can call, each with its entry point. Pulling that table out replaced a guess-by-shape heuristic with a real list: about 98.5% of the heuristic's candidates turned out to be genuine, and roughly 33 names per install were coincidence.

It also shows how much engine surface the scripts never touch.

A third of the corpus is pure language

Measured

406 of one install's 1,681 scripts run to completion with no engine support whatsoever. Of the rest, only 124 stop first on something that genuinely requires the engine, and 23 stop on a name that nothing in the scripts or the executable explains.

The two large remaining groups — scripts waiting on a name another script defines, and scripts waiting on a declared constant — are both cheap to satisfy. That ratio is the reason the project's assessment for this workstream is 'continue' rather than 'park'.

Small lexical details that bite

Measured

Definitions end with a keyword, not a semicolon — a community post that implies otherwise is quoting its own trailing comment. Strings have no backslash escaping, so Windows paths in the shipped scripts tokenise as written. And the scripts use a bare carriage return as a line ending, which silently breaks any tool that assumes otherwise.

This project got caught by that last one: a scan for tileset declarations read seven files' worth of commented-out code as live, because it neither honoured comments nor split lines correctly.

A comparison that inverted under correction

We were wrong about this

Classifying what blocks each script first produced a clear-looking result until someone noticed the comparison was case-insensitive. Nothing in the scripts defines the constant GOLD; a different file defines a lowercase variable of the same spelling. Folding case moved that name and 53 others into the wrong column — 75 scripts on one name alone — and flipped which group was larger.

The corrected figures are a near tie. The project's own next-step decision was re-grounded on a third number that the correction did not touch.

One mod ships a real bug

Measured

Running a community balance overhaul's utility library through the interpreter showed its minimum and maximum helpers are swapped relative to the originals. That is a live bug in a mod people play, found by executing the script rather than reading it.

Still unknown

Named as open rather than guessed at.

  • Module loading — making one script pull in another from inside the archive.
  • The engine-side operators themselves. None of the 1,906 is implemented; the interpreter stops at every one of them by design.
  • Whether the order of the operator table means anything. Measured, and it does not.

All file formats