Workshop journal · · 9 min read
Building a map expansion, from zero to 100: the Season Expanded build, live
On 25 September I started the Season's natural next step: enlarging its map to all of Bretonnia, without touching the beta. This build happens in public, and this article follows it phase by phase, with our real tools, our real files and our missteps. Enough to understand how a map expansion comes to life, borrow ideas from it, or come and help.

A living article
Season Expanded is the Season's map enlarged to all of Bretonnia. In the middle, the Warhammer I map, 100% identical. Around it, the expansion's land, drawn from this site's Atlas.
The paper method is told in All of Bretonnia. This is the build: four phases, each with its own check.
For each phase: its goal, its steps, its tools and files, its pitfalls, its status. Everything is shown, screenshots and numbers included. Only the pack stays private, like the beta's: it contains Warhammer I files.
Before the phases: a copy and two inventories
On 25 September at 3:25 pm, I wrote to Claude's “Construction” session: make a copy of the pack, call it Expanded, and start drawing the whole expansion. Ten minutes later I added: “I don't want a flat map: the relief, the plains, the forests.”
Four rules frame the whole build:
- The beta stays untouched. Expanded is a copy, with its own map name, files and pack. Nothing is written into the beta's folders.
- Warhammer I at 100% in the middle. Around it, the Atlas, the single source: the site and the game show the same map.
- Land as scenery first: off-limits, impassable, under the fog, like the edges of Immortal Empires. Playable regions come later, one by one.
- Keys:
saison_for what we create,wh_dlc05_only for what comes from Warhammer I.
Two research agents read everything first, writing nothing: the Atlas on one side, our terrain pipeline on the other. Good news: the Atlas is already in our hex coordinates, a 560 × 575-hex frame where the Warhammer I map sits at x + 120. Its 32 new regions and 11 seas drop straight onto it.

Hence a surprise: some of the new regions, such as Château Artois, Grung Zint, Helmgart or Karak Norn, already sit inside the Warhammer I frame, on its non-playable scenery border. More on that in phase 2.
The pipeline, though, was written for one map only. A single constant, CARTE, named both the source (Warhammer I's terrain) and the target (the files in the kit). The size, 400 × 440 hexes, was hard-coded in some thirty modules. The four-phase plan came out of that finding.
Phase 1: a pipeline that knows several maps
- Goal: the same pipeline builds the beta, byte for byte, and the Expanded map.
- Status: in progress, started 25.09 at 4:45 pm.
- Tools: Python;
carte_config.py,releve_constantes.py.
Before touching a single module, we recorded the values of 952 constants across 30 modules: that's the baseline. Then one module, carte_config.py, took over everything that depends on the map: its key, its campaign, its size, where Warhammer I sits, the work folder, the pack.
An environment variable, SAISON_CARTE, picks the profile. Without it, you get the beta.
Eleven modules are wired in: the generator, the camera, the ground textures, the lighting, the trees, the rivers, the entities, the mountains… The check compares the constants before and after:
python releve_constantes.py --sortie avant.json
python releve_constantes.py --sortie apres.json --comparer avant.jsonResult: 0 differences out of 955 for the beta. For Expanded, 28, all of them targets (map key, kit and workshop folders), no Warhammer I source.
Still to wire in: the water masks, the pack build, the tables and the startpos, the names of the water and snow materials. Then comes the placement step, which will set all of Warhammer I into the enlarged world. The phase's final check will be tougher: the beta's pipeline must produce the same compiled terrain, byte for byte.
Phase 2: the enlarged grid in CAIME
- Goal: the new map's
map.hex. The Season in the middle, the expansion around it, off-limits and impassable; only the Season is playable. - Status: in progress; grid laid out at 5:30 pm, map and campaign declared in the kit at 6:08 pm.
- Tools: CAIME and command-line commands added to our copy;
grille_expanded.py,rendu_grille.py.
A bigger grid than planned
The grid was meant to match the Atlas frame: 560 × 575 hexes, the Season at x + 120. At 4:15 pm I settled a question: the Dreaming Wood, our reflection of Athel Loren, goes in the south, mirroring the forest, behind an impassable veil about 26 rows deep.
That reflection is our own addition. According to the Wood Elves army book (8th edition), as cited by the Warhammer Fantasy wiki, it runs along the whole forest: hence its place, reserved from the grid onward. So the game grid is 560 × 825 hexes: the Atlas, plus 250 rows in the south for the Dreaming Wood. The Season sits at (x + 120, y + 250) in it.
Filling the grid, hex by hex
From the command line, CAIME only knows process and validate. To script the whole thing, I used command-line commands added to our copy of CAIME, not yet offered to its authors: config, create, info, sync-names, import-layer and export-layer. If you work with an AI, that's what lets it build a map end to end, without a single click.
- Create the empty map at the right size:
create --name saison_expanded_map --width 560 --height 825, thensync-names, which writes the database names into it: 15 land grounds, 6 sea grounds, 42 climates, 12 attritions. - Copy the Season over: 8 layers from the beta (ground, climates, attritions, passable, rivers, roads, beaches, bridges), renumbered by name to the new map's lists, set at (x + 120, y + 250).
- Lay down the Atlas everywhere outside the Season's playable part: its ground types and its rivers.
- Close everything outside the Season: impassable. The southern band stays empty.
- Import and check:
import-layer, thenexport-layer --format png, and a natural-colour render.
The grid's actual commands, at 5:07 pm (the script passes all 8 layers in one go):
CAIME.exe create --name saison_expanded_map --width 560 --height 825
CAIME.exe sync-names --map saison_expanded_map\map.hex
CAIME.exe import-layer --map saison_expanded_map\map.hex
--layer GroundTypes --file layer_groundtypes.hex_layer
--layer Rivers --file layer_rivers.hex_layer …
CAIME.exe export-layer --map saison_expanded_map\map.hex --out export-png
--layer GroundTypes --layer Impassable --layer Rivers --format pngWhy does the Atlas win even inside the Warhammer I frame? We measured it. On the Season's playable part, the Atlas matches our layers at 98.5%. On the scenery border, only at 61%: it draws 25,680 hexes of new regions there, the ones behind the 4 pm surprise. Hence the rule: Warhammer I as is wherever you play, the Atlas everywhere else.

The map enters the kit
At 6:08 pm, Expanded came to exist in the kit's database. A script writes its specification (spec_expanded.py → map_spec_expanded.json), then declare_map.py registers it, after a backup: the saison_expanded_map map (560 × 825), the saison_expanded campaign (“The Season of Revelation: Expanded”), its playable area (the Season's, shifted), its roads, and the 61 Warhammer I regions linked to the map.
Those regions keep their wh_dlc05_ keys: the Season's scripts still work on the new map. Every new key was checked to be free before writing.
Still to come, in phase 2b: the new regions and seas (saison_<key>, saison_sea_<key>), then the settlement slots and trade routes (the tables to declare). CAIME screenshots to come.
Phase 3: the expansion's terrain
- Goal: land that isn't flat. Relief, ground, forests, rivers, coasts and mountains from the Atlas, plus the Dreaming Wood.
- Status: in progress since 5:45 pm, in the build's sandbox (nothing in the kit or the game).
- Tools:
relief_monde.py(previews),projet_expanded.py(the terrain project), Terry.
A first prototype, at 4:05 pm, started from the Atlas's pseudo-altitude. It topped out far too low: 3 height units, where Warhammer I climbs to 13.8. The session that draws the Atlas gave us the lesson: its alt value is not a height but a drawing class, to be converted with a table calibrated on Warhammer I.
At 5:35 pm, a first assembly of the world, as data: in the middle, the real height of the Season's Terry project; around it, the calibrated Atlas (grassland around 1.6, hills from 2.4 to 6.9, mountains from 3.2 to 10.5). The Dreaming Wood joined it at 5:45 pm.
The terrain project
At 5:45 pm the real terrain began. projet_expanded.py builds Expanded's Terry project from the Season's, read and never written: 10 enlarged rasters (relief, sea floor, colours, corruption, snow, trees…), the tile map, 51,523 shifted object positions. The whole 400 × 440 frame stays Warhammer I's: its mountains are draped on its relief.
At 6 pm, I asked for the Warhammer I map to “flow out naturally, with no border”. Its relief is extended beyond the frame by a smooth fill, then blended into the Atlas's over 12 hexes. The expansion's coasts are smoothed, and the Atlas relief is eroded with fine gullies, like Warhammer I's.
The data, 5:45 pm
The terrain project, 6:40 pmThe Dreaming Wood
From 6:30 to 6:40 pm, the Dreaming Wood entered the terrain project: Athel Loren mirrored from Warhammer I, relief, water, ground, trees and winter snow included. A lilac tint, a corrupted magenta edge, a veil of mist; around it, a dark violet sea of aether where the reflection floats like an island. The Slaanesh colours are the project's artistic choice.

Phase 4: the Expanded campaign
- Goal: a playable campaign on the new map, alongside the beta's.
- Status: to come.
- Tools: RPFM, startpos generation.
The map key, the campaign key and the playable area are already declared (phase 2, 6:08 pm). A campaign knows only one map, through the map_name column of the campaigns table: Expanded's points to its own.
Follow along, and lend a hand with the map
The site's Atlas is the single source: what changes on the map will change in the game. A name that rings false, a misplaced border, a forgotten ruin from the lore? Suggest them on the map, right where they belong.
Later, no rush: a slice of the Reikland at the border, with Helmgart facing Montfort and the Gisoreux Gap; Marienburg, once I've seen it in the game.
This article grows with the build: each phase brings its screenshots, numbers and pitfalls. The tools have their guides: CAIME, Terry, RPFM and the other tools.