Skip to content

File format

Maps and scenarios

The world grid, its terrain, and the objects standing on it — decoded, written back, and accepted by the game.

.scn .smp .lgd .map

In short

A Lords of Magic map is a short header, a grid of fixed-size cells, and a trailing list of the objects placed on that grid. All 365 maps installed on the research machine parse completely, re-encode to the exact bytes they were read from, and give up all 21,117 of their placed-object records as typed fields.

The game itself then accepted maps written by the project: a shipped map re-encoded, an edited one, one with a new object placed, one built from nothing, and one that is not square. All seven test maps loaded.

What was found

A cell is three fields, and the game never looks at its bits

Measured

Each cell holds a tile number, a second small signed number, and an elevation value. Every place the engine reads that second number, it reads it as a whole signed quantity — it is never masked, tested or set as a bitfield anywhere in the code that was surveyed.

That matters because two earlier readings of this project, and a long-standing community reading, treated one value in that field as an on/off flag. It is not a flag. It is a number that happened to be sitting at its maximum.

Rows run across, not down

We were wrong about this

Cells are stored one display row at a time. For months this project documented — and implemented, and regression-tested — the opposite order, where cells run down a column first.

Nothing in the shipped data could catch that, because every map the game ships is square, so both readings produce the same file size and plausible-looking terrain. It took placing three objects at deliberately asymmetric coordinates and reading back where the game had put them.

The general lesson is worth more than the fact: a test corpus that is uniform in the dimension you are guessing about cannot falsify your guess.

The blend rule was shipped as data all along

We were wrong about this

When you paint terrain in the editor, the game does not just fill a rectangle — it re-picks the tile for every cell whose surroundings changed, which is what produces a clean coastline instead of a hard square edge.

This project spent an attended session in the running game painting 121 test blobs to measure that rule. It then found the rule already written down, in plain text, in the tileset files the game ships and this project had been opening since the first week. The parser was reading two columns of each line and throwing the other nine away — including the eight that state what a tile requires of each of its neighbours.

Reading those columns reproduces the game exactly on 2,084 of 2,084 cells where the answer is determined. The lesson recorded in the repo is blunt: read every column of a format you claim to parse, or say in the parser which ones you are dropping and why.

Some things the game does cannot be reproduced, ever

Measured

The edge of a painted region is fully determined and reproducible. Its interior is not: the game draws a random tile from a family of near-identical variants. Running the identical experiment twice produced different interiors around a byte-identical edge.

So this is a property of the game, not a gap in the measurement, and no map writer will ever match a hand-painted interior tile for tile.

Painting a real world map is refused about 30% of the time

Measured

Plan a small paint at every position it legally fits on a shipped map and a large fraction come back refused — 30.6% on one map, 1.0% on a nearly blank one. The rate tracks how mixed the map already is, because a refusal means the tileset declares no tile for the resulting neighbourhood.

Impassable terrain cannot be painted as an area at all: 0 of 63,504 attempts across four maps succeeded. Its tiles each demand that all eight neighbours be impassable too, so a rectangle of it has no legal boundary anywhere.

Battle maps do not all share a tileset

We were wrong about this

This project asserted, for a few hours, that all 337 battle maps are read through one tileset. Two independent reviews reproduced every supporting number and endorsed it. It was still wrong.

A battle map's tileset is declared per encounter in the game script. 169 of the 337 resolve that way; 168 have no declaration anywhere and are honestly listed as unresolved rather than guessed at.

Shipped maps break their own rules

Measured

About 5.9% of cells in the shipped world maps hold a tile that does not satisfy the constraints its own tileset declares for it. The constraints are enforced when you paint, not when the game loads — so a map can be saved into a state the editor would never create.

Still unknown

Named as open rather than guessed at.

  • What elevation is measured in.
  • What the second cell field actually controls. It behaves like visibility, and its range is inferred rather than observed.
  • What several fields of a placed-object record mean, and why four of the six record layouts carry no trailing footer.
  • Which tileset the 168 unresolved battle maps are drawn with.

All file formats