Warcraft II map files: GraphViz block diagram (.dot) source

Warcraft II game engine uses this format for map files. External maps can be edited by official Warcraft II map editor and saved in .pud files. Maps supplied with the game (i.e. single player campaign) follow the same format, but are instead embedded inside the game container files.

There are two major versions: 0x11 (original one) and 0x13 (roughly corresponds to v1.33 of the game engine, although some of the features got limited support in v1.3).

File consists of a sequence of typed sections.

Application

Warcraft II engine

File extension

pud

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.6

This page hosts a formal specification of Warcraft II map files using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

warcraft_2_pud.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__warcraft_2_pud {
		label="Warcraft2Pud";
		graph[style=dotted];

		warcraft_2_pud__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			<TR><TD PORT="sections_pos">0</TD><TD PORT="sections_size">...</TD><TD>Section</TD><TD PORT="sections_type">sections</TD></TR>
			<TR><TD COLSPAN="4" PORT="sections__repeat">repeat to end of stream</TD></TR>
		</TABLE>>];
		subgraph cluster__section_starting_resource {
			label="Warcraft2Pud::SectionStartingResource";
			graph[style=dotted];

			section_starting_resource__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="resources_by_player_pos">0</TD><TD PORT="resources_by_player_size">2</TD><TD>u2le</TD><TD PORT="resources_by_player_type">resources_by_player</TD></TR>
				<TR><TD COLSPAN="4" PORT="resources_by_player__repeat">repeat to end of stream</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__section_era {
			label="Warcraft2Pud::SectionEra";
			graph[style=dotted];

			section_era__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="terrain_pos">0</TD><TD PORT="terrain_size">2</TD><TD>u2le→TerrainType</TD><TD PORT="terrain_type">terrain</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__section_ver {
			label="Warcraft2Pud::SectionVer";
			graph[style=dotted];

			section_ver__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="version_pos">0</TD><TD PORT="version_size">2</TD><TD>u2le</TD><TD PORT="version_type">version</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__section_dim {
			label="Warcraft2Pud::SectionDim";
			graph[style=dotted];

			section_dim__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="x_pos">0</TD><TD PORT="x_size">2</TD><TD>u2le</TD><TD PORT="x_type">x</TD></TR>
				<TR><TD PORT="y_pos">2</TD><TD PORT="y_size">2</TD><TD>u2le</TD><TD PORT="y_type">y</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__section_type {
			label="Warcraft2Pud::SectionType";
			graph[style=dotted];

			section_type__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="magic_pos">0</TD><TD PORT="magic_size">10</TD><TD>57 41 52 32 20 4D 41 50 00 00</TD><TD PORT="magic_type">magic</TD></TR>
				<TR><TD PORT="unused_pos">10</TD><TD PORT="unused_size">2</TD><TD></TD><TD PORT="unused_type">unused</TD></TR>
				<TR><TD PORT="id_tag_pos">12</TD><TD PORT="id_tag_size">4</TD><TD>u4le</TD><TD PORT="id_tag_type">id_tag</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__section_unit {
			label="Warcraft2Pud::SectionUnit";
			graph[style=dotted];

			section_unit__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="units_pos">0</TD><TD PORT="units_size">8</TD><TD>Unit</TD><TD PORT="units_type">units</TD></TR>
				<TR><TD COLSPAN="4" PORT="units__repeat">repeat to end of stream</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__section {
			label="Warcraft2Pud::Section";
			graph[style=dotted];

			section__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="name_pos">0</TD><TD PORT="name_size">4</TD><TD>str(ASCII)</TD><TD PORT="name_type">name</TD></TR>
				<TR><TD PORT="size_pos">4</TD><TD PORT="size_size">4</TD><TD>u4le</TD><TD PORT="size_type">size</TD></TR>
				<TR><TD PORT="body_pos">8</TD><TD PORT="body_size">...</TD><TD>switch (name)</TD><TD PORT="body_type">body</TD></TR>
			</TABLE>>];
section__seq_body_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
	<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
	<TR><TD>&quot;SLBR&quot;</TD><TD PORT="case0">SectionStartingResource</TD></TR>
	<TR><TD>&quot;ERAX&quot;</TD><TD PORT="case1">SectionEra</TD></TR>
	<TR><TD>&quot;OWNR&quot;</TD><TD PORT="case2">SectionOwnr</TD></TR>
	<TR><TD>&quot;ERA &quot;</TD><TD PORT="case3">SectionEra</TD></TR>
	<TR><TD>&quot;SGLD&quot;</TD><TD PORT="case4">SectionStartingResource</TD></TR>
	<TR><TD>&quot;VER &quot;</TD><TD PORT="case5">SectionVer</TD></TR>
	<TR><TD>&quot;SOIL&quot;</TD><TD PORT="case6">SectionStartingResource</TD></TR>
	<TR><TD>&quot;UNIT&quot;</TD><TD PORT="case7">SectionUnit</TD></TR>
	<TR><TD>&quot;DIM &quot;</TD><TD PORT="case8">SectionDim</TD></TR>
	<TR><TD>&quot;TYPE&quot;</TD><TD PORT="case9">SectionType</TD></TR>
</TABLE>>];
		}
		subgraph cluster__section_ownr {
			label="Warcraft2Pud::SectionOwnr";
			graph[style=dotted];

			section_ownr__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="controller_by_player_pos">0</TD><TD PORT="controller_by_player_size">1</TD><TD>u1→Controller</TD><TD PORT="controller_by_player_type">controller_by_player</TD></TR>
				<TR><TD COLSPAN="4" PORT="controller_by_player__repeat">repeat to end of stream</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__unit {
			label="Warcraft2Pud::Unit";
			graph[style=dotted];

			unit__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="x_pos">0</TD><TD PORT="x_size">2</TD><TD>u2le</TD><TD PORT="x_type">x</TD></TR>
				<TR><TD PORT="y_pos">2</TD><TD PORT="y_size">2</TD><TD>u2le</TD><TD PORT="y_type">y</TD></TR>
				<TR><TD PORT="u_type_pos">4</TD><TD PORT="u_type_size">1</TD><TD>u1→UnitType</TD><TD PORT="u_type_type">u_type</TD></TR>
				<TR><TD PORT="owner_pos">5</TD><TD PORT="owner_size">1</TD><TD>u1</TD><TD PORT="owner_type">owner</TD></TR>
				<TR><TD PORT="options_pos">6</TD><TD PORT="options_size">2</TD><TD>u2le</TD><TD PORT="options_type">options</TD></TR>
			</TABLE>>];
			unit__inst__resource [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>resource</TD><TD>(options * 2500)</TD></TR>
			</TABLE>>];
		}
	}
	warcraft_2_pud__seq:sections_type -> section__seq [style=bold];
	section_unit__seq:units_type -> unit__seq [style=bold];
	section__seq:body_type -> section__seq_body_switch [style=bold];
	section__seq_body_switch:case0 -> section_starting_resource__seq [style=bold];
	section__seq_body_switch:case1 -> section_era__seq [style=bold];
	section__seq_body_switch:case2 -> section_ownr__seq [style=bold];
	section__seq_body_switch:case3 -> section_era__seq [style=bold];
	section__seq_body_switch:case4 -> section_starting_resource__seq [style=bold];
	section__seq_body_switch:case5 -> section_ver__seq [style=bold];
	section__seq_body_switch:case6 -> section_starting_resource__seq [style=bold];
	section__seq_body_switch:case7 -> section_unit__seq [style=bold];
	section__seq_body_switch:case8 -> section_dim__seq [style=bold];
	section__seq_body_switch:case9 -> section_type__seq [style=bold];
	section__seq:name_type -> section__seq:body_type [color="#404040"];
	unit__seq:options_type -> unit__inst__resource [color="#404040"];
}