← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/cleanup_map into lp:widelands

 

SirVer has proposed merging lp:~widelands-dev/widelands/cleanup_map into lp:widelands.

Commit message:
Cleanups map handling in EditorGameBase

- remove set_map which was unused.
- remove redundant functions, only keep map() and get_map().
- mark more functions around path finding as const to make the API of the map clearer.

This is a simple, but huge refactoring since it needs to touch all code that deals with the map.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/cleanup_map/+merge/329282
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/cleanup_map into lp:widelands.
=== modified file 'src/ai/ai_help_structs.cc'
--- src/ai/ai_help_structs.cc	2017-08-19 10:00:07 +0000
+++ src/ai/ai_help_structs.cc	2017-08-19 22:24:59 +0000
@@ -41,7 +41,7 @@
 }
 
 bool CheckStepRoadAI::allowed(
-   Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const {
+   const Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const {
 	uint8_t endcaps = player->get_buildcaps(end);
 
 	// we should not cross fields with road or flags (or any other immovable)

=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2017-08-19 08:59:54 +0000
+++ src/ai/ai_help_structs.h	2017-08-19 22:24:59 +0000
@@ -131,7 +131,7 @@
 struct CheckStepRoadAI {
 	CheckStepRoadAI(Player* const pl, uint8_t const mc, bool const oe);
 
-	bool allowed(Map&, FCoords start, FCoords end, int32_t dir, CheckStep::StepId) const;
+	bool allowed(const Map&, FCoords start, FCoords end, int32_t dir, CheckStep::StepId) const;
 	bool reachable_dest(const Map&, const FCoords& dest) const;
 
 	Player* player;

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2017-08-18 20:00:09 +0000
+++ src/ai/defaultai.cc	2017-08-19 22:24:59 +0000
@@ -244,7 +244,7 @@
 
 	const int32_t delay_time = gametime - taskPool.front().due_time;
 
-	Map& map = game().map();
+	const Map& map = game().map();
 
 	// Here we decide how many jobs will be run now (none - 5)
 	// in case no job is due now, it can be zero
@@ -690,7 +690,7 @@
 			for (const DescriptionIndex& temp_output : prod.output_ware_types()) {
 				bo.outputs.push_back(temp_output);
 			}
-			for (const auto temp_position : prod.working_positions()) {
+			for (const auto& temp_position : prod.working_positions()) {
 				bo.positions.push_back(temp_position.first);
 			}
 
@@ -925,7 +925,7 @@
 	taskPool.push_back(SchedulerTask(
 	   std::max<uint32_t>(gametime, 10 * 1000), SchedulerTaskId::kUpdateStats, 15, "review"));
 
-	Map& map = game().map();
+	const Map& map = game().map();
 
 	// here we generate list of all ports and their vicinity from entire map
 	for (const Coords& c : map.get_port_spaces()) {
@@ -1185,7 +1185,7 @@
 /// Updates one buildable field
 void DefaultAI::update_buildable_field(BuildableField& field) {
 	// look if there is any unowned land nearby
-	Map& map = game().map();
+	const Map& map = game().map();
 	const uint32_t gametime = game().get_gametime();
 	FindNodeUnownedWalkable find_unowned_walkable(player_, game());
 	FindEnemyNodeWalkable find_enemy_owned_walkable(player_, game());
@@ -1813,7 +1813,7 @@
 void DefaultAI::update_mineable_field(MineableField& field) {
 	// collect information about resources in the area
 	std::vector<ImmovableFound> immovables;
-	Map& map = game().map();
+	const Map& map = game().map();
 	map.find_immovables(Area<FCoords>(field.coords, 5), &immovables);
 	field.preferred = false;
 	field.mines_nearby = 0;
@@ -1948,7 +1948,7 @@
 	bool mine = false;
 	uint32_t consumers_nearby_count = 0;
 
-	Map& map = game().map();
+	const Map& map = game().map();
 
 	for (int32_t i = 0; i < 4; ++i)
 		spots_avail.at(i) = 0;
@@ -3226,7 +3226,7 @@
 	} else {
 		checkradius = 15;
 	}
-	Map& map = game().map();
+	const Map& map = game().map();
 
 	// algorithm to walk on roads
 	while (!queue.empty()) {
@@ -3371,7 +3371,7 @@
 		checkradius += 2;
 	}
 
-	Map& map = game().map();
+	const Map& map = game().map();
 
 	// initializing new object of FlagsForRoads, we will push there all candidate flags
 	Widelands::FlagsForRoads RoadCandidates(min_reduction);
@@ -3605,7 +3605,7 @@
 		}
 	}
 
-	Map& map = game().map();
+	const Map& map = game().map();
 
 	// The code here is bit complicated
 	// a) Either this site is pending for upgrade, if ready, order the upgrade
@@ -5437,7 +5437,7 @@
                                         uint16_t* mineable_fields_count,
                                         const Coords& starting_spot,
                                         const WalkSearch& type) {
-	Map& map = game().map();
+	const Map& map = game().map();
 	std::list<uint32_t> queue;
 	std::unordered_set<uint32_t> done;
 	queue.push_front(starting_spot.hash());
@@ -5640,7 +5640,7 @@
 				++num_ports;
 				seafaring_economy = true;
 				// unblock nearby fields, might be used for other buildings...
-				Map& map = game().map();
+				const Map& map = game().map();
 				MapRegion<Area<FCoords>> mr(
 				   map, Area<FCoords>(map.get_fcoords(warehousesites.back().site->get_position()), 3));
 				do {
@@ -5809,7 +5809,7 @@
 		return;
 	}
 	player_statistics.set_update_time(gametime);
-	Map& map = game().map();
+	const Map& map = game().map();
 	Widelands::PlayerNumber const pn = player_number();
 	PlayerNumber const nr_players = map.get_nrplayers();
 	uint32_t plr_in_game = 0;

=== modified file 'src/ai/defaultai_seafaring.cc'
--- src/ai/defaultai_seafaring.cc	2017-06-26 15:09:21 +0000
+++ src/ai/defaultai_seafaring.cc	2017-08-19 22:24:59 +0000
@@ -26,7 +26,7 @@
 // this scores spot for potential colony
 uint8_t DefaultAI::spot_scoring(Widelands::Coords candidate_spot) {
 
-	Map& map = game().map();
+	const Map& map = game().map();
 	PlayerNumber const pn = player_->player_number();
 	uint8_t score = 0;
 	uint16_t mineable_fields_count = 0;
@@ -421,7 +421,7 @@
 // navigation decisions (these notifications are processes not in 'real time')
 void DefaultAI::expedition_management(ShipObserver& so) {
 
-	Map& map = game().map();
+	const Map& map = game().map();
 	const int32_t gametime = game().get_gametime();
 	PlayerNumber const pn = player_->player_number();
 	// probability for island exploration repetition

=== modified file 'src/ai/defaultai_warfare.cc'
--- src/ai/defaultai_warfare.cc	2017-08-19 13:27:38 +0000
+++ src/ai/defaultai_warfare.cc	2017-08-19 22:24:59 +0000
@@ -23,7 +23,7 @@
 
 bool DefaultAI::check_enemy_sites(uint32_t const gametime) {
 
-	Map& map = game().map();
+	const Map& map = game().map();
 
 	PlayerNumber const nr_players = map.get_nrplayers();
 	uint32_t plr_in_game = 0;
@@ -777,7 +777,7 @@
 
 	// Check next militarysite
 	bool changed = false;
-	Map& map = game().map();
+	const Map& map = game().map();
 	MilitarySite* ms = militarysites.front().site;
 
 	// Don't do anything if last change took place lately

=== modified file 'src/economy/economy.cc'
--- src/economy/economy.cc	2017-06-20 08:17:02 +0000
+++ src/economy/economy.cc	2017-08-19 22:24:59 +0000
@@ -136,8 +136,6 @@
 
 void Economy::check_splits() {
 	EditorGameBase& egbase = owner().egbase();
-	Map& map = egbase.map();
-
 	while (split_checks_.size()) {
 		Flag* f1 = split_checks_.back().first.get(egbase);
 		Flag* f2 = split_checks_.back().second.get(egbase);
@@ -172,7 +170,7 @@
 		// reached from f1. These nodes induce a connected subgraph.
 		// This means that the newly created economy, which contains all the
 		// flags that have been split, is already connected.
-		RouteAStar<AStarEstimator> astar(*router_, wwWORKER, AStarEstimator(map, *f2));
+		RouteAStar<AStarEstimator> astar(*router_, wwWORKER, AStarEstimator(*egbase.mutable_map(), *f2));
 		astar.push(*f1);
 		std::set<OPtr<Flag>> reachable;
 
@@ -198,10 +196,8 @@
    Flag& start, Flag& end, Route* const route, WareWorker const type, int32_t const cost_cutoff) {
 	assert(start.get_economy() == this);
 	assert(end.get_economy() == this);
-
-	Map& map = owner().egbase().map();
-
-	return router_->find_route(start, end, route, type, cost_cutoff, map);
+	return router_->find_route(
+	   start, end, route, type, cost_cutoff, *owner().egbase().mutable_map());
 }
 
 struct ZeroEstimator {
@@ -604,7 +600,7 @@
 	Route* best_route = nullptr;
 	int32_t best_cost = -1;
 	Flag& target_flag = req.target_flag();
-	Map& map = game.map();
+	const Map& map = game.map();
 
 	available_supplies_.clear();
 

=== modified file 'src/economy/fleet.cc'
--- src/economy/fleet.cc	2017-08-09 19:25:04 +0000
+++ src/economy/fleet.cc	2017-08-19 22:24:59 +0000
@@ -138,9 +138,7 @@
  * of the same player.
  */
 void Fleet::find_other_fleet(EditorGameBase& egbase) {
-	Map& map = egbase.map();
-	MapAStar<StepEvalFindFleet> astar(map, StepEvalFindFleet());
-
+	MapAStar<StepEvalFindFleet> astar(*egbase.mutable_map(), StepEvalFindFleet());
 	for (const Ship* temp_ship : ships_) {
 		astar.push(temp_ship->get_position());
 	}
@@ -443,7 +441,6 @@
  * because path finding is flaky during map loading.
  */
 void Fleet::connect_port(EditorGameBase& egbase, uint32_t idx) {
-	Map& map = egbase.map();
 	StepEvalFindPorts se;
 
 	for (uint32_t i = 0; i < ports_.size(); ++i) {
@@ -463,7 +460,7 @@
 	if (se.targets.empty())
 		return;
 
-	MapAStar<StepEvalFindPorts> astar(map, se);
+	MapAStar<StepEvalFindPorts> astar(*egbase.mutable_map(), se);
 
 	BaseImmovable::PositionList src(ports_[idx]->get_positions(egbase));
 	for (const Coords& temp_pos : src) {

=== modified file 'src/economy/road.cc'
--- src/economy/road.cc	2017-04-23 12:11:19 +0000
+++ src/economy/road.cc	2017-08-19 22:24:59 +0000
@@ -109,7 +109,7 @@
 }
 
 BaseImmovable::PositionList Road::get_positions(const EditorGameBase& egbase) const {
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	Coords curf = map.get_fcoords(path_.get_start());
 
 	PositionList rv;
@@ -155,7 +155,7 @@
  * Add road markings to the map
 */
 void Road::mark_map(EditorGameBase& egbase) {
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	FCoords curf = map.get_fcoords(path_.get_start());
 
 	const Path::StepVector::size_type nr_steps = path_.get_nsteps();
@@ -189,7 +189,7 @@
  * Remove road markings from the map
 */
 void Road::unmark_map(EditorGameBase& egbase) {
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	FCoords curf(path_.get_start(), &map[path_.get_start()]);
 
 	const Path::StepVector::size_type nr_steps = path_.get_nsteps();
@@ -425,7 +425,7 @@
 	oldend.detach_road(flagidx_[FlagEnd]);
 
 	// build our new path and the new road's path
-	Map& map = game.map();
+	const Map& map = game.map();
 	CoordPath path(map, path_);
 	CoordPath secondpath(path);
 	int32_t const index = path.get_index(flag.get_position());

=== modified file 'src/economy/test/test_road.cc'
--- src/economy/test/test_road.cc	2017-06-22 16:49:12 +0000
+++ src/economy/test/test_road.cc	2017-08-19 22:24:59 +0000
@@ -45,14 +45,6 @@
 		set_flag_position(c);
 	}
 };
-struct TestingMap : public Map {
-	TestingMap(int const w, int const h) : Map() {
-		set_size(w, h);
-	}
-
-	void recalc_for_field_area(const World&, Area<FCoords>) override {
-	}
-};
 
 /*************************************************************************/
 /*                                 TESTS                                 */
@@ -69,11 +61,9 @@
 
 struct SimpleRoadTestsFixture : public WlTestFixture {
 	SimpleRoadTestsFixture() : g(nullptr), path(Coords(5, 5)) {
-		map = new TestingMap(32, 32);
-		g.set_map(map);
-
-		path.append(*map, WALK_E);
-		path.append(*map, WALK_E);
+		g.mutable_map()->set_size(32, 32);
+		path.append(g.map(), WALK_E);
+		path.append(g.map(), WALK_E);
 
 		start = new TestingFlag(g, Coords(5, 5));
 		end = new TestingFlag(g, Coords(7, 5));
@@ -84,7 +74,6 @@
 		// Map is deleted by EditorGameBase
 	}
 
-	TestingMap* map;
 	EditorGameBase g;
 	Road r;
 	Path path;

=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2017-08-17 15:34:45 +0000
+++ src/editor/editorinteractive.cc	2017-08-19 22:24:59 +0000
@@ -177,21 +177,21 @@
 }
 
 void EditorInteractive::register_overlays() {
-	Widelands::Map& map = egbase().map();
+	Widelands::Map* map = egbase().mutable_map();
 
 	//  Starting locations
-	Widelands::PlayerNumber const nr_players = map.get_nrplayers();
+	Widelands::PlayerNumber const nr_players = map->get_nrplayers();
 	assert(nr_players <= kMaxPlayers);
 	iterate_player_numbers(p, nr_players) {
-		if (Widelands::Coords const sp = map.get_starting_pos(p)) {
-			tools_->set_starting_pos.set_starting_pos(*this, p, sp, &map);
+		if (Widelands::Coords const sp = map->get_starting_pos(p)) {
+			tools_->set_starting_pos.set_starting_pos(*this, p, sp, map);
 		}
 	}
 
 	//  Resources: we do not calculate default resources, therefore we do not
 	//  expect to meet them here.
-	Widelands::Extent const extent = map.extent();
-	iterate_Map_FCoords(map, extent, fc) {
+	Widelands::Extent const extent = map->extent();
+	iterate_Map_FCoords(*map, extent, fc) {
 		if (uint8_t const amount = fc.field->get_resources_amount()) {
 			const std::string& immname =
 			   egbase().world().get_resource(fc.field->get_resources())->editor_image(amount);
@@ -206,11 +206,11 @@
 void EditorInteractive::load(const std::string& filename) {
 	assert(filename.size());
 
-	Widelands::Map& map = egbase().map();
+	Widelands::Map* map = egbase().mutable_map();
 
 	cleanup_for_load();
 
-	std::unique_ptr<Widelands::MapLoader> ml(map.get_correct_loader(filename));
+	std::unique_ptr<Widelands::MapLoader> ml(map->get_correct_loader(filename));
 	if (!ml.get())
 		throw WLWarning(
 		   _("Unsupported format"),
@@ -228,8 +228,8 @@
 
 	// Create the players. TODO(SirVer): this must be managed better
 	loader_ui.step(_("Creating players"));
-	iterate_player_numbers(p, map.get_nrplayers()) {
-		egbase().add_player(p, 0, map.get_scenario_player_tribe(p), map.get_scenario_player_name(p));
+	iterate_player_numbers(p, map->get_nrplayers()) {
+		egbase().add_player(p, 0, map->get_scenario_player_tribe(p), map->get_scenario_player_name(p));
 	}
 
 	ml->load_map_complete(egbase(), Widelands::MapLoader::LoadType::kEditor);
@@ -288,8 +288,8 @@
 }
 
 void EditorInteractive::map_clicked(bool should_draw) {
-	history_->do_action(tools_->current(), tools_->use_tool, egbase().map(), egbase().world(),
-	                    get_sel_pos(), *this, should_draw);
+	history_->do_action(tools_->current(), tools_->use_tool, *egbase().mutable_map(),
+	                    egbase().world(), get_sel_pos(), *this, should_draw);
 	set_need_save(true);
 }
 
@@ -523,11 +523,10 @@
 				toolsize_menu.update(toolsize_menu.value());
 			}
 		}
-		Widelands::Map& map = egbase().map();
 		//  A new tool has been selected. Remove all registered overlay callback
 		//  functions.
 		mutable_field_overlay_manager()->register_overlay_callback_function(nullptr);
-		map.recalc_whole_map(egbase().world());
+		egbase().mutable_map()->recalc_whole_map(egbase().world());
 	}
 	tools_->current_pointer = &primary;
 	tools_->use_tool = which;
@@ -603,16 +602,15 @@
 		GameTips editortips(loader_ui, tipstext);
 
 		{
-			Widelands::Map& map = *new Widelands::Map;
-			egbase.set_map(&map);
 			if (filename.empty()) {
 				loader_ui.step(_("Creating empty map…"));
-				map.create_empty_map(egbase.world(), 64, 64, 0,
-				                     /** TRANSLATORS: Default name for new map */
-				                     _("No Name"),
-				                     /** TRANSLATORS: Map author name when it hasn't been set yet */
-				                     g_options.pull_section("global").get_string(
-				                        "realname", pgettext("author_name", "Unknown")));
+				egbase.mutable_map()->create_empty_map(
+				   egbase.world(), 64, 64, 0,
+				   /** TRANSLATORS: Default name for new map */
+				   _("No Name"),
+				   /** TRANSLATORS: Map author name when it hasn't been set yet */
+				   g_options.pull_section("global").get_string(
+				      "realname", pgettext("author_name", "Unknown")));
 
 				load_all_tribes(&egbase, &loader_ui);
 

=== modified file 'src/editor/ui_menus/main_menu_map_options.cc'
--- src/editor/ui_menus/main_menu_map_options.cc	2017-06-11 20:09:05 +0000
+++ src/editor/ui_menus/main_menu_map_options.cc	2017-08-19 22:24:59 +0000
@@ -193,16 +193,16 @@
 }
 
 void MainMenuMapOptions::clicked_ok() {
-	eia().egbase().map().set_name(name_.text());
-	eia().egbase().map().set_author(author_.text());
+	eia().egbase().mutable_map()->set_name(name_.text());
+	eia().egbase().mutable_map()->set_author(author_.text());
 	g_options.pull_section("global").set_string("realname", author_.text());
-	eia().egbase().map().set_description(descr_->get_text());
-	eia().egbase().map().set_hint(hint_->get_text());
+	eia().egbase().mutable_map()->set_description(descr_->get_text());
+	eia().egbase().mutable_map()->set_hint(hint_->get_text());
 
-	eia().egbase().map().clear_tags();
+	eia().egbase().mutable_map()->clear_tags();
 	for (const auto& tag : tags_checkboxes_) {
 		if (tag.second->get_state()) {
-			eia().egbase().map().add_tag(tag.first);
+			eia().egbase().mutable_map()->add_tag(tag.first);
 		}
 	}
 

=== modified file 'src/editor/ui_menus/main_menu_new_map.cc'
--- src/editor/ui_menus/main_menu_new_map.cc	2017-02-25 11:17:28 +0000
+++ src/editor/ui_menus/main_menu_new_map.cc	2017-08-19 22:24:59 +0000
@@ -138,14 +138,14 @@
 void MainMenuNewMap::clicked_create_map() {
 	EditorInteractive& parent = eia();
 	Widelands::EditorGameBase& egbase = parent.egbase();
-	Widelands::Map& map = egbase.map();
+	Widelands::Map* map = egbase.mutable_map();
 	UI::ProgressWindow loader_ui;
 
 	loader_ui.step(_("Creating empty map…"));
 
 	parent.cleanup_for_load();
 
-	map.create_empty_map(
+	map->create_empty_map(
 	   egbase.world(), width_.get_value() > 0 ? width_.get_value() : Widelands::kMapDimensions[0],
 	   height_.get_value() > 0 ? height_.get_value() : Widelands::kMapDimensions[0],
 	   list_.get_selected(), _("No Name"),
@@ -154,7 +154,7 @@
 	egbase.postload();
 	egbase.load_graphics(loader_ui);
 
-	map.recalc_whole_map(egbase.world());
+	map->recalc_whole_map(egbase.world());
 	parent.map_changed(EditorInteractive::MapWas::kReplaced);
 	die();
 }

=== modified file 'src/editor/ui_menus/main_menu_random_map.cc'
--- src/editor/ui_menus/main_menu_random_map.cc	2017-06-20 08:18:38 +0000
+++ src/editor/ui_menus/main_menu_random_map.cc	2017-08-19 22:24:59 +0000
@@ -512,7 +512,7 @@
 	cancel_button_.set_enabled(false);
 	EditorInteractive& eia = dynamic_cast<EditorInteractive&>(*get_parent());
 	Widelands::EditorGameBase& egbase = eia.egbase();
-	Widelands::Map& map = egbase.map();
+	 Widelands::Map* map = egbase.mutable_map();
 	UI::ProgressWindow loader_ui;
 
 	eia.cleanup_for_load();
@@ -528,12 +528,12 @@
 	      << "Resources = " << resources_.get_title() << "\n"
 	      << "ID = " << map_id_edit_.text() << "\n";
 
-	MapGenerator gen(map, map_info, egbase);
-	map.create_empty_map(
-	   egbase.world(), map_info.w, map_info.h, 0, _("No Name"),
-	   g_options.pull_section("global").get_string("realname", pgettext("author_name", "Unknown")),
-	   sstrm.str().c_str());
-	loader_ui.step(_("Generating random map…"));
+		MapGenerator gen(*map, map_info, egbase);
+		map->create_empty_map(
+			egbase.world(), map_info.w, map_info.h, 0, _("No Name"),
+			g_options.pull_section("global").get_string("realname", pgettext("author_name", "Unknown")),
+			sstrm.str().c_str());
+		loader_ui.step(_("Generating random map…"));
 
 	log("============== Generating Map ==============\n");
 	log("ID:            %s\n", map_id_edit_.text().c_str());
@@ -564,7 +564,7 @@
 	egbase.postload();
 	egbase.load_graphics(loader_ui);
 
-	map.recalc_whole_map(egbase.world());
+	map->recalc_whole_map(egbase.world());
 	eia.map_changed(EditorInteractive::MapWas::kReplaced);
 	UI::WLMessageBox mbox(
 	   &eia,

=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2017-02-26 12:16:09 +0000
+++ src/editor/ui_menus/main_menu_save_map.cc	2017-08-19 22:24:59 +0000
@@ -129,10 +129,10 @@
 		set_current_directory(complete_filename);
 		fill_table();
 	} else {  //  Ok, save this map
-		Widelands::Map& map = eia().egbase().map();
-		if (map.get_name() == _("No Name")) {
+		Widelands::Map* map = eia().egbase().mutable_map();
+		if (map->get_name() == _("No Name")) {
 			std::string::size_type const filename_size = filename.size();
-			map.set_name(4 <= filename_size && boost::iends_with(filename, WLMF_SUFFIX) ?
+			map->set_name(4 <= filename_size && boost::iends_with(filename, WLMF_SUFFIX) ?
 			                filename.substr(0, filename_size - 4) :
 			                filename);
 		}
@@ -272,23 +272,23 @@
 	}
 
 	Widelands::EditorGameBase& egbase = eia().egbase();
-	Widelands::Map& map = egbase.map();
+	Widelands::Map* map = egbase.mutable_map();
 
 	{  // fs scope
 		std::unique_ptr<FileSystem> fs(
 		   g_fs->create_sub_file_system(tmp_name, binary ? FileSystem::ZIP : FileSystem::DIR));
 
 		// Recompute seafaring tag
-		if (map.allows_seafaring()) {
-			map.add_tag("seafaring");
+		if (map->allows_seafaring()) {
+			map->add_tag("seafaring");
 		} else {
-			map.delete_tag("seafaring");
+			map->delete_tag("seafaring");
 		}
 
-		if (map.has_artifacts()) {
-			map.add_tag("artifacts");
+		if (map->has_artifacts()) {
+			map->add_tag("artifacts");
 		} else {
-			map.delete_tag("artifacts");
+			map->delete_tag("artifacts");
 		}
 
 		try {
@@ -297,14 +297,14 @@
 			delete wms;
 			// Reset filesystem to avoid file locks on saves
 			fs.reset();
-			map.reset_filesystem();
+			map->reset_filesystem();
 			eia().set_need_save(false);
 			g_fs->fs_unlink(complete_filename);
 			g_fs->fs_rename(tmp_name, complete_filename);
 			// Also change fs, as we assign it to the map below
 			fs.reset(g_fs->make_sub_file_system(complete_filename));
 			// Set the filesystem of the map to the current save file / directory
-			map.swap_filesystem(fs);
+			map->swap_filesystem(fs);
 			// DONT use fs as of here, its garbage now!
 
 		} catch (const std::exception& e) {

=== modified file 'src/editor/ui_menus/player_menu.cc'
--- src/editor/ui_menus/player_menu.cc	2017-08-18 02:28:27 +0000
+++ src/editor/ui_menus/player_menu.cc	2017-08-19 22:24:59 +0000
@@ -110,8 +110,8 @@
 	if (is_minimal())
 		return;
 
-	Widelands::Map& map = eia().egbase().map();
-	Widelands::PlayerNumber const nr_players = map.get_nrplayers();
+	Widelands::Map* map = eia().egbase().mutable_map();
+	Widelands::PlayerNumber const nr_players = map->get_nrplayers();
 	{
 		assert(nr_players <= 99);  //  2 decimal digits
 		char text[3];
@@ -147,7 +147,7 @@
 			plr_names_[p - 1]->changed.connect(
 			   boost::bind(&EditorPlayerMenu::name_changed, this, p - 1));
 			posx += 140 + spacing;
-			plr_names_[p - 1]->set_text(map.get_scenario_player_name(p));
+			plr_names_[p - 1]->set_text(map->get_scenario_player_name(p));
 		}
 
 		if (!plr_set_tribes_buts_[p - 1]) {
@@ -160,19 +160,19 @@
 		}
 
 		// Get/Set (localized) tribe names
-		if (map.get_scenario_player_tribe(p) != UNDEFINED_TRIBE_NAME) {
-			selected_tribes_[p - 1] = map.get_scenario_player_tribe(p);
+		if (map->get_scenario_player_tribe(p) != UNDEFINED_TRIBE_NAME) {
+			selected_tribes_[p - 1] = map->get_scenario_player_tribe(p);
 		} else {
 			selected_tribes_[p - 1] = tribenames_[0];
-			map.set_scenario_player_tribe(p, selected_tribes_[p - 1]);
+			map->set_scenario_player_tribe(p, selected_tribes_[p - 1]);
 		}
 
 		plr_set_tribes_buts_[p - 1]->set_title(
 		   Widelands::get_tribeinfo(selected_tribes_[p - 1]).descname);
 
 		// Set default AI and closeable to false (always default - should be changed by hand)
-		map.set_scenario_player_ai(p, "");
-		map.set_scenario_player_closeable(p, false);
+		map->set_scenario_player_ai(p, "");
+		map->set_scenario_player_closeable(p, false);
 
 		//  Set Starting pos button.
 		if (!plr_set_pos_buts_[p - 1]) {
@@ -195,18 +195,18 @@
 }
 
 void EditorPlayerMenu::clicked_add_player() {
-	Widelands::Map& map = eia().egbase().map();
-	Widelands::PlayerNumber const nr_players = map.get_nrplayers() + 1;
+	Widelands::Map* map = eia().egbase().mutable_map();
+	Widelands::PlayerNumber const nr_players = map->get_nrplayers() + 1;
 	assert(nr_players <= kMaxPlayers);
-	map.set_nrplayers(nr_players);
+	map->set_nrplayers(nr_players);
 	{                             //  register new default name for this players
 		assert(nr_players <= 99);  //  2 decimal digits
 		/** TRANSLATORS: Default player name, e.g. Player 1 */
 		const std::string name =
 		   (boost::format(_("Player %u")) % static_cast<unsigned int>(nr_players)).str();
-		map.set_scenario_player_name(nr_players, name);
+		map->set_scenario_player_name(nr_players, name);
 	}
-	map.set_scenario_player_tribe(nr_players, tribenames_[0]);
+	map->set_scenario_player_tribe(nr_players, tribenames_[0]);
 	eia().set_need_save(true);
 	add_player_.set_enabled(nr_players < kMaxPlayers);
 	remove_last_player_.set_enabled(true);
@@ -215,13 +215,13 @@
 
 void EditorPlayerMenu::clicked_remove_last_player() {
 	EditorInteractive& menu = eia();
-	Widelands::Map& map = menu.egbase().map();
-	Widelands::PlayerNumber const old_nr_players = map.get_nrplayers();
+	Widelands::Map* map = menu.egbase().mutable_map();
+	Widelands::PlayerNumber const old_nr_players = map->get_nrplayers();
 	Widelands::PlayerNumber const nr_players = old_nr_players - 1;
 	assert(1 <= nr_players);
 
 	if (!menu.is_player_tribe_referenced(old_nr_players)) {
-		if (const Widelands::Coords sp = map.get_starting_pos(old_nr_players)) {
+		if (const Widelands::Coords sp = map->get_starting_pos(old_nr_players)) {
 			//  Remove starting position marker.
 			const Image* player_image =
 			   playercolor_image(old_nr_players - 1, "images/players/player_position.png");
@@ -232,7 +232,7 @@
 		if (old_nr_players == menu.tools()->set_starting_pos.get_current_player())
 			set_starting_pos_clicked(nr_players);
 	}
-	map.set_nrplayers(nr_players);
+	map->set_nrplayers(nr_players);
 	add_player_.set_enabled(nr_players < kMaxPlayers);
 	remove_last_player_.set_enabled(1 < nr_players);
 	update();
@@ -257,7 +257,7 @@
 			}
 		}
 		selected_tribes_[n] = i == tribenames_.size() - 1 ? tribenames_[0] : tribenames_[++i];
-		menu.egbase().map().set_scenario_player_tribe(n + 1, selected_tribes_[n]);
+		menu.egbase().mutable_map()->set_scenario_player_tribe(n + 1, selected_tribes_[n]);
 		menu.set_need_save(true);
 	} else {
 		UI::WLMessageBox mmb(&menu, _("Error!"),
@@ -275,8 +275,8 @@
 void EditorPlayerMenu::set_starting_pos_clicked(uint8_t n) {
 	EditorInteractive& menu = eia();
 	//  jump to the current node
-	Widelands::Map& map = menu.egbase().map();
-	if (Widelands::Coords const sp = map.get_starting_pos(n)) {
+	Widelands::Map* map = menu.egbase().mutable_map();
+	if (Widelands::Coords const sp = map->get_starting_pos(n)) {
 		menu.map_view()->scroll_to_field(sp, MapView::Transition::Smooth);
 	}
 
@@ -290,8 +290,8 @@
 	//  Register callback function to make sure that only valid locations are
 	//  selected.
 	menu.mutable_field_overlay_manager()->register_overlay_callback_function(
-	   boost::bind(&editor_tool_set_starting_pos_callback, _1, boost::ref(map)));
-	map.recalc_whole_map(menu.egbase().world());
+	   boost::bind(&editor_tool_set_starting_pos_callback, _1, boost::ref(*map)));
+	map->recalc_whole_map(menu.egbase().world());
 	update();
 }
 
@@ -302,8 +302,8 @@
 	//  Player name has been changed.
 	std::string text = plr_names_[m]->text();
 	EditorInteractive& menu = eia();
-	Widelands::Map& map = menu.egbase().map();
-	map.set_scenario_player_name(m + 1, text);
-	plr_names_[m]->set_text(map.get_scenario_player_name(m + 1));
+	Widelands::Map* map = menu.egbase().mutable_map();
+	map->set_scenario_player_name(m + 1, text);
+	plr_names_[m]->set_text(map->get_scenario_player_name(m + 1));
 	menu.set_need_save(true);
 }

=== modified file 'src/editor/ui_menus/tool_change_resources_options_menu.cc'
--- src/editor/ui_menus/tool_change_resources_options_menu.cc	2017-08-13 18:02:53 +0000
+++ src/editor/ui_menus/tool_change_resources_options_menu.cc	2017-08-19 22:24:59 +0000
@@ -154,16 +154,16 @@
 	increase_tool_.decrease_tool().set_cur_res(resource_index);
 
 	Widelands::EditorGameBase& egbase = eia().egbase();
-	Widelands::Map& map = egbase.map();
+	Widelands::Map* map = egbase.mutable_map();
 	eia().mutable_field_overlay_manager()->register_overlay_callback_function(
-	   [resource_index, &map, &egbase](const Widelands::FCoords& fc) -> uint32_t {
-		   if (map.is_resource_valid(egbase.world(), fc, resource_index)) {
+	   [resource_index, map, &egbase](const Widelands::FCoords& fc) -> uint32_t {
+		   if (map->is_resource_valid(egbase.world(), fc, resource_index)) {
 			   return fc.field->nodecaps();
 		   }
 		   return 0;
 		});
 
-	map.recalc_whole_map(egbase.world());
+	map->recalc_whole_map(egbase.world());
 	select_correct_tool();
 	update();
 }

=== modified file 'src/editor/ui_menus/tool_menu.cc'
--- src/editor/ui_menus/tool_menu.cc	2017-08-13 18:02:53 +0000
+++ src/editor/ui_menus/tool_menu.cc	2017-08-19 22:24:59 +0000
@@ -142,10 +142,10 @@
 	parent.select_tool(*current_tool_pointer, EditorTool::First);
 	if (current_tool_pointer == &parent.tools()->set_port_space) {
 		// Set correct overlay
-		Widelands::Map& map = parent.egbase().map();
+		Widelands::Map* map = parent.egbase().mutable_map();
 		parent.mutable_field_overlay_manager()->register_overlay_callback_function(
-		   boost::bind(&editor_tool_set_port_space_callback, _1, boost::ref(map)));
-		map.recalc_whole_map(parent.egbase().world());
+		   boost::bind(&editor_tool_set_port_space_callback, _1, boost::ref(*map)));
+		map->recalc_whole_map(parent.egbase().world());
 	}
 
 	if (current_registry_pointer) {

=== modified file 'src/game_io/game_map_packet.cc'
--- src/game_io/game_map_packet.cc	2017-01-25 18:55:59 +0000
+++ src/game_io/game_map_packet.cc	2017-08-19 22:24:59 +0000
@@ -41,7 +41,7 @@
 	//  Now Load the map as it would be a normal map saving.
 	delete wml_;
 
-	wml_ = new WidelandsMapLoader(fs.make_sub_file_system("map"), &game.map());
+	wml_ = new WidelandsMapLoader(fs.make_sub_file_system("map"), game.mutable_map());
 
 	wml_->preload_map(true);
 

=== modified file 'src/graphic/game_renderer.cc'
--- src/graphic/game_renderer.cc	2017-08-16 08:59:09 +0000
+++ src/graphic/game_renderer.cc	2017-08-19 22:24:59 +0000
@@ -340,7 +340,7 @@
 	const int surface_width = surface->width();
 	const int surface_height = surface->height();
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	const uint32_t gametime = egbase.get_gametime();
 
 	const float scale = 1.f / zoom;

=== modified file 'src/graphic/minimap_renderer.cc'
--- src/graphic/minimap_renderer.cc	2017-08-09 19:25:04 +0000
+++ src/graphic/minimap_renderer.cc	2017-08-19 22:24:59 +0000
@@ -158,7 +158,7 @@
 	const Widelands::Map& map = egbase.map();
 	const uint16_t surface_h = texture->height();
 	const uint16_t surface_w = texture->width();
-	const int32_t mapwidth = egbase.get_map().get_width();
+	const int32_t mapwidth = map.get_width();
 
 	for (uint32_t y = 0; y < surface_h; ++y) {
 		Widelands::FCoords f(

=== modified file 'src/logic/editor_game_base.cc'
--- src/logic/editor_game_base.cc	2017-06-25 08:20:25 +0000
+++ src/logic/editor_game_base.cc	2017-08-19 22:24:59 +0000
@@ -67,14 +67,13 @@
    : gametime_(0),
      lua_(lua_interface),
      player_manager_(new PlayersManager(*this)),
-     ibase_(nullptr),
-     map_(nullptr) {
+     ibase_(nullptr) {
+		  // NOCOM(#sirver): Why not initialize in the editor?
 	if (!lua_)  // TODO(SirVer): this is sooo ugly, I can't say
 		lua_.reset(new LuaEditorInterface(this));
 }
 
 EditorGameBase::~EditorGameBase() {
-	delete map_;
 	delete player_manager_.release();
 }
 
@@ -187,19 +186,6 @@
 		}
 }
 
-/**
- * Replaces the current map with the given one. Ownership of the map is transferred
- * to the EditorGameBase object.
- */
-void EditorGameBase::set_map(Map* const new_map) {
-	assert(new_map != map_);
-	assert(new_map);
-
-	delete map_;
-
-	map_ = new_map;
-}
-
 void EditorGameBase::allocate_player_maps() {
 	iterate_players_existing(plnum, kMaxPlayers, *this, p) {
 		p->allocate_map();
@@ -412,8 +398,7 @@
 
 	player_manager_->cleanup();
 
-	if (map_)
-		map_->cleanup();
+	map_.cleanup();
 }
 
 void EditorGameBase::set_road(const FCoords& f, uint8_t const direction, uint8_t const roadtype) {
@@ -566,7 +551,7 @@
 	//  This must reach one step beyond the conquered area to adjust the borders
 	//  of neighbour players.
 	++player_area.radius;
-	map().recalc_for_field_area(world(), player_area);
+	map_.recalc_for_field_area(world(), player_area);
 }
 
 /// Conquers the given area for that player; does the actual work.
@@ -642,21 +627,20 @@
 	// This must reach one step beyond the conquered area to adjust the borders
 	// of neighbour players.
 	++player_area.radius;
-	map().recalc_for_field_area(world(), player_area);
+	map_.recalc_for_field_area(world(), player_area);
 }
 
 /// Makes sure that buildings cannot exist outside their owner's territory.
 void EditorGameBase::cleanup_playerimmovables_area(PlayerArea<Area<FCoords>> const area) {
 	std::vector<ImmovableFound> immovables;
 	std::vector<PlayerImmovable*> burnlist;
-	Map& m = map();
 
 	//  find all immovables that need fixing
-	m.find_immovables(area, &immovables, FindImmovablePlayerImmovable());
+	map_.find_immovables(area, &immovables, FindImmovablePlayerImmovable());
 
 	for (const ImmovableFound& temp_imm : immovables) {
 		upcast(PlayerImmovable, imm, temp_imm.object);
-		if (!m[temp_imm.coords].is_interior(imm->owner().player_number())) {
+		if (!map_[temp_imm.coords].is_interior(imm->owner().player_number())) {
 			if (std::find(burnlist.begin(), burnlist.end(), imm) == burnlist.end()) {
 				burnlist.push_back(imm);
 			}

=== modified file 'src/logic/editor_game_base.h'
--- src/logic/editor_game_base.h	2017-06-25 19:12:30 +0000
+++ src/logic/editor_game_base.h	2017-08-19 22:24:59 +0000
@@ -84,16 +84,11 @@
 	explicit EditorGameBase(LuaInterface* lua);
 	virtual ~EditorGameBase();
 
-	void set_map(Map*);
-	// TODO(sirver): this should just be const Map& map() and Map* mutable_map().
-	Map& map() const {
-		return *map_;
-	}
-	Map* get_map() {
+	const Map& map() const {
 		return map_;
 	}
-	Map& get_map() const {
-		return *map_;
+	Map* mutable_map() {
+		return &map_;
 	}
 	const ObjectManager& objects() const {
 		return objects_;
@@ -258,7 +253,7 @@
 	std::unique_ptr<World> world_;
 	std::unique_ptr<Tribes> tribes_;
 	std::unique_ptr<InteractiveBase> ibase_;
-	Map* map_;
+	Map map_;
 
 	DISALLOW_COPY_AND_ASSIGN(EditorGameBase);
 };

=== modified file 'src/logic/game.cc'
--- src/logic/game.cc	2017-08-18 02:28:27 +0000
+++ src/logic/game.cc	2017-08-19 22:24:59 +0000
@@ -197,9 +197,7 @@
 	// Replays can't handle scenarios
 	set_write_replay(false);
 
-	set_map(new Map);
-
-	std::unique_ptr<MapLoader> maploader(map().get_correct_loader(mapname));
+	std::unique_ptr<MapLoader> maploader(mutable_map()->get_correct_loader(mapname));
 	if (!maploader)
 		throw wexception("could not load \"%s\"", mapname.c_str());
 	UI::ProgressWindow loader_ui;
@@ -252,10 +250,7 @@
 
 	loader_ui->step(_("Preloading map"));
 
-	assert(!get_map());
-	set_map(new Map);
-
-	std::unique_ptr<MapLoader> maploader(map().get_correct_loader(settings.mapfilename));
+	std::unique_ptr<MapLoader> maploader(mutable_map()->get_correct_loader(settings.mapfilename));
 	assert(maploader != nullptr);
 	maploader->preload_map(settings.scenario);
 
@@ -325,8 +320,6 @@
 
 	loader_ui->step(_("Preloading map"));
 
-	assert(!get_map());
-	set_map(new Map);
 	try {
 		GameLoader gl(settings.mapfilename, *this);
 		Widelands::GamePreloadPacket gpdp;
@@ -355,9 +348,6 @@
 
 	loader_ui.step(_("Preloading map"));
 
-	// We have to create an empty map, otherwise nothing will load properly
-	set_map(new Map);
-
 	{
 		GameLoader gl(filename, *this);
 
@@ -462,7 +452,7 @@
 		}
 
 		// Prepare the map, set default textures
-		map().recalc_default_resources(world());
+		mutable_map()->recalc_default_resources(world());
 
 		// Finally, set the scenario names and tribes to represent
 		// the correct names of the players
@@ -472,10 +462,10 @@
 			const std::string& player_tribe = plr ? plr->tribe().name() : no_name;
 			const std::string& player_name = plr ? plr->get_name() : no_name;
 			const std::string& player_ai = plr ? plr->get_ai() : no_name;
-			map().set_scenario_player_tribe(p, player_tribe);
-			map().set_scenario_player_name(p, player_name);
-			map().set_scenario_player_ai(p, player_ai);
-			map().set_scenario_player_closeable(p, false);  // player is already initialized.
+			mutable_map()->set_scenario_player_tribe(p, player_tribe);
+			mutable_map()->set_scenario_player_name(p, player_name);
+			mutable_map()->set_scenario_player_ai(p, player_ai);
+			mutable_map()->set_scenario_player_closeable(p, false);  // player is already initialized.
 		}
 
 		// Run the init script, if the map provides one.

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2017-08-12 20:13:24 +0000
+++ src/logic/map.cc	2017-08-19 22:24:59 +0000
@@ -565,7 +565,7 @@
 ===============
 */
 template <typename functorT>
-void Map::find_reachable(const Area<FCoords>& area, const CheckStep& checkstep, functorT& functor) {
+void Map::find_reachable(const Area<FCoords>& area, const CheckStep& checkstep, functorT& functor) const {
 	std::vector<Coords> queue;
 	boost::shared_ptr<Pathfields> pathfields = pathfieldmgr_->allocate();
 
@@ -655,7 +655,7 @@
 ===============
 */
 uint32_t
-Map::find_bobs(Area<FCoords> const area, std::vector<Bob*>* const list, const FindBob& functor) {
+Map::find_bobs(Area<FCoords> const area, std::vector<Bob*>* const list, const FindBob& functor) const {
 	FindBobsCallback cb(list, functor);
 
 	find(area, cb);
@@ -678,7 +678,7 @@
 uint32_t Map::find_reachable_bobs(Area<FCoords> const area,
                                   std::vector<Bob*>* const list,
                                   const CheckStep& checkstep,
-                                  const FindBob& functor) {
+                                  const FindBob& functor) const {
 	FindBobsCallback cb(list, functor);
 
 	find_reachable(area, checkstep, cb);
@@ -731,7 +731,7 @@
 */
 uint32_t Map::find_immovables(Area<FCoords> const area,
                               std::vector<ImmovableFound>* const list,
-                              const FindImmovable& functor) {
+                              const FindImmovable& functor) const{
 	FindImmovablesCallback cb(list, functor);
 
 	find(area, cb);
@@ -752,7 +752,7 @@
 uint32_t Map::find_reachable_immovables(Area<FCoords> const area,
                                         std::vector<ImmovableFound>* const list,
                                         const CheckStep& checkstep,
-                                        const FindImmovable& functor) {
+                                        const FindImmovable& functor) const {
 	FindImmovablesCallback cb(list, functor);
 
 	find_reachable(area, checkstep, cb);
@@ -770,7 +770,7 @@
 uint32_t Map::find_reachable_immovables_unique(const Area<FCoords> area,
                                                std::vector<BaseImmovable*>& list,
                                                const CheckStep& checkstep,
-                                               const FindImmovable& functor) {
+                                               const FindImmovable& functor) const {
 	std::vector<ImmovableFound> duplist;
 	FindImmovablesCallback cb(&duplist, find_immovable_always_true());
 
@@ -824,7 +824,7 @@
 ===============
 */
 uint32_t
-Map::find_fields(Area<FCoords> const area, std::vector<Coords>* list, const FindNode& functor) {
+Map::find_fields(Area<FCoords> const area, std::vector<Coords>* list, const FindNode& functor) const {
 	FindNodesCallback cb(list, functor);
 
 	find(area, cb);
@@ -844,7 +844,7 @@
 uint32_t Map::find_reachable_fields(Area<FCoords> const area,
                                     std::vector<Coords>* list,
                                     const CheckStep& checkstep,
-                                    const FindNode& functor) {
+                                    const FindNode& functor) const {
 	FindNodesCallback cb(list, functor);
 
 	find_reachable(area, checkstep, cb);
@@ -1595,7 +1595,7 @@
                       int32_t const persist,
                       Path& path,
                       const CheckStep& checkstep,
-                      uint32_t const flags) {
+                      uint32_t const flags) const {
 	FCoords start;
 	FCoords end;
 	int32_t upper_cost_limit;

=== modified file 'src/logic/map.h'
--- src/logic/map.h	2017-08-12 06:51:08 +0000
+++ src/logic/map.h	2017-08-19 22:24:59 +0000
@@ -181,7 +181,7 @@
 	    const std::string& description = _("No description defined"));
 
 	void recalc_whole_map(const World& world);
-	virtual void recalc_for_field_area(const World& world, Area<FCoords>);
+	void recalc_for_field_area(const World& world, Area<FCoords>);
 
 	/***
 	 * Ensures that resources match their adjacent terrains.
@@ -292,27 +292,27 @@
 	BaseImmovable* get_immovable(const Coords&) const;
 	uint32_t find_bobs(const Area<FCoords>,
 	                   std::vector<Bob*>* list,
-	                   const FindBob& functor = FindBobAlwaysTrue());
+	                   const FindBob& functor = FindBobAlwaysTrue()) const;
 	uint32_t find_reachable_bobs(const Area<FCoords>,
 	                             std::vector<Bob*>* list,
 	                             const CheckStep&,
-	                             const FindBob& functor = FindBobAlwaysTrue());
+	                             const FindBob& functor = FindBobAlwaysTrue()) const;
 	uint32_t find_immovables(const Area<FCoords>,
 	                         std::vector<ImmovableFound>* list,
-	                         const FindImmovable& = find_immovable_always_true());
+	                         const FindImmovable& = find_immovable_always_true()) const;
 	uint32_t find_reachable_immovables(const Area<FCoords>,
 	                                   std::vector<ImmovableFound>* list,
 	                                   const CheckStep&,
-	                                   const FindImmovable& = find_immovable_always_true());
+	                                   const FindImmovable& = find_immovable_always_true()) const;
 	uint32_t find_reachable_immovables_unique(const Area<FCoords>,
 	                                          std::vector<BaseImmovable*>& list,
 	                                          const CheckStep&,
-	                                          const FindImmovable& = find_immovable_always_true());
-	uint32_t find_fields(const Area<FCoords>, std::vector<Coords>* list, const FindNode& functor);
+	                                          const FindImmovable& = find_immovable_always_true()) const;
+	uint32_t find_fields(const Area<FCoords>, std::vector<Coords>* list, const FindNode& functor) const;
 	uint32_t find_reachable_fields(const Area<FCoords>,
 	                               std::vector<Coords>* list,
 	                               const CheckStep&,
-	                               const FindNode&);
+	                               const FindNode&) const;
 
 	// Field logic
 	static MapIndex get_index(const Coords&, int16_t width);
@@ -370,7 +370,7 @@
 	                 const int32_t persist,
 	                 Path&,
 	                 const CheckStep&,
-	                 const uint32_t flags = 0);
+	                 const uint32_t flags = 0) const;
 
 	/**
 	 * We can reach a field by water either if it has MOVECAPS_SWIM or if it has
@@ -464,11 +464,31 @@
 	/// Checks whether there are any artifacts on the map
 	bool has_artifacts();
 
-protected:  /// These functions are needed in Testclasses
+	// Visible for testing.
 	void set_size(uint32_t w, uint32_t h);
 
 private:
 	void recalc_border(const FCoords&);
+	void recalc_brightness(const FCoords&);
+	void recalc_nodecaps_pass1(const World& world, const FCoords&);
+	void recalc_nodecaps_pass2(const World& world, const FCoords& f);
+	NodeCaps calc_nodecaps_pass1(const World& world, const FCoords&, bool consider_mobs = true);
+	NodeCaps calc_nodecaps_pass2(const World& world,
+	                             const FCoords&,
+	                             bool consider_mobs = true,
+	                             NodeCaps initcaps = CAPS_NONE);
+	void check_neighbour_heights(FCoords, uint32_t& radius);
+	int calc_buildsize(const World& world,
+	                   const FCoords& f,
+	                   bool avoidnature,
+	                   bool* ismine = nullptr,
+	                   bool consider_mobs = true,
+	                   NodeCaps initcaps = CAPS_NONE);
+	bool is_cycle_connected(const FCoords& start, uint32_t length, const WalkingDir* dirs);
+	template <typename functorT>
+	void find_reachable(const Area<FCoords>&, const CheckStep&, functorT&) const;
+	template <typename functorT> void find(const Area<FCoords>&, functorT&) const;
+
 
 	/// # of players this map supports (!= Game's number of players!)
 	PlayerNumber nrplayers_;
@@ -501,26 +521,6 @@
 	PortSpacesSet port_spaces_;
 	Objectives objectives_;
 
-	void recalc_brightness(const FCoords&);
-	void recalc_nodecaps_pass1(const World& world, const FCoords&);
-	void recalc_nodecaps_pass2(const World& world, const FCoords& f);
-	NodeCaps calc_nodecaps_pass1(const World& world, const FCoords&, bool consider_mobs = true);
-	NodeCaps calc_nodecaps_pass2(const World& world,
-	                             const FCoords&,
-	                             bool consider_mobs = true,
-	                             NodeCaps initcaps = CAPS_NONE);
-	void check_neighbour_heights(FCoords, uint32_t& radius);
-	int calc_buildsize(const World& world,
-	                   const FCoords& f,
-	                   bool avoidnature,
-	                   bool* ismine = nullptr,
-	                   bool consider_mobs = true,
-	                   NodeCaps initcaps = CAPS_NONE);
-	bool is_cycle_connected(const FCoords& start, uint32_t length, const WalkingDir* dirs);
-	template <typename functorT>
-	void find_reachable(const Area<FCoords>&, const CheckStep&, functorT&);
-	template <typename functorT> void find(const Area<FCoords>&, functorT&) const;
-
 	MapVersion map_version_;
 };
 

=== modified file 'src/logic/map_objects/bob.cc'
--- src/logic/map_objects/bob.cc	2017-06-24 08:47:46 +0000
+++ src/logic/map_objects/bob.cc	2017-08-19 22:24:59 +0000
@@ -464,7 +464,7 @@
 
 	Game& game_;
 	Bob& bob_;
-	Map& map_;
+	const Map& map_;
 	Coords finaldest_;
 	Cache nodes_;
 	int nrblocked_;
@@ -475,13 +475,13 @@
 	explicit CheckStepBlocked(BlockedTracker& tracker) : tracker_(tracker) {
 	}
 
-	bool allowed(Map&, FCoords, FCoords end, int32_t, CheckStep::StepId) const {
+	bool allowed(const Map&, FCoords, FCoords end, int32_t, CheckStep::StepId) const {
 		if (end == tracker_.finaldest_)
 			return true;
 
 		return !tracker_.is_blocked(end);
 	}
-	bool reachable_dest(Map&, FCoords) const {
+	bool reachable_dest(const Map&, FCoords) const {
 		return true;
 	}
 
@@ -519,7 +519,7 @@
 	if (forceall)
 		tracker.disabled_ = true;
 
-	Map& map = game.map();
+	const Map& map = game.map();
 	if (map.findpath(position_, dest, persist, path, cstep) < 0) {
 		if (!tracker.nrblocked_)
 			return false;
@@ -634,7 +634,7 @@
 	// Using probability of 1/8 and pausing it for 5, 10 or 15 seconds
 	if (game.logic_rand() % 8 == 0) {
 		if (is_a(Ship, this)) {
-			Map& map = game.map();
+			const Map& map = game.map();
 			const uint32_t ships_count = map.find_bobs(
 			   Widelands::Area<Widelands::FCoords>(get_position(), 0), nullptr, FindBobShip());
 			assert(ships_count > 0);
@@ -694,7 +694,7 @@
 Vector2f Bob::calc_drawpos(const EditorGameBase& game,
                            const Vector2f& field_on_dst,
                            const float scale) const {
-	const Map& map = game.get_map();
+	const Map& map = game.map();
 	const FCoords end = position_;
 	FCoords start;
 	Vector2f spos = field_on_dst;
@@ -793,7 +793,7 @@
 int32_t Bob::start_walk(Game& game, WalkingDir const dir, uint32_t const a, bool const force) {
 	FCoords newnode;
 
-	Map& map = game.map();
+	const Map& map = game.map();
 	map.get_neighbour(position_, dir, &newnode);
 
 	// Move capability check

=== modified file 'src/logic/map_objects/checkstep.cc'
--- src/logic/map_objects/checkstep.cc	2017-01-25 18:55:59 +0000
+++ src/logic/map_objects/checkstep.cc	2017-08-19 22:24:59 +0000
@@ -34,10 +34,10 @@
 }
 
 struct CheckStepAlwaysFalse {
-	bool allowed(Map&, const FCoords&, const FCoords&, int32_t, CheckStep::StepId) const {
+	bool allowed(const Map&, const FCoords&, const FCoords&, int32_t, CheckStep::StepId) const {
 		return false;
 	}
-	bool reachable_dest(Map&, const FCoords&) const {
+	bool reachable_dest(const Map&, const FCoords&) const {
 		return false;
 	}
 };
@@ -51,7 +51,7 @@
 	subs.push_back(sub);
 }
 
-bool CheckStepAnd::allowed(Map& map,
+bool CheckStepAnd::allowed(const Map& map,
                            const FCoords& start,
                            const FCoords& end,
                            int32_t const dir,
@@ -64,7 +64,7 @@
 	return true;
 }
 
-bool CheckStepAnd::reachable_dest(Map& map, const FCoords& dest) const {
+bool CheckStepAnd::reachable_dest(const Map& map, const FCoords& dest) const {
 	for (const CheckStep& checkstep : subs) {
 		if (!checkstep.reachable_dest(map, dest)) {
 			return false;
@@ -79,7 +79,7 @@
 ===============
 */
 bool CheckStepDefault::allowed(
-   Map&, const FCoords& start, const FCoords& end, int32_t, CheckStep::StepId) const {
+   const Map&, const FCoords& start, const FCoords& end, int32_t, CheckStep::StepId) const {
 	NodeCaps const endcaps = end.field->nodecaps();
 
 	if (endcaps & movecaps_)
@@ -94,7 +94,7 @@
 	return false;
 }
 
-bool CheckStepDefault::reachable_dest(Map& map, const FCoords& dest) const {
+bool CheckStepDefault::reachable_dest(const Map& map, const FCoords& dest) const {
 	NodeCaps const caps = dest.field->nodecaps();
 
 	if (!(caps & movecaps_)) {
@@ -114,7 +114,7 @@
 ===============
 */
 bool CheckStepWalkOn::allowed(
-   Map&, const FCoords& start, const FCoords& end, int32_t, CheckStep::StepId const id) const {
+   const Map&, const FCoords& start, const FCoords& end, int32_t, CheckStep::StepId const id) const {
 	NodeCaps const startcaps = start.field->nodecaps();
 	NodeCaps const endcaps = end.field->nodecaps();
 
@@ -138,13 +138,13 @@
 	return false;
 }
 
-bool CheckStepWalkOn::reachable_dest(Map&, FCoords) const {
+bool CheckStepWalkOn::reachable_dest(const Map&, FCoords) const {
 	// Don't bother solving this.
 	return true;
 }
 
 bool CheckStepRoad::allowed(
-   Map& map, const FCoords& start, const FCoords& end, int32_t, CheckStep::StepId const id) const {
+   const Map& map, const FCoords& start, const FCoords& end, int32_t, CheckStep::StepId const id) const {
 	uint8_t const endcaps = player_.get_buildcaps(end);
 
 	// Calculate cost and passability
@@ -165,7 +165,7 @@
 	return true;
 }
 
-bool CheckStepRoad::reachable_dest(Map& map, const FCoords& dest) const {
+bool CheckStepRoad::reachable_dest(const Map& map, const FCoords& dest) const {
 	NodeCaps const caps = dest.field->nodecaps();
 
 	if (!(caps & movecaps_)) {
@@ -180,11 +180,11 @@
 }
 
 bool CheckStepLimited::allowed(
-   Map&, const FCoords&, const FCoords& end, int32_t, CheckStep::StepId) const {
+   const Map&, const FCoords&, const FCoords& end, int32_t, CheckStep::StepId) const {
 	return allowed_locations_.find(end) != allowed_locations_.end();
 }
 
-bool CheckStepLimited::reachable_dest(Map&, FCoords) const {
+bool CheckStepLimited::reachable_dest(const Map&, FCoords) const {
 	return true;
 }
 }

=== modified file 'src/logic/map_objects/checkstep.h'
--- src/logic/map_objects/checkstep.h	2017-08-12 06:51:08 +0000
+++ src/logic/map_objects/checkstep.h	2017-08-19 22:24:59 +0000
@@ -44,21 +44,21 @@
 		virtual ~BaseCapsule() {
 		}
 		virtual bool
-		allowed(Map&, const FCoords& start, const FCoords& end, int32_t dir, StepId id) const = 0;
-		virtual bool reachable_dest(Map&, const FCoords& dest) const = 0;
+		allowed(const Map&, const FCoords& start, const FCoords& end, int32_t dir, StepId id) const = 0;
+		virtual bool reachable_dest(const Map&, const FCoords& dest) const = 0;
 	};
 	template <typename T> struct Capsule : public BaseCapsule {
 		Capsule(const T& init_op) : op(init_op) {
 		}
 
-		bool allowed(Map& map,
+		bool allowed(const Map& map,
 		             const FCoords& start,
 		             const FCoords& end,
 		             int32_t const dir,
 		             StepId const id) const override {
 			return op.allowed(map, start, end, dir, id);
 		}
-		bool reachable_dest(Map& map, const FCoords& dest) const override {
+		bool reachable_dest(const Map& map, const FCoords& dest) const override {
 			return op.reachable_dest(map, dest);
 		}
 
@@ -79,7 +79,7 @@
 	 * \return \c true true if moving from start to end (single step in the given
 	 * direction) is allowed.
 	 */
-	bool allowed(Map& map,
+	bool allowed(const Map& map,
 	             const FCoords& start,
 	             const FCoords& end,
 	             int32_t const dir,
@@ -91,7 +91,7 @@
 	 * \return \c true if the destination field can be reached at all
 	 * (e.g. return false for land-based bobs when dest is in water).
 	 */
-	bool reachable_dest(Map& map, const FCoords& dest) const {
+	bool reachable_dest(const Map& map, const FCoords& dest) const {
 		return capsule->reachable_dest(map, dest);
 	}
 };
@@ -104,8 +104,8 @@
 	void add(const CheckStep& sub);
 
 	bool
-	allowed(Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId id) const;
-	bool reachable_dest(Map&, const FCoords& dest) const;
+	allowed(const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId id) const;
+	bool reachable_dest(const Map&, const FCoords& dest) const;
 
 private:
 	std::vector<CheckStep> subs;
@@ -123,8 +123,8 @@
 	}
 
 	bool
-	allowed(Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
-	bool reachable_dest(Map&, const FCoords& dest) const;
+	allowed(const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
+	bool reachable_dest(const Map&, const FCoords& dest) const;
 
 private:
 	uint8_t movecaps_;
@@ -141,8 +141,8 @@
 	}
 
 	bool
-	allowed(Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
-	bool reachable_dest(Map&, FCoords dest) const;
+	allowed(const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
+	bool reachable_dest(const Map&, FCoords dest) const;
 
 private:
 	uint8_t movecaps_;
@@ -162,8 +162,8 @@
 	}
 
 	bool
-	allowed(Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
-	bool reachable_dest(Map&, const FCoords& dest) const;
+	allowed(const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
+	bool reachable_dest(const Map&, const FCoords& dest) const;
 
 private:
 	const Player& player_;
@@ -179,8 +179,8 @@
 		allowed_locations_.insert(c);
 	}
 	bool
-	allowed(Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
-	bool reachable_dest(Map&, FCoords dest) const;
+	allowed(const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const;
+	bool reachable_dest(const Map&, FCoords dest) const;
 
 private:
 	// The ordering of the set does not matter, as long as it is system

=== modified file 'src/logic/map_objects/immovable.cc'
--- src/logic/map_objects/immovable.cc	2017-07-04 11:34:00 +0000
+++ src/logic/map_objects/immovable.cc	2017-08-19 22:24:59 +0000
@@ -100,15 +100,16 @@
 void BaseImmovable::set_position(EditorGameBase& egbase, const Coords& c) {
 	assert(c);
 
-	Map& map = egbase.map();
-	FCoords f = map.get_fcoords(c);
+	Map* map = egbase.mutable_map();
+	FCoords f = map->get_fcoords(c);
 	if (f.field->immovable && f.field->immovable != this)
 		f.field->immovable->remove(egbase);
 
 	f.field->immovable = this;
 
-	if (get_size() >= SMALL)
-		map.recalc_for_field_area(egbase.world(), Area<FCoords>(f, 2));
+	if (get_size() >= SMALL) {
+		map->recalc_for_field_area(egbase.world(), Area<FCoords>(f, 2));
+	}
 }
 
 /**
@@ -117,8 +118,8 @@
  * Only call this during cleanup.
 */
 void BaseImmovable::unset_position(EditorGameBase& egbase, const Coords& c) {
-	Map& map = egbase.map();
-	FCoords const f = map.get_fcoords(c);
+	Map* map = egbase.mutable_map();
+	FCoords const f = map->get_fcoords(c);
 
 	// this is to help to debug failing assertion below (see bug 1542238)
 	if (f.field->immovable != this) {
@@ -130,10 +131,11 @@
 	assert(f.field->immovable == this);
 
 	f.field->immovable = nullptr;
-	egbase.inform_players_about_immovable(f.field - &map[0], nullptr);
+	egbase.inform_players_about_immovable(f.field - &(*map)[0], nullptr);
 
-	if (get_size() >= SMALL)
-		map.recalc_for_field_area(egbase.world(), Area<FCoords>(f, 2));
+	if (get_size() >= SMALL) {
+		map->recalc_for_field_area(egbase.world(), Area<FCoords>(f, 2));
+	}
 }
 
 /*

=== modified file 'src/logic/map_objects/tribes/building.cc'
--- src/logic/map_objects/tribes/building.cc	2017-08-16 04:31:56 +0000
+++ src/logic/map_objects/tribes/building.cc	2017-08-19 22:24:59 +0000
@@ -329,7 +329,7 @@
 	PlayerImmovable::init(egbase);
 
 	// Set the building onto the map
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	Coords neighb;
 
 	set_position(egbase, position_);
@@ -385,7 +385,7 @@
 	unset_position(egbase, position_);
 
 	if (get_size() == BIG) {
-		Map& map = egbase.map();
+		const Map& map = egbase.map();
 		Coords neighb;
 
 		map.get_ln(position_, &neighb);
@@ -421,7 +421,7 @@
 
 	rv.push_back(position_);
 	if (get_size() == BIG) {
-		Map& map = egbase.map();
+		const Map& map = egbase.map();
 		Coords neighb;
 
 		map.get_ln(position_, &neighb);
@@ -727,7 +727,7 @@
 		return;
 
 	Player& player = owner();
-	Map& map = player.egbase().map();
+	const Map& map = player.egbase().map();
 
 	if (see)
 		player.see_area(Area<FCoords>(map.get_fcoords(get_position()), descr().vision_range()));

=== modified file 'src/logic/map_objects/tribes/carrier.cc'
--- src/logic/map_objects/tribes/carrier.cc	2017-04-22 06:45:52 +0000
+++ src/logic/map_objects/tribes/carrier.cc	2017-08-19 22:24:59 +0000
@@ -432,7 +432,7 @@
  * Find the flag we are closest to (in walking time).
  */
 int32_t Carrier::find_closest_flag(Game& game) {
-	Map& map = game.map();
+	const Map& map = game.map();
 	CoordPath startpath(map, dynamic_cast<Road&>(*get_location(game)).get_path());
 
 	CoordPath endpath;

=== modified file 'src/logic/map_objects/tribes/militarysite.cc'
--- src/logic/map_objects/tribes/militarysite.cc	2017-08-16 13:23:15 +0000
+++ src/logic/map_objects/tribes/militarysite.cc	2017-08-19 22:24:59 +0000
@@ -156,7 +156,7 @@
 void MilitarySite::AttackTarget::enemy_soldier_approaches(const Soldier& enemy) const {
 	auto& owner = military_site_->owner();
 	Game& game = dynamic_cast<Game&>(owner.egbase());
-	Map& map = game.map();
+	const Map& map = game.map();
 	if (enemy.get_owner() == &owner || enemy.get_battle() ||
 	    military_site_->descr().get_conquers() <=
 	       map.calc_distance(enemy.get_position(), military_site_->get_position()))

=== modified file 'src/logic/map_objects/tribes/production_program.cc'
--- src/logic/map_objects/tribes/production_program.cc	2017-08-16 04:31:56 +0000
+++ src/logic/map_objects/tribes/production_program.cc	2017-08-19 22:24:59 +0000
@@ -1138,7 +1138,7 @@
 }
 
 void ProductionProgram::ActMine::execute(Game& game, ProductionSite& ps) const {
-	Map& map = game.map();
+	Map* map = game.mutable_map();
 
 	//  select one of the nodes randomly
 	uint32_t totalres = 0;
@@ -1147,7 +1147,7 @@
 
 	{
 		MapRegion<Area<FCoords>> mr(
-		   map, Area<FCoords>(map.get_fcoords(ps.get_position()), distance_));
+		   *map, Area<FCoords>(map->get_fcoords(ps.get_position()), distance_));
 		do {
 			DescriptionIndex fres = mr.location().field->get_resources();
 			ResourceAmount amount = mr.location().field->get_resources_amount();
@@ -1172,7 +1172,7 @@
 				totalchance += 4;
 			else if (amount <= 6)
 				totalchance += 2;
-		} while (mr.advance(map));
+		} while (mr.advance(*map));
 	}
 
 	//  how much is digged
@@ -1193,7 +1193,7 @@
 
 		{
 			MapRegion<Area<FCoords>> mr(
-			   map, Area<FCoords>(map.get_fcoords(ps.get_position()), distance_));
+			   *map, Area<FCoords>(map->get_fcoords(ps.get_position()), distance_));
 			do {
 				DescriptionIndex fres = mr.location().field->get_resources();
 				ResourceAmount amount = mr.location().field->get_resources_amount();
@@ -1206,10 +1206,10 @@
 					assert(amount > 0);
 
 					--amount;
-					map.set_resources(mr.location(), amount);
+					map->set_resources(mr.location(), amount);
 					break;
 				}
-			} while (mr.advance(map));
+			} while (mr.advance(*map));
 		}
 
 		if (pick >= 0) {
@@ -1502,7 +1502,7 @@
 
 	// No object found, look for a field where we can build
 	std::vector<Coords> fields;
-	Map& map = game.map();
+	const Map& map = game.map();
 	FindNodeAnd fna;
 	// 10 is custom value to make sure the "water" is at least 10 nodes big
 	fna.add(FindNodeShore(10));

=== modified file 'src/logic/map_objects/tribes/ship.cc'
--- src/logic/map_objects/tribes/ship.cc	2017-08-16 14:30:17 +0000
+++ src/logic/map_objects/tribes/ship.cc	2017-08-19 22:24:59 +0000
@@ -288,7 +288,7 @@
 
 /// updates a ships tasks in transport mode \returns false if failed to update tasks
 bool Ship::ship_update_transport(Game& game, Bob::State& state) {
-	Map& map = game.map();
+	const Map& map = game.map();
 
 	PortDock* dst = get_destination(game);
 	if (!dst) {
@@ -366,7 +366,7 @@
 
 /// updates a ships tasks in expedition mode
 void Ship::ship_update_expedition(Game& game, Bob::State&) {
-	Map& map = game.map();
+	Map* map = game.mutable_map();
 
 	assert(expedition_);
 
@@ -374,29 +374,29 @@
 	FCoords position = get_position();
 	for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
 		expedition_->swimmable[dir - 1] =
-		   map.get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
+		   map->get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
 	}
 
 	if (ship_state_ == ShipStates::kExpeditionScouting) {
 		// Check surrounding fields for port buildspaces
 		std::vector<Coords> temp_port_buildspaces;
-		MapRegion<Area<Coords>> mr(map, Area<Coords>(position, descr().vision_range()));
+		MapRegion<Area<Coords>> mr(*map, Area<Coords>(position, descr().vision_range()));
 		bool new_port_space = false;
 		do {
-			if (!map.is_port_space(mr.location())) {
+			if (!map->is_port_space(mr.location())) {
 				continue;
 			}
 
-			const FCoords fc = map.get_fcoords(mr.location());
+			const FCoords fc = map->get_fcoords(mr.location());
 
 			// Check whether the maximum theoretical possible NodeCap of the field
 			// is of the size big and whether it can theoretically be a port space
-			if ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
-			    map.find_portdock(fc).empty()) {
+			if ((map->get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
+			    map->find_portdock(fc).empty()) {
 				continue;
 			}
 
-			if (!can_build_port_here(get_owner()->player_number(), map, fc)) {
+			if (!can_build_port_here(get_owner()->player_number(), *map, fc)) {
 				continue;
 			}
 
@@ -409,7 +409,7 @@
 				new_port_space = true;
 				temp_port_buildspaces.insert(temp_port_buildspaces.begin(), mr.location());
 			}
-		} while (mr.advance(map));
+		} while (mr.advance(*map));
 
 		if (new_port_space) {
 			ship_state_ = ShipStates::kExpeditionPortspaceFound;
@@ -441,7 +441,7 @@
 	switch (ship_state_) {
 	case ShipStates::kTransport: {
 		FCoords position = get_position();
-		Map& map = game.map();
+		const Map& map = game.map();
 		unsigned int dirs[LAST_DIRECTION + 1];
 		unsigned int dirmax = 0;
 
@@ -569,7 +569,7 @@
 				// Most likely the command was send as the ship was on an exploration and just leaving
 				// the island - therefore we try to find the island again.
 				FCoords position = get_position();
-				Map& map = game.map();
+				const Map& map = game.map();
 				for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
 					FCoords neighbour = map.get_neighbour(position, dir);
 					for (uint8_t sur = FIRST_DIRECTION; sur <= LAST_DIRECTION; ++sur)
@@ -742,13 +742,13 @@
  * Find a path to the dock @p pd, returns its length, and the path optionally.
  */
 uint32_t Ship::calculate_sea_route(Game& game, PortDock& pd, Path* finalpath) const {
-	Map& map = game.map();
+	Map* map = game.mutable_map();
 	StepEvalAStar se(pd.get_warehouse()->get_position());
 	se.swim_ = true;
 	se.conservative_ = false;
-	se.estimator_bias_ = -5 * map.calc_cost(0);
+	se.estimator_bias_ = -5 * map->calc_cost(0);
 
-	MapAStar<StepEvalAStar> astar(map, se);
+	MapAStar<StepEvalAStar> astar(*map, se);
 
 	astar.push(get_position());
 

=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc	2017-07-05 19:21:57 +0000
+++ src/logic/map_objects/tribes/soldier.cc	2017-08-19 22:24:59 +0000
@@ -793,11 +793,11 @@
 					return pop_task(game);
 				}
 				// Try to find our land
-				Map* map = game.get_map();
+				const Map& map = game.map();
 				std::vector<Coords> coords;
 				uint32_t maxdist = descr().vision_range() * 2;
-				Area<FCoords> area(map->get_fcoords(get_position()), maxdist);
-				if (map->find_reachable_fields(area, &coords, CheckStepDefault(descr().movecaps()),
+				Area<FCoords> area(map.get_fcoords(get_position()), maxdist);
+				if (map.find_reachable_fields(area, &coords, CheckStepDefault(descr().movecaps()),
 				                               FindNodeOwned(get_owner()->player_number()))) {
 					// Found home land
 					target = coords.front();
@@ -1182,7 +1182,7 @@
 		throw GameDataError("bad direction '%d'", dir);
 	}
 
-	Map& map = game.map();
+	const Map& map = game.map();
 	int32_t const tdelta = (map.calc_cost(get_position(), mapdir)) / 2;
 	molog("[move_in_battle] dir: (%d) tdelta: (%d)\n", dir, tdelta);
 	combat_walking_ = dir;
@@ -1275,7 +1275,7 @@
 		return pop_task(game);
 	}
 
-	Map& map = game.map();
+	const Map& map = game.map();
 	Soldier& opponent = *battle_->opponent(*this);
 	if (opponent.get_position() != get_position()) {
 		if (is_a(Building, map[get_position()].get_immovable())) {

=== modified file 'src/logic/map_objects/tribes/warehouse.cc'
--- src/logic/map_objects/tribes/warehouse.cc	2017-07-01 15:36:36 +0000
+++ src/logic/map_objects/tribes/warehouse.cc	2017-08-19 22:24:59 +0000
@@ -80,13 +80,13 @@
 
 	Player& owner = warehouse_->owner();
 	Game& game = dynamic_cast<Game&>(owner.egbase());
-	Map& map = game.map();
+	const Map& map = game.map();
 	if (enemy.get_owner() == &owner || enemy.get_battle() ||
 	    warehouse_->descr().get_conquers() <=
 	       map.calc_distance(enemy.get_position(), warehouse_->get_position()))
 		return;
 
-	if (game.map().find_bobs(
+	if (map.find_bobs(
 	       Area<FCoords>(map.get_fcoords(warehouse_->base_flag().get_position()), 2), nullptr,
 	       FindBobEnemySoldier(&owner)))
 		return;
@@ -581,7 +581,7 @@
 void Warehouse::init_portdock(EditorGameBase& egbase) {
 	molog("Setting up port dock fields\n");
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	std::vector<Coords> dock = map.find_portdock(get_position());
 	if (dock.empty()) {
 		log("Attempting to setup port without neighboring water (coords: %3dx%3d).\n",
@@ -670,7 +670,7 @@
 		planned_workers_.pop_back();
 	}
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	if (const uint32_t conquer_radius = descr().get_conquers())
 		egbase.unconquer_area(
 		   PlayerArea<Area<FCoords>>(owner().player_number(),

=== modified file 'src/logic/map_objects/tribes/worker.cc'
--- src/logic/map_objects/tribes/worker.cc	2017-07-07 11:19:07 +0000
+++ src/logic/map_objects/tribes/worker.cc	2017-08-19 22:24:59 +0000
@@ -106,7 +106,7 @@
  */
 // TODO(unknown): Lots of magic numbers in here
 bool Worker::run_mine(Game& game, State& state, const Action& action) {
-	Map& map = game.map();
+	Map* map = game.mutable_map();
 
 	// Make sure that the specified resource is available in this world
 	DescriptionIndex const res = game.world().get_resource(action.sparam1.c_str());
@@ -119,7 +119,7 @@
 	uint32_t totalres = 0;
 	uint32_t totalchance = 0;
 	int32_t pick;
-	MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(get_position()), action.iparam1));
+	MapRegion<Area<FCoords>> mr(*map, Area<FCoords>(map->get_fcoords(get_position()), action.iparam1));
 	do {
 		DescriptionIndex fres = mr.location().field->get_resources();
 		ResourceAmount amount = mr.location().field->get_resources_amount();
@@ -143,7 +143,7 @@
 			totalchance += 4;
 		else if (amount <= 6)
 			totalchance += 2;
-	} while (mr.advance(map));
+	} while (mr.advance(*map));
 
 	if (totalres == 0) {
 		molog("  Run out of resources\n");
@@ -155,7 +155,7 @@
 	// Second pass through fields - reset mr
 	pick = game.logic_rand() % totalchance;
 	mr =
-	   MapRegion<Area<FCoords>>(map, Area<FCoords>(map.get_fcoords(get_position()), action.iparam1));
+	   MapRegion<Area<FCoords>>(*map, Area<FCoords>(map->get_fcoords(get_position()), action.iparam1));
 	do {
 		DescriptionIndex fres = mr.location().field->get_resources();
 		if (fres != res) {
@@ -169,10 +169,10 @@
 			assert(amount > 0);
 
 			--amount;
-			map.set_resources(mr.location(), amount);
+			map->set_resources(mr.location(), amount);
 			break;
 		}
-	} while (mr.advance(map));
+	} while (mr.advance(*map));
 
 	if (pick >= 0) {
 		molog("  Not successful this time\n");
@@ -206,7 +206,7 @@
 bool Worker::run_breed(Game& game, State& state, const Action& action) {
 	molog(" Breed(%s, %i)\n", action.sparam1.c_str(), action.iparam1);
 
-	Map& map = game.map();
+	Map* map = game.mutable_map();
 
 	// Make sure that the specified resource is available in this world
 	DescriptionIndex const res = game.world().get_resource(action.sparam1.c_str());
@@ -219,7 +219,7 @@
 	uint32_t totalres = 0;
 	uint32_t totalchance = 0;
 	int32_t pick;
-	MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(get_position()), action.iparam1));
+	MapRegion<Area<FCoords>> mr(*map, Area<FCoords>(map->get_fcoords(get_position()), action.iparam1));
 	do {
 		DescriptionIndex fres = mr.location().field->get_resources();
 		ResourceAmount amount = mr.location().field->get_initial_res_amount() -
@@ -244,7 +244,7 @@
 			totalchance += 4;
 		else if (amount <= 6)
 			totalchance += 2;
-	} while (mr.advance(map));
+	} while (mr.advance(*map));
 
 	if (totalres == 0) {
 		molog("  All resources full\n");
@@ -257,7 +257,7 @@
 	assert(totalchance);
 	pick = game.logic_rand() % totalchance;
 	mr =
-	   MapRegion<Area<FCoords>>(map, Area<FCoords>(map.get_fcoords(get_position()), action.iparam1));
+	   MapRegion<Area<FCoords>>(*map, Area<FCoords>(map->get_fcoords(get_position()), action.iparam1));
 
 	do {
 		DescriptionIndex fres = mr.location().field->get_resources();
@@ -272,10 +272,10 @@
 			assert(amount > 0);
 
 			--amount;
-			map.set_resources(mr.location(), mr.location().field->get_initial_res_amount() - amount);
+			map->set_resources(mr.location(), mr.location().field->get_initial_res_amount() - amount);
 			break;
 		}
-	} while (mr.advance(map));
+	} while (mr.advance(*map));
 
 	if (pick >= 0) {
 		molog("  Not successful this time\n");
@@ -341,7 +341,7 @@
 bool Worker::run_findobject(Game& game, State& state, const Action& action) {
 	CheckStepWalkOn cstep(descr().movecaps(), false);
 
-	Map& map = game.map();
+	const Map& map = game.map();
 	Area<FCoords> area(map.get_fcoords(get_position()), 0);
 	bool found_reserved = false;
 
@@ -486,7 +486,7 @@
 
 bool Worker::run_findspace(Game& game, State& state, const Action& action) {
 	std::vector<Coords> list;
-	Map& map = game.map();
+	const Map& map = game.map();
 	const World& world = game.world();
 
 	CheckStepDefault cstep(descr().movecaps());
@@ -706,7 +706,7 @@
 		}
 	}
 
-	Map& map = game.map();
+	const Map& map = game.map();
 	Coords pos = get_position();
 	FCoords fpos = map.get_fcoords(pos);
 
@@ -1285,7 +1285,7 @@
 }
 
 void Worker::transfer_update(Game& game, State& /* state */) {
-	Map& map = game.map();
+	const Map& map = game.map();
 	PlayerImmovable* location = get_location(game);
 
 	// We expect to always have a location at this point,
@@ -2235,7 +2235,7 @@
 		return pop_task(game);
 	}
 
-	Map& map = game.map();
+	const Map& map = game.map();
 	PlayerImmovable const* location = get_location(game);
 
 	if (location && &location->owner() == &owner()) {
@@ -2354,7 +2354,7 @@
 	}
 
 	//
-	Map& map = game.map();
+	const Map& map = game.map();
 	const World& world = game.world();
 	Area<FCoords> owner_area(
 	   map.get_fcoords(dynamic_cast<Flag&>(*get_location(game)).get_position()), state.ivar2);
@@ -2482,7 +2482,7 @@
 		return pop_task(game);
 	}
 
-	Map& map = game.map();
+	const Map& map = game.map();
 
 	// If not yet time to go home
 	if (static_cast<int32_t>(state.ivar2 - game.get_gametime()) > 0) {

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc	2017-08-16 04:31:56 +0000
+++ src/logic/player.cc	2017-08-19 22:24:59 +0000
@@ -60,7 +60,7 @@
                             const Widelands::PlayerNumber player_number,
                             const Widelands::Coords& location,
                             const Widelands::BuildingDescr* descr) {
-	Widelands::Map& map = egbase.map();
+	const Widelands::Map& map = egbase.map();
 	Widelands::FCoords c[4];  //  Big buildings occupy 4 locations.
 	c[0] = map.get_fcoords(location);
 	map.get_brn(c[0], &c[1]);
@@ -412,7 +412,7 @@
 ===============
 */
 Road* Player::build_road(const Path& path) {
-	Map& map = egbase().map();
+	const Map& map = egbase().map();
 	FCoords fc = map.get_fcoords(path.get_start());
 	if (upcast(Flag, start, fc.field->get_immovable())) {
 		if (upcast(Flag, end, map.get_immovable(path.get_end()))) {
@@ -441,7 +441,7 @@
 }
 
 Road& Player::force_road(const Path& path) {
-	Map& map = egbase().map();
+	const Map& map = egbase().map();
 	FCoords c = map.get_fcoords(path.get_start());
 	Flag& start = force_flag(c);
 	Flag& end = force_flag(map.get_fcoords(path.get_end()));
@@ -466,7 +466,7 @@
 
 Building& Player::force_building(Coords const location,
                                  const BuildingDescr::FormerBuildings& former_buildings) {
-	Map& map = egbase().map();
+	const Map& map = egbase().map();
 	DescriptionIndex idx = former_buildings.back();
 	const BuildingDescr* descr = egbase().tribes().get_building_descr(idx);
 	terraform_for_building(egbase(), player_number(), location, descr);
@@ -481,7 +481,7 @@
                               DescriptionIndex b_idx,
                               const BuildingDescr::FormerBuildings& former_buildings) {
 	EditorGameBase& eg = egbase();
-	Map& map = eg.map();
+	const Map& map = eg.map();
 	const Tribes& tribes = eg.tribes();
 	const PlayerNumber pn = player_number();
 
@@ -833,7 +833,7 @@
 	if (soldiers)
 		soldiers->clear();
 
-	Map& map = egbase().map();
+	const Map& map = egbase().map();
 	std::vector<BaseImmovable*> flags;
 
 	map.find_reachable_immovables_unique(Area<FCoords>(map.get_fcoords(flag.get_position()), 25),

=== modified file 'src/logic/replay_game_controller.cc'
--- src/logic/replay_game_controller.cc	2017-06-24 10:38:19 +0000
+++ src/logic/replay_game_controller.cc	2017-08-19 22:24:59 +0000
@@ -31,9 +31,6 @@
      speed_(1000),
      paused_(false) {
 	game_.set_game_controller(this);
-
-	// We have to create an empty map, otherwise nothing will load properly
-	game.set_map(new Widelands::Map);
 	replayreader_.reset(new Widelands::ReplayReader(game_, filename));
 }
 

=== modified file 'src/map_io/map_bob_packet.cc'
--- src/map_io/map_bob_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_bob_packet.cc	2017-08-19 22:24:59 +0000
@@ -75,13 +75,13 @@
 	FileRead fr;
 	fr.open(fs, "binary/bob");
 
-	Map& map = egbase.map();
-	map.recalc_whole_map(egbase.world());  //  for movecaps checks in ReadBob
+	Map* map = egbase.mutable_map();
+	map->recalc_whole_map(egbase.world());  //  for movecaps checks in ReadBob
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
 		if (packet_version == kCurrentPacketVersion)
-			for (uint16_t y = 0; y < map.get_height(); ++y) {
-				for (uint16_t x = 0; x < map.get_width(); ++x) {
+			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();
 					for (uint32_t i = 0; i < nr_bobs; ++i)
 						read_bob(fr, egbase, mol, Coords(x, y), lookup_table);

=== modified file 'src/map_io/map_building_packet.cc'
--- src/map_io/map_building_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_building_packet.cc	2017-08-19 22:24:59 +0000
@@ -60,7 +60,7 @@
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
 		if (packet_version == kCurrentPacketVersion) {
-			Map& map = egbase.map();
+			const Map& map = egbase.map();
 			uint16_t const width = map.get_width();
 			uint16_t const height = map.get_height();
 			FCoords c;

=== modified file 'src/map_io/map_buildingdata_packet.cc'
--- src/map_io/map_buildingdata_packet.cc	2017-08-16 13:23:15 +0000
+++ src/map_io/map_buildingdata_packet.cc	2017-08-19 22:24:59 +0000
@@ -830,7 +830,7 @@
 	fw.unsigned_16(kCurrentPacketVersion);
 
 	// Walk the map again
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	const uint32_t mapwidth = map.get_width();
 	MapIndex const max_index = map.max_index();
 	for (MapIndex i = 0; i < max_index; ++i) {

=== modified file 'src/map_io/map_elemental_packet.cc'
--- src/map_io/map_elemental_packet.cc	2017-08-16 13:23:15 +0000
+++ src/map_io/map_elemental_packet.cc	2017-08-19 22:24:59 +0000
@@ -114,7 +114,7 @@
 }
 
 void MapElementalPacket::read(FileSystem& fs, EditorGameBase& egbase, bool, MapObjectLoader&) {
-	pre_read(fs, &egbase.map());
+	pre_read(fs, egbase.mutable_map());
 }
 
 void MapElementalPacket::write(FileSystem& fs, EditorGameBase& egbase, MapObjectSaver&) {

=== modified file 'src/map_io/map_exploration_packet.cc'
--- src/map_io/map_exploration_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_exploration_packet.cc	2017-08-19 22:24:59 +0000
@@ -50,7 +50,7 @@
 	}
 
 	static_assert(kMaxPlayers < 32, "assert(MAX_PLAYERS < 32) failed.");
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	PlayerNumber const nr_players = map.get_nrplayers();
 	MapIndex const max_index = map.max_index();
 	try {
@@ -82,7 +82,7 @@
 	fw.unsigned_16(kCurrentPacketVersion);
 
 	static_assert(kMaxPlayers < 32, "assert(MAX_PLAYERS < 32) failed.");
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	PlayerNumber const nr_players = map.get_nrplayers();
 	MapIndex const max_index = map.max_index();
 	for (MapIndex i = 0; i < max_index; ++i) {

=== modified file 'src/map_io/map_heights_packet.cc'
--- src/map_io/map_heights_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_heights_packet.cc	2017-08-19 22:24:59 +0000
@@ -38,7 +38,7 @@
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
 		if (packet_version == kCurrentPacketVersion) {
-			Map& map = egbase.map();
+			const 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());
@@ -60,7 +60,7 @@
 
 	fw.unsigned_16(kCurrentPacketVersion);
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	MapIndex const max_index = map.max_index();
 	for (MapIndex i = 0; i < max_index; ++i)
 		fw.unsigned_8(map[i].get_height());

=== modified file 'src/map_io/map_node_ownership_packet.cc'
--- src/map_io/map_node_ownership_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_node_ownership_packet.cc	2017-08-19 22:24:59 +0000
@@ -51,7 +51,7 @@
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
 		if (packet_version == kCurrentPacketVersion) {
-			Map& map = egbase.map();
+			const 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());
@@ -69,7 +69,7 @@
 
 	fw.unsigned_16(kCurrentPacketVersion);
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	MapIndex const max_index = map.max_index();
 	for (MapIndex i = 0; i < max_index; ++i)
 		fw.unsigned_8(map[i].get_owned_by());

=== modified file 'src/map_io/map_objective_packet.cc'
--- src/map_io/map_objective_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_objective_packet.cc	2017-08-19 22:24:59 +0000
@@ -45,7 +45,7 @@
 				char const* const name = s->get_name();
 				try {
 					std::unique_ptr<Objective> objective(new Objective(name));
-					Map::Objectives* objectives = egbase.map().mutable_objectives();
+					Map::Objectives* objectives = egbase.mutable_map()->mutable_objectives();
 					if (objectives->count(name)) {
 						throw GameDataError("duplicated");
 					}

=== modified file 'src/map_io/map_player_names_and_tribes_packet.cc'
--- src/map_io/map_player_names_and_tribes_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_player_names_and_tribes_packet.cc	2017-08-19 22:24:59 +0000
@@ -44,7 +44,7 @@
                                          EditorGameBase& egbase,
                                          bool const skip,
                                          MapObjectLoader&) {
-	pre_read(fs, egbase.get_map(), skip);
+	pre_read(fs, egbase.mutable_map(), skip);
 }
 
 void MapPlayerNamesAndTribesPacket::pre_read(FileSystem& fs, Map* const map, bool const skip) {

=== modified file 'src/map_io/map_player_position_packet.cc'
--- src/map_io/map_player_position_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_player_position_packet.cc	2017-08-19 22:24:59 +0000
@@ -42,12 +42,12 @@
 			//  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.
-			Map& map = egbase.map();
-			Extent const extent = map.extent();
-			PlayerNumber const nr_players = map.get_nrplayers();
+			Map* map = egbase.mutable_map();
+			Extent const extent = map->extent();
+			PlayerNumber const nr_players = map->get_nrplayers();
 			iterate_player_numbers(p, nr_players) {
 				try {
-					map.set_starting_pos(
+					map->set_starting_pos(
 					   p,
 					   get_safe_coords((boost::format("player_%u") % static_cast<unsigned int>(p)).str(),
 					                   extent, &s));

=== modified file 'src/map_io/map_port_spaces_packet.cc'
--- src/map_io/map_port_spaces_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_port_spaces_packet.cc	2017-08-19 22:24:59 +0000
@@ -39,8 +39,8 @@
 	prof.read("port_spaces", nullptr, fs);
 	Section& s1 = prof.get_safe_section("global");
 
-	Map& map = egbase.map();
-	Extent ext(map.extent());
+	Map* map = egbase.mutable_map();
+	Extent ext(map->extent());
 
 	try {
 		int32_t const packet_version = s1.get_int("packet_version");
@@ -51,7 +51,7 @@
 
 			Section& s2 = prof.get_safe_section("port_spaces");
 			for (uint16_t i = 0; i < num; ++i) {
-				map.set_port_space(
+				map->set_port_space(
 				   get_safe_coords(std::to_string(static_cast<unsigned int>(i)), ext, &s2), true);
 			}
 		} else {
@@ -69,7 +69,7 @@
 	Section& s1 = prof.create_section("global");
 	s1.set_int("packet_version", kCurrentPacketVersion);
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	const uint16_t num = map.get_port_spaces().size();
 	s1.set_int("number_of_port_spaces", num);
 

=== modified file 'src/map_io/map_resources_packet.cc'
--- src/map_io/map_resources_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_resources_packet.cc	2017-08-19 22:24:59 +0000
@@ -39,7 +39,7 @@
 	FileRead fr;
 	fr.open(fs, "binary/resource");
 
-	Map& map = egbase.map();
+	Map* map = egbase.mutable_map();
 	const World& world = egbase.world();
 
 	try {
@@ -63,8 +63,8 @@
 				smap[id] = res;
 			}
 
-			for (uint16_t y = 0; y < map.get_height(); ++y) {
-				for (uint16_t x = 0; x < map.get_width(); ++x) {
+			for (uint16_t y = 0; y < map->get_height(); ++y) {
+				for (uint16_t x = 0; x < map->get_width(); ++x) {
 					DescriptionIndex const id = fr.unsigned_8();
 					ResourceAmount const found_amount = fr.unsigned_8();
 					ResourceAmount const amount = found_amount;
@@ -85,9 +85,9 @@
 
 					if (0xa < set_id)
 						throw "Unknown resource in map file. It is not in world!\n";
-					const auto fcoords = map.get_fcoords(Coords(x, y));
-					map.initialize_resources(fcoords, set_id, set_start_amount);
-					map.set_resources(fcoords, set_amount);
+					const auto fcoords = map->get_fcoords(Coords(x, y));
+					map->initialize_resources(fcoords, set_id, set_start_amount);
+					map->set_resources(fcoords, set_amount);
 				}
 			}
 		} else {

=== modified file 'src/map_io/map_terrain_packet.cc'
--- src/map_io/map_terrain_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_terrain_packet.cc	2017-08-19 22:24:59 +0000
@@ -41,7 +41,7 @@
 	FileRead fr;
 	fr.open(fs, "binary/terrain");
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	const World& world = egbase.world();
 
 	try {

=== modified file 'src/map_io/map_version_packet.cc'
--- src/map_io/map_version_packet.cc	2017-01-25 18:55:59 +0000
+++ src/map_io/map_version_packet.cc	2017-08-19 22:24:59 +0000
@@ -42,9 +42,9 @@
 	try {
 		prof.read("version", nullptr, fs);
 	} catch (...) {
-		Map& map = egbase.map();
-		map.map_version_.map_version_timestamp = 0;
-		map.map_version_.map_creator_version = "unknown";
+		Map* map = egbase.mutable_map();
+		map->map_version_.map_version_timestamp = 0;
+		map->map_version_.map_creator_version = "unknown";
 		return;
 	}
 
@@ -55,14 +55,14 @@
 		if ((packet_version == kCurrentPacketVersion) ||
 		    (packet_version > kCurrentPacketVersion &&
 		     forward_compatibility <= kCurrentPacketVersion)) {
-			Map& map = egbase.map();
-			map.map_version_.map_source_url = globv.get_safe_string("map_source_url");
-			map.map_version_.map_source_release = globv.get_safe_string("map_release");
-			map.map_version_.map_creator_version = globv.get_safe_string("map_creator_version");
-			map.map_version_.map_version_major = globv.get_safe_int("map_version_major");
-			map.map_version_.map_version_minor = globv.get_safe_int("map_version_minor");
+			Map* map = egbase.mutable_map();
+			map->map_version_.map_source_url = globv.get_safe_string("map_source_url");
+			map->map_version_.map_source_release = globv.get_safe_string("map_release");
+			map->map_version_.map_creator_version = globv.get_safe_string("map_creator_version");
+			map->map_version_.map_version_major = globv.get_safe_int("map_version_major");
+			map->map_version_.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.map_version_.map_version_timestamp = ts;
+			map->map_version_.map_version_timestamp = ts;
 		} else {
 			throw UnhandledVersionError("MapVersionPacket", packet_version, kCurrentPacketVersion);
 		}
@@ -108,7 +108,7 @@
 	// TODO(unknown): -- we could store the unix time in uint32, as a partial fix to 2038 problem.
 	// There seems to be a get_safe_natural method, but not corresponding setter.
 
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 	globs.set_string("map_source_url", map.map_version_.map_source_url);
 	globs.set_string("map_release", map.map_version_.map_source_release);
 	globs.set_string("map_creator_version", map.map_version_.map_creator_version);

=== modified file 'src/scripting/lua_bases.cc'
--- src/scripting/lua_bases.cc	2017-01-30 14:40:12 +0000
+++ src/scripting/lua_bases.cc	2017-08-19 22:24:59 +0000
@@ -458,7 +458,7 @@
 */
 int LuaPlayerBase::place_road(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 
 	Flag* starting_flag = (*get_user_class<LuaMaps::LuaFlag>(L, 2))->get(L, egbase);
 	Coords current = starting_flag->get_position();

=== modified file 'src/scripting/lua_game.cc'
--- src/scripting/lua_game.cc	2017-08-17 15:34:45 +0000
+++ src/scripting/lua_game.cc	2017-08-19 22:24:59 +0000
@@ -565,8 +565,7 @@
 int LuaPlayer::add_objective(lua_State* L) {
 	Game& game = get_game(L);
 
-	Map* map = game.get_map();
-	Map::Objectives* objectives = map->mutable_objectives();
+	Map::Objectives* objectives = game.mutable_map()->mutable_objectives();
 
 	const std::string name = luaL_checkstring(L, 2);
 	if (objectives->count(name))
@@ -596,13 +595,13 @@
 int LuaPlayer::reveal_fields(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
 	Player& p = get(L, egbase);
-	Map& m = egbase.map();
+	const Map& map = egbase.map();
 
 	luaL_checktype(L, 2, LUA_TTABLE);
 
 	lua_pushnil(L); /* first key */
 	while (lua_next(L, 2) != 0) {
-		p.see_node(m, m[0], (*get_user_class<LuaField>(L, -1))->fcoords(L), egbase.get_gametime());
+		p.see_node(map, map[0], (*get_user_class<LuaField>(L, -1))->fcoords(L), egbase.get_gametime());
 		lua_pop(L, 1);
 	}
 
@@ -626,14 +625,14 @@
 int LuaPlayer::hide_fields(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
 	Player& p = get(L, egbase);
-	Map& m = egbase.map();
+	const Map& map = egbase.map();
 
 	luaL_checktype(L, 2, LUA_TTABLE);
 	const bool mode = !lua_isnone(L, 3) && luaL_checkboolean(L, 3);
 
 	lua_pushnil(L); /* first key */
 	while (lua_next(L, 2) != 0) {
-		p.unsee_node((*get_user_class<LuaField>(L, -1))->fcoords(L).field - &m[0],
+		p.unsee_node((*get_user_class<LuaField>(L, -1))->fcoords(L).field - &map[0],
 		             egbase.get_gametime(),
 		             mode ? Player::UnseeNodeMode::kUnexplore : Player::UnseeNodeMode::kUnsee);
 		lua_pop(L, 1);
@@ -691,15 +690,15 @@
 */
 int LuaPlayer::get_ships(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
-	Map* map = egbase.get_map();
+	const Map& map = egbase.map();
 	PlayerNumber p = (get(L, egbase)).player_number();
 	lua_newtable(L);
 	uint32_t cidx = 1;
 
 	std::set<OPtr<Ship>> found_ships;
-	for (int16_t y = 0; y < map->get_height(); ++y) {
-		for (int16_t x = 0; x < map->get_width(); ++x) {
-			FCoords f = map->get_fcoords(Coords(x, y));
+	for (int16_t y = 0; y < map.get_height(); ++y) {
+		for (int16_t x = 0; x < map.get_width(); ++x) {
+			FCoords f = map.get_fcoords(Coords(x, y));
 			// there are too many bobs on the map so we investigate
 			// only bobs on water
 			if (f.field->nodecaps() & MOVECAPS_SWIM) {
@@ -734,7 +733,7 @@
 */
 int LuaPlayer::get_buildings(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
-	Map* map = egbase.get_map();
+	const Map& map = egbase.map();
 	Player& p = get(L, egbase);
 
 	// if only one string, convert to array so that we can use
@@ -770,7 +769,7 @@
 				continue;
 
 			lua_pushuint32(L, cidx++);
-			upcasted_map_object_to_lua(L, (*map)[vec[l].pos].get_immovable());
+			upcasted_map_object_to_lua(L, map[vec[l].pos].get_immovable());
 			lua_rawset(L, -3);
 		}
 
@@ -1087,7 +1086,7 @@
 		std::string filename = _("%1% (%2%)");
 		i18n::Textdomain td("maps");
 		filename =
-		   (boost::format(filename) % _(get_egbase(L).get_map()->get_name()) % o.descname().c_str())
+		   (boost::format(filename) % _(get_egbase(L).map().get_name()) % o.descname().c_str())
 		      .str();
 		get_game(L).save_handler().request_save(filename);
 	}
@@ -1103,7 +1102,7 @@
 	Game& g = get_game(L);
 	// The next call checks if the Objective still exists
 	get(L, g);
-	g.map().mutable_objectives()->erase(name_);
+	g.mutable_map()->mutable_objectives()->erase(name_);
 	return 0;
 }
 
@@ -1125,7 +1124,7 @@
  ==========================================================
  */
 Objective& LuaObjective::get(lua_State* L, Widelands::Game& g) {
-	Map::Objectives* objectives = g.map().mutable_objectives();
+	Map::Objectives* objectives = g.mutable_map()->mutable_objectives();
 	Map::Objectives::iterator i = objectives->find(name_);
 	if (i == objectives->end()) {
 		report_error(L, "Objective with name '%s' doesn't exist!", name_.c_str());

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2017-08-16 04:31:56 +0000
+++ src/scripting/lua_map.cc	2017-08-19 22:24:59 +0000
@@ -1171,10 +1171,10 @@
       for each player defined in the map.
 */
 int LuaMap::get_player_slots(lua_State* L) {
-	Map& m = get_egbase(L).map();
+	const Map& map = get_egbase(L).map();
 
-	lua_createtable(L, m.get_nrplayers(), 0);
-	for (Widelands::PlayerNumber i = 0; i < m.get_nrplayers(); i++) {
+	lua_createtable(L, map.get_nrplayers(), 0);
+	for (Widelands::PlayerNumber i = 0; i < map.get_nrplayers(); i++) {
 		lua_pushuint32(L, i + 1);
 		to_lua<LuaMaps::LuaPlayerSlot>(L, new LuaMaps::LuaPlayerSlot(i + 1));
 		lua_settable(L, -3);
@@ -1252,11 +1252,11 @@
 	uint32_t x = luaL_checkuint32(L, 2);
 	uint32_t y = luaL_checkuint32(L, 3);
 
-	Map& m = get_egbase(L).map();
+	const Map& map = get_egbase(L).map();
 
-	if (x >= static_cast<uint32_t>(m.get_width()))
+	if (x >= static_cast<uint32_t>(map.get_width()))
 		report_error(L, "x coordinate out of range!");
-	if (y >= static_cast<uint32_t>(m.get_height()))
+	if (y >= static_cast<uint32_t>(map.get_height()))
 		report_error(L, "y coordinate out of range!");
 
 	return to_lua<LuaMaps::LuaField>(L, new LuaMaps::LuaField(x, y));
@@ -1272,7 +1272,7 @@
 // TODO(unknown): do we really want this function?
 int LuaMap::recalculate(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
-	egbase.map().recalc_whole_map(egbase.world());
+	egbase.mutable_map()->recalc_whole_map(egbase.world());
 	return 0;
 }
 
@@ -5787,7 +5787,7 @@
 		report_error(L, "height must be <= %i", MAX_FIELD_HEIGHT);
 
 	EditorGameBase& egbase = get_egbase(L);
-	egbase.map().set_height(egbase.world(), f, height);
+	egbase.mutable_map()->set_height(egbase.world(), f, height);
 
 	return 0;
 }
@@ -5865,9 +5865,9 @@
 
 	auto c = fcoords(L);
 	const auto current_amount = c.field->get_resources_amount();
-	auto& map = egbase.map();
-	map.initialize_resources(c, res, c.field->get_initial_res_amount());
-	map.set_resources(c, current_amount);
+	auto* map = egbase.mutable_map();
+	map->initialize_resources(c, res, c.field->get_initial_res_amount());
+	map->set_resources(c, current_amount);
 	return 0;
 }
 
@@ -5894,12 +5894,12 @@
 		report_error(L, "Illegal amount: %i, must be >= 0 and <= %i", amount,
 		             static_cast<unsigned int>(max_amount));
 
-	auto& map = egbase.map();
+	auto* map = egbase.mutable_map();
 	if (is_a(Game, &egbase)) {
-		map.set_resources(c, amount);
+		map->set_resources(c, amount);
 	} else {
 		// in editor, reset also initial amount
-		map.initialize_resources(c, res, amount);
+		map->initialize_resources(c, res, amount);
 	}
 	return 0;
 }
@@ -5972,7 +5972,7 @@
 	if (td == static_cast<DescriptionIndex>(-1))
 		report_error(L, "Unknown terrain '%s'", name);
 
-	egbase.map().change_terrain(world, TCoords<FCoords>(fcoords(L), TCoords<FCoords>::R), td);
+	egbase.mutable_map()->change_terrain(world, TCoords<FCoords>(fcoords(L), TCoords<FCoords>::R), td);
 
 	lua_pushstring(L, name);
 	return 1;
@@ -5991,7 +5991,8 @@
 	if (td == static_cast<DescriptionIndex>(INVALID_INDEX))
 		report_error(L, "Unknown terrain '%s'", name);
 
-	egbase.map().change_terrain(world, TCoords<FCoords>(fcoords(L), TCoords<FCoords>::D), td);
+	egbase.mutable_map()->change_terrain(
+	   world, TCoords<FCoords>(fcoords(L), TCoords<FCoords>::D), td);
 
 	lua_pushstring(L, name);
 	return 1;
@@ -6058,7 +6059,7 @@
 */
 int LuaField::get_claimers(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
-	Map& map = egbase.map();
+	const Map& map = egbase.map();
 
 	std::vector<PlrInfluence> claimers;
 
@@ -6187,7 +6188,7 @@
  ==========================================================
  */
 int LuaField::region(lua_State* L, uint32_t radius) {
-	Map& map = get_egbase(L).map();
+	const Map& map = get_egbase(L).map();
 	MapRegion<Area<FCoords>> mr(map, Area<FCoords>(fcoords(L), radius));
 
 	lua_newtable(L);
@@ -6203,7 +6204,7 @@
 }
 
 int LuaField::hollow_region(lua_State* L, uint32_t radius, uint32_t inner_radius) {
-	Map& map = get_egbase(L).map();
+	const Map& map = get_egbase(L).map();
 	HollowArea<Area<>> har(Area<>(coords_, radius), inner_radius);
 
 	MapHollowRegion<Area<>> mr(map, har);
@@ -6265,7 +6266,7 @@
       (RO) The name of the tribe suggested for this player in this map
 */
 int LuaPlayerSlot::get_tribe_name(lua_State* L) {
-	lua_pushstring(L, get_egbase(L).get_map()->get_scenario_player_tribe(player_number_));
+	lua_pushstring(L, get_egbase(L).map().get_scenario_player_tribe(player_number_));
 	return 1;
 }
 
@@ -6275,7 +6276,7 @@
       (RO) The name for this player as suggested in this map
 */
 int LuaPlayerSlot::get_name(lua_State* L) {
-	lua_pushstring(L, get_egbase(L).get_map()->get_scenario_player_name(player_number_));
+	lua_pushstring(L, get_egbase(L).map().get_scenario_player_name(player_number_));
 	return 1;
 }
 

=== modified file 'src/website/map_info.cc'
--- src/website/map_info.cc	2017-01-25 18:55:59 +0000
+++ src/website/map_info.cc	2017-08-19 22:24:59 +0000
@@ -75,9 +75,8 @@
 		FileSystem* in_out_filesystem = &FileSystem::create(map_dir);
 		g_fs->add_file_system(in_out_filesystem);
 
-		Map* map = new Map();
 		EditorGameBase egbase(nullptr);
-		egbase.set_map(map);
+		auto* map = egbase.mutable_map();
 		std::unique_ptr<Widelands::MapLoader> ml(map->get_correct_loader(map_file));
 
 		if (!ml) {

=== modified file 'src/wui/attack_box.cc'
--- src/wui/attack_box.cc	2017-02-25 13:27:40 +0000
+++ src/wui/attack_box.cc	2017-08-19 22:24:59 +0000
@@ -40,17 +40,16 @@
                      uint32_t const y)
    : UI::Box(parent, x, y, UI::Box::Vertical),
      player_(player),
-     map_(&player_->egbase().map()),
+     map_(player_->egbase().map()),
      node_coordinates_(target),
      lastupdate_(0) {
 	init();
 }
 
 uint32_t AttackBox::get_max_attackers() {
-	assert(map_);
 	assert(player_);
 
-	if (upcast(Building, building, map_->get_immovable(*node_coordinates_)))
+	if (upcast(Building, building, map_.get_immovable(*node_coordinates_)))
 		return player_->find_attack_soldiers(building->base_flag());
 	return 0;
 }

=== modified file 'src/wui/attack_box.h'
--- src/wui/attack_box.h	2017-05-20 22:42:49 +0000
+++ src/wui/attack_box.h	2017-08-19 22:24:59 +0000
@@ -80,7 +80,7 @@
 
 private:
 	Widelands::Player* player_;
-	Widelands::Map* map_;
+	const Widelands::Map& map_;
 	Widelands::FCoords* node_coordinates_;
 
 	std::unique_ptr<UI::Slider> soldiers_slider_;

=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc	2017-08-17 15:34:45 +0000
+++ src/wui/fieldaction.cc	2017-08-19 22:24:59 +0000
@@ -195,7 +195,7 @@
 	void reset_mouse_and_die();
 
 	Widelands::Player* player_;
-	Widelands::Map* map_;
+	const Widelands::Map& map_;
 	FieldOverlayManager& field_overlay_manager_;
 
 	Widelands::FCoords node_;
@@ -246,9 +246,9 @@
                                      UI::UniqueWindow::Registry* const registry)
    : UI::UniqueWindow(ib, "field_action", registry, 68, 34, _("Action")),
      player_(plr),
-     map_(&ib->egbase().map()),
+     map_(ib->egbase().map()),
      field_overlay_manager_(*ib->mutable_field_overlay_manager()),
-     node_(ib->get_sel_pos().node, &(*map_)[ib->get_sel_pos().node]),
+     node_(ib->get_sel_pos().node, &map_[ib->get_sel_pos().node]),
      tabpanel_(this, g_gr->images().get("images/ui_basic/but1.png")),
      fastclick_(true),
      best_tab_(0),
@@ -305,7 +305,7 @@
 	const Widelands::PlayerNumber owner = node_.field->get_owned_by();
 
 	if (!igbase || igbase->can_see(owner)) {
-		Widelands::BaseImmovable* const imm = map_->get_immovable(node_);
+		Widelands::BaseImmovable* const imm = map_.get_immovable(node_);
 		const bool can_act = igbase ? igbase->can_act(owner) : true;
 
 		// The box with road-building buttons
@@ -380,7 +380,7 @@
 void FieldActionWindow::add_buttons_attack() {
 	UI::Box& a_box = *new UI::Box(&tabpanel_, 0, 0, UI::Box::Horizontal);
 
-	if (upcast(Widelands::Building, building, map_->get_immovable(node_))) {
+	if (upcast(Widelands::Building, building, map_.get_immovable(node_))) {
 		if (const Widelands::AttackTarget* attack_target = building->attack_target()) {
 			if (player_ && player_->is_hostile(building->owner()) &&
 			    attack_target->can_be_attacked()) {

=== modified file 'src/wui/game_debug_ui.cc'
--- src/wui/game_debug_ui.cc	2017-06-28 07:17:12 +0000
+++ src/wui/game_debug_ui.cc	2017-08-19 22:24:59 +0000
@@ -198,7 +198,7 @@
 	void open_bob(uint32_t);
 
 private:
-	Widelands::Map& map_;
+	const Widelands::Map& map_;
 	Widelands::FCoords const coords_;
 
 	UI::MultilineTextarea ui_field_;

=== modified file 'src/wui/game_main_menu_save_game.cc'
--- src/wui/game_main_menu_save_game.cc	2017-06-24 11:18:12 +0000
+++ src/wui/game_main_menu_save_game.cc	2017-08-19 22:24:59 +0000
@@ -113,7 +113,7 @@
 		{
 			// Try to translate the map name.
 			i18n::Textdomain td("maps");
-			mapname_.set_text(_(parent.game().get_map()->get_name()));
+			mapname_.set_text(_(parent.game().map().get_name()));
 		}
 		uint32_t gametime = parent.game().get_gametime();
 		gametime_.set_text(gametimestring(gametime));

=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc	2017-08-18 02:28:27 +0000
+++ src/wui/interactive_base.cc	2017-08-19 22:24:59 +0000
@@ -144,7 +144,7 @@
 }
 
 void InteractiveBase::set_sel_pos(Widelands::NodeAndTriangle<> const center) {
-	Map& map = egbase().map();
+	const Map& map = egbase().map();
 
 	// Remove old sel pointer
 	if (sel_.jobid)
@@ -278,7 +278,7 @@
 	default:
 		throw wexception("Encountered unexpected WorkareaInfo size %i", workareas_nrs);
 	}
-	Widelands::Map& map = egbase_.map();
+	const Widelands::Map& map = egbase_.map();
 	FieldOverlayManager::OverlayId overlay_id = field_overlay_manager_->next_overlay_id();
 
 	Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0);
@@ -606,7 +606,7 @@
 bool InteractiveBase::append_build_road(Coords const field) {
 	assert(buildroad_);
 
-	Map& map = egbase().map();
+	const Map& map = egbase().map();
 	const Widelands::Player& player = egbase().player(road_build_player_);
 
 	{  //  find a path to the clicked-on node
@@ -708,7 +708,7 @@
 	assert(buildroad_);
 	assert(road_building_preview_.empty());
 
-	Map& map = egbase().map();
+	const Map& map = egbase().map();
 
 	// preview of the road
 	const CoordPath::StepVector::size_type nr_steps = buildroad_->get_nsteps();

=== modified file 'src/wui/interactive_gamebase.cc'
--- src/wui/interactive_gamebase.cc	2017-08-17 15:34:45 +0000
+++ src/wui/interactive_gamebase.cc	2017-08-19 22:24:59 +0000
@@ -137,7 +137,6 @@
  * during single/multiplayer/scenario).
  */
 void InteractiveGameBase::postload() {
-	Widelands::Map& map = egbase().map();
 	auto* overlay_manager = mutable_field_overlay_manager();
 	show_buildhelp(false);
 	on_buildhelp_changed(buildhelp());
@@ -146,7 +145,7 @@
 	   boost::bind(&InteractiveGameBase::calculate_buildcaps, this, _1));
 
 	// Recalc whole map for changed owner stuff
-	map.recalc_whole_map(egbase().world());
+	egbase().mutable_map()->recalc_whole_map(egbase().world());
 
 	// Close game-relevant UI windows (but keep main menu open)
 	fieldaction_.destroy();
@@ -224,7 +223,7 @@
  * If so, do it and return true; otherwise, return false.
  */
 bool InteractiveGameBase::try_show_ship_window() {
-	Widelands::Map& map(game().map());
+	const Widelands::Map& map= game().map();
 	Widelands::Area<Widelands::FCoords> area(map.get_fcoords(get_sel_pos().node), 1);
 
 	if (!(area.field->nodecaps() & Widelands::MOVECAPS_SWIM))

=== modified file 'src/wui/watchwindow.cc'
--- src/wui/watchwindow.cc	2017-08-17 15:34:45 +0000
+++ src/wui/watchwindow.cc	2017-08-19 22:24:59 +0000
@@ -214,7 +214,7 @@
 		   MapviewPixelFunctions::to_map_pixel(game().map(), bob->get_position());
 		const Vector2f pos = bob->calc_drawpos(game(), field_position, 1.f);
 
-		Widelands::Map& map = game().map();
+		const Widelands::Map& map = game().map();
 		// Drop the tracking if it leaves our vision range
 		InteractivePlayer* ipl = game().get_ipl();
 		if (ipl && 1 >= ipl->player().vision(map.get_index(bob->get_position(), map.get_width()))) {
@@ -253,7 +253,7 @@
 		//  Find the nearest bob. Other object types can not move and are
 		//  therefore not of interest.
 		Vector2f center_map_pixel = mapview_.view_area().rect().center();
-		Widelands::Map& map = g.map();
+		const Widelands::Map& map = g.map();
 		MapviewPixelFunctions::normalize_pix(map, &center_map_pixel);
 		std::vector<Widelands::Bob*> bobs;
 		//  Scan progressively larger circles around the given position for


Follow ups