how Civilization & Colonization ran a planet in real-mode DOS

CHAPTER 4 · WORLD STATE

A HEMISPHERE IN 24K

Strip away the paged code of Chapter 1 and the streamed art of Chapter 3, and what remains is the thing the machine was actually for. In Colonization, the entire New World — every unit, colony, tribe, market price and tile — is a 25,311-byte file. Call it 24K. The simulation itself never needed more than 4% of the machine; the other 96% was spent making it visible.

25,311 B
colony09.sav — the whole New World, decomposed to the byte
37,856 B
every Civ save — fixed layout, byte-identical size, all ten checked
28 B
one Colonization unit record
12 B
one Civilization unit record
16 bit
the seed that places every special resource and hut
6 B
a Civ leader's whole personality — three signed words

A save that adds up — to the byte

Modern save files are serialised object graphs: tags, lengths, versions, slack. Colonization's save is none of those things. It is a memory image of fixed-size records, laid end to end, in a fixed order. colony09.sav — a save written by the game running under mddosem, year 1495, no colonies founded yet — is 25,311 bytes long, and every one of them is accounted for:

390 (header) + 0×202 (colonies) + 95×28 (units) + 4×316 (powers)
+ 80×18 (villages) + 8×78 (tribes) + 727 (reports) + 4×4,176 (map planes)
+ 270 (sea routes) + 270 (land routes) + 74 (unknown) + 888 (trade routes)
= 25,311 = EOF      — zero bytes unaccounted

The header is the schema's own witness. It opens with the magic COLONIZE; the map dimensions 58×72 sit at 0x0C/0x0E; the year 1495 at 0x1A; and the record counts at 0x2A0x2E read 80, 95, 0 — precisely the multipliers (80 villages, 95 units, 0 colonies) that make the arithmetic above close. There is no compression and no framing: the offsets are the format.

The header also carries the whole transatlantic economy: a sixteen-good market price table at 0x7A (values 611–937 in this save), followed by four 52-byte player blocks — 24 bytes of leader, 24 of country, 4 unidentified: “Walter Raleigh / New England”, “Jacques Cartier / New France”, “Christopher Columbus / New Spain”, and a renamed “Jah / New Netherlands”. Deeper in, each European power's 316-byte record keeps its gold in a single word at record offset +0x2A — still zero for all four in 1495.

colony09.sav, assembling ▶ assemble builds the file section by section — hover any section for its arithmetic
header 390 B units 95×28 powers 4×316 villages 80×18 tribes 8×78 reports 727 map planes 4×4,176 route caches 2×270 unknown 74 trade routes 888
Measured decomposition of colony09.sav (2026 fresh analysis), record sizes cross-checked against the community SAV format documentation (nawagers). The colonies section is present but zero bytes long — none founded yet in 1495.
colony09.sav — 25,311 bytes, no remainder
SectionOffsetArithmeticBytesObserved in this save
Header0x0000390390magic COLONIZE, 58×72, year 1495, market table, 4 player blocks
Colonies0x01860 × 2020none founded yet
Units0x018695 × 282,66090/95 records with plausible x<58, y<72; one dead slot marked x=0xF0
Powers0x0BEA4 × 3161,264gold word at +0x2A = 0 for all four
Indian villages0x10DA80 × 181,44080/80 plausible coordinates; tribe byte at +2 spans 8 values
Tribes0x167A8 × 78624one 78-byte record per nation
Reports0x18EA727727precomputed report data
Map planes0x1BC14 × 4,17616,704terrain plane dominant byte 0x19 — ocean, 2,329 of 4,176 tiles
Sea routes0x5D012702704×4-chunked routing plane (15×18 chunks)
Land routes0x5E0F270270ditto
Unknown0x5F1D7474unidentified
Trade routes0x5F6712 × 74888
Total= EOF25,311zero bytes unaccounted

Sum the mutable world itself — header, colonies, units, powers, villages, tribes and the four map planes — and you get 23,082 bytes. Add the precomputed report and route caches and the whole file is still 25,311 bytes: 3.9% of the 640 KB arena. The RAM problem this site keeps describing was never the simulation. It was presentation.

Twenty-eight bytes of conquistador

A Colonization unit — a galleon, a wagon train, a dragoon — is a 28-byte record. Our byte-level pass verified the first two fields directly: 90 of the 95 records in this save carry a plausible x < 58 at offset +0 and y < 72 at +1, and one dead slot is flagged in place by the sentinel x = 0xF0 — suggesting records are retired by marker, not by shuffling the array. An Indian village is 18 bytes, with its tribe in a single byte at +2; an entire tribal nation is one 78-byte record. Civilization is leaner still: its unit record is 12 bytes.

Anatomy of a unit record hover a byte for its field and provenance — [measured] marks byte-verified fields
hover a byte…
Colonization: x/y fields measured in colony09.sav (2026 analysis); the rest per the community SAV format (nawagers), not independently re-verified. Civilization: field list per darkpanda's SVE thread — order as documented there, three bytes undocumented.

The terrain under those units is stored the same way: as four parallel byte planes of 58×72 = 4,176 bytes each. Every tile of the hemisphere owns exactly four bytes — one per plane. In this save the terrain plane's dominant byte is 0x19, ocean, filling 2,329 of its 4,176 tiles. The fixed America map ships in the same shape: amer2.mp is 12,534 bytes — a 6-byte header reading 58, 72, 4, then three uncompressed 4,176-byte planes. Our save's terrain agrees with amer2.mp's first plane in only 30.8% of bytes, which is the arithmetic way of saying: this game was played on a generated random New World, not the canned America.

One tile, four bytes the map is four parallel 58×72 byte planes — hover one
hover a plane…
Terrain plane content measured (2026 analysis); the names of the three companion planes — flags, region, value — follow the community SAV documentation. amer2.mp, the shipped America map, carries the same 4,176-byte planes uncompressed.

A planet in 37,856 bytes

Civilization, three years earlier, made an even blunter choice: every save is exactly 37,856 bytes. All ten saves in our install match to the byte — a fixed-layout memory dump with no compression at all. (The one known variant is the French 474.05 release at 37,912 bytes: unit-type names grow from 12 to 14 characters, and 28 types × 2 characters is exactly the 56-byte delta.) The size is constant because the world's limits are compiled in: 128 cities world-total, 8 civilisations × 128 units, 28 unit types, 20 workable squares per city. Nothing grows; everything is an array.

CIVIL#.SVE — selected blocks of the fixed layout
OffsetBlockArithmeticBytes
0x0000header — turn, human civ, map seed at 0x6, year, difficulty1616
0x0010leader names8 × 14112
0x0138treasury per civ32
0x1508cities128 × 283,584
0x2308unit-type table — the rules, inside the save28 × 34952
0x26C0units8 × 128 × 1212,288
0x56C0visibility mask — bit per civ, byte per tile80 × 504,000
0x76F0±end-of-game replay logvariable records~4,100
0x8AA0land-pathfinding helper data260
whole file, every English 475.01 save37,856

Offsets and block sizes per darkpanda's SVE thread; the turn counter at 0x0000, the leader names at 0x0010 and the unit-type table at 0x2308 were byte-verified in our install — the remaining offsets are not independently re-verified.

Two details deserve a pause. First, the 28-entry unit-type table — Settlers, Militia, PhalanxNuclear, Diplomat, Caravan, 34 bytes each — lives inside the save. Unit definitions are savegame state, which is precisely what made the community's later “hack the save” editors possible. Second, the 28-byte city record packs a city's whole existence — four bytes of building bit-flags, coordinates, status bits, production, food and shields stored, six bytes of worked-square and specialist bitfields — with population as a single byte: the community's field map reads 0x01 as 10,000 people and 0x7F as 81,280,000.

And the terrain? It is not in the .SVE at all. Each save carries a companion CIVIL#.MAP whose payload is a single X0 image block in the game's own picture codec (Chapter 3): a “320×200” 8-bit image, LZW+RLE compressed, which decodes to 64,000 bytes = 16 stacked 80×50 byte planes. That 16-plane structure is the binary fact; the community's format work describes about ten of the planes as semantically used — terrain, occupation, continent IDs, land value, visibility, improvements. All ten .MAP files in our install decode cleanly with the from-scratch decoder we wrote for the art. The map is stored, quite literally, as a screenshot of itself — MicroProse reused its image compressor as a general-purpose map compressor.

The world that was never stored

Here is the chapter's best trick. Civilization's special resources — the fish, oases, coal and gems that decide where cities thrive — and its tribal huts appear on every map, on every tile they should, game after game. None of them is stored anywhere. They are pure functions of the coordinates and one 16-bit word — the map seed the community calls the TerrainMasterWord, saved at offset 0x6 of the .SVE header (and sitting in memory at ds:6E00 while the game runs):

special(x,y) :=  y>1 && y<48
             &&  (x%4)*4 + (y%4)  ==  ((x/4)*13 + (y/4)*11 + seed) % 16

hut(x,y)     :=  y>1 && y<48  &&  no city here  &&  not seen by barbarians
             &&  (x%4)*4 + (y%4)  ==  ((x/4)*13 + (y/4)*11 + seed + 8) % 32

shielded grassland :=  (x+y) % 4 == 0  ||  (x+y) % 4 == 3     // no seed at all

The left-hand side indexes the sixteen cells of the 4×4 block a tile sits in; the right-hand side hashes the block's coordinates (x/4, y/4 — integer division) with the primes 13 and 11, plus the seed. Exactly one cell per 4×4 block matches mod 16 — one special per block — while the hut variant's mod 32 can only land in half the blocks. The primes stop the pattern visibly repeating inside an 80×50 world. It is a procedural texture for game content: 4,000 tiles of riches, at a storage cost of two bytes.

The seed formula, running drag the seed — the world's riches rearrange; hover a tile for the arithmetic
special resource hut shielded-grassland stripe polar rows (excluded)
1991
This is the published formula executing live — zero bytes of stored placement. Constants 13 / 11 / +8 / mod 32 as independently documented by darkpanda (2013) and Gowron & Dack (2009). The real hut rule also checks game state (no city, not seen by barbarians), which a static demo cannot model; shield stripes are the separate seedless grassland rule.

Intelligence in bytes

The same economy governs the AI. A Civilization leader's personality is three signed words, each restricted to −1, 0 or +1, at offsets +0x30, +0x32 and +0x34 of a 58-byte leader record: attitude (friendly…aggressive), expansion (perfectionist…expansionistic), style (militaristic…civilised). Two tables of seven records serve fourteen civilisations. Six bytes of soul.

Movement is a compass, not a planner. The community's disassembly found no pathfinding at all: each turn, the AI scores a unit's eight neighbouring squares by desirability — role, terrain, combat odds — and stores the chosen heading in a single byte of the 12-byte unit record (the field the threads called “unknown9” for years). The routine doing this scoring is the third-largest function in CIV.EXE. Its special cases are period comedy: pillaging requires, verbatim, if(UnitTypes[unit.typeID].totalMoves < 2) plus an enemy city within 4 squares, a state of war and an improvement to destroy; AI diplomats reaching one code path are simply disbanded — as the thread paraphrases, “useless, just get rid of him already”.

Research strategy is a lookup: the 72-advance tech tree carries a parallel table of 72 × 2 bytes — a base priority and a modifier, the modifier added for civilised leaders and subtracted for militaristic ones. That personality-signed static table is the entire tech-choice AI.

THE RENAME EXPLOIT

Civilization's RNG is not bespoke: its constants — multiplier 0x343FD (214,013), increment 0x269EC3 (2,531,011), state in two 16-bit words at ds:5BDA/5BDC — are Microsoft C's stock rand(). And the community found the leak: “when displaying a City View, the random seed is re-initialized to the total sum of the city name's ASCII character codes” — a determinism trick so every visit draws the same procedural street layout. Players learnt to rename a city, open its view, and replay a now-fixed random sequence to force combat results and hut outcomes. The street-art optimisation became a combat cheat.

MYTH CHECK · NUCLEAR GANDHI

The famous story — Gandhi's aggression of 1 underflowing an unsigned byte to 255 when India adopts Democracy — never happened. The aggression field has three values (−1/0/+1, above); roughly a third of leaders share Gandhi's lowest setting; government changes never modified it; and Sid Meier's 2020 memoir states the C variables were signed anyway. Brian Reynolds put it at “99.99% certain” apocryphal: a leader with aggression 255 “would act the same way as a leader with an aggression level of 3”. The tale traces to an unsourced 2012 TV Tropes edit, went viral through 2014, and was only run to ground in 2019–20. Firaxis then implemented it deliberately in Civ V and VI as an Easter egg — the joke became real after the fact. The fabricated byte-underflow has even been used to teach integer overflow at Harvard; the truth — six bytes of personality — is better engineering and a better story.

Twenty kilobytes of truth

Put the two answers side by side. Colonization: a 25,311-byte record file whose header counts prove its own decomposition. Civilization: a 37,856-byte fixed dump, a map stored as a screenshot of itself, and a resource economy conjured from sixteen bits. Every screen the player ever saw was a rendering of roughly twenty kilobytes of truth.

Colonization's mainland map view, with units and terrain
Colonization's mainland view, captured running under mddosem. Every unit, village and tile on this screen is a read of the 25,311-byte save.
Civilization's map screen with cities and units
Civilization at the same job, under mddosem: an 80×50 world whose truth is a 37,856-byte .SVE plus a .MAP compressed by the art codec.

Sources for this chapter — byte-level: colony09.sav exact-fit decomposition, CIVILx.SVE / CIVILx.MAP walk and amer2.mp parse (2026 fresh analysis); community: darkpanda's SVE / MAP / RNG / pattern threads, Gowron & Dack's EXE tables, nawagers' Colonization SAV format, lateblt's city-record notes; myth-check: the Nuclear Gandhi record and Sid Meier's Memoir! (2020). Full credits in How We Know.