← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1291904 into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1291904 into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1291904 in widelands: "Remove compatibility in game_io and map_io"
  https://bugs.launchpad.net/widelands/+bug/1291904

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1291904/+merge/237128

Removed compatibility for old savegames and added a new exception "OldVersionError" to give useful, unified feedback to the user. This exception will show a localizable description so users will know the reason for the error, and non-localizable info for the coders.

Some compatibility code still remains, because it is needed by the tutorial, campaigns, maps and scenarios. Lowest versions for these are:

MapPlayerNamesAndTribesPacket: 1 (Current version: 2)
Immovables:                    1 (Current version: 5)
Buildings:                     2 (Current version: 4)

For finding all remaining instances of compatibility code:

    grep "// Supporting older versions" src/* -r
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1291904/+merge/237128
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1291904 into lp:widelands.
=== modified file 'src/economy/cmd_call_economy_balance.cc'
--- src/economy/cmd_call_economy_balance.cc	2014-09-20 09:37:47 +0000
+++ src/economy/cmd_call_economy_balance.cc	2014-10-03 19:24:49 +0000
@@ -48,7 +48,7 @@
 		flag->get_economy()->balance(m_timerid);
 }
 
-#define CURRENT_CMD_CALL_ECONOMY_VERSION 3
+constexpr uint16_t kCurrentPacketVersion = 3;
 
 /**
  * Read and write
@@ -58,34 +58,15 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_CMD_CALL_ECONOMY_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			GameLogicCommand::read(fr, egbase, mol);
 			uint32_t serial = fr.unsigned_32();
 			if (serial)
 				m_flag = &mol.get<Flag>(serial);
 			m_timerid = fr.unsigned_32();
-		} else if (packet_version == 1 || packet_version == 2) {
-			GameLogicCommand::read(fr, egbase, mol);
-			uint8_t const player_number = fr.unsigned_8();
-			if (Player * const player = egbase.get_player(player_number)) {
-				if (!fr.unsigned_8())
-					throw wexception("0 is not allowed here");
-				uint16_t const economy_number = fr.unsigned_16();
-				if (economy_number < player->get_nr_economies())
-					m_flag =
-						player->get_economy_by_number(economy_number)
-						->get_arbitrary_flag();
-				else
-					throw wexception("invalid economy number %u", economy_number);
-			} else
-				throw wexception("invalid player number %u", player_number);
-			if (packet_version >= 2)
-				m_timerid = fr.unsigned_32();
-			else
-				m_timerid = 0;
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw wexception("call economy balance: %s", e.what());
 	}
@@ -93,7 +74,7 @@
 void CmdCallEconomyBalance::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(CURRENT_CMD_CALL_ECONOMY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// Write Base Commands
 	GameLogicCommand::write(fw, egbase, mos);

=== modified file 'src/economy/economy_data_packet.cc'
--- src/economy/economy_data_packet.cc	2014-09-20 09:37:47 +0000
+++ src/economy/economy_data_packet.cc	2014-10-03 19:24:49 +0000
@@ -27,73 +27,69 @@
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
 
-#define CURRENT_ECONOMY_VERSION 3
+constexpr uint16_t kCurrentPacketVersion = 3;
 
 namespace Widelands {
 
 void EconomyDataPacket::read(FileRead & fr)
 {
-	uint16_t const version = fr.unsigned_16();
-
 	try {
-		if (1 <= version && version <= CURRENT_ECONOMY_VERSION) {
-			if (2 <= version)
-				try {
-					const TribeDescr & tribe = m_eco->owner().tribe();
-					while (Time const last_modified = fr.unsigned_32()) {
-						char const * const type_name = fr.c_string();
-						uint32_t const permanent = fr.unsigned_32();
-						if (version <= 2)
-							fr.unsigned_32();
-						WareIndex i = tribe.ware_index(type_name);
-						if (i != INVALID_INDEX) {
-							if (tribe.get_ware_descr(i)->default_target_quantity() ==
-							    std::numeric_limits<uint32_t>::max())
-								log("WARNING: target quantity configured for %s, "
-								    "which should not have target quantity, "
-								    "ignoring\n",
-								    type_name);
-							else {
-								Economy::TargetQuantity & tq =
-									m_eco->m_ware_target_quantities[i];
-								if (tq.last_modified)
-									throw GameDataError
-										("duplicated entry for %s", type_name);
-								tq.permanent         = permanent;
-								tq.last_modified     = last_modified;
-							}
-						} else if ((i = tribe.worker_index(type_name)) != INVALID_INDEX) {
-							if
-								(tribe.get_worker_descr(i)->default_target_quantity()
-								 ==
-								 std::numeric_limits<uint32_t>::max())
-								log
-									("WARNING: target quantity configured for %s, "
-									 "which should not have target quantity, "
-									 "ignoring\n",
-									 type_name);
-							else {
-								Economy::TargetQuantity & tq =
-									m_eco->m_worker_target_quantities[i];
-								if (tq.last_modified)
-									throw GameDataError
-										("duplicated entry for %s", type_name);
-								tq.permanent         = permanent;
-								tq.last_modified     = last_modified;
-							}
-						} else
+		uint16_t const packet_version = fr.unsigned_16();
+		if (packet_version == kCurrentPacketVersion) {
+			try {
+				const TribeDescr & tribe = m_eco->owner().tribe();
+				while (Time const last_modified = fr.unsigned_32()) {
+					char const * const type_name = fr.c_string();
+					uint32_t const permanent = fr.unsigned_32();
+					WareIndex i = tribe.ware_index(type_name);
+					if (i != INVALID_INDEX) {
+						if (tribe.get_ware_descr(i)->default_target_quantity() ==
+							 std::numeric_limits<uint32_t>::max())
+							log("WARNING: target quantity configured for %s, "
+								 "which should not have target quantity, "
+								 "ignoring\n",
+								 type_name);
+						else {
+							Economy::TargetQuantity & tq =
+								m_eco->m_ware_target_quantities[i];
+							if (tq.last_modified)
+								throw GameDataError
+									("duplicated entry for %s", type_name);
+							tq.permanent         = permanent;
+							tq.last_modified     = last_modified;
+						}
+					} else if ((i = tribe.worker_index(type_name)) != INVALID_INDEX) {
+						if
+							(tribe.get_worker_descr(i)->default_target_quantity()
+							 ==
+							 std::numeric_limits<uint32_t>::max())
 							log
-								("WARNING: target quantity configured for \"%s\", "
-								 "which is not a ware or worker type defined in tribe "
-								 "%s, ignoring\n",
-								 type_name, tribe.name().c_str());
-					}
-				} catch (const WException & e) {
-					throw GameDataError("target quantities: %s", e.what());
+								("WARNING: target quantity configured for %s, "
+								 "which should not have target quantity, "
+								 "ignoring\n",
+								 type_name);
+						else {
+							Economy::TargetQuantity & tq =
+								m_eco->m_worker_target_quantities[i];
+							if (tq.last_modified)
+								throw GameDataError
+									("duplicated entry for %s", type_name);
+							tq.permanent         = permanent;
+							tq.last_modified     = last_modified;
+						}
+					} else
+						log
+							("WARNING: target quantity configured for \"%s\", "
+							 "which is not a ware or worker type defined in tribe "
+							 "%s, ignoring\n",
+							 type_name, tribe.name().c_str());
 				}
-			m_eco->m_request_timerid = fr.unsigned_32();
+			} catch (const WException & e) {
+				throw GameDataError("target quantities: %s", e.what());
+			}
+		m_eco->m_request_timerid = fr.unsigned_32();
 		} else {
-			throw GameDataError("unknown version %u", version);
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
 		}
 	} catch (const std::exception & e) {
 		throw GameDataError("economy: %s", e.what());
@@ -102,7 +98,7 @@
 
 void EconomyDataPacket::write(FileWrite & fw)
 {
-	fw.unsigned_16(CURRENT_ECONOMY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 	const TribeDescr & tribe = m_eco->owner().tribe();
 	for (WareIndex i = tribe.get_nrwares(); i;) {
 		--i;

=== modified file 'src/economy/fleet.cc'
--- src/economy/fleet.cc	2014-09-20 09:37:47 +0000
+++ src/economy/fleet.cc	2014-10-03 19:24:49 +0000
@@ -680,13 +680,13 @@
 		("%" PRIuS " ships and %" PRIuS " ports\n",  m_ships.size(), m_ports.size());
 }
 
-#define FLEET_SAVEGAME_VERSION 4
+constexpr uint8_t kCurrentPacketVersion = 4;
 
 Fleet::Loader::Loader()
 {
 }
 
-void Fleet::Loader::load(FileRead & fr, uint8_t version)
+void Fleet::Loader::load(FileRead & fr)
 {
 	MapObject::Loader::load(fr);
 
@@ -702,13 +702,7 @@
 	for (uint32_t i = 0; i < nrports; ++i)
 		m_ports[i] = fr.unsigned_32();
 
-	if (version >= 2) {
-		fleet.m_act_pending = fr.unsigned_8();
-		if (version < 3)
-			fleet.m_act_pending = false;
-		if (version < 4)
-			fr.unsigned_32(); // m_roundrobin
-	}
+	fleet.m_act_pending = fr.unsigned_8();
 }
 
 void Fleet::Loader::load_pointers()
@@ -756,8 +750,8 @@
 
 	try {
 		// The header has been peeled away by the caller
-		uint8_t const version = fr.unsigned_8();
-		if (1 <= version && version <= FLEET_SAVEGAME_VERSION) {
+		uint8_t const packet_version = fr.unsigned_8();
+		if (1 <= packet_version && packet_version  <= kCurrentPacketVersion) {
 			PlayerNumber owner_number = fr.unsigned_8();
 			if (!owner_number || owner_number > egbase.map().get_nrplayers())
 				throw GameDataError
@@ -769,9 +763,10 @@
 				throw GameDataError("owning player %u does not exist", owner_number);
 
 			loader->init(egbase, mol, *(new Fleet(*owner)));
-			loader->load(fr, version);
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+			loader->load(fr);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const std::exception & e) {
 		throw wexception("loading portdock: %s", e.what());
 	}
@@ -782,7 +777,7 @@
 void Fleet::save(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
 {
 	fw.unsigned_8(HeaderFleet);
-	fw.unsigned_8(FLEET_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 
 	fw.unsigned_8(m_owner.player_number());
 

=== modified file 'src/economy/fleet.h'
--- src/economy/fleet.h	2014-09-10 08:55:04 +0000
+++ src/economy/fleet.h	2014-10-03 19:24:49 +0000
@@ -131,7 +131,7 @@
 	struct Loader : MapObject::Loader {
 		Loader();
 
-		void load(FileRead &, uint8_t version);
+		void load(FileRead &);
 		void load_pointers() override;
 		void load_finish() override;
 

=== modified file 'src/economy/portdock.cc'
--- src/economy/portdock.cc	2014-09-20 09:37:47 +0000
+++ src/economy/portdock.cc	2014-10-03 19:24:49 +0000
@@ -466,13 +466,13 @@
 	}
 }
 
-#define PORTDOCK_SAVEGAME_VERSION 3
+constexpr uint8_t kCurrentPacketVersion = 3;
 
 PortDock::Loader::Loader() : m_warehouse(0)
 {
 }
 
-void PortDock::Loader::load(FileRead & fr, uint8_t version)
+void PortDock::Loader::load(FileRead & fr)
 {
 	PlayerImmovable::Loader::load(fr);
 
@@ -487,24 +487,18 @@
 		pd.set_position(egbase(), pd.m_dockpoints[i]);
 	}
 
-	if (version >= 2) {
-		pd.m_need_ship = fr.unsigned_8();
-
-		m_waiting.resize(fr.unsigned_32());
-		for (ShippingItem::Loader& shipping_loader : m_waiting) {
-			shipping_loader.load(fr);
-		}
-
-		if (version >= 3) {
-			// All the other expedition specific stuff is saved in the warehouse.
-			if (fr.unsigned_8()) {  // Do we have an expedition?
-				pd.m_expedition_bootstrap.reset(new ExpeditionBootstrap(&pd));
-			}
-			pd.m_expedition_ready = (fr.unsigned_8() == 1) ? true : false;
-		} else {
-			pd.m_expedition_ready = false;
-		}
-	}
+	pd.m_need_ship = fr.unsigned_8();
+
+	m_waiting.resize(fr.unsigned_32());
+	for (ShippingItem::Loader& shipping_loader : m_waiting) {
+		shipping_loader.load(fr);
+	}
+
+	// All the other expedition specific stuff is saved in the warehouse.
+	if (fr.unsigned_8()) {  // Do we have an expedition?
+		pd.m_expedition_bootstrap.reset(new ExpeditionBootstrap(&pd));
+	}
+	pd.m_expedition_ready = (fr.unsigned_8() == 1) ? true : false;
 }
 
 void PortDock::Loader::load_pointers()
@@ -545,12 +539,14 @@
 	try {
 		// The header has been peeled away by the caller
 
-		uint8_t const version = fr.unsigned_8();
-		if (1 <= version && version <= PORTDOCK_SAVEGAME_VERSION) {
+		uint8_t const packet_version = fr.unsigned_8();
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version  <= kCurrentPacketVersion) {
 			loader->init(egbase, mol, *new PortDock(nullptr));
-			loader->load(fr, version);
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+			loader->load(fr);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const std::exception & e) {
 		throw wexception("loading portdock: %s", e.what());
 	}
@@ -561,7 +557,7 @@
 void PortDock::save(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
 {
 	fw.unsigned_8(HeaderPortDock);
-	fw.unsigned_8(PORTDOCK_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 
 	PlayerImmovable::save(egbase, mos, fw);
 

=== modified file 'src/economy/portdock.h'
--- src/economy/portdock.h	2014-09-10 10:18:46 +0000
+++ src/economy/portdock.h	2014-10-03 19:24:49 +0000
@@ -151,7 +151,7 @@
 	public:
 		Loader();
 
-		void load(FileRead &, uint8_t version);
+		void load(FileRead &);
 		void load_pointers() override;
 		void load_finish() override;
 

=== modified file 'src/economy/request.cc'
--- src/economy/request.cc	2014-09-20 09:37:47 +0000
+++ src/economy/request.cc	2014-10-03 19:24:49 +0000
@@ -95,7 +95,7 @@
 }
 
 // Modified to allow Requirements and SoldierRequests
-#define REQUEST_VERSION 6
+constexpr uint16_t kCurrentPacketVersion = 6;
 
 /**
  * Read this request from a file
@@ -109,8 +109,8 @@
 	(FileRead & fr, Game & game, MapObjectLoader & mol)
 {
 	try {
-		uint16_t const version = fr.unsigned_16();
-		if (version == 6) {
+		uint16_t const packet_version = fr.unsigned_16();
+		if (packet_version == kCurrentPacketVersion) {
 			const TribeDescr& tribe = m_target.owner().tribe();
 			char const* const type_name = fr.c_string();
 			WareIndex const wai = tribe.ware_index(type_name);
@@ -167,8 +167,9 @@
 			m_requirements.read (fr, game, mol);
 			if (!is_open() && m_economy)
 				m_economy->remove_request(*this);
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw wexception("request: %s", e.what());
 	}
@@ -180,7 +181,7 @@
 void Request::write
 	(FileWrite & fw, Game & game, MapObjectSaver & mos) const
 {
-	fw.unsigned_16(REQUEST_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	//  Target and econmy should be set. Same is true for callback stuff.
 

=== modified file 'src/economy/shippingitem.cc'
--- src/economy/shippingitem.cc	2014-09-20 09:37:47 +0000
+++ src/economy/shippingitem.cc	2014-10-03 19:24:49 +0000
@@ -163,15 +163,21 @@
 }
 
 
-#define SHIPPINGITEM_SAVEGAME_VERSION 1
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void ShippingItem::Loader::load(FileRead & fr)
 {
-	uint8_t version = fr.unsigned_8();
-	if (1 <= version && version <= SHIPPINGITEM_SAVEGAME_VERSION) {
-		m_serial = fr.unsigned_32();
-	} else
-		throw GameDataError("unknown ShippingItem version %u", version);
+	try {
+		uint8_t packet_version = fr.unsigned_8();
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version <= kCurrentPacketVersion) {
+			m_serial = fr.unsigned_32();
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
+	} catch (const WException & e) {
+		throw GameDataError("shipping item: %s", e.what());
+	}
 }
 
 ShippingItem ShippingItem::Loader::get(MapObjectLoader & mol)
@@ -184,7 +190,7 @@
 
 void ShippingItem::save(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
 {
-	fw.unsigned_8(SHIPPINGITEM_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 	fw.unsigned_32(mos.get_object_file_index_or_zero(m_object.get(egbase)));
 }
 

=== modified file 'src/economy/transfer.cc'
--- src/economy/transfer.cc	2014-09-20 09:37:47 +0000
+++ src/economy/transfer.cc	2014-10-03 19:24:49 +0000
@@ -312,15 +312,20 @@
 ==============================
 */
 
-#define TRANSFER_SAVEGAME_VERSION 1
+constexpr uint8_t kCurrentPacketVersion = 1;
 
 void Transfer::read(FileRead & fr, Transfer::ReadData & rd)
 {
-	uint8_t version = fr.unsigned_8();
-	if (version != TRANSFER_SAVEGAME_VERSION)
-		throw wexception("unhandled/unknown transfer version %u", version);
-
-	rd.destination = fr.unsigned_32();
+	try {
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersion) {
+			rd.destination = fr.unsigned_32();
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
+	} catch (const WException & e) {
+		throw wexception("transfer: %s", e.what());
+	}
 }
 
 void Transfer::read_pointers
@@ -332,7 +337,7 @@
 
 void Transfer::write(MapObjectSaver & mos, FileWrite & fw)
 {
-	fw.unsigned_8(TRANSFER_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 	fw.unsigned_32(mos.get_object_file_index_or_zero(m_destination.get(m_game)));
 	// not saving route right now, will be recaculated anyway
 }

=== modified file 'src/economy/ware_instance.cc'
--- src/economy/ware_instance.cc	2014-09-20 09:37:47 +0000
+++ src/economy/ware_instance.cc	2014-10-03 19:24:49 +0000
@@ -544,7 +544,7 @@
 ==============================
 */
 
-#define WAREINSTANCE_SAVEGAME_VERSION 1
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 WareInstance::Loader::Loader() :
 	m_location(0),
@@ -599,7 +599,7 @@
 	(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
 {
 	fw.unsigned_8(HeaderWareInstance);
-	fw.unsigned_8(WAREINSTANCE_SAVEGAME_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 	fw.c_string(descr().tribe().name());
 	fw.c_string(descr().name());
 
@@ -620,28 +620,30 @@
 	(EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr)
 {
 	try {
-		uint8_t version = fr.unsigned_8();
-
-		if (version != WAREINSTANCE_SAVEGAME_VERSION)
-			throw wexception("unknown/unhandled version %i", version);
-
-		const std::string tribename = fr.c_string();
-		const std::string warename = fr.c_string();
-
-		egbase.manually_load_tribe(tribename);
-
-		const TribeDescr * tribe = egbase.get_tribe(tribename);
-		if (!tribe)
-			throw wexception("unknown tribe '%s'", tribename.c_str());
-
-		WareIndex wareindex = tribe->ware_index(warename);
-		const WareDescr * descr = tribe->get_ware_descr(wareindex);
-
-		std::unique_ptr<Loader> loader(new Loader);
-		loader->init(egbase, mol, *new WareInstance(wareindex, descr));
-		loader->load(fr);
-
-		return loader.release();
+		uint16_t packet_version = fr.unsigned_16();
+
+		if (packet_version == kCurrentPacketVersion) {
+
+			const std::string tribename = fr.c_string();
+			const std::string warename = fr.c_string();
+
+			egbase.manually_load_tribe(tribename);
+
+			const TribeDescr * tribe = egbase.get_tribe(tribename);
+			if (!tribe)
+				throw wexception("unknown tribe '%s'", tribename.c_str());
+
+			WareIndex wareindex = tribe->ware_index(warename);
+			const WareDescr * descr = tribe->get_ware_descr(wareindex);
+
+			std::unique_ptr<Loader> loader(new Loader);
+			loader->init(egbase, mol, *new WareInstance(wareindex, descr));
+			loader->load(fr);
+
+			return loader.release();
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const std::exception & e) {
 		throw wexception("WareInstance: %s", e.what());
 	}

=== modified file 'src/economy/wares_queue.cc'
--- src/economy/wares_queue.cc	2014-09-20 09:37:47 +0000
+++ src/economy/wares_queue.cc	2014-10-03 19:24:49 +0000
@@ -234,10 +234,12 @@
 /**
  * Read and write
  */
-#define WARES_QUEUE_DATA_PACKET_VERSION 2
+
+constexpr uint16_t kCurrentPacketVersion = 2;
+
 void WaresQueue::write(FileWrite & fw, Game & game, MapObjectSaver & mos)
 {
-	fw.unsigned_16(WARES_QUEUE_DATA_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	//  Owner and callback is not saved, but this should be obvious on load.
 	fw.c_string
@@ -258,14 +260,11 @@
 {
 	uint16_t const packet_version = fr.unsigned_16();
 	try {
-		if (packet_version == WARES_QUEUE_DATA_PACKET_VERSION || packet_version == 1) {
+		if (packet_version == kCurrentPacketVersion) {
 			delete m_request;
 			m_ware             = owner().tribe().ware_index(fr.c_string  ());
 			m_max_size         =                            fr.unsigned_32();
-			if (packet_version == 1)
-				m_max_fill = m_max_size;
-			else
-				m_max_fill = fr.signed_32();
+			m_max_fill = fr.signed_32();
 			m_filled           =                            fr.unsigned_32();
 			m_consume_interval =                            fr.unsigned_32();
 			if                                             (fr.unsigned_8 ()) {
@@ -282,9 +281,9 @@
 			//  Now Economy stuff. We have to add our filled items to the economy.
 			if (m_owner.get_economy())
 				add_to_economy(*m_owner.get_economy());
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const GameDataError & e) {
 		throw GameDataError("waresqueue: %s", e.what());
 	}

=== modified file 'src/game_io/game_class_packet.cc'
--- src/game_io/game_class_packet.cc	2014-09-20 09:37:47 +0000
+++ src/game_io/game_class_packet.cc	2014-10-03 19:24:49 +0000
@@ -26,8 +26,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 2
-
+constexpr uint16_t kCurrentPacketVersion = 2;
 
 void GameClassPacket::read
 	(FileSystem & fs, Game & game, MapObjectLoader *)
@@ -36,12 +35,12 @@
 		FileRead fr;
 		fr.open(fs, "binary/game_class");
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version <= CURRENT_PACKET_VERSION) {
+		if (packet_version <= kCurrentPacketVersion) {
 			fr.signed_16(); // This used to be game speed
 			game.gametime_ = fr.unsigned_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("game class: %s", e.what());
 	}
@@ -55,8 +54,7 @@
 {
 	FileWrite fw;
 
-	// Packet version
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// State is running, we do not need to save this
 	// Save speed

=== modified file 'src/game_io/game_cmd_queue_packet.cc'
--- src/game_io/game_cmd_queue_packet.cc	2014-09-20 09:37:47 +0000
+++ src/game_io/game_cmd_queue_packet.cc	2014-10-03 19:24:49 +0000
@@ -29,8 +29,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 2
-
+constexpr uint16_t kCurrentPacketVersion = 2;
 
 void GameCmdQueuePacket::read
 	(FileSystem & fs, Game & game, MapObjectLoader * const ol)
@@ -39,7 +38,7 @@
 		FileRead fr;
 		fr.open(fs, "binary/cmd_queue");
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			CmdQueue & cmdq = game.cmdqueue();
 
 			// nothing to be done for m_game
@@ -60,16 +59,6 @@
 				item.category = fr.signed_32();
 				item.serial = fr.unsigned_32();
 
-				if (packet_id == 129) {
-					// For backwards compatibility with savegames up to build15:
-					// Discard old CheckEventChain commands
-					fr.unsigned_16(); // CheckEventChain version
-					fr.unsigned_16(); // GameLogicCommand version
-					fr.unsigned_32(); // GameLogicCommand duetime
-					fr.unsigned_16(); // CheckEventChain ID
-					continue;
-				}
-
 				GameLogicCommand & cmd =
 					QueueCmdFactory::create_correct_queue_command(packet_id);
 				cmd.read(fr, game, *ol);
@@ -79,9 +68,9 @@
 				cmdq.m_cmds[cmd.duetime() % CMD_QUEUE_BUCKET_SIZE].push(item);
 				++ cmdq.m_ncmds;
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("command queue: %s", e.what());
 	}
@@ -93,8 +82,7 @@
 {
 	FileWrite fw;
 
-	// Now packet version
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	const CmdQueue & cmdq = game.cmdqueue();
 

=== modified file 'src/game_io/game_interactive_player_packet.cc'
--- src/game_io/game_interactive_player_packet.cc	2014-09-20 09:37:47 +0000
+++ src/game_io/game_interactive_player_packet.cc	2014-10-03 19:24:49 +0000
@@ -31,8 +31,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 2
-
+constexpr uint16_t kCurrentPacketVersion = 2;
 
 void GameInteractivePlayerPacket::read
 	(FileSystem & fs, Game & game, MapObjectLoader *)
@@ -41,7 +40,7 @@
 		FileRead fr;
 		fr.open(fs, "binary/interactive_player");
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			PlayerNumber player_number = fr.unsigned_8();
 			if (!(0 < player_number && player_number <= game.map().get_nrplayers())) {
 				throw GameDataError("Invalid player number: %i.", player_number);
@@ -77,9 +76,9 @@
 			if (InteractivePlayer * const ipl = game.get_ipl()) {
 				ipl->set_player_number(player_number);
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("interactive player: %s", e.what());
 	}
@@ -93,8 +92,7 @@
 {
 	FileWrite fw;
 
-	// Now packet version
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	InteractiveBase * const ibase = game.get_ibase();
 	InteractivePlayer * const iplayer = game.get_ipl();

=== modified file 'src/game_io/game_player_economies_packet.cc'
--- src/game_io/game_player_economies_packet.cc	2014-09-20 09:37:47 +0000
+++ src/game_io/game_player_economies_packet.cc	2014-10-03 19:24:49 +0000
@@ -32,8 +32,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 3
-
+constexpr uint16_t kCurrentPacketVersion = 3;
 
 void GamePlayerEconomiesPacket::read
 	(FileSystem & fs, Game & game, MapObjectLoader *)
@@ -46,7 +45,7 @@
 		FileRead fr;
 		fr.open(fs, "binary/player_economies");
 		uint16_t const packet_version = fr.unsigned_16();
-		if (3 <= packet_version && packet_version <= CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			iterate_players_existing(p, nr_players, game, player)
 				try {
 					Player::Economies & economies = player->m_economies;
@@ -80,9 +79,9 @@
 				} catch (const WException & e) {
 					throw GameDataError("player %u: %s", p, e.what());
 				}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("economies: %s", e.what());
 	}
@@ -96,7 +95,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	const Map & map = game.map();
 	const Field & field_0 = map[0];

=== modified file 'src/game_io/game_player_info_packet.cc'
--- src/game_io/game_player_info_packet.cc	2014-09-20 09:37:47 +0000
+++ src/game_io/game_player_info_packet.cc	2014-10-03 19:24:49 +0000
@@ -30,20 +30,19 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 15
-
+constexpr uint16_t kCurrentPacketVersion = 16;
 
 void GamePlayerInfoPacket::read
-	(FileSystem & fs, Game & game, MapObjectLoader *)
-{
+	(FileSystem & fs, Game & game, MapObjectLoader *) {
 	try {
 		FileRead fr;
 		fr.open(fs, "binary/player_info");
 		uint16_t const packet_version = fr.unsigned_16();
-		if (5 <= packet_version && packet_version <= CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			uint32_t const max_players = fr.unsigned_16();
 			for (uint32_t i = 1; i < max_players + 1; ++i) {
 				game.remove_player(i);
+
 				if (fr.unsigned_8()) {
 					bool const see_all = fr.unsigned_8();
 
@@ -52,28 +51,16 @@
 						throw GameDataError
 							("player number (%i) is out of range (1 .. %u)",
 							 plnum, MAX_PLAYERS);
-					Widelands::TeamNumber team = 0;
-					if (packet_version >= 9)
-						team = fr.unsigned_8();
 
+					Widelands::TeamNumber team = fr.unsigned_8();
 					char const * const tribe_name = fr.c_string();
-
 					std::string const name = fr.c_string();
-
 					game.add_player(plnum, 0, tribe_name, name, team);
+
 					Player & player = game.player(plnum);
 					player.set_see_all(see_all);
-
 					player.set_ai(fr.c_string());
-
-					if (packet_version >= 15)
-						player.read_statistics(fr, 3);
-					else if (packet_version >= 14)
-						player.read_statistics(fr, 2);
-					else if (packet_version >= 12)
-						player.read_statistics(fr, 1);
-					else
-						player.read_statistics(fr, 0);
+					player.read_statistics(fr);
 
 					player.m_casualties = fr.unsigned_32();
 					player.m_kills      = fr.unsigned_32();
@@ -83,14 +70,10 @@
 					player.m_civil_blds_defeated = fr.unsigned_32();
 				}
 			}
-
-			if (packet_version <= 10)
-				game.read_statistics(fr, 3);
-			else
-				game.read_statistics(fr, 4);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+			game.read_statistics(fr);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("player info: %s", e.what());
 	}
@@ -102,8 +85,7 @@
 {
 	FileWrite fw;
 
-	// Now packet version
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// Number of (potential) players
 	PlayerNumber const nr_players = game.map().get_nrplayers();

=== modified file 'src/game_io/game_preload_packet.cc'
--- src/game_io/game_preload_packet.cc	2014-09-20 09:37:47 +0000
+++ src/game_io/game_preload_packet.cc	2014-10-03 19:24:49 +0000
@@ -40,10 +40,8 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 5
-#define PLAYERS_AMOUNT_KEY_V4 "player_amount"
-#define MINIMAP_FILENAME "minimap.png"
-
+constexpr uint16_t kCurrentPacketVersion = 5;
+constexpr const char* kMinimapFilename = "minimap.png";
 
 void GamePreloadPacket::read
 	(FileSystem & fs, Game &, MapObjectLoader * const)
@@ -54,20 +52,19 @@
 		Section & s = prof.get_safe_section("global");
 		int32_t const packet_version = s.get_int("packet_version");
 
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			m_gametime = s.get_safe_int("gametime");
 			m_mapname = s.get_safe_string("mapname");
 
 			m_background = s.get_safe_string("background");
 			m_player_nr = s.get_safe_int("player_nr");
 			m_win_condition = s.get_safe_string("win_condition");
-			m_number_of_players = s.get_safe_int(PLAYERS_AMOUNT_KEY_V4);
-			if (fs.file_exists(MINIMAP_FILENAME)) {
-				m_minimap_path = MINIMAP_FILENAME;
+			m_number_of_players = s.get_safe_int("player_amount");
+			if (fs.file_exists(kMinimapFilename)) {
+				m_minimap_path = kMinimapFilename;
 			}
 		} else {
-			throw GameDataError
-				("unknown/unhandled version %i", packet_version);
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
 		}
 	} catch (const WException & e) {
 		throw GameDataError("preload: %s", e.what());
@@ -84,7 +81,7 @@
 
 	InteractivePlayer const * const ipl = game.get_ipl();
 
-	s.set_int   ("packet_version", CURRENT_PACKET_VERSION);
+	s.set_int   ("packet_version", kCurrentPacketVersion);
 
 	//  save some kind of header.
 	s.set_int   ("gametime",       game.get_gametime());
@@ -103,7 +100,7 @@
 			}
 		}
 	}
-	s.set_int(PLAYERS_AMOUNT_KEY_V4, game.player_manager()->get_number_of_players());
+	s.set_int("player_amount", game.player_manager()->get_number_of_players());
 
 	s.set_string("background", map.get_background());
 	s.set_string("win_condition", game.get_win_condition_displayname());
@@ -116,7 +113,7 @@
 	if (ipl != nullptr) {
 		const MiniMapLayer flags = MiniMapLayer::Owner | MiniMapLayer::Building | MiniMapLayer::Terrain;
 		const Point& vp = ipl->get_viewpoint();
-		std::unique_ptr< ::StreamWrite> sw(fs.open_stream_write(MINIMAP_FILENAME));
+		std::unique_ptr< ::StreamWrite> sw(fs.open_stream_write(kMinimapFilename));
 		if (sw.get() != nullptr) {
 			write_minimap_image(game, &ipl->player(), vp, flags, sw.get());
 			sw->flush();

=== modified file 'src/logic/battle.cc'
--- src/logic/battle.cc	2014-09-20 09:37:47 +0000
+++ src/logic/battle.cc	2014-10-03 19:24:49 +0000
@@ -338,9 +338,9 @@
 ==============================
 */
 
-#define BATTLE_SAVEGAME_VERSION 2
+constexpr uint8_t kCurrentPacketVersion = 2;
 
-void Battle::Loader::load(FileRead & fr, uint8_t const version)
+void Battle::Loader::load(FileRead & fr)
 {
 	MapObject::Loader::load(fr);
 
@@ -349,10 +349,7 @@
 	battle.m_creationtime  = fr.signed_32();
 	battle.m_readyflags    = fr.unsigned_8();
 	battle.m_first_strikes = fr.unsigned_8();
-
-	if (version == BATTLE_SAVEGAME_VERSION)
-		battle.m_damage     = fr.unsigned_32();
-
+	battle.m_damage     = fr.unsigned_32();
 	m_first                = fr.unsigned_32();
 	m_second               = fr.unsigned_32();
 }
@@ -383,7 +380,7 @@
 	(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
 {
 	fw.unsigned_8(HeaderBattle);
-	fw.unsigned_8(BATTLE_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 
 	MapObject::save(egbase, mos, fw);
 
@@ -406,12 +403,13 @@
 	try {
 		// Header has been peeled away by caller
 
-		uint8_t const version = fr.unsigned_8();
-		if (version <= BATTLE_SAVEGAME_VERSION) {
+		uint8_t const packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersion) {
 			loader->init(egbase, mol, *new Battle);
-			loader->load(fr, version);
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+			loader->load(fr);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const std::exception & e) {
 		throw wexception("Loading Battle: %s", e.what());
 	}

=== modified file 'src/logic/battle.h'
--- src/logic/battle.h	2014-09-19 12:54:54 +0000
+++ src/logic/battle.h	2014-10-03 19:24:49 +0000
@@ -80,7 +80,7 @@
 
 private:
 	struct Loader : public MapObject::Loader {
-		virtual void load(FileRead &, uint8_t version);
+		virtual void load(FileRead &);
 		void load_pointers() override;
 
 		Serial m_first;

=== modified file 'src/logic/bob.cc'
--- src/logic/bob.cc	2014-09-20 09:37:47 +0000
+++ src/logic/bob.cc	2014-10-03 19:24:49 +0000
@@ -1065,7 +1065,7 @@
 ==============================
 */
 
-#define BOB_SAVEGAME_VERSION 1
+constexpr uint8_t kCurrentPacketVersion = 1;
 
 Bob::Loader::Loader()
 {
@@ -1075,74 +1075,80 @@
 {
 	MapObject::Loader::load(fr);
 
-	uint8_t version = fr.unsigned_8();
-	if (version != BOB_SAVEGAME_VERSION)
-		throw GameDataError("unknown/unhandled version: %u", version);
-
-	Bob & bob = get<Bob>();
-
-	if (PlayerNumber owner_number = fr.unsigned_8()) {
-		if (owner_number > egbase().map().get_nrplayers())
-			throw GameDataError
-				("owner number is %u but there are only %u players",
-				 owner_number, egbase().map().get_nrplayers());
-
-		Player * owner = egbase().get_player(owner_number);
-		if (!owner)
-			throw GameDataError("owning player %u does not exist", owner_number);
-
-		bob.set_owner(owner);
-	}
-
-	bob.set_position(egbase(), read_coords_32(&fr));
-
-	std::string animname = fr.c_string();
-	bob.m_anim = animname.size() ? bob.descr().get_animation(animname) : 0;
-	bob.m_animstart = fr.signed_32();
-	bob.m_walking = static_cast<WalkingDir>(read_direction_8_allow_null(&fr));
-	if (bob.m_walking) {
-		bob.m_walkstart = fr.signed_32();
-		bob.m_walkend = fr.signed_32();
-	}
-
-	bob.m_actid = fr.unsigned_32();
-	bob.m_signal = fr.c_string();
-
-	uint32_t stacksize = fr.unsigned_32();
-	bob.m_stack.resize(stacksize);
-	states.resize(stacksize);
-	for (uint32_t i = 0; i < stacksize; ++i) {
-		State & state = bob.m_stack[i];
-		LoadState & loadstate = states[i];
-
-		state.task = get_task(fr.c_string());
-		state.ivar1 = fr.signed_32();
-		state.ivar2 = fr.signed_32();
-		state.ivar3 = fr.signed_32();
-		loadstate.objvar1 = fr.unsigned_32();
-		state.svar1 = fr.c_string();
-		state.coords = read_coords_32_allow_null(&fr, egbase().map().extent());
-
-		if (fr.unsigned_8()) {
-			uint32_t anims[6];
-			for (int j = 0; j < 6; ++j)
-				anims[j] = bob.descr().get_animation(fr.c_string());
-			state.diranims = DirAnimations(anims[0], anims[1], anims[2], anims[3], anims[4], anims[5]);
-		}
-
-		if (fr.unsigned_8()) {
-			state.path = new Path;
-			state.path->load(fr, egbase().map());
-		}
-
-		if (fr.unsigned_8()) {
-			state.route = new Route;
-			state.route->load(loadstate.route, fr);
-		}
-
-		std::string programname = fr.c_string();
-		if (programname.size())
-			state.program = get_program(programname);
+	try {
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersion) {
+
+			Bob & bob = get<Bob>();
+
+			if (PlayerNumber owner_number = fr.unsigned_8()) {
+				if (owner_number > egbase().map().get_nrplayers())
+					throw GameDataError
+						("owner number is %u but there are only %u players",
+						 owner_number, egbase().map().get_nrplayers());
+
+				Player * owner = egbase().get_player(owner_number);
+				if (!owner)
+					throw GameDataError("owning player %u does not exist", owner_number);
+
+				bob.set_owner(owner);
+			}
+
+			bob.set_position(egbase(), read_coords_32(&fr));
+
+			std::string animname = fr.c_string();
+			bob.m_anim = animname.size() ? bob.descr().get_animation(animname) : 0;
+			bob.m_animstart = fr.signed_32();
+			bob.m_walking = static_cast<WalkingDir>(read_direction_8_allow_null(&fr));
+			if (bob.m_walking) {
+				bob.m_walkstart = fr.signed_32();
+				bob.m_walkend = fr.signed_32();
+			}
+
+			bob.m_actid = fr.unsigned_32();
+			bob.m_signal = fr.c_string();
+
+			uint32_t stacksize = fr.unsigned_32();
+			bob.m_stack.resize(stacksize);
+			states.resize(stacksize);
+			for (uint32_t i = 0; i < stacksize; ++i) {
+				State & state = bob.m_stack[i];
+				LoadState & loadstate = states[i];
+
+				state.task = get_task(fr.c_string());
+				state.ivar1 = fr.signed_32();
+				state.ivar2 = fr.signed_32();
+				state.ivar3 = fr.signed_32();
+				loadstate.objvar1 = fr.unsigned_32();
+				state.svar1 = fr.c_string();
+				state.coords = read_coords_32_allow_null(&fr, egbase().map().extent());
+
+				if (fr.unsigned_8()) {
+					uint32_t anims[6];
+					for (int j = 0; j < 6; ++j)
+						anims[j] = bob.descr().get_animation(fr.c_string());
+					state.diranims = DirAnimations(anims[0], anims[1], anims[2], anims[3], anims[4], anims[5]);
+				}
+
+				if (fr.unsigned_8()) {
+					state.path = new Path;
+					state.path->load(fr, egbase().map());
+				}
+
+				if (fr.unsigned_8()) {
+					state.route = new Route;
+					state.route->load(loadstate.route, fr);
+				}
+
+				std::string programname = fr.c_string();
+				if (programname.size())
+					state.program = get_program(programname);
+			}
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
+	} catch (const WException & e) {
+		throw wexception("loading bob: %s", e.what());
 	}
 }
 
@@ -1198,7 +1204,7 @@
 {
 	MapObject::save(eg, mos, fw);
 
-	fw.unsigned_8(BOB_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 
 	fw.unsigned_8(m_owner ? m_owner->player_number() : 0);
 	write_coords_32(&fw, m_position);

=== modified file 'src/logic/carrier.cc'
--- src/logic/carrier.cc	2014-09-20 09:37:47 +0000
+++ src/logic/carrier.cc	2014-10-03 19:24:49 +0000
@@ -586,7 +586,7 @@
 ==============================
 */
 
-#define CARRIER_SAVEGAME_VERSION 1
+constexpr uint8_t kCurrentPacketVersion = 1;
 
 Carrier::Loader::Loader()
 {
@@ -596,12 +596,18 @@
 {
 	Worker::Loader::load(fr);
 
-	uint8_t version = fr.unsigned_8();
-	if (version != CARRIER_SAVEGAME_VERSION)
-		throw GameDataError("unknown/unhandled version %u", version);
+	try {
 
-	Carrier & carrier = get<Carrier>();
-	carrier.m_promised_pickup_to = fr.signed_32();
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersion) {
+			Carrier & carrier = get<Carrier>();
+			carrier.m_promised_pickup_to = fr.signed_32();
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
+	} catch (const WException & e) {
+		throw wexception("loading carrier: %s", e.what());
+	}
 }
 
 const Bob::Task * Carrier::Loader::get_task(const std::string & name)
@@ -621,7 +627,7 @@
 {
 	Worker::do_save(egbase, mos, fw);
 
-	fw.unsigned_8(CARRIER_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 	fw.signed_32(m_promised_pickup_to);
 }
 

=== modified file 'src/logic/cmd_calculate_statistics.cc'
--- src/logic/cmd_calculate_statistics.cc	2014-09-20 09:37:47 +0000
+++ src/logic/cmd_calculate_statistics.cc	2014-10-03 19:24:49 +0000
@@ -34,17 +34,18 @@
 		 (game.get_gametime() + STATISTICS_SAMPLE_TIME));
 }
 
-#define CMD_CALCULATE_STATISTICS_VERSION 1
+constexpr uint16_t kCurrentPacketVersion = 1;
+
 void CmdCalculateStatistics::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CMD_CALCULATE_STATISTICS_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			GameLogicCommand::read(fr, egbase, mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("calculate statistics function: %s", e.what());
 	}
@@ -52,7 +53,7 @@
 void CmdCalculateStatistics::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(CMD_CALCULATE_STATISTICS_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 	GameLogicCommand::write(fw, egbase, mos);
 
 }

=== modified file 'src/logic/cmd_incorporate.cc'
--- src/logic/cmd_incorporate.cc	2014-09-20 09:37:47 +0000
+++ src/logic/cmd_incorporate.cc	2014-10-03 19:24:49 +0000
@@ -28,12 +28,14 @@
 
 namespace Widelands {
 
+constexpr uint16_t kCurrentPacketVersion = 1;
+
 void CmdIncorporate::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CMD_INCORPORATE_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			GameLogicCommand::read(fr, egbase, mol);
 			uint32_t const worker_serial = fr.unsigned_32();
 			try {
@@ -41,9 +43,10 @@
 			} catch (const WException & e) {
 				throw wexception("worker %u: %s", worker_serial, e.what());
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
+
 	} catch (const WException & e) {
 		throw wexception("incorporate: %s", e.what());
 	}
@@ -53,8 +56,7 @@
 void CmdIncorporate::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	// First, write version
-	fw.unsigned_16(CMD_INCORPORATE_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// Write base classes
 	GameLogicCommand::write(fw, egbase, mos);

=== modified file 'src/logic/cmd_incorporate.h'
--- src/logic/cmd_incorporate.h	2014-09-19 12:54:54 +0000
+++ src/logic/cmd_incorporate.h	2014-10-03 19:24:49 +0000
@@ -25,8 +25,6 @@
 
 namespace Widelands {
 
-#define CMD_INCORPORATE_VERSION 1
-
 struct CmdIncorporate : public GameLogicCommand {
 	CmdIncorporate() : GameLogicCommand(0), worker(nullptr) {} // For savegame loading
 	CmdIncorporate (int32_t const t, Worker * const w)

=== modified file 'src/logic/cmd_luacoroutine.cc'
--- src/logic/cmd_luacoroutine.cc	2014-09-20 09:37:47 +0000
+++ src/logic/cmd_luacoroutine.cc	2014-10-03 19:24:49 +0000
@@ -57,11 +57,12 @@
 	}
 }
 
-#define CMD_LUACOROUTINE_VERSION 3
+constexpr uint16_t kCurrentPacketVersion = 3;
+
 void CmdLuaCoroutine::read(FileRead& fr, EditorGameBase& egbase, MapObjectLoader& mol) {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CMD_LUACOROUTINE_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			GameLogicCommand::read(fr, egbase, mol);
 
 			// This function is only called when saving/loading savegames. So save
@@ -70,9 +71,9 @@
 			assert(lgi); // If this is not true, this is not a game.
 
 			m_cr = lgi->read_coroutine(fr);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("lua function: %s", e.what());
 	}
@@ -80,7 +81,7 @@
 void CmdLuaCoroutine::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(CMD_LUACOROUTINE_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 	GameLogicCommand::write(fw, egbase, mos);
 
 	// This function is only called when saving/loading savegames. So save to

=== modified file 'src/logic/cmd_luascript.cc'
--- src/logic/cmd_luascript.cc	2014-09-20 09:37:47 +0000
+++ src/logic/cmd_luascript.cc	2014-10-03 19:24:49 +0000
@@ -44,18 +44,19 @@
 	return;
 }
 
-#define CMD_LUASCRIPT_VERSION 1
+constexpr uint16_t kCurrentPacketVersion = 1;
+
 void CmdLuaScript::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CMD_LUASCRIPT_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			GameLogicCommand::read(fr, egbase, mol);
 			script_ = fr.string();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("lua: %s", e.what());
 	}
@@ -63,7 +64,7 @@
 void CmdLuaScript::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(CMD_LUASCRIPT_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 	GameLogicCommand::write(fw, egbase, mos);
 
 	fw.string(script_);

=== modified file 'src/logic/cmd_queue.cc'
--- src/logic/cmd_queue.cc	2014-09-20 09:37:47 +0000
+++ src/logic/cmd_queue.cc	2014-10-03 19:24:49 +0000
@@ -138,8 +138,7 @@
 
 Command::~Command () {}
 
-
-#define BASE_CMD_VERSION 1
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 /**
  * Write variables from the base command to a file.
@@ -155,8 +154,7 @@
 #endif
 	 MapObjectSaver &)
 {
-	// First version
-	fw.unsigned_16(BASE_CMD_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// Write duetime
 	assert(egbase.get_gametime() <= duetime());
@@ -173,15 +171,15 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == BASE_CMD_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			set_duetime(fr.unsigned_32());
 			int32_t const gametime = egbase.get_gametime();
 			if (duetime() < gametime)
 				throw GameDataError
 					("duetime (%i) < gametime (%i)", duetime(), gametime);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("game logic: %s", e.what());
 	}

=== modified file 'src/logic/critter.cc'
--- src/logic/critter.cc	2014-09-20 09:37:47 +0000
+++ src/logic/critter.cc	2014-10-03 19:24:49 +0000
@@ -379,7 +379,7 @@
 ==============================
 */
 
-#define CRITTER_SAVEGAME_VERSION 1
+constexpr uint8_t kCurrentPacketVersion = 1;
 
 Critter::Loader::Loader()
 {
@@ -408,8 +408,9 @@
 	try {
 		// The header has been peeled away by the caller
 
-		uint8_t const version = fr.unsigned_8();
-		if (1 <= version && version <= CRITTER_SAVEGAME_VERSION) {
+		uint8_t const packet_version = fr.unsigned_8();
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version  <= kCurrentPacketVersion) {
 			const std::string owner = fr.c_string();
 			std::string critter_name = fr.c_string();
 			const CritterDescr * descr = nullptr;
@@ -432,8 +433,9 @@
 
 			loader->init(egbase, mol, descr->create_object());
 			loader->load(fr);
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const std::exception & e) {
 		throw wexception("loading critter: %s", e.what());
 	}
@@ -445,7 +447,7 @@
 	(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
 {
 	fw.unsigned_8(HeaderCritter);
-	fw.unsigned_8(CRITTER_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 
 	std::string owner =
 		descr().get_owner_tribe() ? descr().get_owner_tribe()->name() : "world";

=== modified file 'src/logic/expedition_bootstrap.cc'
--- src/logic/expedition_bootstrap.cc	2014-09-20 09:37:47 +0000
+++ src/logic/expedition_bootstrap.cc	2014-10-03 19:24:49 +0000
@@ -260,12 +260,10 @@
 	}
 }
 
-void ExpeditionBootstrap::load
-	(uint32_t warehouse_packet_version, Warehouse& warehouse, FileRead& fr,
-	 Game& game, MapObjectLoader& mol)
+void ExpeditionBootstrap::load(uint32_t warehouse_packet_version, Warehouse& warehouse, FileRead& fr,
+										 Game& game, MapObjectLoader& mol)
 {
 	assert(warehouse_packet_version >= 6);
-
 	// Expedition workers
 	const uint8_t num_workers = fr.unsigned_8();
 	for (uint8_t i = 0; i < num_workers; ++i) {

=== modified file 'src/logic/expedition_bootstrap.h'
--- src/logic/expedition_bootstrap.h	2014-09-10 10:18:46 +0000
+++ src/logic/expedition_bootstrap.h	2014-10-03 19:24:49 +0000
@@ -75,9 +75,8 @@
 
 	// Save/Load this into a file. The actual data is stored in the buildingdata
 	// packet, and there in the warehouse data packet.
-	void load
-		(uint32_t warehouse_packet_version, Warehouse& warehouse,
-		 FileRead& fr, Game& game, MapObjectLoader& mol);
+	void load(uint32_t warehouse_packet_version, Warehouse& warehouse, FileRead& fr,
+				 Game& game, MapObjectLoader& mol);
 	void save(FileWrite& fw, Game& game, MapObjectSaver& mos);
 
 private:

=== modified file 'src/logic/game.cc'
--- src/logic/game.cc	2014-09-20 09:37:47 +0000
+++ src/logic/game.cc	2014-10-03 19:24:49 +0000
@@ -1066,56 +1066,49 @@
  * Read statistics data from a file.
  *
  * \param fr file to read from
- * \param version indicates the kind of statistics file; the current version
- *   is 4, support for older versions (used in widelands build <= 12) was
- *   dropped after the release of build 15
  */
-void Game::read_statistics(FileRead & fr, uint32_t const version)
+void Game::read_statistics(FileRead & fr)
 {
-	if (version >= 3) {
-		fr.unsigned_32(); // used to be last stats update time
-
-		// Read general statistics
-		uint32_t entries = fr.unsigned_16();
-		const PlayerNumber nr_players = map().get_nrplayers();
-		m_general_stats.resize(nr_players);
-
-		iterate_players_existing_novar(p, nr_players, *this) {
-			m_general_stats[p - 1].land_size       .resize(entries);
-			m_general_stats[p - 1].nr_workers      .resize(entries);
-			m_general_stats[p - 1].nr_buildings    .resize(entries);
-			m_general_stats[p - 1].nr_wares        .resize(entries);
-			m_general_stats[p - 1].productivity    .resize(entries);
-			m_general_stats[p - 1].nr_casualties   .resize(entries);
-			m_general_stats[p - 1].nr_kills        .resize(entries);
-			m_general_stats[p - 1].nr_msites_lost        .resize(entries);
-			m_general_stats[p - 1].nr_msites_defeated    .resize(entries);
-			m_general_stats[p - 1].nr_civil_blds_lost    .resize(entries);
-			m_general_stats[p - 1].nr_civil_blds_defeated.resize(entries);
-			m_general_stats[p - 1].miltary_strength.resize(entries);
-			m_general_stats[p - 1].custom_statistic.resize(entries);
+	fr.unsigned_32(); // used to be last stats update time
+
+	// Read general statistics
+	uint32_t entries = fr.unsigned_16();
+	const PlayerNumber nr_players = map().get_nrplayers();
+	m_general_stats.resize(nr_players);
+
+	iterate_players_existing_novar(p, nr_players, *this) {
+		m_general_stats[p - 1].land_size       .resize(entries);
+		m_general_stats[p - 1].nr_workers      .resize(entries);
+		m_general_stats[p - 1].nr_buildings    .resize(entries);
+		m_general_stats[p - 1].nr_wares        .resize(entries);
+		m_general_stats[p - 1].productivity    .resize(entries);
+		m_general_stats[p - 1].nr_casualties   .resize(entries);
+		m_general_stats[p - 1].nr_kills        .resize(entries);
+		m_general_stats[p - 1].nr_msites_lost        .resize(entries);
+		m_general_stats[p - 1].nr_msites_defeated    .resize(entries);
+		m_general_stats[p - 1].nr_civil_blds_lost    .resize(entries);
+		m_general_stats[p - 1].nr_civil_blds_defeated.resize(entries);
+		m_general_stats[p - 1].miltary_strength.resize(entries);
+		m_general_stats[p - 1].custom_statistic.resize(entries);
+	}
+
+	iterate_players_existing_novar(p, nr_players, *this)
+		for (uint32_t j = 0; j < m_general_stats[p - 1].land_size.size(); ++j)
+		{
+			m_general_stats[p - 1].land_size       [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_workers      [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_buildings    [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_wares        [j] = fr.unsigned_32();
+			m_general_stats[p - 1].productivity    [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_casualties   [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_kills        [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_msites_lost        [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_msites_defeated    [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_civil_blds_lost    [j] = fr.unsigned_32();
+			m_general_stats[p - 1].nr_civil_blds_defeated[j] = fr.unsigned_32();
+			m_general_stats[p - 1].miltary_strength[j] = fr.unsigned_32();
+			m_general_stats[p - 1].custom_statistic[j] = fr.unsigned_32();
 		}
-
-		iterate_players_existing_novar(p, nr_players, *this)
-			for (uint32_t j = 0; j < m_general_stats[p - 1].land_size.size(); ++j)
-			{
-				m_general_stats[p - 1].land_size       [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_workers      [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_buildings    [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_wares        [j] = fr.unsigned_32();
-				m_general_stats[p - 1].productivity    [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_casualties   [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_kills        [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_msites_lost        [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_msites_defeated    [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_civil_blds_lost    [j] = fr.unsigned_32();
-				m_general_stats[p - 1].nr_civil_blds_defeated[j] = fr.unsigned_32();
-				m_general_stats[p - 1].miltary_strength[j] = fr.unsigned_32();
-				if (version == 4)
-					m_general_stats[p - 1].custom_statistic[j] = fr.unsigned_32();
-			}
-	} else
-		throw wexception("Unsupported version %i", version);
 }
 
 

=== modified file 'src/logic/game.h'
--- src/logic/game.h	2014-09-19 12:54:54 +0000
+++ src/logic/game.h	2014-10-03 19:24:49 +0000
@@ -191,7 +191,7 @@
 		return m_general_stats;
 	}
 
-	void read_statistics(FileRead &, uint32_t version);
+	void read_statistics(FileRead &);
 	void write_statistics(FileWrite &);
 
 	void sample_statistics();

=== modified file 'src/logic/game_data_error.cc'
--- src/logic/game_data_error.cc	2014-09-09 17:15:20 +0000
+++ src/logic/game_data_error.cc	2014-10-03 19:24:49 +0000
@@ -22,6 +22,10 @@
 #include <cstdarg>
 #include <cstdio>
 
+#include <boost/format.hpp>
+
+#include "base/i18n.h"
+
 namespace Widelands {
 
 GameDataError::GameDataError(char const * const fmt, ...)
@@ -36,4 +40,14 @@
 	m_what = buffer;
 }
 
+
+OldVersionError::OldVersionError(int32_t packet_version,
+											int32_t current_packet_version)
+{
+	m_what = (boost::format("\n\nOldVersionError: %s\n\nSaved Version: %i\nCurrent Version: %i")
+				 % _("This game was saved using an older version of Widelands and cannot be loaded anymore.")
+				 % static_cast<int>(packet_version)
+				 % static_cast<int>(current_packet_version)).str();
+}
+
 }

=== modified file 'src/logic/game_data_error.h'
--- src/logic/game_data_error.h	2014-09-09 17:15:20 +0000
+++ src/logic/game_data_error.h	2014-10-03 19:24:49 +0000
@@ -24,7 +24,7 @@
 
 namespace Widelands {
 
-/// Exceptiont that is thrown when game data (world/tribe definitions, maps,
+/// Exception that is thrown when game data (world/tribe definitions, maps,
 /// savegames or replays) are erroneous.
 struct GameDataError : public WException {
 	explicit GameDataError(char const * fmt, ...) PRINTF_FORMAT(2, 3);
@@ -34,6 +34,20 @@
 	GameDataError() {}
 };
 
+/// This exception's message compiles information for the user when an old savegame could not be
+/// loaded due to packet version mismatch.
+/// The main message is localizeable, the technical information is not.
+/// \param packet_version:         The version of the packet that Widelands is trying to load.
+/// \param current_packet_version: The packet version that Widelands is currently using.
+struct OldVersionError : public GameDataError {
+	explicit OldVersionError(int32_t packet_version,
+									 int32_t current_packet_version);
+
+	char const * what() const noexcept override {return m_what.c_str();}
+protected:
+	OldVersionError() {}
+};
+
 }
 
 #endif  // end of include guard: WL_LOGIC_GAME_DATA_ERROR_H

=== modified file 'src/logic/immovable.cc'
--- src/logic/immovable.cc	2014-09-20 09:37:47 +0000
+++ src/logic/immovable.cc	2014-10-03 19:24:49 +0000
@@ -610,15 +610,16 @@
 ==============================
 */
 
-#define IMMOVABLE_SAVEGAME_VERSION 5
+constexpr uint8_t kCurrentPacketVersionImmovable = 5;
 
-void Immovable::Loader::load(FileRead & fr, uint8_t const version)
+// Supporting older versions for map loading
+void Immovable::Loader::load(FileRead & fr, uint8_t const packet_version)
 {
 	BaseImmovable::Loader::load(fr);
 
 	Immovable & imm = ref_cast<Immovable, MapObject>(*get_object());
 
-	if (version >= 5) {
+	if (packet_version >= 5) {
 		PlayerNumber pn = fr.unsigned_8();
 		if (pn && pn <= MAX_PLAYERS) {
 			Player * plr = egbase().get_player(pn);
@@ -643,7 +644,7 @@
 			 imm.descr().name().c_str(), animname, imm.descr().get_animation_name(imm.m_anim).c_str());
 	}
 	imm.m_animstart = fr.signed_32();
-	if (version >= 4) {
+	if (packet_version >= 4) {
 		imm.m_anim_construction_total = fr.unsigned_32();
 		if (imm.m_anim_construction_total)
 			imm.m_anim_construction_done = fr.unsigned_32();
@@ -651,7 +652,7 @@
 
 	{ //  program
 		std::string program_name;
-		if (1 == version) {
+		if (1 == packet_version) {
 			program_name = fr.unsigned_8() ? fr.c_string() : "program";
 			std::transform
 				(program_name.begin(), program_name.end(), program_name.begin(),
@@ -683,10 +684,10 @@
 
 	imm.m_program_step = fr.signed_32();
 
-	if (version >= 3)
+	if (packet_version >= 3)
 		imm.m_reserved_by_worker = fr.unsigned_8();
 
-	if (version >= 4) {
+	if (packet_version >= 4) {
 		std::string dataname = fr.c_string();
 		if (!dataname.empty()) {
 			imm.set_action_data(ImmovableActionData::load(fr, imm, dataname));
@@ -718,7 +719,7 @@
 	// This is in front because it is required to obtain the description
 	// necessary to create the Immovable
 	fw.unsigned_8(HeaderImmovable);
-	fw.unsigned_8(IMMOVABLE_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersionImmovable);
 
 	if (const TribeDescr * const tribe = descr().get_owner_tribe())
 		fw.string(tribe->name());
@@ -764,8 +765,9 @@
 
 	try {
 		// The header has been peeled away by the caller
-		uint8_t const version = fr.unsigned_8();
-		if (1 <= version && version <= IMMOVABLE_SAVEGAME_VERSION) {
+		uint8_t const packet_version = fr.unsigned_8();
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version <= kCurrentPacketVersionImmovable) {
 
 			const std::string owner_name = fr.c_string();
 			const std::string old_name = fr.c_string();
@@ -796,11 +798,12 @@
 			}
 
 			loader->init(egbase, mol, *imm);
-			loader->load(fr, version);
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+			loader->load(fr, packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionImmovable);
+		}
 	} catch (const std::exception & e) {
-		throw wexception("immovable type %s", e.what());
+		throw wexception("immovable type: %s", e.what());
 	}
 
 	return loader.release();
@@ -1161,12 +1164,12 @@
 	}
 }
 
-#define CONSTRUCTION_DATA_VERSION 1
+constexpr uint8_t kCurrentPacketVersionConstructionData = 1;
 
 struct ActConstructionData : ImmovableActionData {
 	const char * name() const override {return "construction";}
 	void save(FileWrite & fw, Immovable & imm) override {
-		fw.unsigned_8(CONSTRUCTION_DATA_VERSION);
+		fw.unsigned_8(kCurrentPacketVersionConstructionData);
 		delivered.save(fw, *imm.descr().get_owner_tribe());
 	}
 
@@ -1174,11 +1177,12 @@
 		ActConstructionData * d = new ActConstructionData;
 
 		try {
-			uint8_t version = fr.unsigned_8();
-			if (version == CONSTRUCTION_DATA_VERSION) {
+			uint8_t packet_version = fr.unsigned_8();
+			if (packet_version == kCurrentPacketVersionConstructionData) {
 				d->delivered.load(fr, *imm.descr().get_owner_tribe());
-			} else
-				throw GameDataError("unknown version %u", version);
+			} else {
+				throw OldVersionError(packet_version, kCurrentPacketVersionConstructionData);
+			}
 		} catch (const WException & e) {
 			delete d;
 			d = nullptr;
@@ -1449,7 +1453,7 @@
 	molog("m_economy: %p\n", m_economy);
 }
 
-#define PLAYERIMMOVABLE_SAVEGAME_VERSION 1
+constexpr uint8_t kCurrentPacketVersionPlayerImmovable = 1;
 
 PlayerImmovable::Loader::Loader()
 {
@@ -1462,9 +1466,8 @@
 	PlayerImmovable & imm = get<PlayerImmovable>();
 
 	try {
-		uint8_t version = fr.unsigned_8();
-
-		if (1 <= version && version <= PLAYERIMMOVABLE_SAVEGAME_VERSION) {
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersionPlayerImmovable) {
 			PlayerNumber owner_number = fr.unsigned_8();
 
 			if (!owner_number || owner_number > egbase().map().get_nrplayers())
@@ -1477,8 +1480,9 @@
 				throw GameDataError("owning player %u does not exist", owner_number);
 
 			imm.m_owner = owner;
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionPlayerImmovable);
+		}
 	} catch (const std::exception & e) {
 		throw wexception("loading player immovable: %s", e.what());
 	}
@@ -1488,7 +1492,7 @@
 {
 	BaseImmovable::save(egbase, mos, fw);
 
-	fw.unsigned_8(PLAYERIMMOVABLE_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersionPlayerImmovable);
 	fw.unsigned_8(owner().player_number());
 }
 

=== modified file 'src/logic/immovable.h'
--- src/logic/immovable.h	2014-09-14 11:31:58 +0000
+++ src/logic/immovable.h	2014-10-03 19:24:49 +0000
@@ -258,7 +258,7 @@
 	// Load/save support
 protected:
 	struct Loader : public BaseImmovable::Loader {
-		void load(FileRead &, uint8_t version);
+		void load(FileRead &, uint8_t packet_version);
 		void load_pointers() override;
 		void load_finish() override;
 	};

=== modified file 'src/logic/instances.cc'
--- src/logic/instances.cc	2014-09-20 09:37:47 +0000
+++ src/logic/instances.cc	2014-10-03 19:24:49 +0000
@@ -50,13 +50,14 @@
 		obj->destroy (game);
 }
 
-#define CMD_DESTROY_MAP_OBJECT_VERSION 1
+constexpr uint16_t kCurrentPacketVersionDestroyMapObject = 1;
+
 void CmdDestroyMapObject::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CMD_DESTROY_MAP_OBJECT_VERSION) {
+		if (packet_version == kCurrentPacketVersionDestroyMapObject) {
 			GameLogicCommand::read(fr, egbase, mol);
 			if (Serial const serial = fr.unsigned_32())
 				try {
@@ -66,9 +67,9 @@
 				}
 			else
 				obj_serial = 0;
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionDestroyMapObject);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("destroy map object: %s", e.what());
 	}
@@ -77,7 +78,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(CMD_DESTROY_MAP_OBJECT_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionDestroyMapObject);
 
 	// Write base classes
 	GameLogicCommand::write(fw, egbase, mos);
@@ -100,13 +101,14 @@
 	// the object must queue the next CMD_ACT itself if necessary
 }
 
-#define CMD_ACT_VERSION 1
+constexpr uint16_t kCurrentPacketVersionCmdAct = 1;
+
 void CmdAct::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CMD_ACT_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdAct) {
 			GameLogicCommand::read(fr, egbase, mol);
 			if (Serial const object_serial = fr.unsigned_32())
 				try {
@@ -118,9 +120,9 @@
 			else
 				obj_serial = 0;
 			arg = fr.unsigned_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdAct);
+		}
 	} catch (const WException & e) {
 		throw wexception("act: %s", e.what());
 	}
@@ -129,7 +131,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(CMD_ACT_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdAct);
 
 	// Write base classes
 	GameLogicCommand::write(fw, egbase, mos);
@@ -480,8 +482,7 @@
 	log("MO(%u,%s): %s", m_serial, descr().name().c_str(), buffer);
 }
 
-
-#define CURRENT_SAVEGAME_VERSION 1
+constexpr uint8_t kCurrentPacketVersionMapObject = 1;
 
 /**
  * Load the entire data package from the given file.
@@ -500,15 +501,17 @@
 			throw wexception
 				("header is %u, expected %u", header, HeaderMapObject);
 
-		uint8_t const version = fr.unsigned_8();
-		if (version != CURRENT_SAVEGAME_VERSION)
-			throw GameDataError("unknown/unhandled version %u", version);
+		uint8_t const packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersionMapObject) {
 
-		Serial const serial = fr.unsigned_32();
-		try {
-			mol().register_object<MapObject>(serial, *get_object());
-		} catch (const WException & e) {
-			throw wexception("%u: %s", serial, e.what());
+			Serial const serial = fr.unsigned_32();
+			try {
+				mol().register_object<MapObject>(serial, *get_object());
+			} catch (const WException & e) {
+				throw wexception("%u: %s", serial, e.what());
+			}
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionMapObject);
 		}
 	} catch (const WException & e) {
 		throw wexception("map object: %s", e.what());
@@ -548,7 +551,7 @@
 	(EditorGameBase &, MapObjectSaver & mos, FileWrite & fw)
 {
 	fw.unsigned_8(HeaderMapObject);
-	fw.unsigned_8(CURRENT_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersionMapObject);
 
 	fw.unsigned_32(mos.get_object_file_index(*this));
 }

=== modified file 'src/logic/path.cc'
--- src/logic/path.cc	2014-09-20 09:37:47 +0000
+++ src/logic/path.cc	2014-10-03 19:24:49 +0000
@@ -30,6 +30,8 @@
 
 namespace Widelands {
 
+constexpr uint8_t kCurrentPacketVersion = 1;
+
 Path::Path(CoordPath & o)
 	: m_start(o.get_start()), m_end(o.get_end()), m_path(o.steps())
 {
@@ -65,7 +67,7 @@
  */
 void Path::save(FileWrite & fw) const
 {
-	fw.unsigned_8(1); // version number
+	fw.unsigned_8(kCurrentPacketVersion);
 	write_coords_32(&fw, m_start);
 
 	// Careful: steps are stored in the reverse order in m_path
@@ -83,15 +85,21 @@
  */
 void Path::load(FileRead & fr, const Map & map)
 {
-	uint8_t version = fr.unsigned_8();
-	if (version != 1)
-		throw GameDataError("path: unknown version %u", version);
+	try {
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersion) {
 
-	m_start = m_end = read_coords_32(&fr, map.extent());
-	m_path.clear();
-	uint32_t steps = fr.unsigned_32();
-	while (steps--)
-		append(map, read_direction_8(&fr));
+			m_start = m_end = read_coords_32(&fr, map.extent());
+			m_path.clear();
+			uint32_t steps = fr.unsigned_32();
+			while (steps--)
+				append(map, read_direction_8(&fr));
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
+	} catch (const WException & e) {
+		throw GameDataError("player names and tribes: %s", e.what());
+	}
 }
 
 /*

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc	2014-09-20 09:37:47 +0000
+++ src/logic/player.cc	2014-10-03 19:24:49 +0000
@@ -1294,144 +1294,73 @@
  * Read statistics data from a file.
  *
  * \param fr source stream
- * \param version indicates the kind of statistics file, which may be
- *   0 - old style statistics (before WiHack 2010)
- *   1 - statistics with ware names
- *   2 - with consumption statistics
- *   3 - with stock statistics
  */
-void Player::read_statistics(FileRead & fr, uint32_t const version)
+void Player::read_statistics(FileRead & fr)
 {
-	 //version 1, 2 and 3 only differs in an additional statistic.
-	 //Use version 1 code for all of them
-	if ((version == 2) || (version == 1) || (version == 3)) {
-		uint16_t nr_wares = fr.unsigned_16();
-		uint16_t nr_entries = fr.unsigned_16();
-
-		for (uint32_t i = 0; i < m_current_produced_statistics.size(); ++i)
-			m_ware_productions[i].resize(nr_entries);
-
-		for (uint16_t i = 0; i < nr_wares; ++i) {
-			std::string name = fr.c_string();
-			WareIndex idx = tribe().ware_index(name);
-			if (idx == INVALID_INDEX) {
-				log
-					("Player %u statistics: unknown ware name %s",
-					 player_number(), name.c_str());
-				continue;
-			}
-
-			m_current_produced_statistics[idx] = fr.unsigned_32();
-
-			for (uint32_t j = 0; j < nr_entries; ++j)
-				m_ware_productions[idx][j] = fr.unsigned_32();
-		}
-
-		//read consumption statistics if it exists
-		if ((version == 2) || (version == 3)) {
-			nr_wares = fr.unsigned_16();
-			nr_entries = fr.unsigned_16();
-
-			for (uint32_t i = 0; i < m_current_consumed_statistics.size(); ++i)
-				m_ware_consumptions[i].resize(nr_entries);
-
-			for (uint16_t i = 0; i < nr_wares; ++i) {
-				std::string name = fr.c_string();
-				WareIndex idx = tribe().ware_index(name);
-				if (idx == INVALID_INDEX) {
-					log
-						("Player %u consumption statistics: unknown ware name %s",
-						player_number(), name.c_str());
-					continue;
-				}
-
-				m_current_consumed_statistics[idx] = fr.unsigned_32();
-
-				for (uint32_t j = 0; j < nr_entries; ++j)
-					m_ware_consumptions[idx][j] = fr.unsigned_32();
-			}
-
-			//read stock statistics if it exists
-			if (version == 3) {
-				nr_wares = fr.unsigned_16();
-				nr_entries = fr.unsigned_16();
-
-				for (uint32_t i = 0; i < m_ware_stocks.size(); ++i)
-					m_ware_stocks[i].resize(nr_entries);
-
-				for (uint16_t i = 0; i < nr_wares; ++i) {
-					std::string name = fr.c_string();
-					WareIndex idx = tribe().ware_index(name);
-					if (idx == INVALID_INDEX) {
-						log
-							("Player %u stock statistics: unknown ware name %s",
-							player_number(), name.c_str());
-						continue;
-					}
-
-					for (uint32_t j = 0; j < nr_entries; ++j)
-						m_ware_stocks[idx][j] = fr.unsigned_32();
-				}
-			}
-		}
-	} else if (version == 0) {
-		uint16_t nr_wares = fr.unsigned_16();
-		uint16_t nr_entries = fr.unsigned_16();
-
-		if (nr_wares > 0) {
-			if (nr_wares == tribe().get_nrwares()) {
-				assert(m_ware_productions.size() == nr_wares);
-				assert(m_current_produced_statistics.size() == nr_wares);
-
-				for (uint32_t i = 0; i < m_current_produced_statistics.size(); ++i) {
-					m_current_produced_statistics[i] = fr.unsigned_32();
-					m_ware_productions[i].resize(nr_entries);
-
-					for (uint32_t j = 0; j < m_ware_productions[i].size(); ++j)
-						m_ware_productions[i][j] = fr.unsigned_32();
-				}
-			} else {
-				log
-					("Statistics for player %u (%s) has %u ware types "
-					 "(should be %u). Statistics will be discarded.",
-					 player_number(), tribe().name().c_str(),
-					 nr_wares, tribe().get_nrwares());
-
-				// Eat and discard all data
-				for (uint32_t i = 0; i < nr_wares; ++i) {
-					fr.unsigned_32();
-
-					for (uint32_t j = 0; j < nr_entries; ++j)
-						fr.unsigned_32();
-				}
-			}
-		}
-	} else
-		throw wexception("Unsupported version %i", version);
-
-	//create empty consumption statistic if it is missing
-	if (version < 2) {
-		uint16_t nr_entries = m_ware_productions[0].size();
-
-		for (uint32_t i = 0; i < m_current_consumed_statistics.size(); ++i) {
-			m_ware_consumptions[i].resize(nr_entries);
-			m_current_consumed_statistics[i] = 0;
-
-			for (uint32_t j = 0; j < nr_entries; ++j)
-				m_ware_consumptions[i][j] = 0;
-		}
-	}
-
-	//create empty stock statistic if it is missing
-	if (version < 3) {
-		uint16_t nr_entries = m_ware_productions[0].size();
-
-		for (uint32_t i = 0; i < m_current_consumed_statistics.size(); ++i) {
-			m_ware_stocks[i].resize(nr_entries);
-
-			for (uint32_t j = 0; j < nr_entries; ++j)
-				m_ware_stocks[i][j] = 0;
-		}
+	uint16_t nr_wares = fr.unsigned_16();
+	uint16_t nr_entries = fr.unsigned_16();
+
+	for (uint32_t i = 0; i < m_current_produced_statistics.size(); ++i)
+		m_ware_productions[i].resize(nr_entries);
+
+	for (uint16_t i = 0; i < nr_wares; ++i) {
+		std::string name = fr.c_string();
+		WareIndex idx = tribe().ware_index(name);
+		if (idx == INVALID_INDEX) {
+			log
+				("Player %u statistics: unknown ware name %s",
+				 player_number(), name.c_str());
+			continue;
+		}
+
+		m_current_produced_statistics[idx] = fr.unsigned_32();
+
+		for (uint32_t j = 0; j < nr_entries; ++j)
+			m_ware_productions[idx][j] = fr.unsigned_32();
+	}
+
+	//read consumption statistics
+	nr_wares = fr.unsigned_16();
+	nr_entries = fr.unsigned_16();
+
+	for (uint32_t i = 0; i < m_current_consumed_statistics.size(); ++i)
+		m_ware_consumptions[i].resize(nr_entries);
+
+	for (uint16_t i = 0; i < nr_wares; ++i) {
+		std::string name = fr.c_string();
+		WareIndex idx = tribe().ware_index(name);
+		if (idx == INVALID_INDEX) {
+			log
+				("Player %u consumption statistics: unknown ware name %s",
+				player_number(), name.c_str());
+			continue;
+		}
+
+		m_current_consumed_statistics[idx] = fr.unsigned_32();
+
+		for (uint32_t j = 0; j < nr_entries; ++j)
+			m_ware_consumptions[idx][j] = fr.unsigned_32();
+	}
+
+	//read stock statistics
+	nr_wares = fr.unsigned_16();
+	nr_entries = fr.unsigned_16();
+
+	for (uint32_t i = 0; i < m_ware_stocks.size(); ++i)
+		m_ware_stocks[i].resize(nr_entries);
+
+	for (uint16_t i = 0; i < nr_wares; ++i) {
+		std::string name = fr.c_string();
+		WareIndex idx = tribe().ware_index(name);
+		if (idx == INVALID_INDEX) {
+			log
+				("Player %u stock statistics: unknown ware name %s",
+				player_number(), name.c_str());
+			continue;
+		}
+
+		for (uint32_t j = 0; j < nr_entries; ++j)
+			m_ware_stocks[idx][j] = fr.unsigned_32();
 	}
 
 	//all statistics should have the same size

=== modified file 'src/logic/player.h'
--- src/logic/player.h	2014-09-19 12:54:54 +0000
+++ src/logic/player.h	2014-10-03 19:24:49 +0000
@@ -504,7 +504,7 @@
 	std::vector<uint32_t> const * get_ware_stock_statistics
 		(WareIndex const) const;
 
-	void read_statistics(FileRead &, uint32_t version);
+	void read_statistics(FileRead &);
 	void write_statistics(FileWrite &) const;
 	void sample_statistics();
 	void ware_produced(WareIndex);

=== modified file 'src/logic/playercommand.cc'
--- src/logic/playercommand.cc	2014-09-20 09:37:47 +0000
+++ src/logic/playercommand.cc	2014-10-03 19:24:49 +0000
@@ -138,12 +138,13 @@
 /**
  * Write this player command to a file. Call this from base classes
  */
-#define PLAYER_COMMAND_VERSION 2
+constexpr uint16_t kCurrentPacketVersionPlayerCommand = 2;
+
 void PlayerCommand::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_COMMAND_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionPlayerCommand);
 
 	GameLogicCommand::write(fw, egbase, mos);
 	// Now sender
@@ -156,15 +157,15 @@
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (2 <= packet_version && packet_version <= PLAYER_COMMAND_VERSION) {
+		if (packet_version == kCurrentPacketVersionPlayerCommand) {
 			GameLogicCommand::read(fr, egbase, mol);
 			m_sender    = fr.unsigned_8 ();
 			if (!egbase.get_player(m_sender))
 				throw GameDataError("player %u does not exist", m_sender);
 			m_cmdserial = fr.unsigned_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionPlayerCommand);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("player command: %s", e.what());
 	}
@@ -191,22 +192,21 @@
 	ser.unsigned_32(serial);
 	ser.unsigned_8 (recurse);
 }
-#define PLAYER_CMD_BULLDOZE_VERSION 2
+
+constexpr uint16_t kCurrentPacketVersionCmdBulldoze = 2;
+
 void CmdBulldoze::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if
-			(1 <= packet_version &&
-			 packet_version <= PLAYER_CMD_BULLDOZE_VERSION)
-		{
+		if (packet_version == kCurrentPacketVersionCmdBulldoze) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<PlayerImmovable>(fr.unsigned_32(), mol);
 			recurse = 2 <= packet_version ? fr.unsigned_8() : false;
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdBulldoze);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("bulldoze: %s", e.what());
 	}
@@ -215,7 +215,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_BULLDOZE_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdBulldoze);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 	// Now serial
@@ -245,19 +245,22 @@
 	ser.signed_16  (bi);
 	write_coords_32  (&ser, coords);
 }
-#define PLAYER_CMD_BUILD_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionCmdBuild = 1;
+
 void CmdBuild::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_BUILD_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdBuild) {
 			PlayerCommand::read(fr, egbase, mol);
 			bi = fr.unsigned_16();
 			coords = read_coords_32(&fr, egbase.map().extent());
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdBuild);
+		}
+
 	} catch (const WException & e) {
 		throw GameDataError("build: %s", e.what());
 	}
@@ -267,7 +270,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_BUILD_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdBuild);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 	fw.unsigned_16(bi);
@@ -294,18 +297,20 @@
 	ser.unsigned_8 (sender());
 	write_coords_32  (&ser, coords);
 }
-#define PLAYER_CMD_BUILDFLAG_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionCmdBuildFlag = 1;
+
 void CmdBuildFlag::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_BUILDFLAG_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdBuildFlag) {
 			PlayerCommand::read(fr, egbase, mol);
 			coords = read_coords_32(&fr, egbase.map().extent());
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdBuildFlag);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("build flag: %s", e.what());
 	}
@@ -314,7 +319,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_BUILDFLAG_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdBuildFlag);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 	write_coords_32  (&fw, coords);
@@ -376,13 +381,15 @@
 	for (Path::StepVector::size_type i = 0; i < nsteps; ++i)
 		ser.unsigned_8(path ? (*path)[i] : steps[i]);
 }
-#define PLAYER_CMD_BUILDROAD_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionCmdBuildRoad = 1;
+
 void CmdBuildRoad::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_BUILDROAD_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdBuildRoad) {
 			PlayerCommand::read(fr, egbase, mol);
 			start = read_coords_32(&fr, egbase.map().extent());
 			nsteps = fr.unsigned_16();
@@ -390,9 +397,9 @@
 			steps = new char[nsteps];
 			for (Path::StepVector::size_type i = 0; i < nsteps; ++i)
 			steps[i] = fr.unsigned_8();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdBuildRoad);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("build road: %s", e.what());
 	}
@@ -401,7 +408,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_BUILDROAD_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdBuildRoad);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 	write_coords_32  (&fw, start);
@@ -435,19 +442,20 @@
 	ser.unsigned_32(serial);
 }
 
-#define PLAYER_CMD_FLAGACTION_VERSION 1
+constexpr uint16_t kCurrentPacketVersionCmdFlagAction = 1;
+
 void CmdFlagAction::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_FLAGACTION_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdFlagAction) {
 			PlayerCommand::read(fr, egbase, mol);
 			fr                             .unsigned_8 ();
 			serial = get_object_serial_or_zero<Flag>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdFlagAction);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("flag action: %s", e.what());
 	}
@@ -456,7 +464,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_FLAGACTION_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdFlagAction);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 	// Now action
@@ -486,18 +494,20 @@
 	ser.unsigned_8 (sender());
 	ser.unsigned_32(serial);
 }
-#define PLAYER_CMD_STOPBUILDING_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionCmdStartStopBuilding = 1;
+
 void CmdStartStopBuilding::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_STOPBUILDING_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdStartStopBuilding) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Building>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdStartStopBuilding);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("start/stop building: %s", e.what());
 	}
@@ -506,7 +516,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_STOPBUILDING_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdStartStopBuilding);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -537,12 +547,13 @@
 
 }
 
-#define PLAYER_CMD_SOLDIERPREFERENCE_VERSION 1
+constexpr uint16_t kCurrentPacketVersionSoldierPreference = 1;
+
 void CmdMilitarySiteSetSoldierPreference::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_SOLDIERPREFERENCE_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionSoldierPreference);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -558,13 +569,13 @@
 	try
 	{
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SOLDIERPREFERENCE_VERSION) {
+		if (packet_version == kCurrentPacketVersionSoldierPreference) {
 			PlayerCommand::read(fr, egbase, mol);
 			preference = fr.unsigned_8();
 			serial = get_object_serial_or_zero<MilitarySite>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionSoldierPreference);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("start/stop building: %s", e.what());
 	}
@@ -591,18 +602,20 @@
 	ser.unsigned_8 (sender());
 	ser.unsigned_32(serial);
 }
-#define PLAYER_CMD_EXPEDITION_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionExpedition = 1;
+
 void CmdStartOrCancelExpedition::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_EXPEDITION_VERSION) {
+		if (packet_version == kCurrentPacketVersionExpedition) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Warehouse>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionExpedition);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("start/stop building: %s", e.what());
 	}
@@ -611,7 +624,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_EXPEDITION_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionExpedition);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -642,19 +655,21 @@
 	ser.unsigned_32(serial);
 	ser.unsigned_16(bi);
 }
-#define PLAYER_CMD_ENHANCEBUILDING_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionCmdEnhanceBuilding = 1;
+
 void CmdEnhanceBuilding::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_ENHANCEBUILDING_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdEnhanceBuilding) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Building>(fr.unsigned_32(), mol);
 			bi = fr.unsigned_16();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdEnhanceBuilding);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("enhance building: %s", e.what());
 	}
@@ -663,7 +678,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_ENHANCEBUILDING_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdEnhanceBuilding);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -694,18 +709,20 @@
 	ser.unsigned_8 (sender());
 	ser.unsigned_32(serial);
 }
-#define PLAYER_CMD_DISMANTLEBUILDING_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionDismantleBuilding = 1;
+
 void CmdDismantleBuilding::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_DISMANTLEBUILDING_VERSION) {
+		if (packet_version == kCurrentPacketVersionDismantleBuilding) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Building>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionDismantleBuilding);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("dismantle building: %s", e.what());
 	}
@@ -714,7 +731,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_DISMANTLEBUILDING_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionDismantleBuilding);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -743,18 +760,20 @@
 	ser.unsigned_8 (sender());
 	ser.unsigned_32(serial);
 }
-#define PLAYER_CMD_EVICTWORKER_VERSION 1
+
+constexpr uint16_t kCurrentPacketVersionCmdEvictWorker = 1;
+
 void CmdEvictWorker::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_EVICTWORKER_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdEvictWorker) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Worker>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdEvictWorker);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("evict worker: %s", e.what());
 	}
@@ -763,7 +782,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_EVICTWORKER_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdEvictWorker);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -796,19 +815,21 @@
 	ser.unsigned_8 (dir);
 }
 
-#define PLAYER_CMD_SHIP_SCOUT_DIRECTION_VERSION 1
+constexpr uint16_t kCurrentPacketVersionShipScoutDirection = 1;
+
 void CmdShipScoutDirection::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SHIP_SCOUT_DIRECTION_VERSION) {
+		if (packet_version == kCurrentPacketVersionShipScoutDirection) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Ship>(fr.unsigned_32(), mol);
 			// direction
 			dir = fr.unsigned_8();
-		} else
-			throw GameDataError("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionShipScoutDirection);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("Ship scout: %s", e.what());
 	}
@@ -817,7 +838,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_SHIP_SCOUT_DIRECTION_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionShipScoutDirection);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -853,19 +874,21 @@
 	write_coords_32  (&ser, coords);
 }
 
-#define PLAYER_CMD_SHIP_CONSTRUCT_PORT_VERSION 1
+constexpr uint16_t kCurrentPacketVersionShipConstructPort = 1;
+
 void CmdShipConstructPort::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SHIP_CONSTRUCT_PORT_VERSION) {
+		if (packet_version == kCurrentPacketVersionShipConstructPort) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Ship>(fr.unsigned_32(), mol);
 			// Coords
 			coords = read_coords_32(&fr);
-		} else
-			throw GameDataError("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionShipConstructPort);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("Ship construct port: %s", e.what());
 	}
@@ -874,7 +897,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_SHIP_CONSTRUCT_PORT_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionShipConstructPort);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -910,18 +933,20 @@
 	ser.unsigned_8 (clockwise ? 1 : 0);
 }
 
-#define PLAYER_CMD_SHIP_EXPLORE_ISLAND_VERSION 1
+constexpr uint16_t kCurrentPacketVersionShipExploreIsland = 1;
+
 void CmdShipExploreIsland::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SHIP_EXPLORE_ISLAND_VERSION) {
+		if (packet_version == kCurrentPacketVersionShipExploreIsland) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Ship>(fr.unsigned_32(), mol);
 			clockwise = fr.unsigned_8() == 1;
-		} else
-			throw GameDataError("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionShipExploreIsland);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("Ship explore: %s", e.what());
 	}
@@ -930,7 +955,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_SHIP_EXPLORE_ISLAND_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionShipExploreIsland);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -964,17 +989,19 @@
 	ser.unsigned_32(serial);
 }
 
-#define PLAYER_CMD_SHIP_SINK_VERSION 1
+constexpr uint16_t kCurrentPacketVersionCmdShipSink = 1;
+
 void CmdShipSink::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SHIP_SINK_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdShipSink) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Ship>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdShipSink);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("Ship explore: %s", e.what());
 	}
@@ -983,7 +1010,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_SHIP_SINK_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdShipSink);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -1014,17 +1041,19 @@
 	ser.unsigned_32(serial);
 }
 
-#define PLAYER_CMD_SHIP_CANCELEXPEDITION_VERSION 1
+constexpr uint16_t kCurrentPacketVersionShipCancelExpedition = 1;
+
 void CmdShipCancelExpedition::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SHIP_CANCELEXPEDITION_VERSION) {
+		if (packet_version == kCurrentPacketVersionShipCancelExpedition) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Ship>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionShipCancelExpedition);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("Ship explore: %s", e.what());
 	}
@@ -1033,7 +1062,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_SHIP_CANCELEXPEDITION_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionShipCancelExpedition);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -1067,12 +1096,12 @@
 	psite->set_priority(m_type, m_index, m_priority);
 }
 
-#define PLAYER_CMD_SETWAREPRIORITY_VERSION 1
+constexpr uint16_t kCurrentPacketVersionCmdSetWarePriority = 1;
 
 void CmdSetWarePriority::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(PLAYER_CMD_SETWAREPRIORITY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdSetWarePriority);
 
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -1087,15 +1116,16 @@
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SETWAREPRIORITY_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdSetWarePriority) {
 			PlayerCommand::read(fr, egbase, mol);
 			m_serial = get_object_serial_or_zero<Building>(fr.unsigned_32(), mol);
 			m_type = fr.unsigned_8();
 			m_index = fr.signed_32();
 			m_priority = fr.signed_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdSetWarePriority);
+		}
+
 	} catch (const WException & e) {
 		throw GameDataError("set ware priority: %s", e.what());
 	}
@@ -1143,12 +1173,12 @@
 	b->waresqueue(m_index).set_max_fill(m_max_fill);
 }
 
-#define PLAYER_CMD_SETWAREMAXFILL_SIZE_VERSION 1
+constexpr uint16_t kCurrentPacketVersionCmdSetWareMaxFill = 1;
 
 void CmdSetWareMaxFill::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(PLAYER_CMD_SETWAREMAXFILL_SIZE_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdSetWareMaxFill);
 
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -1162,14 +1192,14 @@
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_SETWAREMAXFILL_SIZE_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdSetWareMaxFill) {
 			PlayerCommand::read(fr, egbase, mol);
 			m_serial = get_object_serial_or_zero<Building>(fr.unsigned_32(), mol);
 			m_index = fr.signed_32();
 			m_max_fill = fr.unsigned_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdSetWareMaxFill);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("set ware max fill: %s", e.what());
 	}
@@ -1257,12 +1287,12 @@
 			(ware_type(),  m_permanent, duetime());
 }
 
-#define PLAYER_CMD_SETWARETARGETQUANTITY_VERSION 2
+constexpr uint16_t kCurrentPacketVersionSetWareTargetQuantity = 2;
 
 void CmdSetWareTargetQuantity::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(PLAYER_CMD_SETWARETARGETQUANTITY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionSetWareTargetQuantity);
 	CmdChangeTargetQuantity::write(fw, egbase, mos);
 	fw.unsigned_32(m_permanent);
 }
@@ -1272,14 +1302,13 @@
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version <= PLAYER_CMD_SETWARETARGETQUANTITY_VERSION) {
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version  <= kCurrentPacketVersionSetWareTargetQuantity) {
 			CmdChangeTargetQuantity::read(fr, egbase, mol);
 			m_permanent = fr.unsigned_32();
-			if (packet_version == 1)
-				fr.unsigned_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionSetWareTargetQuantity);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("set ware target quantity: %s", e.what());
 	}
@@ -1324,12 +1353,12 @@
 	}
 }
 
-#define PLAYER_CMD_RESETWARETARGETQUANTITY_VERSION 1
+constexpr uint16_t kCurrentPacketVersionResetWareTargetQuantity = 1;
 
 void CmdResetWareTargetQuantity::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(PLAYER_CMD_RESETWARETARGETQUANTITY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionResetWareTargetQuantity);
 	CmdChangeTargetQuantity::write(fw, egbase, mos);
 }
 
@@ -1338,11 +1367,11 @@
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_RESETWARETARGETQUANTITY_VERSION)
+		if (packet_version == kCurrentPacketVersionResetWareTargetQuantity) {
 			CmdChangeTargetQuantity::read(fr, egbase, mol);
-		else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionResetWareTargetQuantity);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("reset target quantity: %s", e.what());
 	}
@@ -1379,12 +1408,12 @@
 			(ware_type(),  m_permanent, duetime());
 }
 
-#define PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION 2
+constexpr uint16_t kCurrentPacketVersionSetWorkerTargetQuantity = 2;
 
 void CmdSetWorkerTargetQuantity::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionSetWorkerTargetQuantity);
 	CmdChangeTargetQuantity::write(fw, egbase, mos);
 	fw.unsigned_32(m_permanent);
 }
@@ -1394,14 +1423,13 @@
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version <= PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION) {
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version  <= kCurrentPacketVersionSetWorkerTargetQuantity) {
 			CmdChangeTargetQuantity::read(fr, egbase, mol);
 			m_permanent = fr.unsigned_32();
-			if (packet_version == 1)
-				fr.unsigned_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionSetWorkerTargetQuantity);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("set worker target quantity: %s", e.what());
 	}
@@ -1446,12 +1474,12 @@
 	}
 }
 
-#define PLAYER_CMD_RESETWORKERTARGETQUANTITY_VERSION 1
+constexpr uint16_t kCurrentPacketVersionResetWorkerTargetQuantity = 1;
 
 void CmdResetWorkerTargetQuantity::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(PLAYER_CMD_RESETWORKERTARGETQUANTITY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionResetWorkerTargetQuantity);
 	CmdChangeTargetQuantity::write(fw, egbase, mos);
 }
 
@@ -1460,11 +1488,11 @@
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_RESETWORKERTARGETQUANTITY_VERSION) {
+		if (packet_version == kCurrentPacketVersionResetWorkerTargetQuantity) {
 			CmdChangeTargetQuantity::read(fr, egbase, mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionResetWorkerTargetQuantity);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("reset worker target quantity: %s", e.what());
 	}
@@ -1506,21 +1534,21 @@
 	ser.unsigned_16(value);
 }
 
+constexpr uint16_t kCurrentPacketVersionChangeTrainingOptions = 1;
 
-#define PLAYER_CMD_CHANGETRAININGOPTIONS_VERSION 1
 void CmdChangeTrainingOptions::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_CHANGETRAININGOPTIONS_VERSION) {
+		if (packet_version == kCurrentPacketVersionChangeTrainingOptions) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<TrainingSite>(fr.unsigned_32(), mol);
 			attribute = fr.unsigned_16();
 			value     = fr.unsigned_16();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionChangeTrainingOptions);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("change training options: %s", e.what());
 	}
@@ -1530,7 +1558,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_CHANGETRAININGOPTIONS_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionChangeTrainingOptions);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -1565,19 +1593,20 @@
 	ser.unsigned_32(soldier);
 }
 
-#define PLAYER_CMD_DROPSOLDIER_VERSION 1
+constexpr uint16_t kCurrentPacketVersionCmdDropSoldier = 1;
+
 void CmdDropSoldier::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_DROPSOLDIER_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdDropSoldier) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<PlayerImmovable>(fr.unsigned_32(), mol);
 			soldier = get_object_serial_or_zero<Soldier>(fr.unsigned_32(), mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdDropSoldier);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("drop soldier: %s", e.what());
 	}
@@ -1587,7 +1616,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_DROPSOLDIER_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdDropSoldier);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -1624,19 +1653,20 @@
 	ser.signed_16(val);
 }
 
-#define PLAYER_CMD_CHANGESOLDIERCAPACITY_VERSION 1
+constexpr uint16_t kCurrentPacketVersionChangeSoldierCapacity = 1;
+
 void CmdChangeSoldierCapacity::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_CHANGESOLDIERCAPACITY_VERSION) {
+		if (packet_version == kCurrentPacketVersionChangeSoldierCapacity) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<Building>(fr.unsigned_32(), mol);
 			val = fr.signed_16();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionChangeSoldierCapacity);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("change soldier capacity: %s", e.what());
 	}
@@ -1646,7 +1676,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_CHANGESOLDIERCAPACITY_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionChangeSoldierCapacity);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 
@@ -1706,21 +1736,22 @@
 	ser.unsigned_8 (number);
 }
 
-#define PLAYER_CMD_ENEMYFLAGACTION_VERSION 3
+constexpr uint16_t kCurrentPacketVersionCmdEnemyFlagAction = 3;
+
 void CmdEnemyFlagAction::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_CMD_ENEMYFLAGACTION_VERSION) {
+		if (packet_version == kCurrentPacketVersionCmdEnemyFlagAction) {
 			PlayerCommand::read(fr, egbase, mol);
 			fr           .unsigned_8 ();
 			serial = get_object_serial_or_zero<Flag>(fr.unsigned_32(), mol);
 			fr           .unsigned_8 ();
 			number   = fr.unsigned_8 ();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdEnemyFlagAction);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("enemy flag action: %s", e.what());
 	}
@@ -1730,7 +1761,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
 	// First, write version
-	fw.unsigned_16(PLAYER_CMD_ENEMYFLAGACTION_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionCmdEnemyFlagAction);
 	// Write base classes
 	PlayerCommand::write(fw, egbase, mos);
 	// Now action
@@ -1750,21 +1781,22 @@
 PlayerCommand (0, des.unsigned_8()), m_message_id(des.unsigned_32())
 {}
 
-#define PLAYER_MESSAGE_CMD_VERSION 1
+constexpr uint16_t kCurrentPacketVersionPlayerMessageCommand = 1;
+
 void PlayerMessageCommand::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
 		const uint16_t packet_version = fr.unsigned_16();
-		if (packet_version == PLAYER_MESSAGE_CMD_VERSION) {
+		if (packet_version == kCurrentPacketVersionPlayerMessageCommand) {
 			PlayerCommand::read(fr, egbase, mol);
 			m_message_id = MessageId(fr.unsigned_32());
 			if (!m_message_id)
 				throw GameDataError
 					("(player %u): message id is null", sender());
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionPlayerMessageCommand);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("player message: %s", e.what());
 	}
@@ -1773,7 +1805,7 @@
 void PlayerMessageCommand::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_16(PLAYER_MESSAGE_CMD_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionPlayerMessageCommand);
 	PlayerCommand::write(fw, egbase, mos);
 	fw.unsigned_32(mos.message_savers[sender() - 1][message_id()].value());
 }
@@ -1900,19 +1932,22 @@
 	ser.unsigned_8(m_policy);
 }
 
-#define PLAYER_CMD_SETSTOCKPOLICY_VERSION 1
+constexpr uint8_t kCurrentPacketVersionCmdSetStockPolicy = 1;
+
 void CmdSetStockPolicy::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
 {
 	try {
-		uint8_t version = fr.unsigned_8();
-		if (version != PLAYER_CMD_SETSTOCKPOLICY_VERSION)
-			throw GameDataError("unknown/unhandled version %u", version);
-		PlayerCommand::read(fr, egbase, mol);
-		m_warehouse = fr.unsigned_32();
-		m_isworker = fr.unsigned_8();
-		m_ware = WareIndex(fr.unsigned_8());
-		m_policy = static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersionCmdSetStockPolicy) {
+			PlayerCommand::read(fr, egbase, mol);
+			m_warehouse = fr.unsigned_32();
+			m_isworker = fr.unsigned_8();
+			m_ware = WareIndex(fr.unsigned_8());
+			m_policy = static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionCmdSetStockPolicy);
+		}
 	} catch (const std::exception & e) {
 		throw GameDataError("Cmd_SetStockPolicy: %s", e.what());
 	}
@@ -1921,7 +1956,7 @@
 void CmdSetStockPolicy::write
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 {
-	fw.unsigned_8(PLAYER_CMD_SETSTOCKPOLICY_VERSION);
+	fw.unsigned_8(kCurrentPacketVersionCmdSetStockPolicy);
 	PlayerCommand::write(fw, egbase, mos);
 	fw.unsigned_32(m_warehouse);
 	fw.unsigned_8(m_isworker);

=== modified file 'src/logic/replay.cc'
--- src/logic/replay.cc	2014-09-20 09:37:47 +0000
+++ src/logic/replay.cc	2014-10-03 19:24:49 +0000
@@ -36,8 +36,9 @@
 namespace Widelands {
 
 // File format definitions
-#define REPLAY_MAGIC 0x2E21A101
-#define REPLAY_VERSION 2
+constexpr uint32_t kReplayMagic = 0x2E21A101;
+constexpr uint8_t kCurrentPacketVersion = 2;
+constexpr uint32_t kSyncInterval = 200;
 
 enum {
 	pkt_end = 2,
@@ -45,9 +46,6 @@
 	pkt_syncreport = 4
 };
 
-#define SYNC_INTERVAL 200
-
-
 class CmdReplaySyncRead : public Command {
 public:
 	CmdReplaySyncRead(const uint32_t _duetime, const Md5Checksum & hash)
@@ -102,16 +100,16 @@
 				("%s is a replay from a version that is known to have desync "
 				 "problems",
 				 filename.c_str());
-		if (magic != REPLAY_MAGIC)
+		if (magic != kReplayMagic)
 			throw wexception
 				("%s apparently not a valid replay file", filename.c_str());
 
-		const uint8_t version = m_cmdlog->unsigned_8();
-		if (version < REPLAY_VERSION)
+		const uint8_t packet_version = m_cmdlog->unsigned_8();
+		if (packet_version < kCurrentPacketVersion)
 			throw wexception
-				("Replay of version %u is known to have desync problems", version);
-		if (version != REPLAY_VERSION)
-			throw GameDataError("unknown/unhandled version %u", version);
+				("Replay of version %u is known to have desync problems", packet_version);
+		if (packet_version != kCurrentPacketVersion)
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
 
 		game.rng().read_state(*m_cmdlog);
 	}
@@ -215,7 +213,7 @@
 			rw->send_sync (game.get_sync_hash());
 
 			game.enqueue_command
-				(new CmdReplaySyncWrite(duetime() + SYNC_INTERVAL));
+				(new CmdReplaySyncWrite(duetime() + kSyncInterval));
 		}
 	}
 };
@@ -248,11 +246,11 @@
 	log("Done reloading the game from replay\n");
 
 	game.enqueue_command
-		(new CmdReplaySyncWrite(game.get_gametime() + SYNC_INTERVAL));
+		(new CmdReplaySyncWrite(game.get_gametime() + kSyncInterval));
 
 	m_cmdlog = g_fs->open_stream_write(filename);
-	m_cmdlog->unsigned_32(REPLAY_MAGIC);
-	m_cmdlog->unsigned_8(REPLAY_VERSION);
+	m_cmdlog->unsigned_32(kReplayMagic);
+	m_cmdlog->unsigned_8(kCurrentPacketVersion);
 
 	game.rng().write_state(*m_cmdlog);
 }

=== modified file 'src/logic/requirements.cc'
--- src/logic/requirements.cc	2014-09-20 09:37:47 +0000
+++ src/logic/requirements.cc	2014-10-03 19:24:49 +0000
@@ -33,7 +33,7 @@
 	return !m || m->check(obj);
 }
 
-#define REQUIREMENTS_VERSION 3
+constexpr uint16_t kCurrentPacketVersion = 3;
 
 /**
  * Read this requirement from a file
@@ -43,11 +43,11 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == REQUIREMENTS_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			*this = RequirementsStorage::read(fr, egbase, mol);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw wexception("requirements: %s", e.what());
 	}
@@ -57,7 +57,7 @@
 	(FileWrite & fw, EditorGameBase & egbase, MapObjectSaver & mos)
 	const
 {
-	fw.unsigned_16(REQUIREMENTS_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	if (!m) {
 		fw.unsigned_16(0);

=== modified file 'src/logic/ship.cc'
--- src/logic/ship.cc	2014-09-20 09:37:47 +0000
+++ src/logic/ship.cc	2014-10-03 19:24:49 +0000
@@ -928,7 +928,7 @@
 ==============================
 */
 
-#define SHIP_SAVEGAME_VERSION 4
+constexpr uint8_t kCurrentPacketVersion = 4;
 
 Ship::Loader::Loader() :
 	m_lastdock(0),
@@ -942,53 +942,48 @@
 	return Bob::Loader::get_task(name);
 }
 
-void Ship::Loader::load(FileRead & fr, uint8_t version)
+void Ship::Loader::load(FileRead & fr)
 {
 	Bob::Loader::load(fr);
 
-	if (version >= 2) {
-		// The state the ship is in
-		if (version >= 3) {
-			m_ship_state = fr.unsigned_8();
-
-			// Expedition specific data
-			if
-				(m_ship_state == EXP_SCOUTING
-				 ||
-				 m_ship_state == EXP_WAITING
-				 ||
-				 m_ship_state == EXP_FOUNDPORTSPACE
-				 ||
-				 m_ship_state == EXP_COLONIZING)
-			{
-				m_expedition.reset(new Expedition());
-				// Currently seen port build spaces
-				m_expedition->seen_port_buildspaces.reset(new std::list<Coords>());
-				uint8_t numofports = fr.unsigned_8();
-				for (uint8_t i = 0; i < numofports; ++i)
-					m_expedition->seen_port_buildspaces->push_back(read_coords_32(&fr));
-				// Swimability of the directions
-				for (uint8_t i = 0; i < LAST_DIRECTION; ++i)
-					m_expedition->swimable[i] = (fr.unsigned_8() == 1);
-				// whether scouting or exploring
-				m_expedition->island_exploration = fr.unsigned_8() == 1;
-				// current direction
-				m_expedition->direction = fr.unsigned_8();
-				// Start coordinates of an island exploration
-				m_expedition->exploration_start = read_coords_32(&fr);
-				// Whether the exploration is done clockwise or counter clockwise
-				m_expedition->clockwise = fr.unsigned_8() == 1;
-			}
-		} else
-			m_ship_state = TRANSPORT;
-
-		m_lastdock = fr.unsigned_32();
-		m_destination = fr.unsigned_32();
-
-		m_items.resize(fr.unsigned_32());
-		for (ShippingItem::Loader& item_loader : m_items) {
-			item_loader.load(fr);
-		}
+	// The state the ship is in
+	m_ship_state = fr.unsigned_8();
+
+	// Expedition specific data
+	if
+		(m_ship_state == EXP_SCOUTING
+		 ||
+		 m_ship_state == EXP_WAITING
+		 ||
+		 m_ship_state == EXP_FOUNDPORTSPACE
+		 ||
+		 m_ship_state == EXP_COLONIZING)
+	{
+		m_expedition.reset(new Expedition());
+		// Currently seen port build spaces
+		m_expedition->seen_port_buildspaces.reset(new std::list<Coords>());
+		uint8_t numofports = fr.unsigned_8();
+		for (uint8_t i = 0; i < numofports; ++i)
+			m_expedition->seen_port_buildspaces->push_back(read_coords_32(&fr));
+		// Swimability of the directions
+		for (uint8_t i = 0; i < LAST_DIRECTION; ++i)
+			m_expedition->swimable[i] = (fr.unsigned_8() == 1);
+		// whether scouting or exploring
+		m_expedition->island_exploration = fr.unsigned_8() == 1;
+		// current direction
+		m_expedition->direction = fr.unsigned_8();
+		// Start coordinates of an island exploration
+		m_expedition->exploration_start = read_coords_32(&fr);
+		// Whether the exploration is done clockwise or counter clockwise
+		m_expedition->clockwise = fr.unsigned_8() == 1;
+	}
+
+	m_lastdock = fr.unsigned_32();
+	m_destination = fr.unsigned_32();
+
+	m_items.resize(fr.unsigned_32());
+	for (ShippingItem::Loader& item_loader : m_items) {
+		item_loader.load(fr);
 	}
 }
 
@@ -1043,8 +1038,9 @@
 	try {
 		// The header has been peeled away by the caller
 
-		uint8_t const version = fr.unsigned_8();
-		if (1 <= version && version <= SHIP_SAVEGAME_VERSION) {
+		uint8_t const packet_version = fr.unsigned_8();
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version  <= kCurrentPacketVersion) {
 			std::string owner = fr.c_string();
 			std::string name = fr.c_string();
 			const ShipDescr * descr = nullptr;
@@ -1060,9 +1056,10 @@
 					("undefined ship %s/%s", owner.c_str(), name.c_str());
 
 			loader->init(egbase, mol, descr->create_object());
-			loader->load(fr, version);
-		} else
-			throw GameDataError("unknown/unhandled version %u", version);
+			loader->load(fr);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const std::exception & e) {
 		throw wexception("loading ship: %s", e.what());
 	}
@@ -1074,7 +1071,7 @@
 	(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
 {
 	fw.unsigned_8(HeaderShip);
-	fw.unsigned_8(SHIP_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 
 	fw.c_string(descr().get_owner_tribe()->name());
 	fw.c_string(descr().name());

=== modified file 'src/logic/ship.h'
--- src/logic/ship.h	2014-09-10 08:55:04 +0000
+++ src/logic/ship.h	2014-10-03 19:24:49 +0000
@@ -238,7 +238,7 @@
 
 		const Task * get_task(const std::string & name) override;
 
-		void load(FileRead & fr, uint8_t version);
+		void load(FileRead & fr);
 		void load_pointers() override;
 		void load_finish() override;
 

=== modified file 'src/logic/soldier.cc'
--- src/logic/soldier.cc	2014-09-20 09:37:47 +0000
+++ src/logic/soldier.cc	2014-10-03 19:24:49 +0000
@@ -1843,7 +1843,7 @@
 ==============================
 */
 
-#define SOLDIER_SAVEGAME_VERSION 2
+constexpr uint8_t kCurrentPacketVersion = 2;
 
 Soldier::Loader::Loader() :
 		m_battle(0)
@@ -1854,34 +1854,38 @@
 {
 	Worker::Loader::load(fr);
 
-	uint8_t version = fr.unsigned_8();
-	if (version > SOLDIER_SAVEGAME_VERSION)
-		throw GameDataError("unknown/unhandled version %u", version);
-
-	Soldier & soldier = get<Soldier>();
-	soldier.m_hp_current = fr.unsigned_32();
-	if (SOLDIER_SAVEGAME_VERSION < 2) // Hitpoints multiplied to make balance easier
-		soldier.m_hp_current *= 100;
-
-	soldier.m_hp_level =
-		std::min(fr.unsigned_32(), soldier.descr().get_max_hp_level());
-	soldier.m_attack_level =
-		std::min(fr.unsigned_32(), soldier.descr().get_max_attack_level());
-	soldier.m_defense_level =
-		std::min(fr.unsigned_32(), soldier.descr().get_max_defense_level());
-	soldier.m_evade_level =
-		std::min(fr.unsigned_32(), soldier.descr().get_max_evade_level());
-
-	if (soldier.m_hp_current > soldier.get_max_hitpoints())
-		soldier.m_hp_current = soldier.get_max_hitpoints();
-
-	soldier.m_combat_walking = static_cast<CombatWalkingDir>(fr.unsigned_8());
-	if (soldier.m_combat_walking != CD_NONE) {
-		soldier.m_combat_walkstart = fr.signed_32();
-		soldier.m_combat_walkend = fr.signed_32();
+	try {
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersion) {
+
+			Soldier & soldier = get<Soldier>();
+			soldier.m_hp_current = fr.unsigned_32();
+
+			soldier.m_hp_level =
+				std::min(fr.unsigned_32(), soldier.descr().get_max_hp_level());
+			soldier.m_attack_level =
+				std::min(fr.unsigned_32(), soldier.descr().get_max_attack_level());
+			soldier.m_defense_level =
+				std::min(fr.unsigned_32(), soldier.descr().get_max_defense_level());
+			soldier.m_evade_level =
+				std::min(fr.unsigned_32(), soldier.descr().get_max_evade_level());
+
+			if (soldier.m_hp_current > soldier.get_max_hitpoints())
+				soldier.m_hp_current = soldier.get_max_hitpoints();
+
+			soldier.m_combat_walking = static_cast<CombatWalkingDir>(fr.unsigned_8());
+			if (soldier.m_combat_walking != CD_NONE) {
+				soldier.m_combat_walkstart = fr.signed_32();
+				soldier.m_combat_walkend = fr.signed_32();
+			}
+
+			m_battle = fr.unsigned_32();
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
+	} catch (const std::exception & e) {
+		throw wexception("loading player immovable: %s", e.what());
 	}
-
-	m_battle = fr.unsigned_32();
 }
 
 void Soldier::Loader::load_pointers()
@@ -1914,7 +1918,7 @@
 {
 	Worker::do_save(egbase, mos, fw);
 
-	fw.unsigned_8(SOLDIER_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 	fw.unsigned_32(m_hp_current);
 	fw.unsigned_32(m_hp_level);
 	fw.unsigned_32(m_attack_level);

=== modified file 'src/logic/worker.cc'
--- src/logic/worker.cc	2014-09-20 09:37:47 +0000
+++ src/logic/worker.cc	2014-10-03 19:24:49 +0000
@@ -2933,7 +2933,7 @@
 ==============================
 */
 
-#define WORKER_SAVEGAME_VERSION 2
+constexpr uint8_t kCurrentPacketVersion = 2;
 
 Worker::Loader::Loader() :
 	m_location(0),
@@ -2944,22 +2944,25 @@
 void Worker::Loader::load(FileRead & fr)
 {
 	Bob::Loader::load(fr);
-
-	uint8_t version = fr.unsigned_8();
-	if (!(1 <= version && version <= WORKER_SAVEGAME_VERSION))
-		throw GameDataError("unknown/unhandled version %u", version);
-
-	Worker & worker = get<Worker>();
-	m_location = fr.unsigned_32();
-	m_carried_ware = fr.unsigned_32();
-	worker.m_current_exp = fr.signed_32();
-
-	if (version >= 2) {
-		if (fr.unsigned_8()) {
-			worker.m_transfer =
-				new Transfer(ref_cast<Game, EditorGameBase>(egbase()), worker);
-			worker.m_transfer->read(fr, m_transfer);
+	try {
+		uint8_t packet_version = fr.unsigned_8();
+		if (packet_version == kCurrentPacketVersion) {
+
+			Worker & worker = get<Worker>();
+			m_location = fr.unsigned_32();
+			m_carried_ware = fr.unsigned_32();
+			worker.m_current_exp = fr.signed_32();
+
+			if (fr.unsigned_8()) {
+				worker.m_transfer =
+					new Transfer(ref_cast<Game, EditorGameBase>(egbase()), worker);
+				worker.m_transfer->read(fr, m_transfer);
+			}
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
 		}
+	} catch (const std::exception & e) {
+		throw wexception("loading player immovable: %s", e.what());
 	}
 }
 
@@ -3084,7 +3087,7 @@
 {
 	Bob::save(egbase, mos, fw);
 
-	fw.unsigned_8(WORKER_SAVEGAME_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 	fw.unsigned_32(mos.get_object_file_index_or_zero(m_location.get(egbase)));
 	fw.unsigned_32(mos.get_object_file_index_or_zero(m_carried_ware.get(egbase)));
 	fw.signed_32(m_current_exp);

=== modified file 'src/map_io/map_allowed_building_types_packet.cc'
--- src/map_io/map_allowed_building_types_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_allowed_building_types_packet.cc	2014-10-03 19:24:49 +0000
@@ -28,7 +28,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
+constexpr int32_t kCurrentPacketVersion = 1;
 
 void MapAllowedBuildingTypesPacket::read
 	(FileSystem            &       fs,
@@ -54,7 +54,7 @@
 	try {
 		int32_t const packet_version =
 			prof.get_safe_section("global").get_safe_int("packet_version");
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			PlayerNumber const nr_players = egbase.map().get_nrplayers();
 			upcast(Game const, game, &egbase);
 
@@ -88,9 +88,9 @@
 						("player %u (%s): %s", p, tribe.name().c_str(), e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %i", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("allowed buildings: %s", e.what());
 	}
@@ -102,7 +102,7 @@
 {
 	Profile prof;
 	prof.create_section("global").set_int
-		("packet_version", CURRENT_PACKET_VERSION);
+		("packet_version", kCurrentPacketVersion);
 
 	PlayerNumber const nr_players = egbase.map().get_nrplayers();
 	iterate_players_existing_const(p, nr_players, egbase, player) {

=== modified file 'src/map_io/map_allowed_worker_types_packet.cc'
--- src/map_io/map_allowed_worker_types_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_allowed_worker_types_packet.cc	2014-10-03 19:24:49 +0000
@@ -28,13 +28,13 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
+constexpr int32_t kCurrentPacketVersion = 1;
 
 void MapAllowedWorkerTypesPacket::read
-	(FileSystem            &       fs,
-	 EditorGameBase      &       egbase,
-	 bool                    skip,
-	 MapObjectLoader &)
+	(FileSystem& fs,
+	 EditorGameBase& egbase,
+	 bool skip,
+	 MapObjectLoader&)
 {
 	if (skip)
 		return;
@@ -52,7 +52,7 @@
 	try {
 		const int32_t packet_version =
 			prof.get_safe_section("global").get_safe_int("packet_version");
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			iterate_players_existing(p, egbase.map().get_nrplayers(), egbase, player) {
 				const TribeDescr & tribe = player->tribe();
 				char buffer[10];
@@ -73,9 +73,9 @@
 						("player %u (%s): %s", p, tribe.name().c_str(), e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %i", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("allowed worker types: %s", e.what());
 	}
@@ -87,7 +87,7 @@
 {
 	Profile prof;
 	prof.create_section("global").set_int
-		("packet_version", CURRENT_PACKET_VERSION);
+		("packet_version", kCurrentPacketVersion);
 
 	bool forbidden_worker_seen = false;
 	iterate_players_existing_const(p, egbase.map().get_nrplayers(), egbase, player) {

=== modified file 'src/map_io/map_bob_packet.cc'
--- src/map_io/map_bob_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_bob_packet.cc	2014-10-03 19:24:49 +0000
@@ -29,13 +29,13 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapBobPacket::read_bob(FileRead& fr,
-                                  EditorGameBase& egbase,
-											 MapObjectLoader&,
-                                  Coords const coords,
-                                  const OneWorldLegacyLookupTable& lookup_table) {
+									 EditorGameBase& egbase,
+									 MapObjectLoader&,
+									 Coords const coords,
+									 const OneWorldLegacyLookupTable& lookup_table) {
 	const std::string owner = fr.c_string();
 	char const* const read_name = fr.c_string();
 	uint8_t subtype = fr.unsigned_8();
@@ -68,9 +68,9 @@
 }
 
 void MapBobPacket::read(FileSystem& fs,
-                               EditorGameBase& egbase,
-										 MapObjectLoader& mol,
-                               const OneWorldLegacyLookupTable& lookup_table) {
+								EditorGameBase& egbase,
+								MapObjectLoader& mol,
+								const OneWorldLegacyLookupTable& lookup_table) {
 	FileRead fr;
 	fr.open(fs, "binary/bob");
 
@@ -78,7 +78,7 @@
 	map.recalc_whole_map(egbase.world());  //  for movecaps checks in ReadBob
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION)
+		if (packet_version == kCurrentPacketVersion)
 			for (uint16_t y = 0; y < map.get_height(); ++y) {
 				for (uint16_t x = 0; x < map.get_width(); ++x) {
 					uint32_t const nr_bobs = fr.unsigned_32();
@@ -86,8 +86,9 @@
 						read_bob(fr, egbase, mol, Coords(x, y), lookup_table);
 				}
 			}
-		else
-			throw GameDataError("unknown/unhandled version %u", packet_version);
+		else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException& e) {
 		throw GameDataError("bobs: %s", e.what());
 	}

=== modified file 'src/map_io/map_building_packet.cc'
--- src/map_io/map_building_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_building_packet.cc	2014-10-03 19:24:49 +0000
@@ -37,17 +37,17 @@
 
 namespace Widelands {
 
-#define LOWEST_SUPPORTED_VERSION           1
-#define PRIORITIES_INTRODUCED_IN_VERSION   2
-#define CURRENT_PACKET_VERSION             3
-
-
-void MapBuildingPacket::read
-	(FileSystem            &       fs,
-	 EditorGameBase      &       egbase,
-	 bool                    const skip,
-	 MapObjectLoader &       mol)
-{
+constexpr uint16_t kCurrentPacketVersion = 4;
+
+// constants to handle special building types
+constexpr uint8_t kTypeBuilding = 0;
+constexpr uint8_t kTypeConstructionSite = 1;
+constexpr uint8_t kTypeDismantleSite = 2;
+
+void MapBuildingPacket::read(FileSystem& fs,
+									  EditorGameBase& egbase,
+									  bool const skip,
+									  MapObjectLoader& mol) {
 	if (skip)
 		return;
 	FileRead fr;
@@ -55,7 +55,8 @@
 	InteractiveBase & ibase = *egbase.get_ibase();
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version >= LOWEST_SUPPORTED_VERSION) {
+		// Supporting older versions for scenario loading
+		if (2 <= packet_version && packet_version <= kCurrentPacketVersion) {
 			Map & map = egbase.map();
 			uint16_t const width  = map.get_width ();
 			uint16_t const height = map.get_height();
@@ -63,10 +64,10 @@
 			for (c.y = 0; c.y < height; ++c.y) {
 				for (c.x = 0; c.x < width; ++c.x) {
 					if (fr.unsigned_8()) {
-						PlayerNumber const p                   = fr.unsigned_8 ();
+						PlayerNumber  const p                   = fr.unsigned_8 ();
 						Serial        const serial              = fr.unsigned_32();
 						char  const * const name                = fr.c_string   ();
-						uint8_t       const special_type        = fr.unsigned_8 ();
+						uint8_t const building_type             = fr.unsigned_8 ();
 
 						//  No building lives on more than one main place.
 
@@ -83,9 +84,9 @@
 							//  Now, create this Building, take extra special care for
 							//  constructionsites. All data is read later.
 							Building * building;
-							if (special_type == 1) { // Constructionsite
+							if (building_type == kTypeConstructionSite) {
 								building = &egbase.warp_constructionsite(c, p, index, true);
-							} else if (special_type == 2) {// DismantleSite
+							} else if (building_type == kTypeDismantleSite) {
 								Building::FormerBuildings formers = {index};
 								building = &egbase.warp_dismantlesite(c, p, true, formers);
 							} else {
@@ -94,8 +95,7 @@
 
 							mol.register_object<Building> (serial, *building);
 
-							if (packet_version >= PRIORITIES_INTRODUCED_IN_VERSION)
-								read_priorities (*building, fr);
+							read_priorities (*building, fr);
 
 							//  Reference the players tribe if in editor.
 							if (g_gr) // but not on dedicated servers ;)
@@ -105,9 +105,9 @@
 					}
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("buildings: %s", e.what());
 	}
@@ -123,7 +123,7 @@
 	FileWrite fw;
 
 	// now packet version
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// Write buildings and owner, register this with the map_object_saver so that
 	// it's data can be saved later.
@@ -140,18 +140,19 @@
 			fw.unsigned_8(building->owner().player_number());
 			fw.unsigned_32(mos.register_object(*building));
 
-			upcast(PartiallyFinishedBuilding const, pfb, building);
-			fw.c_string
-				((pfb ? *pfb->m_building : building->descr())
-				 .name().c_str());
-
-			if (!pfb)
-				fw.unsigned_8(0);
-			else {
-				if (is_a(ConstructionSite, pfb))
-					fw.unsigned_8(1);
-				else // DismantleSite
-					fw.unsigned_8(2);
+			if (building->descr().type() == MapObjectType::CONSTRUCTIONSITE) {
+				upcast(PartiallyFinishedBuilding const, pfb, building);
+				fw.c_string((*pfb->m_building).name().c_str());
+				fw.unsigned_8(kTypeConstructionSite);
+
+			} else if (building->descr().type() == MapObjectType::DISMANTLESITE) {
+				upcast(PartiallyFinishedBuilding const, pfb, building);
+				fw.c_string((*pfb->m_building).name().c_str());
+				fw.unsigned_8(kTypeDismantleSite);
+
+			} else {
+				fw.c_string(building->descr().name().c_str());
+				fw.unsigned_8(kTypeBuilding);
 			}
 
 			write_priorities(*building, fw);

=== modified file 'src/map_io/map_buildingdata_packet.cc'
--- src/map_io/map_buildingdata_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_buildingdata_packet.cc	2014-10-03 19:24:49 +0000
@@ -51,20 +51,17 @@
 
 namespace Widelands {
 
-// Versions
-// Since V3: m_old_buildings vector
-#define CURRENT_PACKET_VERSION 3
-
-// Subversions
-#define CURRENT_DISMANTLESITE_PACKET_VERSION    1
-// Since V3: m_prev_building not written
-#define CURRENT_CONSTRUCTIONSITE_PACKET_VERSION 3
-#define CURRENT_PARTIALLYFB_PACKET_VERSION      1
-#define CURRENT_WAREHOUSE_PACKET_VERSION        6
-#define CURRENT_MILITARYSITE_PACKET_VERSION     4
-#define CURRENT_PRODUCTIONSITE_PACKET_VERSION   5
-#define CURRENT_TRAININGSITE_PACKET_VERSION     4
-
+// Overall package version
+constexpr uint16_t kCurrentPacketVersion = 4;
+
+// Building type package versions
+constexpr uint16_t kCurrentPacketVersionDismantlesite = 1;
+constexpr uint16_t kCurrentPacketVersionConstructionsite = 3;
+constexpr uint16_t kCurrentPacketPFBuilding = 1;
+constexpr uint16_t kCurrentPacketVersionWarehouse = 6;
+constexpr uint16_t kCurrentPacketVersionMilitarysite = 4;
+constexpr uint16_t kCurrentPacketVersionProductionsite = 5;
+constexpr uint16_t kCurrentPacketVersionTrainingsite = 4;
 
 void MapBuildingdataPacket::read
 	(FileSystem            &       fs,
@@ -80,17 +77,9 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (1 <= packet_version && packet_version <= CURRENT_PACKET_VERSION) {
-			for (;;) {
-				if (2 <= packet_version && fr.end_of_file())
-					break;
+		if (packet_version == kCurrentPacketVersion) {
+			while (! fr.end_of_file()) {
 				Serial const serial = fr.unsigned_32();
-				if (packet_version < 2 && serial == 0xffffffff) {
-					if (!fr.end_of_file())
-						throw GameDataError
-							("expected end of file after serial 0xffffffff");
-					break;
-				}
 				try {
 					Building & building = mol.get<Building>(serial);
 
@@ -108,8 +97,9 @@
 								 animation_name);
 							building.m_anim = building.descr().get_animation("idle");
 						}
-					} else
+					} else {
 						building.m_anim = 0;
+					}
 					building.m_animstart = fr.unsigned_32();
 
 					{
@@ -153,24 +143,22 @@
 					else {
 						building.m_leave_allow = nullptr;
 					}
-					if (packet_version >= 3) {
-						// For former versions, the former buildings vector
-						// will be built after other data are loaded, see below.
-						// read_formerbuildings_v2()
-						while (fr.unsigned_8()) {
-							BuildingIndex oldidx = building.descr().tribe().safe_building_index(fr.c_string());
-							building.m_old_buildings.push_back(oldidx);
-						}
-						// Only construction sites may have an empty list
-						if (building.m_old_buildings.empty() && !is_a(ConstructionSite, &building)) {
-							throw GameDataError
-								("Failed to read %s %u: No former buildings informations.\n"
-								"Your savegame is corrupted", building.descr().descname().c_str(), building.serial());
-						}
-					}
+
+					while (fr.unsigned_8()) {
+						BuildingIndex oldidx = building.descr().tribe().safe_building_index(fr.c_string());
+						building.m_old_buildings.push_back(oldidx);
+					}
+					// Only construction sites may have an empty list
+					if (building.m_old_buildings.empty() &&
+						 building.descr().type() != MapObjectType::CONSTRUCTIONSITE) {
+						throw GameDataError
+							("Failed to read %s %u: No former buildings information.\n"
+							"Your savegame is corrupted", building.descr().descname().c_str(), building.serial());
+					}
+
 					if (fr.unsigned_8()) {
-						if (upcast(ProductionSite, productionsite, &building))
-							if (dynamic_cast<MilitarySite const *>(productionsite)) {
+						if (upcast(ProductionSite, productionsite, &building)) {
+							if (building.descr().type() == MapObjectType::MILITARYSITE) {
 								log
 									("WARNING: Found a stopped %s at (%i, %i) in the "
 									 "savegame. Militarysites are not stoppable. "
@@ -181,7 +169,7 @@
 							} else {
 								productionsite->set_stopped(true);
 							}
-						else
+						} else
 							log
 								("WARNING: Found a stopped %s at (%i, %i) in the "
 								 "savegame. Only productionsites are stoppable. "
@@ -194,107 +182,79 @@
 					//  Set economy now, some stuff below will count on this.
 					building.set_economy(building.m_flag->get_economy());
 
-					if (upcast(ConstructionSite, constructionsite, &building)) {
-						read_constructionsite
-							(*constructionsite,
-							 fr,
-							 ref_cast<Game, EditorGameBase>(egbase),
-							 mol);
-					} else if (upcast(DismantleSite, dms, &building)) {
-						read_dismantlesite
-							(*dms,
-							 fr,
-							 ref_cast<Game, EditorGameBase>(egbase),
-							 mol);
-					} else if (upcast(Warehouse, warehouse, &building)) {
-						read_warehouse
-							(*warehouse,
-							 fr,
-							 ref_cast<Game, EditorGameBase>(egbase),
-							 mol);
-					} else if (upcast(ProductionSite, productionsite, &building)) {
-						if (upcast(MilitarySite, militarysite, productionsite)) {
-							read_militarysite
-								(*militarysite,
-								 fr,
-								 ref_cast<Game, EditorGameBase>(egbase),
-								 mol);
-						} else if (upcast(TrainingSite, trainingsite, productionsite)) {
+					switch (building.descr().type()) {
+						case MapObjectType::CONSTRUCTIONSITE: {
+							upcast(ConstructionSite, constructionsite, &building);
+							read_constructionsite
+								(*constructionsite,
+								 fr,
+								 ref_cast<Game, EditorGameBase>(egbase),
+								 mol);
+							break;
+						}
+						case MapObjectType::DISMANTLESITE: {
+							upcast(DismantleSite, dms, &building);
+							read_dismantlesite
+								(*dms,
+								 fr,
+								 ref_cast<Game, EditorGameBase>(egbase),
+								 mol);
+							break;
+						}
+						case MapObjectType::WAREHOUSE: {
+							upcast(Warehouse, warehouse, &building);
+							read_warehouse
+								(*warehouse,
+								 fr,
+								 ref_cast<Game, EditorGameBase>(egbase),
+								 mol);
+							break;
+						}
+						case MapObjectType::MILITARYSITE: {
+							upcast(MilitarySite, militarysite, &building);
+								read_militarysite
+									(*militarysite,
+									 fr,
+									 ref_cast<Game, EditorGameBase>(egbase),
+									 mol);
+							break;
+						}
+						case MapObjectType::TRAININGSITE: {
+							upcast(TrainingSite, trainingsite, &building);
 							read_trainingsite
 								(*trainingsite,
 								 fr,
 								 ref_cast<Game, EditorGameBase>(egbase),
 								 mol);
-						} else {
+							break;
+						}
+						case MapObjectType::PRODUCTIONSITE: {
+							upcast(ProductionSite, productionsite, &building);
 							read_productionsite
 								(*productionsite,
 								 fr,
 								 ref_cast<Game, EditorGameBase>(egbase),
 								 mol);
+							break;
 						}
-					} else {
-						//  type of building is not one of (or derived from)
-						//  {ConstructionSite, Warehouse, ProductionSite}
-						assert(false);
-					}
-					if (packet_version < 3) {
-						read_formerbuildings_v2
-							(building, fr, ref_cast<Game, EditorGameBase>(egbase), mol);
-					}
-
+						default:
+							//  type of building is not one of (or derived from)
+							//  {ConstructionSite, Warehouse, ProductionSite}
+							assert(false);
+					}
 					mol.mark_object_as_loaded(building);
 				} catch (const WException & e) {
 					throw GameDataError("building %u: %s", serial, e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("buildingdata: %s", e.what());
 	}
 }
 
-void MapBuildingdataPacket::read_formerbuildings_v2
-	(Building& b, FileRead&, Game&, MapObjectLoader&)
-{
-	const TribeDescr & t = b.descr().tribe();
-	BuildingIndex b_idx = t.building_index(b.descr().name());
-	if (is_a(ProductionSite, &b)) {
-		assert(b.m_old_buildings.empty());
-		b.m_old_buildings.push_back(b_idx);
-	} else if (is_a(Warehouse, &b)) {
-		assert(b.m_old_buildings.empty());
-		b.m_old_buildings.push_back(b_idx);
-	} else if (is_a(DismantleSite, &b)) {
-		// Former buildings filled with the current one
-		// upon building init.
-		assert(!b.m_old_buildings.empty());
-	} else if (is_a(ConstructionSite, &b)) {
-		// Not needed for csite.
-		return;
-	} else {
-		assert(false);
-	}
-
-	// iterate through all buildings to find first predecessor
-	for (;;) {
-		BuildingIndex former_idx = b.m_old_buildings.front();
-		const BuildingDescr * oldest = t.get_building_descr(former_idx);
-		if (!oldest->is_enhanced()) {
-			break;
-		}
-		for (BuildingIndex i = 0; i < t.get_nrbuildings(); ++i) {
-			BuildingDescr const * ob = t.get_building_descr(i);
-			if (ob->enhancement() == former_idx) {
-				b.m_old_buildings.insert(b.m_old_buildings.begin(), i);
-				break;
-			}
-		}
-	}
-}
-
-
 void MapBuildingdataPacket::read_partially_finished_building
 	(PartiallyFinishedBuilding  & pfb,
 	 FileRead              & fr,
@@ -303,7 +263,7 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PARTIALLYFB_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketPFBuilding) {
 			const TribeDescr & tribe = pfb.descr().tribe();
 			pfb.m_building =
 				tribe.get_building_descr(tribe.safe_building_index(fr.c_string()));
@@ -348,9 +308,9 @@
 			pfb.m_work_steptime  = fr.unsigned_32();
 			pfb.m_work_completed = fr.unsigned_32();
 			pfb.m_work_steps     = fr.unsigned_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketPFBuilding);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("partially_constructed_buildings: %s", e.what());
 	}
@@ -364,14 +324,9 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == 1)
-			return read_constructionsite_v1(constructionsite, fr, game, mol);
-
-		if (packet_version >= 2) {
+		if (packet_version >= kCurrentPacketVersionConstructionsite) {
 			read_partially_finished_building(constructionsite, fr, game, mol);
 
-			const TribeDescr & tribe = constructionsite.descr().tribe();
-
 			for (ConstructionSite::Wares::iterator wares_iter = constructionsite.m_wares.begin();
 				  wares_iter != constructionsite.m_wares.end();
 				  ++wares_iter) {
@@ -380,82 +335,15 @@
 						(ConstructionSite::wares_queue_callback, &constructionsite);
 			}
 
-			if (packet_version <= 2) {
-				if (fr.unsigned_8()) {
-					BuildingIndex idx = tribe.safe_building_index(fr.c_string());
-					constructionsite.m_old_buildings.push_back(idx);
-				}
-			}
-
 			constructionsite.m_fetchfromflag  = fr.  signed_32();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionConstructionsite);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("constructionsite: %s", e.what());
 	}
 }
 
-void MapBuildingdataPacket::read_constructionsite_v1
-	(ConstructionSite      & constructionsite,
-	 FileRead              & fr,
-	 Game                  & game,
-	 MapObjectLoader & mol)
-{
-	const TribeDescr & tribe = constructionsite.descr().tribe();
-	constructionsite.m_building =
-		tribe.get_building_descr(tribe.safe_building_index(fr.c_string()));
-	if (fr.unsigned_8()) {
-		BuildingIndex bidx = tribe.safe_building_index(fr.c_string());
-		constructionsite.m_old_buildings.push_back(bidx);
-	}
-
-	delete constructionsite.m_builder_request;
-	if (fr.unsigned_8()) {
-		constructionsite.m_builder_request =
-			new Request
-			(constructionsite,
-			 0,
-			 ConstructionSite::request_builder_callback,
-			 wwWORKER);
-		constructionsite.m_builder_request->read(fr, game, mol);
-	} else
-		constructionsite.m_builder_request = nullptr;
-
-	if (uint32_t const builder_serial = fr.unsigned_32()) {
-		try {
-			constructionsite.m_builder = &mol.get<Worker>(builder_serial);
-		} catch (const WException & e) {
-			throw GameDataError
-				("builder (%u): %s", builder_serial, e.what());
-		}
-	} else
-		constructionsite.m_builder = nullptr;
-
-	try {
-		uint16_t const size = fr.unsigned_16();
-		constructionsite.m_wares.resize(size);
-		for (uint16_t i = 0; i < constructionsite.m_wares.size(); ++i)
-		{
-			constructionsite.m_wares[i] =
-				new WaresQueue
-				(constructionsite, INVALID_INDEX, 0);
-			constructionsite.m_wares[i]->set_callback
-				(ConstructionSite::wares_queue_callback, &constructionsite);
-			constructionsite.m_wares[i]->read(fr, game, mol);
-		}
-	} catch (const WException & e) {
-		throw GameDataError("wares: %s", e.what());
-	}
-
-	constructionsite.m_fetchfromflag  = fr.  signed_32();
-
-	constructionsite.m_working        = fr.unsigned_8 ();
-	constructionsite.m_work_steptime  = fr.unsigned_32();
-	constructionsite.m_work_completed = fr.unsigned_32();
-	constructionsite.m_work_steps     = fr.unsigned_32();
-}
-
 void MapBuildingdataPacket::read_dismantlesite
 	(DismantleSite         & dms,
 	 FileRead              & fr,
@@ -464,13 +352,13 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_DISMANTLESITE_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersionDismantlesite) {
 			read_partially_finished_building(dms, fr, game, mol);
 
 			// Nothing to do
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionDismantlesite);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("dismantlesite: %s", e.what());
 	}
@@ -485,10 +373,7 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if
-			(1 <= packet_version &&
-			 packet_version <= CURRENT_WAREHOUSE_PACKET_VERSION)
-		{
+		if (packet_version == kCurrentPacketVersionWarehouse) {
 			WareIndex const nr_wares   = warehouse.descr().tribe().get_nrwares();
 			WareIndex const nr_tribe_workers = warehouse.descr().tribe().get_nrworkers();
 			warehouse.m_supply->set_nrwares  (nr_wares);
@@ -496,57 +381,29 @@
 			warehouse.m_ware_policy.resize(nr_wares, Warehouse::SP_Normal);
 			warehouse.m_worker_policy.resize
 				(nr_tribe_workers, Warehouse::SP_Normal);
-			//log("Reading warehouse stuff for %p\n", &warehouse);
+
 			//  supply
 			const TribeDescr & tribe = warehouse.descr().tribe();
 			while (fr.unsigned_8()) {
 				WareIndex const id = tribe.ware_index(fr.c_string());
-				if (packet_version >= 5) {
-					uint32_t amount = fr.unsigned_32();
-					Warehouse::StockPolicy policy =
-						static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
-
-					if (id != INVALID_INDEX) {
-						warehouse.insert_wares(id, amount);
-						warehouse.set_ware_policy(id, policy);
-					}
-				} else {
-					uint16_t amount = fr.unsigned_16();
-
-					if (id != INVALID_INDEX)
-						warehouse.insert_wares(id, amount);
+				uint32_t amount = fr.unsigned_32();
+				Warehouse::StockPolicy policy =
+					static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
+
+				if (id != INVALID_INDEX) {
+					warehouse.insert_wares(id, amount);
+					warehouse.set_ware_policy(id, policy);
 				}
 			}
 			while (fr.unsigned_8()) {
 				WareIndex const id = tribe.worker_index(fr.c_string());
-				if (packet_version >= 5) {
-					uint32_t amount = fr.unsigned_32();
-					Warehouse::StockPolicy policy =
-						static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
-
-					if (id != INVALID_INDEX) {
-						warehouse.insert_workers(id, amount);
-						warehouse.set_worker_policy(id, policy);
-					}
-				} else {
-					uint16_t amount = fr.unsigned_16();
-
-					if (id != INVALID_INDEX)
-						warehouse.insert_workers(id, amount);
-				}
-			}
-
-			if (packet_version <= 3) {
-				// eat the obsolete idle request structures
-				uint32_t nrrequests = fr.unsigned_16();
-				while (nrrequests--) {
-					std::unique_ptr<Request> req
-						(new Request
-						 	(warehouse,
-						 	 0,
-						 	 &Warehouse::request_cb,
-						 	 wwWORKER));
-					req->read(fr, game, mol);
+				uint32_t amount = fr.unsigned_32();
+				Warehouse::StockPolicy policy =
+					static_cast<Warehouse::StockPolicy>(fr.unsigned_8());
+
+				if (id != INVALID_INDEX) {
+					warehouse.insert_workers(id, amount);
+					warehouse.set_worker_policy(id, policy);
 				}
 			}
 
@@ -558,13 +415,6 @@
 
 					try {
 						Worker & worker = mol.get<Worker>(worker_serial);
-						if (1 == packet_version) {
-							char const * const name = fr.c_string();
-							if (name != worker.descr().name())
-								throw GameDataError
-									("expected %s but found \"%s\"",
-									 worker.descr().name().c_str(), name);
-						}
 						WareIndex worker_index = tribe.worker_index(worker.descr().name().c_str());
 						if (!warehouse.m_incorporated_workers.count(worker_index))
 							warehouse.m_incorporated_workers[worker_index] = std::vector<Worker *>();
@@ -580,138 +430,90 @@
 			const std::vector<WareIndex> & worker_types_without_cost =
 				tribe.worker_types_without_cost();
 
-			if (1 == packet_version) { //  a single next_spawn time for "carrier"
-				uint32_t const next_spawn = fr.unsigned_32();
-				WareIndex const worker_index =
-					tribe.safe_worker_index("carrier");
+			for (;;) {
+				char const * const worker_typename = fr.c_string   ();
+				if (!*worker_typename) //  encountered the terminator ("")
+					break;
+				uint32_t     const next_spawn      = fr.unsigned_32();
+				WareIndex   const worker_index    =
+					tribe.safe_worker_index(worker_typename);
 				if (worker_index == INVALID_INDEX) {
 					log
 						("WARNING: %s %u has a next_spawn time for nonexistent "
 						 "worker type \"%s\" set to %u, ignoring\n",
 						 warehouse.descr().descname().c_str(), warehouse.serial(),
-						 "carrier", next_spawn);
-				} else if
-					(tribe.get_worker_descr(worker_index)->buildcost().size())
-				{
+						 worker_typename, next_spawn);
+					continue;
+				}
+				if (tribe.get_worker_descr(worker_index)->buildcost().size()) {
 					log
 						("WARNING: %s %u has a next_spawn time for worker type "
 						 "\"%s\", that costs something to build, set to %u, "
 						 "ignoring\n",
 						 warehouse.descr().descname().c_str(), warehouse.serial(),
-						 "carrier", next_spawn);
-				} else
-					for (uint8_t i = 0;; ++i) {
-						assert(i < worker_types_without_cost.size());
-						if (worker_types_without_cost.at(i) == worker_index) {
-							if
-								(warehouse.m_next_worker_without_cost_spawn[i]
-								 !=
-								 static_cast<uint32_t>(never()))
-							{
-								warehouse.molog
-									("read_warehouse: "
-									 "m_next_worker_without_cost_spawn[%u] = %u\n",
-									 i, warehouse.m_next_worker_without_cost_spawn[i]);
-							}
-							assert
-								(warehouse.m_next_worker_without_cost_spawn[i]
-								 ==
-								 static_cast<uint32_t>(never()));
-							warehouse.m_next_worker_without_cost_spawn[i] =
-								next_spawn;
-							break;
-						}
-					}
-			} else
-				for (;;) {
-					char const * const worker_typename = fr.c_string   ();
-					if (!*worker_typename) //  encountered the terminator ("")
+						 worker_typename, next_spawn);
+					continue;
+				}
+				for (uint8_t i = 0;; ++i) {
+					assert(i < worker_types_without_cost.size());
+					if (worker_types_without_cost.at(i) == worker_index) {
+						if
+							(warehouse.m_next_worker_without_cost_spawn[i]
+							 !=
+							 static_cast<uint32_t>(never()))
+							throw GameDataError
+								(
+								 "%s %u has a next_spawn time for worker type "
+								 "\"%s\" set to %u, but it was previously set "
+								 "to %u\n",
+								 warehouse.descr().descname().c_str(), warehouse.serial(),
+								 worker_typename, next_spawn,
+								 warehouse.m_next_worker_without_cost_spawn[i]);
+						warehouse.m_next_worker_without_cost_spawn[i] =
+							next_spawn;
 						break;
-					uint32_t     const next_spawn      = fr.unsigned_32();
-					WareIndex   const worker_index    =
-						tribe.safe_worker_index(worker_typename);
-					if (worker_index == INVALID_INDEX) {
-						log
-							("WARNING: %s %u has a next_spawn time for nonexistent "
-							 "worker type \"%s\" set to %u, ignoring\n",
-							 warehouse.descr().descname().c_str(), warehouse.serial(),
-							 worker_typename, next_spawn);
-						continue;
-					}
-					if (tribe.get_worker_descr(worker_index)->buildcost().size()) {
-						log
-							("WARNING: %s %u has a next_spawn time for worker type "
-							 "\"%s\", that costs something to build, set to %u, "
-							 "ignoring\n",
-							 warehouse.descr().descname().c_str(), warehouse.serial(),
-							 worker_typename, next_spawn);
-						continue;
-					}
-					for (uint8_t i = 0;; ++i) {
-						assert(i < worker_types_without_cost.size());
-						if (worker_types_without_cost.at(i) == worker_index) {
-							if
-								(warehouse.m_next_worker_without_cost_spawn[i]
-								 !=
-								 static_cast<uint32_t>(never()))
-								throw GameDataError
-									(
-									 "%s %u has a next_spawn time for worker type "
-									 "\"%s\" set to %u, but it was previously set "
-									 "to %u\n",
-									 warehouse.descr().descname().c_str(), warehouse.serial(),
-									 worker_typename, next_spawn,
-									 warehouse.m_next_worker_without_cost_spawn[i]);
-							warehouse.m_next_worker_without_cost_spawn[i] =
-								next_spawn;
-							break;
-						}
-					}
-				}
-				//  The checks that the warehouse has a next_spawn time for each
-				//  worker type that the player is allowed to spawn, is in
-				//  Warehouse::load_finish.
-
-			if (packet_version >= 3) {
-				// Read planned worker data
-				// Consistency checks are in Warehouse::load_finish
-				uint32_t nr_planned_workers = fr.unsigned_32();
-				while (nr_planned_workers--) {
-					warehouse.m_planned_workers.push_back
-						(Warehouse::PlannedWorkers());
-					Warehouse::PlannedWorkers & pw =
-						warehouse.m_planned_workers.back();
-					pw.index = tribe.worker_index(fr.c_string());
-					pw.amount = fr.unsigned_32();
-
-					uint32_t nr_requests = fr.unsigned_32();
-					while (nr_requests--) {
-						pw.requests.push_back
-							(new Request
-							 	(warehouse,
-							 	 0,
-							 	 &Warehouse::request_cb,
-							 	 wwWORKER));
-						pw.requests.back()->read(fr, game, mol);
-					}
-				}
-			}
-
-			if (packet_version >= 5)
-				warehouse.m_next_stock_remove_act = fr.unsigned_32();
-
-			if (packet_version >= 6) {
-				if (warehouse.descr().get_isport()) {
-					if (Serial portdock = fr.unsigned_32()) {
-						warehouse.m_portdock = &mol.get<PortDock>(portdock);
-						warehouse.m_portdock->set_economy(warehouse.get_economy());
-						// Expedition specific stuff. This is done in this packet
-						// because the "new style" loader is not supported and
-						// doesn't lend itself to request and other stuff.
-						if (warehouse.m_portdock->expedition_started()) {
-							warehouse.m_portdock->expedition_bootstrap()->load
+					}
+				}
+			}
+			//  The checks that the warehouse has a next_spawn time for each
+			//  worker type that the player is allowed to spawn, is in
+			//  Warehouse::load_finish.
+
+			// Read planned worker data
+			// Consistency checks are in Warehouse::load_finish
+			uint32_t nr_planned_workers = fr.unsigned_32();
+			while (nr_planned_workers--) {
+				warehouse.m_planned_workers.push_back
+					(Warehouse::PlannedWorkers());
+				Warehouse::PlannedWorkers & pw =
+					warehouse.m_planned_workers.back();
+				pw.index = tribe.worker_index(fr.c_string());
+				pw.amount = fr.unsigned_32();
+
+				uint32_t nr_requests = fr.unsigned_32();
+				while (nr_requests--) {
+					pw.requests.push_back
+						(new Request
+							(warehouse,
+							 0,
+							 &Warehouse::request_cb,
+							 wwWORKER));
+					pw.requests.back()->read(fr, game, mol);
+				}
+			}
+
+			warehouse.m_next_stock_remove_act = fr.unsigned_32();
+
+			if (warehouse.descr().get_isport()) {
+				if (Serial portdock = fr.unsigned_32()) {
+					warehouse.m_portdock = &mol.get<PortDock>(portdock);
+					warehouse.m_portdock->set_economy(warehouse.get_economy());
+					// Expedition specific stuff. This is done in this packet
+					// because the "new style" loader is not supported and
+					// doesn't lend itself to request and other stuff.
+					if (warehouse.m_portdock->expedition_started()) {
+						warehouse.m_portdock->expedition_bootstrap()->load
 								(packet_version, warehouse, fr, game, mol);
-						}
 					}
 				}
 			}
@@ -737,9 +539,9 @@
 				  warehouse.descr().vision_range()));
 			warehouse.m_next_military_act = game.get_gametime();
 			//log("Read warehouse stuff for %p\n", &warehouse);
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionWarehouse);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("warehouse: %s", e.what());
 	}
@@ -754,8 +556,7 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_MILITARYSITE_PACKET_VERSION)
-		{
+		if (packet_version == kCurrentPacketVersionMilitarysite) {
 			read_productionsite(militarysite, fr, game, mol);
 
 			militarysite.m_normal_soldier_request.reset();
@@ -816,9 +617,9 @@
 			militarysite.m_soldier_upgrade_try = 0 != fr.unsigned_8() ? true : false;
 			militarysite.m_doing_upgrade_request = 0 != fr.unsigned_8() ? true : false;
 
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionMilitarysite);
+		}
 
 		//  If the site's capacity is outside the allowed range (can happen if
 		//  the site's type's definition has changed), set the variable to the
@@ -829,7 +630,7 @@
 		//  Cmd_ChangeSoldierCapacity to the beginning of the game's command
 		//  queue. But that would not work because the command queue is not read
 		//  yet and will be cleared before it is read.
-		if        (militarysite.m_capacity < militarysite.min_soldier_capacity()) {
+		if (militarysite.m_capacity < militarysite.min_soldier_capacity()) {
 			log
 				("WARNING: militarysite %u of player %u at (%i, %i) has capacity "
 				 "set to %u but it must be at least %u. Changing to that value.\n",
@@ -859,10 +660,7 @@
 {
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if
-			(1 <= packet_version &&
-			 packet_version <= CURRENT_PRODUCTIONSITE_PACKET_VERSION)
-		{
+		if (packet_version == kCurrentPacketVersionProductionsite) {
 			ProductionSite::WorkingPosition & wp_begin =
 				*productionsite.m_working_positions;
 			const ProductionSiteDescr & pr_descr = productionsite.descr();
@@ -956,7 +754,7 @@
 
 			//  skipped programs
 			uint32_t const gametime = game.get_gametime();
-			for (uint8_t i = 3 <= packet_version ? fr.unsigned_8() : 0; i; --i) {
+			for (uint8_t i = fr.unsigned_8(); i; --i) {
 				char const * const program_name = fr.c_string();
 				if (pr_descr.programs().count(program_name)) {
 					uint32_t const skip_time = fr.unsigned_32();
@@ -991,12 +789,10 @@
 				productionsite.m_stack[i].phase = fr.  signed_32();
 				productionsite.m_stack[i].flags = fr.unsigned_32();
 
-				if (packet_version >= 5) {
-					uint32_t serial = fr.unsigned_32();
-					if (serial)
-						productionsite.m_stack[i].objvar = &mol.get<MapObject>(serial);
-					productionsite.m_stack[i].coord = read_coords_32_allow_null(&fr, game.map().extent());
-				}
+				uint32_t serial = fr.unsigned_32();
+				if (serial)
+					productionsite.m_stack[i].objvar = &mol.get<MapObject>(serial);
+				productionsite.m_stack[i].coord = read_coords_32_allow_null(&fr, game.map().extent());
 			}
 			productionsite.m_program_timer = fr.unsigned_8();
 			productionsite.m_program_time = fr.signed_32();
@@ -1020,9 +816,10 @@
 				productionsite.m_statistics[i] = fr.unsigned_8();
 			productionsite.m_statistics_string_on_changed_statistics = fr.c_string();
 			productionsite.m_production_result = fr.c_string();
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionProductionsite);
+		}
+
 	} catch (const WException & e) {
 		throw GameDataError
 			("productionsite (%s): %s",
@@ -1038,10 +835,8 @@
 	 MapObjectLoader & mol)
 {
 	try {
-		uint16_t const trainingsite_packet_version = fr.unsigned_16();
-
-		if (trainingsite_packet_version == CURRENT_TRAININGSITE_PACKET_VERSION)
-		{
+		uint16_t const packet_version = fr.unsigned_16();
+		if (packet_version == kCurrentPacketVersionTrainingsite) {
 			read_productionsite(trainingsite, fr, game, mol);
 
 			delete trainingsite.m_soldier_request;
@@ -1089,9 +884,9 @@
 				std::pair<uint16_t, uint8_t> t = std::make_pair(trainstall, spresence);
 				trainingsite.training_failure_count[std::make_pair(traintype, trainlevel)] = t;
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", trainingsite_packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersionTrainingsite);
+		}
 
 		//  If the site's capacity is outside the allowed range (can happen if
 		//  the site's type's definition has changed), set the variable to the
@@ -1131,7 +926,7 @@
 	FileWrite fw;
 
 	// now packet version
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// Walk the map again
 	Map & map = egbase.map();
@@ -1190,47 +985,65 @@
 				fw.unsigned_8(is_stopped);
 			}
 
-			if (upcast(ConstructionSite const, constructionsite, building))
-				write_constructionsite
-					(*constructionsite,
-					 fw,
-					 ref_cast<Game, EditorGameBase>(egbase),
-					 mos);
-			else if (upcast(DismantleSite const, dms, building))
-				write_dismantlesite
-					(*dms,
-					 fw,
-					 ref_cast<Game, EditorGameBase>(egbase),
-					 mos);
-			else if (upcast(Warehouse const, warehouse, building))
-				write_warehouse
-					(*warehouse,
-					 fw,
-					 ref_cast<Game, EditorGameBase>(egbase),
-					 mos);
-			else if (upcast(ProductionSite const, productionsite, building)) {
-				if (upcast(MilitarySite const, militarysite, productionsite))
+			switch (building->descr().type()) {
+				case MapObjectType::CONSTRUCTIONSITE: {
+					upcast(const ConstructionSite, constructionsite, building);
+					write_constructionsite
+						(*constructionsite,
+						 fw,
+						 ref_cast<Game, EditorGameBase>(egbase),
+						 mos);
+					break;
+				}
+				case MapObjectType::DISMANTLESITE: {
+					upcast(const DismantleSite, dms, building);
+					write_dismantlesite
+						(*dms,
+						 fw,
+						 ref_cast<Game, EditorGameBase>(egbase),
+						 mos);
+					break;
+				}
+				case MapObjectType::WAREHOUSE: {
+					upcast(const Warehouse, warehouse, building);
+					write_warehouse
+						(*warehouse,
+						 fw,
+						 ref_cast<Game, EditorGameBase>(egbase),
+						 mos);
+					break;
+				}
+				case MapObjectType::MILITARYSITE: {
+					upcast(const MilitarySite, militarysite, building);
 					write_militarysite
 						(*militarysite,
 						 fw,
 						 ref_cast<Game, EditorGameBase>(egbase),
 						 mos);
-				else if (upcast(TrainingSite const, trainingsite, productionsite))
+				}
+					break;
+				case MapObjectType::TRAININGSITE: {
+					upcast(const TrainingSite, trainingsite, building);
 					write_trainingsite
 						(*trainingsite,
 						 fw,
 						 ref_cast<Game, EditorGameBase>(egbase),
 						 mos);
-				else
+					break;
+				}
+				case MapObjectType::PRODUCTIONSITE: {
+					upcast(const ProductionSite, productionsite, building);
 					write_productionsite
 						(*productionsite,
 						 fw,
 						 ref_cast<Game, EditorGameBase>(egbase),
 						 mos);
-			} else {
-				assert(false);
-				//  type of building is not one of (or derived from)
-				//  {ConstructionSite, Warehouse, ProductionSite}
+					break;
+				}
+				default:
+					//  type of building is not one of (or derived from)
+					//  {ConstructionSite, Warehouse, ProductionSite}
+					assert(false);
 			}
 
 			mos.mark_object_as_saved(*building);
@@ -1245,7 +1058,7 @@
 	 Game                   & game,
 	 MapObjectSaver   & mos)
 {
-	fw.unsigned_16(CURRENT_PARTIALLYFB_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketPFBuilding);
 
 	//  descriptions
 	fw.string(pfb.m_building->name());
@@ -1282,7 +1095,7 @@
 	 MapObjectSaver   & mos)
 {
 
-	fw.unsigned_16(CURRENT_CONSTRUCTIONSITE_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionConstructionsite);
 
 	write_partially_finished_building(constructionsite, fw, game, mos);
 
@@ -1296,7 +1109,7 @@
 	 MapObjectSaver   & mos)
 {
 
-	fw.unsigned_16(CURRENT_DISMANTLESITE_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionDismantlesite);
 
 	write_partially_finished_building(dms, fw, game, mos);
 
@@ -1310,7 +1123,7 @@
 	 Game                 & game,
 	 MapObjectSaver & mos)
 {
-	fw.unsigned_16(CURRENT_WAREHOUSE_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionWarehouse);
 
 	//  supply
 	const TribeDescr & tribe = warehouse.descr().tribe();
@@ -1403,7 +1216,7 @@
 	 Game                 & game,
 	 MapObjectSaver & mos)
 {
-	fw.unsigned_16(CURRENT_MILITARYSITE_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionMilitarysite);
 	write_productionsite(militarysite, fw, game, mos);
 
 	if (militarysite.m_normal_soldier_request) {
@@ -1450,7 +1263,7 @@
 	 Game                 & game,
 	 MapObjectSaver & mos)
 {
-	fw.unsigned_16(CURRENT_PRODUCTIONSITE_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionProductionsite);
 
 	uint32_t const nr_working_positions =
 		productionsite.descr().nr_working_positions();
@@ -1527,7 +1340,7 @@
 	 Game                 & game,
 	 MapObjectSaver & mos)
 {
-	fw.unsigned_16(CURRENT_TRAININGSITE_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersionTrainingsite);
 
 	write_productionsite(trainingsite, fw, game, mos);
 

=== modified file 'src/map_io/map_buildingdata_packet.h'
--- src/map_io/map_buildingdata_packet.h	2014-09-19 12:54:54 +0000
+++ src/map_io/map_buildingdata_packet.h	2014-10-03 19:24:49 +0000
@@ -52,8 +52,6 @@
 		(DismantleSite       &, FileRead  &, Game &, MapObjectLoader &);
 	void read_partially_finished_building
 		(PartiallyFinishedBuilding   &, FileRead  &, Game &, MapObjectLoader &);
-	void read_constructionsite_v1
-		(ConstructionSite       &, FileRead  &, Game &, MapObjectLoader &);
 	void read_warehouse
 		(Warehouse              &, FileRead  &, Game &, MapObjectLoader &);
 	void read_militarysite
@@ -62,8 +60,6 @@
 		(TrainingSite           &, FileRead  &, Game &, MapObjectLoader &);
 	void read_productionsite
 		(ProductionSite         &, FileRead  &, Game &, MapObjectLoader &);
-	void read_formerbuildings_v2
-		(Building               &, FileRead  &, Game &, MapObjectLoader &);
 
 	void write_constructionsite
 		(const ConstructionSite &, FileWrite &, Game &, MapObjectSaver  &);

=== modified file 'src/map_io/map_elemental_packet.cc'
--- src/map_io/map_elemental_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_elemental_packet.cc	2014-10-03 19:24:49 +0000
@@ -29,7 +29,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
+constexpr int32_t kCurrentPacketVersion = 1;
 
 void MapElementalPacket::pre_read(FileSystem & fs, Map * map)
 {
@@ -39,7 +39,7 @@
 
 	try {
 		int32_t const packet_version = s.get_int("packet_version");
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			map->m_width       = s.get_int   ("map_w");
 			map->m_height      = s.get_int   ("map_h");
 			map->set_nrplayers  (s.get_int   ("nr_players"));
@@ -61,9 +61,9 @@
 					map->add_tag(tn);
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %i", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("elemental data: %s", e.what());
 	}
@@ -84,7 +84,7 @@
 	Profile prof;
 	Section & s = prof.create_section("global");
 
-	s.set_int   ("packet_version", CURRENT_PACKET_VERSION);
+	s.set_int   ("packet_version", kCurrentPacketVersion);
 	const Map & map = egbase.map();
 	s.set_int   ("map_w",          map.get_width      ());
 	s.set_int   ("map_h",          map.get_height     ());

=== modified file 'src/map_io/map_exploration_packet.cc'
--- src/map_io/map_exploration_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_exploration_packet.cc	2014-10-03 19:24:49 +0000
@@ -30,8 +30,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 2
-
+constexpr uint16_t kCurrentPacketVersion = 2;
 
 void MapExplorationPacket::read
 	(FileSystem            &       fs,
@@ -59,21 +58,7 @@
 	MapIndex const max_index = map.max_index();
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == 1)
-			for (MapIndex i = 0; i < max_index; ++i) {
-				uint32_t const data = fr.unsigned_16();
-				for (uint8_t j = 0; j < nr_players; ++j) {
-					bool const see = data & (1 << j);
-					if (Player * const player = egbase.get_player(j + 1))
-						player->m_fields[i].vision = see ? 1 : 0;
-					else if (see)
-						log
-							("MapExplorationPacket::read: WARNING: Player %u, "
-							 "which does not exist, sees field %u.\n",
-							 j + 1, i);
-				}
-			}
-		else if (packet_version == CURRENT_PACKET_VERSION)
+		if (packet_version == kCurrentPacketVersion) {
 			for (MapIndex i = 0; i < max_index; ++i) {
 				uint32_t const data = fr.unsigned_32();
 				for (uint8_t j = 0; j < nr_players; ++j) {
@@ -87,9 +72,9 @@
 						 j + 1, i);
 				}
 			}
-		else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("seen: %s", e.what());
 	}
@@ -101,7 +86,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	static_assert(MAX_PLAYERS < 32, "assert(MAX_PLAYERS < 32) failed.");
 	Map & map = egbase.map();

=== modified file 'src/map_io/map_extradata_packet.cc'
--- src/map_io/map_extradata_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_extradata_packet.cc	2014-10-03 19:24:49 +0000
@@ -33,7 +33,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
+constexpr int32_t kCurrentPacketVersion = 1;
 
 void MapExtradataPacket::read(FileSystem& fs, bool const skip) {
 	if (skip)
@@ -45,7 +45,7 @@
 	try {
 		int32_t const packet_version =
 			prof.get_safe_section("global").get_safe_int("packet_version");
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			// Read all pics.
 			if (fs.file_exists("pics") && fs.is_directory("pics")) {
 				FilenameSet pictures = fs.list_directory("pics");
@@ -74,9 +74,9 @@
 					assert(image);
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("extradata: %s", e.what());
 	}
@@ -88,7 +88,7 @@
 {
 	Profile prof;
 	prof.create_section("global").set_int
-		("packet_version", CURRENT_PACKET_VERSION);
+		("packet_version", kCurrentPacketVersion);
 
 	// Copy all files from pics/ from the old map to the new.
 	FileSystem* map_fs = egbase.map().filesystem();

=== modified file 'src/map_io/map_flag_packet.cc'
--- src/map_io/map_flag_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_flag_packet.cc	2014-10-03 19:24:49 +0000
@@ -35,8 +35,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapFlagPacket::read
 	(FileSystem            &       fs,
@@ -52,7 +51,7 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			const Map & map = egbase.map();
 			PlayerNumber const nr_players = map.get_nrplayers();
 			Widelands::Extent const extent = map.extent();
@@ -118,9 +117,9 @@
 							 serial, fc.x, fc.y, owner, e.what());
 					}
 				}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("flags: %s", e.what());
 	}
@@ -132,7 +131,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	//  Write flags and owner, register this with the map_object_saver so that
 	//  it's data can be saved later.

=== modified file 'src/map_io/map_flagdata_packet.cc'
--- src/map_io/map_flagdata_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_flagdata_packet.cc	2014-10-03 19:24:49 +0000
@@ -38,7 +38,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 4
+constexpr uint16_t kCurrentPacketVersion = 4;
 
 void MapFlagdataPacket::read
 	(FileSystem            &       fs,
@@ -54,42 +54,15 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (1 <= packet_version && packet_version <= CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			const Map  & map    = egbase.map();
-			Extent const extent = map.extent();
-			for (;;) {
-				if (2 <= packet_version && fr.end_of_file())
-					break;
+			while (! fr.end_of_file()) {
 				Serial const serial = fr.unsigned_32();
-				if (packet_version < 2 && serial == 0xffffffff) {
-					if (!fr.end_of_file())
-						throw GameDataError
-							("expected end of file after serial 0xffffffff");
-					break;
-				}
 				try {
 					Flag & flag = mol.get<Flag>(serial);
 
 					//  Owner is already set, nothing to do from PlayerImmovable.
 
-					if (packet_version < 3) {
-						if
-							(upcast
-							 	(Flag const,
-							 	 mf,
-							 	 map[flag.m_position = read_coords_32(&fr, extent)]
-							 	 .get_immovable()))
-						{
-							if (mf != &flag)
-								throw GameDataError
-									("wrong flag (%u) at given position (%i, %i)",
-									 mf->serial(),
-									 flag.m_position.x, flag.m_position.y);
-						} else
-							throw GameDataError
-								("no flag at given position (%i, %i)",
-								 flag.m_position.x, flag.m_position.y);
-					}
 					flag.m_animstart = fr.unsigned_16();
 
 					{
@@ -99,26 +72,6 @@
 							dynamic_cast<Building *>
 								(building_position.field->get_immovable());
 					}
-					if (packet_version < 3) {
-						if (uint32_t const building_serial = fr.unsigned_32())
-							try {
-								const Building & building =
-									mol.get<Building>(building_serial);
-								if (flag.m_building != &building)
-									throw GameDataError
-										(
-									 	 "has building %u at (%i, %i), which is not "
-									 	 "at the top left node",
-										 building_serial,
-										 building.get_position().x,
-										 building.get_position().y);
-							} catch (const WException & e) {
-								throw GameDataError
-									("building (%u): %s", building_serial, e.what());
-							}
-						else
-							flag.m_building = nullptr;
-					}
 
 					//  Roads are set somewhere else.
 
@@ -134,10 +87,7 @@
 						flag.m_ware_filled = wares_filled;
 						for (uint32_t i = 0; i < wares_filled; ++i) {
 							flag.m_wares[i].pending = fr.unsigned_8();
-							if (packet_version < 4)
-								flag.m_wares[i].priority = 0;
-							else
-								flag.m_wares[i].priority = fr.signed_32();
+							flag.m_wares[i].priority = fr.signed_32();
 							uint32_t const ware_serial = fr.unsigned_32();
 							try {
 								flag.m_wares[i].ware =
@@ -160,7 +110,7 @@
 							}
 						}
 
-						if (uint32_t const always_call_serial = fr.unsigned_32())
+						if (uint32_t const always_call_serial = fr.unsigned_32()) {
 							try {
 								flag.m_always_call_for_flag =
 									&mol.get<Flag>(always_call_serial);
@@ -169,7 +119,7 @@
 									("always_call (%u): %s",
 									 always_call_serial, e.what());
 							}
-						else
+						} else
 							flag.m_always_call_for_flag = nullptr;
 
 						//  workers waiting
@@ -216,9 +166,9 @@
 					throw GameDataError("%u: %s", serial, e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("flagdata: %s", e.what());
 	}
@@ -231,7 +181,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	const Map & map = egbase.map();
 	const Field & fields_end = map[map.max_index()];

=== modified file 'src/map_io/map_heights_packet.cc'
--- src/map_io/map_heights_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_heights_packet.cc	2014-10-03 19:24:49 +0000
@@ -28,8 +28,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapHeightsPacket::read
 	(FileSystem & fs, EditorGameBase & egbase, bool, MapObjectLoader &)
@@ -40,14 +39,14 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			Map & map = egbase.map();
 			MapIndex const max_index = map.max_index();
 			for (MapIndex i = 0; i < max_index; ++i)
 				map[i].set_height(fr.unsigned_8());
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("heights: %s", e.what());
 	}
@@ -63,7 +62,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	Map & map = egbase.map();
 	MapIndex const max_index = map.max_index();

=== modified file 'src/map_io/map_node_ownership_packet.cc'
--- src/map_io/map_node_ownership_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_node_ownership_packet.cc	2014-10-03 19:24:49 +0000
@@ -28,8 +28,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapNodeOwnershipPacket::read
 	(FileSystem            &       fs,
@@ -52,14 +51,14 @@
 	}
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			Map & map = egbase.map();
 			MapIndex const max_index = map.max_index();
 			for (MapIndex i = 0; i < max_index; ++i)
 				map[i].set_owned_by(fr.unsigned_8());
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("ownership: %s", e.what());
 	}
@@ -71,7 +70,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	Map & map = egbase.map();
 	MapIndex const max_index = map.max_index();

=== modified file 'src/map_io/map_object_packet.cc'
--- src/map_io/map_object_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_object_packet.cc	2014-10-03 19:24:49 +0000
@@ -36,8 +36,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-
+constexpr uint8_t kCurrentPacketVersion = 1;
 
 MapObjectPacket::~MapObjectPacket() {
 	while (loaders.size()) {
@@ -56,9 +55,7 @@
 		fr.open(fs, "binary/mapobjects");
 
 		const uint8_t packet_version = fr.unsigned_8();
-		if (packet_version != CURRENT_PACKET_VERSION)
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		if (packet_version == kCurrentPacketVersion) {
 
 		// Initial loading stage
 		for (;;)
@@ -100,6 +97,9 @@
 			default:
 				throw GameDataError("unknown object header %u", header);
 			}
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const std::exception & e) {
 		throw GameDataError("map objects: %s", e.what());
 	}
@@ -137,7 +137,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_8(CURRENT_PACKET_VERSION);
+	fw.unsigned_8(kCurrentPacketVersion);
 
 	std::vector<Serial> obj_serials = egbase.objects().all_object_serials_ordered();
 	for

=== modified file 'src/map_io/map_objective_packet.cc'
--- src/map_io/map_objective_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_objective_packet.cc	2014-10-03 19:24:49 +0000
@@ -29,8 +29,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 2
-
+constexpr int32_t kCurrentPacketVersion = 2;
 
 void MapObjectivePacket::read
 	(FileSystem            &       fs,
@@ -46,7 +45,7 @@
 	try {
 		int32_t const packet_version =
 			prof.get_safe_section("global").get_safe_int("packet_version");
-		if (packet_version <= CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			while (Section * const s = prof.get_next_section(nullptr)) {
 				char const * const         name = s->get_name();
 				try {
@@ -64,9 +63,9 @@
 					throw GameDataError("%s: %s", name, e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %i", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("Objectives: %s", e.what());
 	}
@@ -78,7 +77,7 @@
 {
 	Profile prof;
 	prof.create_section("global").set_int
-		("packet_version", CURRENT_PACKET_VERSION);
+		("packet_version", kCurrentPacketVersion);
 
 	for (const auto& item : egbase.map().objectives()) {
 		Section& s = prof.create_section(item.second->name().c_str());

=== modified file 'src/map_io/map_player_names_and_tribes_packet.cc'
--- src/map_io/map_player_names_and_tribes_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_player_names_and_tribes_packet.cc	2014-10-03 19:24:49 +0000
@@ -27,8 +27,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 2
-
+constexpr int32_t kCurrentPacketVersion = 2;
 
 MapPlayerNamesAndTribesPacket::
 ~MapPlayerNamesAndTribesPacket
@@ -62,7 +61,8 @@
 	try {
 		int32_t const packet_version =
 			prof.get_safe_section("global").get_int("packet_version");
-		if (packet_version <= CURRENT_PACKET_VERSION) {
+		// Supporting older versions for map loading
+		if (1 <= packet_version && packet_version <= kCurrentPacketVersion) {
 			PlayerNumber const nr_players = map->get_nrplayers();
 			iterate_player_numbers(p, nr_players) {
 				char buffer[10];
@@ -73,9 +73,9 @@
 				map->set_scenario_player_ai       (p, s.get_string("ai",    ""));
 				map->set_scenario_player_closeable(p, s.get_bool  ("closeable", false));
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %i", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("player names and tribes: %s", e.what());
 	}
@@ -88,7 +88,7 @@
 	Profile prof;
 
 	prof.create_section("global").set_int
-		("packet_version", CURRENT_PACKET_VERSION);
+		("packet_version", kCurrentPacketVersion);
 
 	const Map & map = egbase.map();
 	PlayerNumber const nr_players = map.get_nrplayers();

=== modified file 'src/map_io/map_player_position_packet.cc'
--- src/map_io/map_player_position_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_player_position_packet.cc	2014-10-03 19:24:49 +0000
@@ -27,8 +27,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 2
-
+constexpr uint32_t kCurrentPacketVersion = 2;
 
 void MapPlayerPositionPacket::read
 	(FileSystem & fs, EditorGameBase & egbase, bool, MapObjectLoader &)
@@ -39,7 +38,7 @@
 
 	try {
 		uint32_t const packet_version = s.get_safe_positive("packet_version");
-		if (2 <= packet_version && packet_version <= CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			//  Read all the positions
 			//  This could bring trouble if one player position/ is not set (this
 			//  is possible in the editor), is also -1, -1.
@@ -55,9 +54,9 @@
 					throw GameDataError("player %u: %s", p, e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("player positions: %s", e.what());
 	}
@@ -70,7 +69,7 @@
 	Profile prof;
 	Section & s = prof.create_section("global");
 
-	s.set_int("packet_version", CURRENT_PACKET_VERSION);
+	s.set_int("packet_version", kCurrentPacketVersion);
 
 	// Now, all positions in order
 	const Map & map = egbase.map();

=== modified file 'src/map_io/map_players_messages_packet.cc'
--- src/map_io/map_players_messages_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_players_messages_packet.cc	2014-10-03 19:24:49 +0000
@@ -19,6 +19,8 @@
 
 #include "map_io/map_players_messages_packet.h"
 
+#include <boost/format.hpp>
+
 #include "logic/game_data_error.h"
 #include "logic/player.h"
 #include "map_io/coords_profile.h"
@@ -28,10 +30,10 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-#define PLAYERDIRNAME_TEMPLATE "player/%u"
-#define FILENAME_TEMPLATE PLAYERDIRNAME_TEMPLATE "/messages"
-#define FILENAME_SIZE 19
+constexpr uint32_t kCurrentPacketVersion = 1;
+
+constexpr const char* kPlayerDirnameTemplate = "player/%u";
+constexpr const char* kFilenameTemplate = "player/%u/messages";
 
 void MapPlayersMessagesPacket::read
 	(FileSystem & fs, EditorGameBase & egbase, bool, MapObjectLoader & mol)
@@ -43,12 +45,13 @@
 	PlayerNumber const nr_players = map   .get_nrplayers();
 	iterate_players_existing(p, nr_players, egbase, player)
 		try {
-			char filename[FILENAME_SIZE];
-			snprintf(filename, sizeof(filename), FILENAME_TEMPLATE, p);
 			Profile prof;
-			try {prof.read(filename, nullptr, fs);} catch (...) {continue;}
+			try {
+				prof.read((boost::format(kFilenameTemplate) % static_cast<unsigned int>(p)).str().c_str(),
+							 nullptr, fs);
+			} catch (...) {continue;}
 			prof.get_safe_section("global").get_positive
-				("packet_version", CURRENT_PACKET_VERSION);
+				("packet_version", kCurrentPacketVersion);
 			MessageQueue & messages = player->messages();
 
 			{
@@ -147,7 +150,7 @@
 	iterate_players_existing_const(p, nr_players, egbase, player) {
 		Profile prof;
 		prof.create_section("global").set_int
-			("packet_version", CURRENT_PACKET_VERSION);
+			("packet_version", kCurrentPacketVersion);
 		const MessageQueue & messages = player->messages();
 		MapMessageSaver & message_saver = mos.message_savers[p - 1];
 		for (const std::pair<MessageId, Message *>& temp_message : messages) {
@@ -180,11 +183,10 @@
 				s.set_int       ("serial",    fileindex);
 			}
 		}
-		char filename[FILENAME_SIZE];
-		snprintf(filename, sizeof(filename), PLAYERDIRNAME_TEMPLATE, p);
-		fs.ensure_directory_exists(filename);
-		snprintf(filename, sizeof(filename),      FILENAME_TEMPLATE, p);
-		prof.write(filename, false, fs);
+		fs.ensure_directory_exists((boost::format(kPlayerDirnameTemplate)
+										  % static_cast<unsigned int>(p)).str().c_str());
+		prof.write((boost::format(kFilenameTemplate)
+						% static_cast<unsigned int>(p)).str().c_str(), false, fs);
 	}
 }
 

=== modified file 'src/map_io/map_players_view_packet.cc'
--- src/map_io/map_players_view_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_players_view_packet.cc	2014-10-03 19:24:49 +0000
@@ -22,6 +22,8 @@
 #include <iostream>
 #include <typeinfo>
 
+#include <boost/format.hpp>
+
 #include "base/log.h"
 #include "base/macros.h"
 #include "economy/flag.h"
@@ -1036,9 +1038,10 @@
 	immovable_kinds_file.unsigned_8(immovable_kind);
 }
 
-#define WRITE(file, filename_template, version)                               \
-   snprintf(filename, sizeof(filename), filename_template, plnum, version);   \
-	(file).write(fs, filename);                                                \
+#define WRITE(file, filename_template, version)       \
+	file.write(fs, (boost::format(filename_template)   \
+						 % static_cast<unsigned int>(plnum) \
+						 % version).str().c_str());         \
 
 void MapPlayersViewPacket::write
 	(FileSystem & fs, EditorGameBase & egbase, MapObjectSaver &)
@@ -1174,12 +1177,10 @@
 				} while (r.x);
 			}
 
-			char filename[FILENAME_SIZE];
-
-			snprintf(filename, sizeof(filename), PLAYERDIRNAME_TEMPLATE, plnum);
-			fs.ensure_directory_exists(filename);
-			snprintf(filename, sizeof(filename),       DIRNAME_TEMPLATE, plnum);
-			fs.ensure_directory_exists(filename);
+			fs.ensure_directory_exists((boost::format(PLAYERDIRNAME_TEMPLATE)
+												 % static_cast<unsigned int>(plnum)).str().c_str());
+			fs.ensure_directory_exists((boost::format(DIRNAME_TEMPLATE)
+												 % static_cast<unsigned int>(plnum)).str().c_str());
 
 			WRITE
 				(unseen_times_file,

=== modified file 'src/map_io/map_port_spaces_packet.cc'
--- src/map_io/map_port_spaces_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_port_spaces_packet.cc	2014-10-03 19:24:49 +0000
@@ -31,7 +31,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
+constexpr int32_t kCurrentPacketVersion = 1;
 
 void MapPortSpacesPacket::read
 	(FileSystem & fs, EditorGameBase & egbase, bool, MapObjectLoader &)
@@ -45,7 +45,7 @@
 
 	try {
 		int32_t const packet_version = s1.get_int("packet_version");
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			const uint16_t num = s1.get_int("number_of_port_spaces", 0);
 			if (!num)
 				return;
@@ -56,9 +56,9 @@
 				snprintf(buf, sizeof(buf), "%u", i);
 				map.set_port_space(get_safe_coords(buf, ext, &s2), true);
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %i", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("port_spaces data: %s", e.what());
 	}
@@ -70,7 +70,7 @@
 {
 	Profile prof;
 	Section & s1 = prof.create_section("global");
-	s1.set_int("packet_version", CURRENT_PACKET_VERSION);
+	s1.set_int("packet_version", kCurrentPacketVersion);
 
 
 	// Clean up before saving: Delete port build spaces that are defined for a

=== modified file 'src/map_io/map_port_spaces_packet.h'
--- src/map_io/map_port_spaces_packet.h	2014-09-19 12:54:54 +0000
+++ src/map_io/map_port_spaces_packet.h	2014-10-03 19:24:49 +0000
@@ -36,11 +36,6 @@
 	//  The following function prereads a given map without the need of a
 	//  properly configured EditorGameBase object.
 	void pre_read(FileSystem &, Map*);
-
-	uint32_t get_version() {return m_version;}
-
-private:
-	uint32_t m_version;
 };
 
 }

=== modified file 'src/map_io/map_resources_packet.cc'
--- src/map_io/map_resources_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_resources_packet.cc	2014-10-03 19:24:49 +0000
@@ -31,8 +31,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapResourcesPacket::read
 	(FileSystem & fs, EditorGameBase & egbase, const OneWorldLegacyLookupTable& lookup_table)
@@ -43,55 +42,59 @@
 	Map   & map   = egbase.map();
 	const World & world = egbase.world();
 
-	const uint16_t packet_version = fr.unsigned_16();
-	if (packet_version == CURRENT_PACKET_VERSION) {
-		int32_t const nr_res = fr.unsigned_16();
-		if (world.get_nr_resources() < nr_res)
-			log
-				("WARNING: Number of resources in map (%i) is bigger than in world "
-				 "(%i)",
-				 nr_res, world.get_nr_resources());
-
-		// construct ids and map
-		std::map<uint8_t, uint8_t> smap;
-		for (uint8_t i = 0; i < nr_res; ++i) {
-			uint8_t const id = fr.unsigned_16();
-			const std::string resource_name = lookup_table.lookup_resource(fr.c_string());
-			int32_t const res = world.get_resource(resource_name.c_str());
-			if (res == -1)
-				throw GameDataError
-					("resource '%s' exists in map but not in world", resource_name.c_str());
-			smap[id] = res;
-		}
-
-		for (uint16_t y = 0; y < map.get_height(); ++y) {
-			for (uint16_t x = 0; x < map.get_width(); ++x) {
-				uint8_t const id           = fr.unsigned_8();
-				uint8_t const found_amount = fr.unsigned_8();
-				uint8_t const amount       = found_amount;
-				uint8_t const start_amount = fr.unsigned_8();
-
-				uint8_t set_id, set_amount, set_start_amount;
-				//  if amount is zero, theres nothing here
-				if (!amount) {
-					set_id           = 0;
-					set_amount       = 0;
-					set_start_amount = 0;
-				} else {
-					set_id           = smap[id];
-					set_amount       = amount;
-					set_start_amount = start_amount;
+	try {
+		const uint16_t packet_version = fr.unsigned_16();
+		if (packet_version == kCurrentPacketVersion) {
+			int32_t const nr_res = fr.unsigned_16();
+			if (world.get_nr_resources() < nr_res)
+				log
+					("WARNING: Number of resources in map (%i) is bigger than in world "
+					 "(%i)",
+					 nr_res, world.get_nr_resources());
+
+			// construct ids and map
+			std::map<uint8_t, uint8_t> smap;
+			for (uint8_t i = 0; i < nr_res; ++i) {
+				uint8_t const id = fr.unsigned_16();
+				const std::string resource_name = lookup_table.lookup_resource(fr.c_string());
+				int32_t const res = world.get_resource(resource_name.c_str());
+				if (res == -1)
+					throw GameDataError
+						("resource '%s' exists in map but not in world", resource_name.c_str());
+				smap[id] = res;
+			}
+
+			for (uint16_t y = 0; y < map.get_height(); ++y) {
+				for (uint16_t x = 0; x < map.get_width(); ++x) {
+					uint8_t const id           = fr.unsigned_8();
+					uint8_t const found_amount = fr.unsigned_8();
+					uint8_t const amount       = found_amount;
+					uint8_t const start_amount = fr.unsigned_8();
+
+					uint8_t set_id, set_amount, set_start_amount;
+					//  if amount is zero, theres nothing here
+					if (!amount) {
+						set_id           = 0;
+						set_amount       = 0;
+						set_start_amount = 0;
+					} else {
+						set_id           = smap[id];
+						set_amount       = amount;
+						set_start_amount = start_amount;
+					}
+
+					if (0xa < set_id)
+						throw "Unknown resource in map file. It is not in world!\n";
+					map[Coords(x, y)].set_resources(set_id, set_amount);
+					map[Coords(x, y)].set_starting_res_amount(set_start_amount);
 				}
-
-				if (0xa < set_id)
-					throw "Unknown resource in map file. It is not in world!\n";
-				map[Coords(x, y)].set_resources(set_id, set_amount);
-				map[Coords(x, y)].set_starting_res_amount(set_start_amount);
 			}
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
 		}
-	} else
-		throw GameDataError
-			("Unknown version in MapResourcesPacket: %u", packet_version);
+	} catch (const WException & e) {
+		throw GameDataError("port spaces: %s", e.what());
+	}
 }
 
 
@@ -107,7 +110,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	// This is a bit more complicated saved so that the order of loading
 	// of the resources at run time doesn't matter.

=== modified file 'src/map_io/map_road_packet.cc'
--- src/map_io/map_road_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_road_packet.cc	2014-10-03 19:24:49 +0000
@@ -33,8 +33,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapRoadPacket::read
 	(FileSystem            &       fs,
@@ -50,7 +49,7 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			Serial serial;
 			while ((serial = fr.unsigned_32()) != 0xffffffff) {
 				try {
@@ -61,9 +60,9 @@
 					throw GameDataError("%u: %s", serial, e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("road: %s", e.what());
 	}
@@ -75,7 +74,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	//  Write roads. Register this with the map_object_saver so that its data
 	//  can be saved later.

=== modified file 'src/map_io/map_roaddata_packet.cc'
--- src/map_io/map_roaddata_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_roaddata_packet.cc	2014-10-03 19:24:49 +0000
@@ -39,7 +39,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 4
+constexpr uint16_t kCurrentPacketVersion = 4;
 
 void MapRoaddataPacket::read
 	(FileSystem            &       fs,
@@ -55,19 +55,11 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (1 <= packet_version && packet_version <= CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			const Map   &       map        = egbase.map();
 			PlayerNumber const nr_players = map.get_nrplayers();
-			for (;;) {
-				if (2 <= packet_version && fr.end_of_file())
-					break;
+			while (! fr.end_of_file()) {
 				Serial const serial = fr.unsigned_32();
-				if (packet_version < 2 && serial == 0xffffffff) {
-					if (!fr.end_of_file())
-						throw GameDataError
-							("expected end of file after serial 0xffffffff");
-					break;
-				}
 				try {
 					Road & road = mol.get<Road>(serial);
 					if (mol.is_object_loaded(road))
@@ -79,10 +71,8 @@
 					Player & plr = egbase.player(player_index);
 
 					road.set_owner(&plr);
-					if (4 <= packet_version) {
-						road.m_busyness             = fr.unsigned_32();
-						road.m_busyness_last_update = fr.unsigned_32();
-					}
+					road.m_busyness             = fr.unsigned_32();
+					road.m_busyness_last_update = fr.unsigned_32();
 					road.m_type = fr.unsigned_32();
 					{
 						uint32_t const flag_0_serial = fr.unsigned_32();
@@ -131,21 +121,13 @@
 					uint32_t const count = fr.unsigned_32();
 					if (!count)
 						throw GameDataError("no carrier slot");
-					if (packet_version <= 2 && 1 < count)
-						throw GameDataError
-							(
-						 	 "expected 1 but found %u carrier slots in road saved "
-						 	 "with packet version 2 (old)",
-							 count);
 
 					for (uint32_t i = 0; i < count; ++i) {
 						Carrier * carrier = nullptr;
 						Request * carrier_request = nullptr;
 
-
 						if (uint32_t const carrier_serial = fr.unsigned_32())
 							try {
-								//log("Read carrier serial %u", carrier_serial);
 								carrier = &mol.get<Carrier>(carrier_serial);
 							} catch (const WException & e) {
 								throw GameDataError
@@ -153,14 +135,9 @@
 							}
 						else {
 							carrier = nullptr;
-							//log("No carrier in this slot");
 						}
 
-						//delete road.m_carrier_slots[i].carrier_request;
-						//carrier_request = 0;
-
 						if (fr.unsigned_8()) {
-							//log("Reading request");
 							(carrier_request =
 							 	new Request
 							 		(road,
@@ -170,10 +147,8 @@
 							->read(fr, ref_cast<Game, EditorGameBase>(egbase), mol);
 						} else {
 							carrier_request = nullptr;
-							//log("No request in this slot");
 						}
-						uint8_t const carrier_type =
-							packet_version < 3 ? 1 : fr.unsigned_32();
+						uint8_t const carrier_type = fr.unsigned_32();
 
 						if
 							(i < road.m_carrier_slots.size() &&
@@ -190,13 +165,9 @@
 						} else {
 							delete carrier_request;
 							if (carrier) {
-								//carrier->set_location (0);
 								carrier->reset_tasks
 									(ref_cast<Game,
 									 EditorGameBase>(egbase));
-								//carrier->send_signal
-								//(ref_cast<Game,
-								//EditorGameBase>(egbase), "location");
 							}
 						}
 					}
@@ -206,9 +177,9 @@
 					throw GameDataError("road %u: %s", serial, e.what());
 				}
 			}
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("roaddata: %s", e.what());
 	}
@@ -220,7 +191,7 @@
 {
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	const Map   & map        = egbase.map();
 	const Field & fields_end = map[map.max_index()];

=== modified file 'src/map_io/map_scripting_packet.cc'
--- src/map_io/map_scripting_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_scripting_packet.cc	2014-10-03 19:24:49 +0000
@@ -38,7 +38,7 @@
 namespace Widelands {
 
 namespace {
-const uint32_t SCRIPTING_DATA_PACKET_VERSION = 1;
+constexpr uint32_t kCurrentPacketVersion = 2;
 }  // namespace
 /*
  * ========================================================================
@@ -46,10 +46,10 @@
  * ========================================================================
  */
 void MapScriptingPacket::read
-	(FileSystem            &       fs,
-	 EditorGameBase      &       egbase,
+	(FileSystem& fs,
+	 EditorGameBase& egbase,
 	 bool,
-	 MapObjectLoader &       mol)
+	 MapObjectLoader& mol)
 {
 	// Always try to load the global State: even in a normal game, some lua
 	// coroutines could run. But make sure that this is really a game, other
@@ -58,14 +58,17 @@
 	FileRead fr;
 	if (g && fr.try_open(fs, "scripting/globals.dump"))
 	{
-		const uint32_t sentinel = fr.unsigned_32();
-		const uint32_t packet_version = fr.unsigned_32();
-		if (sentinel != 0xDEADBEEF && packet_version != SCRIPTING_DATA_PACKET_VERSION) {
-			throw GameDataError(
-			   "This savegame is from an older version of Widelands and can not be loaded any more.");
+		try {
+			const uint32_t packet_version = fr.unsigned_32();
+			if (packet_version == kCurrentPacketVersion) {
+				upcast(LuaGameInterface, lgi, &g->lua());
+				lgi->read_global_env(fr, mol, fr.unsigned_32());
+			} else {
+				throw OldVersionError(packet_version, kCurrentPacketVersion);
+			}
+		} catch (const WException & e) {
+			throw GameDataError("scripting: %s", e.what());
 		}
-		upcast(LuaGameInterface, lgi, &g->lua());
-		lgi->read_global_env(fr, mol, fr.unsigned_32());
 	}
 }
 
@@ -92,8 +95,7 @@
 	// Dump the global environment if this is a game and not in the editor
 	if (upcast(Game, g, &egbase)) {
 		FileWrite fw;
-		fw.unsigned_32(0xDEADBEEF);  // Sentinel, because there was no packet version.
-		fw.unsigned_32(SCRIPTING_DATA_PACKET_VERSION);
+		fw.unsigned_32(kCurrentPacketVersion);
 		const FileWrite::Pos pos = fw.get_pos();
 		fw.unsigned_32(0); // N bytes written, follows below
 

=== modified file 'src/map_io/map_terrain_packet.cc'
--- src/map_io/map_terrain_packet.cc	2014-09-20 09:37:47 +0000
+++ src/map_io/map_terrain_packet.cc	2014-10-03 19:24:49 +0000
@@ -33,7 +33,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapTerrainPacket::read(FileSystem& fs,
                                    EditorGameBase& egbase,
@@ -46,7 +46,7 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == CURRENT_PACKET_VERSION) {
+		if (packet_version == kCurrentPacketVersion) {
 			uint16_t const nr_terrains = fr.unsigned_16();
 
 			using TerrainIdMap = std::map<const uint16_t, TerrainIndex>;
@@ -74,7 +74,7 @@
 				f.set_terrain_d(smap[fr.unsigned_8()]);
 			}
 		} else {
-			throw GameDataError("unknown/unhandled version %u", packet_version);
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
 		}
 	} catch (const WException & e) {
 		throw GameDataError("terrain: %s", e.what());
@@ -88,7 +88,7 @@
 
 	FileWrite fw;
 
-	fw.unsigned_16(CURRENT_PACKET_VERSION);
+	fw.unsigned_16(kCurrentPacketVersion);
 
 	//  This is a bit more complicated saved so that the order of loading of the
 	//  terrains at run time does not matter. This is slow like hell.

=== modified file 'src/map_io/map_version_packet.cc'
--- src/map_io/map_version_packet.cc	2014-09-19 12:54:54 +0000
+++ src/map_io/map_version_packet.cc	2014-10-03 19:24:49 +0000
@@ -29,8 +29,7 @@
 
 namespace Widelands {
 
-#define CURRENT_PACKET_VERSION 1
-
+constexpr uint16_t kCurrentPacketVersion = 1;
 
 void MapVersionPacket::read
 	(FileSystem            &       fs,
@@ -57,8 +56,8 @@
 		int32_t const forward_compatibility =
 			globv.get_safe_int("packet_compatibility");
 		if
-		((packet_version == CURRENT_PACKET_VERSION)
-			|| (packet_version > CURRENT_PACKET_VERSION && forward_compatibility <= CURRENT_PACKET_VERSION))
+		((packet_version == kCurrentPacketVersion)
+			|| (packet_version > kCurrentPacketVersion && forward_compatibility <= kCurrentPacketVersion))
 		{
 			Map & map = egbase.map();
 			map.m_map_version.m_map_source_url = globv.get_safe_string("map_source_url");
@@ -68,9 +67,9 @@
 			map.m_map_version.m_map_version_minor = globv.get_safe_int("map_version_minor");
 			uint32_t ts = static_cast<uint32_t>(globv.get_safe_int("map_version_timestamp"));
 			map.m_map_version.m_map_version_timestamp = ts;
-		} else
-			throw GameDataError
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw OldVersionError(packet_version, kCurrentPacketVersion);
+		}
 	} catch (const WException & e) {
 		throw GameDataError("version: %s", e.what());
 	}
@@ -123,8 +122,8 @@
 	globs.set_int("map_version_major", map.m_map_version.m_map_version_major);
 	globs.set_int("map_version_minor", 1 + map.m_map_version.m_map_version_minor);
 	globs.set_int("map_version_timestamp", static_cast<uint32_t>(time(nullptr)));
-	globs.set_int("packet_version", CURRENT_PACKET_VERSION);
-	globs.set_int("packet_compatibility", CURRENT_PACKET_VERSION);
+	globs.set_int("packet_version", kCurrentPacketVersion);
+	globs.set_int("packet_compatibility", kCurrentPacketVersion);
 
 	prof.write("version", false, fs);
 }


Follow ups