← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/amazons-coding-changes into lp:widelands

 

Benedikt Straub has proposed merging lp:~widelands-dev/widelands/amazons-coding-changes into lp:widelands.

Commit message:
*** REVERT THE data/tribes DIRECTORY BEFORE MERGING ***

Implements the coding changes required for the new amazons tribe:
– findspace:swim (for water gatherers)
– Enhancing terrains (for gardening center)
– Constructing buildings over immovables (for treetop sentry)

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/amazons-coding-changes/+merge/371725

Testcases in this branch:
– barbarian well works as water gatherer
– barbarian forester works as gardening center
– barbarian sentry is constructed over trees

data/tribes needs to be reverted before merging! (The data/world/terrains/init.lua should not be reverted, its changes are intended for merge)
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/amazons-coding-changes into lp:widelands.
=== modified file 'data/tribes/buildings/militarysites/barbarians/sentry/init.lua'
--- data/tribes/buildings/militarysites/barbarians/sentry/init.lua	2015-12-28 22:02:27 +0000
+++ data/tribes/buildings/militarysites/barbarians/sentry/init.lua	2019-08-23 08:59:39 +0000
@@ -8,6 +8,7 @@
    helptext_script = dirname .. "helptexts.lua",
    icon = dirname .. "menu.png",
    size = "small",
+   built_over_immovable = "tree",
 
    buildcost = {
       blackwood = 2

=== modified file 'data/tribes/buildings/productionsites/atlanteans/armorsmithy/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/armorsmithy/init.lua	2019-06-05 14:10:56 +0000
+++ data/tribes/buildings/productionsites/atlanteans/armorsmithy/init.lua	2019-08-23 08:59:39 +0000
@@ -29,6 +29,13 @@
 --        ``"medium"``, or ``"big"``, production sites can also have size ``"mine"``
 --        for defining a mine building to be built on mountains.
 --
+--    **built_over_immovable**
+--        *Optional*. If this is set, this building can be built only over an immovable (world or tribe)
+--        with the given attribute. The immovable will seem to remain existing below the building. Example::
+--
+--            built_over_immovable = "tree",
+--
+--
 --    **working_positions**
 --        *Mandatory*. The name and amount for each worker type working at this
 --        building, e.g.::

=== modified file 'data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua'
--- data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua	2019-06-06 09:11:02 +0000
+++ data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua	2019-08-23 08:59:39 +0000
@@ -55,8 +55,10 @@
          -- TRANSLATORS: Completed/Skipped/Did not start planting trees because ...
          descname = _"planting trees",
          actions = {
-            "callworker=plant",
-            "sleep=11500"
+            -- "callworker=plant",
+            "sleep=11500",
+            "callworker=terraform",
+            -- "sleep=11500"
          }
       },
    },

=== modified file 'data/tribes/buildings/productionsites/barbarians/well/init.lua'
--- data/tribes/buildings/productionsites/barbarians/well/init.lua	2019-06-05 14:10:56 +0000
+++ data/tribes/buildings/productionsites/barbarians/well/init.lua	2019-08-23 08:59:39 +0000
@@ -54,9 +54,7 @@
          descname = _"working",
          actions = {
             "sleep=20000",
-            "animate=working 20000",
-            "mine=water 1 100 65 2",
-            "produce=water",
+            "callworker=fetch_water",
          }
       },
    },

=== modified file 'data/tribes/workers/barbarians/carrier/init.lua'
--- data/tribes/workers/barbarians/carrier/init.lua	2019-04-21 12:23:33 +0000
+++ data/tribes/workers/barbarians/carrier/init.lua	2019-08-23 08:59:39 +0000
@@ -17,5 +17,14 @@
 
    buildcost = {}, -- This will give the worker the property "buildable"
 
+   programs = {
+      fetch_water = {
+         "findspace=size:swim radius:6",
+         "walk=coords",
+         "createware=water",
+         "return"
+      }
+   },
+
    animations = animations,
 }

=== modified file 'data/tribes/workers/barbarians/ranger/init.lua'
--- data/tribes/workers/barbarians/ranger/init.lua	2019-06-02 14:04:16 +0000
+++ data/tribes/workers/barbarians/ranger/init.lua	2019-08-23 08:59:39 +0000
@@ -48,6 +48,12 @@
          "plant=attrib:tree_sapling",
          "animate=water 3500",
          "return"
+      },
+      terraform = {
+         "findspace=size:terraform radius:6",
+         "walk=coords",
+         "terraform",
+         "return"
       }
    },
 

=== modified file 'data/world/terrains/init.lua'
--- data/world/terrains/init.lua	2018-12-19 07:04:55 +0000
+++ data/world/terrains/init.lua	2019-08-23 08:59:39 +0000
@@ -142,6 +142,12 @@
 --
 --            fertility = 700,
 --
+--    **enhancement**
+--        *Optional*. The terrain this terrain can be turned into by buildings like
+--        the amazon gardening center. Example::
+--
+--            enhancement = "summer_meadow3",
+--
 
 ------------------------
 --  Former greenland  --
@@ -188,7 +194,6 @@
    temperature = 100,
    humidity = 600,
    fertility = 650,
-
 }
 
 
@@ -245,6 +250,8 @@
    temperature = 100,
    humidity = 400,
    fertility = 400,
+
+   enhancement = "summer_mountain_meadow"
 }
 
 
@@ -261,6 +268,8 @@
    temperature = 100,
    humidity = 150,
    fertility = 150,
+
+   enhancement = "summer_steppe"
 }
 
 
@@ -277,6 +286,8 @@
    temperature = 75,
    humidity = 800,
    fertility = 450,
+
+   enhancement = "summer_meadow1"
 }
 
 world:new_terrain_type{
@@ -332,6 +343,8 @@
    temperature = 80,
    humidity = 100,
    fertility = 100,
+
+   enhancement = "summer_forested_mountain1"
 }
 
 
@@ -348,6 +361,8 @@
    temperature = 80,
    humidity = 100,
    fertility = 100,
+
+   enhancement = "summer_forested_mountain1"
 }
 
 
@@ -364,6 +379,8 @@
    temperature = 80,
    humidity = 100,
    fertility = 100,
+
+   enhancement = "summer_forested_mountain2"
 }
 
 
@@ -380,6 +397,8 @@
    temperature = 80,
    humidity = 100,
    fertility = 100,
+
+   enhancement = "summer_forested_mountain2"
 }
 
 world:new_terrain_type{
@@ -483,6 +502,8 @@
    temperature = 120,
    humidity = 150,
    fertility = 900,
+
+   enhancement = "hardground3"
 }
 
 
@@ -503,6 +524,8 @@
    temperature = 118,
    humidity = 130,
    fertility = 999,
+
+   enhancement = "hardground1"
 }
 
 
@@ -599,6 +622,8 @@
    temperature = 120,
    humidity = 100,
    fertility = 200,
+
+   enhancement = "drysoil"
 }
 
 
@@ -653,6 +678,8 @@
    temperature = 80,
    humidity = 50,
    fertility = 200,
+
+   enhancement = "wasteland_forested_mountain1"
 }
 
 
@@ -669,6 +696,8 @@
    temperature = 80,
    humidity = 50,
    fertility = 200,
+
+   enhancement = "wasteland_forested_mountain1"
 }
 
 
@@ -685,6 +714,8 @@
    temperature = 80,
    humidity = 50,
    fertility = 200,
+
+   enhancement = "wasteland_forested_mountain2"
 }
 
 
@@ -701,6 +732,8 @@
    temperature = 80,
    humidity = 50,
    fertility = 200,
+
+   enhancement = "wasteland_forested_mountain2"
 }
 
 
@@ -849,6 +882,8 @@
    temperature = 40,
    humidity = 750,
    fertility = 400,
+
+   enhancement = "tundra2"
 }
 
 
@@ -865,6 +900,8 @@
    temperature = 35,
    humidity = 750,
    fertility = 300,
+
+   enhancement = "tundra_taiga"
 }
 
 
@@ -881,6 +918,8 @@
    temperature = 25,
    humidity = 800,
    fertility = 100,
+
+   enhancement = "taiga"
 }
 
 
@@ -935,6 +974,8 @@
    temperature = 20,
    humidity = 300,
    fertility = 50,
+
+   enhancement = "winter_forested_mountain1"
 }
 
 
@@ -951,6 +992,8 @@
    temperature = 20,
    humidity = 300,
    fertility = 50,
+
+   enhancement = "winter_forested_mountain1"
 }
 
 
@@ -967,6 +1010,8 @@
    temperature = 20,
    humidity = 300,
    fertility = 50,
+
+   enhancement = "winter_forested_mountain2"
 }
 
 
@@ -983,6 +1028,8 @@
    temperature = 20,
    humidity = 300,
    fertility = 50,
+
+   enhancement = "winter_forested_mountain2"
 }
 world:new_terrain_type{
    name = "ice",
@@ -1084,6 +1131,8 @@
    temperature = 168,
    humidity = 1,
    fertility = 100,
+
+   enhancement = "drysoil"
 }
 
 world:new_terrain_type{
@@ -1099,6 +1148,8 @@
    temperature = 172,
    humidity = 200,
    fertility = 200,
+
+   enhancement = "highmountainmeadow"
 }
 world:new_terrain_type{
    name = "desert_steppe",
@@ -1157,6 +1208,8 @@
    temperature = 145,
    humidity = 500,
    fertility = 500,
+
+   enhancement = "desert_steppe"
 }
 
 
@@ -1177,6 +1230,8 @@
    temperature = 140,
    humidity = 400,
    fertility = 400,
+
+   enhancement = "mountainmeadow"
 }
 
 
@@ -1232,6 +1287,8 @@
    temperature = 130,
    humidity = 50,
    fertility = 50,
+
+   enhancement = "desert_forested_mountain1"
 }
 
 
@@ -1248,6 +1305,8 @@
    temperature = 130,
    humidity = 50,
    fertility = 50,
+
+   enhancement = "desert_forested_mountain1"
 }
 
 
@@ -1264,6 +1323,8 @@
    temperature = 130,
    humidity = 50,
    fertility = 50,
+
+   enhancement = "desert_forested_mountain2"
 }
 
 
@@ -1280,6 +1341,8 @@
    temperature = 130,
    humidity = 50,
    fertility = 50,
+
+   enhancement = "desert_forested_mountain2"
 }
 world:new_terrain_type{
    name = "desert1",

=== modified file 'src/ai/ai_help_structs.cc'
--- src/ai/ai_help_structs.cc	2019-08-02 09:54:55 +0000
+++ src/ai/ai_help_structs.cc	2019-08-23 08:59:39 +0000
@@ -136,7 +136,7 @@
 FindNodeEnemy::FindNodeEnemy(Player* p, Game& g) : player(p), game(g) {
 }
 
-bool FindNodeEnemy::accept(const Map&, const FCoords& fc) const {
+bool FindNodeEnemy::accept(const EditorGameBase&, const FCoords& fc) const {
 	return (fc.field->nodecaps() & MOVECAPS_WALK) && fc.field->get_owned_by() != 0 &&
 	       player->is_hostile(*game.get_player(fc.field->get_owned_by()));
 }
@@ -147,7 +147,7 @@
 FindNodeEnemiesBuilding::FindNodeEnemiesBuilding(Player* p, Game& g) : player(p), game(g) {
 }
 
-bool FindNodeEnemiesBuilding::accept(const Map&, const FCoords& fc) const {
+bool FindNodeEnemiesBuilding::accept(const EditorGameBase&, const FCoords& fc) const {
 	return (fc.field->get_immovable()) && fc.field->get_owned_by() != 0 &&
 	       player->is_hostile(*game.get_player(fc.field->get_owned_by()));
 }
@@ -158,7 +158,7 @@
 FindEnemyNodeWalkable::FindEnemyNodeWalkable(Player* p, Game& g) : player(p), game(g) {
 }
 
-bool FindEnemyNodeWalkable::accept(const Map&, const FCoords& fc) const {
+bool FindEnemyNodeWalkable::accept(const EditorGameBase&, const FCoords& fc) const {
 	return ((fc.field->nodecaps() & MOVECAPS_WALK) && (fc.field->get_owned_by() > 0) &&
 	        player->is_hostile(*game.get_player(fc.field->get_owned_by())));
 }
@@ -168,7 +168,7 @@
    : player(p), game(g), player_number(n) {
 }
 
-bool FindNodeAllyOwned::accept(const Map&, const FCoords& fc) const {
+bool FindNodeAllyOwned::accept(const EditorGameBase&, const FCoords& fc) const {
 	return (fc.field->nodecaps() & MOVECAPS_WALK) && (fc.field->get_owned_by() != 0) &&
 	       (fc.field->get_owned_by() != player_number) &&
 	       !player->is_hostile(*game.get_player(fc.field->get_owned_by()));
@@ -181,7 +181,7 @@
    : player(p), game(g), ore_type(t) {
 }
 
-bool FindNodeUnownedMineable::accept(const Map&, const FCoords& fc) const {
+bool FindNodeUnownedMineable::accept(const EditorGameBase&, const FCoords& fc) const {
 	if (ore_type == INVALID_INDEX) {
 		return (fc.field->nodecaps() & BUILDCAPS_MINE) && (fc.field->get_owned_by() == neutral());
 	}
@@ -192,7 +192,7 @@
 FindNodeUnownedBuildable::FindNodeUnownedBuildable(Player* p, Game& g) : player(p), game(g) {
 }
 
-bool FindNodeUnownedBuildable::accept(const Map&, const FCoords& fc) const {
+bool FindNodeUnownedBuildable::accept(const EditorGameBase&, const FCoords& fc) const {
 	return ((fc.field->nodecaps() & BUILDCAPS_SIZEMASK) ||
 	        (fc.field->nodecaps() & BUILDCAPS_MINE)) &&
 	       (fc.field->get_owned_by() == neutral());
@@ -202,7 +202,7 @@
 FindNodeUnownedWalkable::FindNodeUnownedWalkable(Player* p, Game& g) : player(p), game(g) {
 }
 
-bool FindNodeUnownedWalkable::accept(const Map&, const FCoords& fc) const {
+bool FindNodeUnownedWalkable::accept(const EditorGameBase&, const FCoords& fc) const {
 	return (fc.field->nodecaps() & MOVECAPS_WALK) && (fc.field->get_owned_by() == neutral());
 }
 
@@ -211,7 +211,7 @@
 FindNodeMineable::FindNodeMineable(Game& g, DescriptionIndex r) : game(g), res(r) {
 }
 
-bool FindNodeMineable::accept(const Map&, const FCoords& fc) const {
+bool FindNodeMineable::accept(const EditorGameBase&, const FCoords& fc) const {
 
 	return (fc.field->nodecaps() & BUILDCAPS_MINE) && (fc.field->get_resources() == res);
 }
@@ -220,21 +220,21 @@
 FindNodeWater::FindNodeWater(const World& world) : world_(world) {
 }
 
-bool FindNodeWater::accept(const Map& map, const FCoords& coord) const {
+bool FindNodeWater::accept(const EditorGameBase& egbase, const FCoords& coord) const {
 	return (world_.terrain_descr(coord.field->terrain_d()).get_is() &
 	        TerrainDescription::Is::kWater) ||
-	       (world_.terrain_descr(map.get_neighbour(coord, WALK_W).field->terrain_r()).get_is() &
+	       (world_.terrain_descr(egbase.map().get_neighbour(coord, WALK_W).field->terrain_r()).get_is() &
 	        TerrainDescription::Is::kWater) ||
-	       (world_.terrain_descr(map.get_neighbour(coord, WALK_NW).field->terrain_r()).get_is() &
+	       (world_.terrain_descr(egbase.map().get_neighbour(coord, WALK_NW).field->terrain_r()).get_is() &
 	        TerrainDescription::Is::kWater);
 }
 
-bool FindNodeOpenWater::accept(const Map& /* map */, const FCoords& coord) const {
+bool FindNodeOpenWater::accept(const EditorGameBase&, const FCoords& coord) const {
 	return !(coord.field->nodecaps() & MOVECAPS_WALK) && (coord.field->nodecaps() & MOVECAPS_SWIM);
 }
 
 // FindNodeWithFlagOrRoad
-bool FindNodeWithFlagOrRoad::accept(const Map&, FCoords fc) const {
+bool FindNodeWithFlagOrRoad::accept(const EditorGameBase&, FCoords fc) const {
 	if (upcast(PlayerImmovable const, pimm, fc.field->get_immovable()))
 		return (dynamic_cast<Flag const*>(pimm) ||
 		        (dynamic_cast<Road const*>(pimm) && (fc.field->nodecaps() & BUILDCAPS_FLAG)));

=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2019-08-02 09:54:55 +0000
+++ src/ai/ai_help_structs.h	2019-08-23 08:59:39 +0000
@@ -168,7 +168,7 @@
 struct FindNodeEnemy {
 	FindNodeEnemy(Player* p, Game& g);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Player* player;
 	Game& game;
@@ -181,7 +181,7 @@
 struct FindNodeEnemiesBuilding {
 	FindNodeEnemiesBuilding(Player* p, Game& g);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Player* player;
 	Game& game;
@@ -191,7 +191,7 @@
 struct FindEnemyNodeWalkable {
 	FindEnemyNodeWalkable(Player* p, Game& g);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Player* player;
 	Game& game;
@@ -201,7 +201,7 @@
 struct FindNodeAllyOwned {
 	FindNodeAllyOwned(Player* p, Game& g, PlayerNumber n);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Player* player;
 	Game& game;
@@ -214,7 +214,7 @@
 struct FindNodeUnownedMineable {
 	FindNodeUnownedMineable(Player* p, Game& g, int32_t t = INVALID_INDEX);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Player* player;
 	Game& game;
@@ -226,7 +226,7 @@
 struct FindNodeUnownedBuildable {
 	FindNodeUnownedBuildable(Player* p, Game& g);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Player* player;
 	Game& game;
@@ -236,7 +236,7 @@
 struct FindNodeUnownedWalkable {
 	FindNodeUnownedWalkable(Player* p, Game& g);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Player* player;
 	Game& game;
@@ -247,7 +247,7 @@
 struct FindNodeMineable {
 	FindNodeMineable(Game& g, DescriptionIndex r);
 
-	bool accept(const Map&, const FCoords& fc) const;
+	bool accept(const EditorGameBase&, const FCoords& fc) const;
 
 	Game& game;
 	int32_t res;
@@ -257,7 +257,7 @@
 struct FindNodeWater {
 	explicit FindNodeWater(const World& world);
 
-	bool accept(const Map& /* map */, const FCoords& coord) const;
+	bool accept(const EditorGameBase&, const FCoords& coord) const;
 
 private:
 	const World& world_;
@@ -270,16 +270,16 @@
 	explicit FindNodeOpenWater(const World& /* world */) {
 	}
 
-	bool accept(const Map& /* map */, const FCoords& coord) const;
+	bool accept(const EditorGameBase&, const FCoords& coord) const;
 };
 
 struct FindNodeWithFlagOrRoad {
-	bool accept(const Map&, FCoords) const;
+	bool accept(const EditorGameBase&, FCoords) const;
 };
 
 // Accepts any field
 struct FindNodeAcceptAll {
-	bool accept(const Map&, FCoords) const {
+	bool accept(const EditorGameBase&, FCoords) const {
 		return true;
 	}
 };

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2019-08-02 09:54:55 +0000
+++ src/ai/defaultai.cc	2019-08-23 08:59:39 +0000
@@ -1342,10 +1342,10 @@
 		}
 	}
 
-	field.unowned_land_nearby = map.find_fields(
+	field.unowned_land_nearby = map.find_fields(game(),
 	   Area<FCoords>(field.coords, actual_enemy_check_area), nullptr, find_unowned_walkable);
 
-	field.enemy_owned_land_nearby = map.find_fields(
+	field.enemy_owned_land_nearby = map.find_fields(game(),
 	   Area<FCoords>(field.coords, actual_enemy_check_area), nullptr, find_enemy_owned_walkable);
 
 	field.nearest_buildable_spot_nearby = std::numeric_limits<uint16_t>::max();
@@ -1359,10 +1359,10 @@
 
 		// first looking for unowned buildable spots
 		field.unowned_buildable_spots_nearby =
-		   map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
+		   map.find_fields(game(), Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
 		                   &found_buildable_fields, find_unowned_buildable);
 		field.unowned_buildable_spots_nearby +=
-		   map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
+		   map.find_fields(game(), Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
 		                   &found_buildable_fields, find_enemy_owned_walkable);
 		// Now iterate over fields to collect statistics
 		for (auto& coords : found_buildable_fields) {
@@ -1389,8 +1389,8 @@
 	}
 
 	// Is this near the border? Get rid of fields owned by ally
-	if (map.find_fields(Area<FCoords>(field.coords, 3), nullptr, find_ally) ||
-	    map.find_fields(Area<FCoords>(field.coords, 3), nullptr, find_unowned_walkable)) {
+	if (map.find_fields(game(), Area<FCoords>(field.coords, 3), nullptr, find_ally) ||
+	    map.find_fields(game(), Area<FCoords>(field.coords, 3), nullptr, find_unowned_walkable)) {
 		field.near_border = true;
 	} else {
 		field.near_border = false;
@@ -1408,10 +1408,10 @@
 
 	// testing mines
 	if (resource_count_now) {
-		uint32_t close_mines = map.find_fields(
+		uint32_t close_mines = map.find_fields(game(),
 		   Area<FCoords>(field.coords, kProductionArea), nullptr, find_unowned_mines_pots);
 		uint32_t distant_mines =
-		   map.find_fields(Area<FCoords>(field.coords, kDistantResourcesArea), nullptr,
+		   map.find_fields(game(), Area<FCoords>(field.coords, kDistantResourcesArea), nullptr,
 
 		                   find_unowned_mines_pots);
 		distant_mines = distant_mines - close_mines;
@@ -1425,7 +1425,7 @@
 		    (mines_per_type[iron_resource_id].in_construction +
 		     mines_per_type[iron_resource_id].finished) <= 1) {
 			// counting iron mines, if we have less than two iron mines
-			field.unowned_iron_mines_nearby = map.find_fields(
+			field.unowned_iron_mines_nearby = map.find_fields(game(),
 			   Area<FCoords>(field.coords, kDistantResourcesArea), nullptr, find_unowned_iron_mines);
 		} else {
 			field.unowned_iron_mines_nearby = 0;
@@ -1488,16 +1488,16 @@
 
 		FindNodeWater find_water(game().world());
 		field.water_nearby =
-		   map.find_fields(Area<FCoords>(field.coords, kProductionArea), nullptr, find_water);
+		   map.find_fields(game(), Area<FCoords>(field.coords, kProductionArea), nullptr, find_water);
 
 		if (field.water_nearby > 0) {
 			FindNodeOpenWater find_open_water(game().world());
 			field.open_water_nearby =
-			   map.find_fields(Area<FCoords>(field.coords, kProductionArea), nullptr, find_open_water);
+			   map.find_fields(game(), Area<FCoords>(field.coords, kProductionArea), nullptr, find_open_water);
 		}
 
 		if (resource_necessity_water_needed_) {  // for atlanteans
-			field.distant_water = map.find_fields(Area<FCoords>(field.coords, kDistantResourcesArea),
+			field.distant_water = map.find_fields(game(), Area<FCoords>(field.coords, kDistantResourcesArea),
 			                                      nullptr, find_water) -
 			                      field.water_nearby;
 			assert(field.open_water_nearby <= field.water_nearby);
@@ -1520,7 +1520,7 @@
 		CheckStepWalkOn fisher_cstep(MOVECAPS_WALK, true);
 		static std::vector<Coords> fish_fields_list;  // pity this contains duplicates
 		fish_fields_list.clear();
-		map.find_reachable_fields(Area<FCoords>(field.coords, kProductionArea), &fish_fields_list,
+		map.find_reachable_fields(game(), Area<FCoords>(field.coords, kProductionArea), &fish_fields_list,
 		                          fisher_cstep, FindNodeResource(world.get_resource("fish")));
 
 		// This is "list" of unique fields in fish_fields_list we got above
@@ -1538,11 +1538,11 @@
 	if (resource_count_now) {
 		// Counting fields with critters (game)
 		field.critters_nearby =
-		   map.find_bobs(Area<FCoords>(field.coords, kProductionArea), nullptr, FindBobCritter());
+		   map.find_bobs(game(), Area<FCoords>(field.coords, kProductionArea), nullptr, FindBobCritter());
 
 		// Rocks are not renewable, we will count them only if previous state is nonzero
 		if (field.rocks_nearby > 0) {
-			field.rocks_nearby = map.find_immovables(
+			field.rocks_nearby = map.find_immovables(game(),
 			   Area<FCoords>(map.get_fcoords(field.coords), kProductionArea), nullptr,
 			   FindImmovableAttribute(MapObjectDescr::get_attribute_id("rocks")));
 
@@ -1559,13 +1559,13 @@
 		// Counting trees nearby
 		int32_t const tree_attr = MapObjectDescr::get_attribute_id("tree");
 		field.trees_nearby =
-		   map.find_immovables(Area<FCoords>(map.get_fcoords(field.coords), kProductionArea), nullptr,
+		   map.find_immovables(game(), Area<FCoords>(map.get_fcoords(field.coords), kProductionArea), nullptr,
 		                       FindImmovableAttribute(tree_attr));
 
 		// Counting bushes nearby
 		int32_t const bush_attr = MapObjectDescr::get_attribute_id("ripe_bush");
 		field.bushes_nearby =
-		   map.find_immovables(Area<FCoords>(map.get_fcoords(field.coords), kProductionArea), nullptr,
+		   map.find_immovables(game(), Area<FCoords>(map.get_fcoords(field.coords), kProductionArea), nullptr,
 		                       FindImmovableAttribute(bush_attr));
 	}
 
@@ -1607,7 +1607,7 @@
 	immovables.reserve(50);
 	immovables.clear();
 	// Search in a radius of range
-	map.find_immovables(Area<FCoords>(field.coords, kProductionArea + 2), &immovables);
+	map.find_immovables(game(), Area<FCoords>(field.coords, kProductionArea + 2), &immovables);
 
 	// function seems to return duplicates, so we will use serial numbers to filter them out
 	static std::set<uint32_t> unique_serials;
@@ -1641,7 +1641,7 @@
 
 	// Now testing military aspects
 	immovables.clear();
-	map.find_immovables(Area<FCoords>(field.coords, actual_enemy_check_area), &immovables);
+	map.find_immovables(game(), Area<FCoords>(field.coords, actual_enemy_check_area), &immovables);
 
 	// We are interested in unconnected immovables, but we must be also close to connected ones
 	static bool any_connected_imm = false;
@@ -2000,7 +2000,7 @@
 	// collect information about resources in the area
 	std::vector<ImmovableFound> immovables;
 	const Map& map = game().map();
-	map.find_immovables(Area<FCoords>(field.coords, 5), &immovables);
+	map.find_immovables(game(), Area<FCoords>(field.coords, 5), &immovables);
 	field.preferred = false;
 	field.mines_nearby = 0;
 	FCoords fse;
@@ -2038,7 +2038,7 @@
 	if (field.same_mine_fields_nearby == 0) {
 		FindNodeMineable find_mines_spots_nearby(game(), field.coords.field->get_resources());
 		field.same_mine_fields_nearby =
-		   map.find_fields(Area<FCoords>(field.coords, 4), nullptr, find_mines_spots_nearby);
+		   map.find_fields(game(), Area<FCoords>(field.coords, 4), nullptr, find_mines_spots_nearby);
 	}
 }
 
@@ -3917,7 +3917,7 @@
 
 	// get all flags within radius
 	std::vector<Coords> reachable;
-	map.find_reachable_fields(
+	map.find_reachable_fields(game(),
 	   Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius), &reachable, check, functor);
 
 	for (const Coords& reachable_coords : reachable) {
@@ -4066,7 +4066,7 @@
 
 			// get all flags within radius
 			std::vector<Coords> reachable_to_block;
-			map.find_reachable_fields(Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius),
+			map.find_reachable_fields(game(), Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius),
 			                          &reachable_to_block, check_own, buildable_functor);
 
 			for (auto coords : reachable_to_block) {
@@ -4467,7 +4467,7 @@
 			return false;
 		}
 
-		const uint32_t remaining_trees = map.find_immovables(
+		const uint32_t remaining_trees = map.find_immovables(game(),
 		   Area<FCoords>(map.get_fcoords(site.site->get_position()), radius), nullptr,
 		   FindImmovableAttribute(MapObjectDescr::get_attribute_id("tree")));
 
@@ -4534,7 +4534,7 @@
 	// Quarry handling
 	if (site.bo->is(BuildingAttribute::kNeedsRocks)) {
 
-		if (map.find_immovables(Area<FCoords>(map.get_fcoords(site.site->get_position()), 6), nullptr,
+		if (map.find_immovables(game(), Area<FCoords>(map.get_fcoords(site.site->get_position()), 6), nullptr,
 
 		                        FindImmovableAttribute(MapObjectDescr::get_attribute_id("rocks"))) ==
 		    0) {
@@ -4690,7 +4690,7 @@
 		}
 
 		const uint32_t trees_in_vicinity =
-		   map.find_immovables(Area<FCoords>(map.get_fcoords(site.site->get_position()), 5), nullptr,
+		   map.find_immovables(game(), Area<FCoords>(map.get_fcoords(site.site->get_position()), 5), nullptr,
 		                       FindImmovableAttribute(MapObjectDescr::get_attribute_id("tree")));
 
 		// stop ranger if enough trees around regardless of policy

=== modified file 'src/ai/defaultai_seafaring.cc'
--- src/ai/defaultai_seafaring.cc	2019-05-13 12:10:28 +0000
+++ src/ai/defaultai_seafaring.cc	2019-08-23 08:59:39 +0000
@@ -74,7 +74,7 @@
 	immovables.clear();
 	immovables.reserve(50);
 	// Search in a radius of range
-	map.find_immovables(Area<FCoords>(map.get_fcoords(candidate_spot), 10), &immovables);
+	map.find_immovables(game(), Area<FCoords>(map.get_fcoords(candidate_spot), 10), &immovables);
 
 	int32_t const rocks_attr = MapObjectDescr::get_attribute_id("rocks");
 	uint16_t rocks = 0;

=== modified file 'src/ai/defaultai_warfare.cc'
--- src/ai/defaultai_warfare.cc	2019-05-07 12:14:02 +0000
+++ src/ai/defaultai_warfare.cc	2019-08-23 08:59:39 +0000
@@ -53,7 +53,7 @@
 		static std::vector<ImmovableFound> immovables;
 		immovables.clear();
 		immovables.reserve(40);
-		map.find_immovables(Area<FCoords>(f, (vision + 3 < 13) ? 13 : vision + 3), &immovables,
+		map.find_immovables(game(), Area<FCoords>(f, (vision + 3 < 13) ? 13 : vision + 3), &immovables,
 		                    FindImmovableAttackTarget());
 
 		for (uint32_t j = 0; j < immovables.size(); ++j) {
@@ -203,7 +203,7 @@
 			if (site->second.mines_nearby == ExtendedBool::kUnset) {
 				FindNodeMineable find_mines_spots_nearby(game(), f.field->get_resources());
 				const int32_t minescount =
-				   map.find_fields(Area<FCoords>(f, 6), nullptr, find_mines_spots_nearby);
+				   map.find_fields(game(), Area<FCoords>(f, 6), nullptr, find_mines_spots_nearby);
 				if (minescount > 0) {
 					site->second.mines_nearby = ExtendedBool::kTrue;
 				} else {

=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2019-08-10 16:38:15 +0000
+++ src/editor/editorinteractive.cc	2019-08-23 08:59:39 +0000
@@ -149,8 +149,8 @@
 
 	history_.reset(new EditorHistory(*undo_, *redo_));
 
-	undo_->sigclicked.connect([this] { history_->undo_action(egbase().world()); });
-	redo_->sigclicked.connect([this] { history_->redo_action(egbase().world()); });
+	undo_->sigclicked.connect([this] { history_->undo_action(egbase()); });
+	redo_->sigclicked.connect([this] { history_->redo_action(egbase()); });
 
 	toolbar()->add_space(15);
 
@@ -528,7 +528,7 @@
 void EditorInteractive::map_clicked(const Widelands::NodeAndTriangle<>& node_and_triangle,
                                     const bool should_draw) {
 	history_->do_action(tools_->current(), tools_->use_tool, *egbase().mutable_map(),
-	                    egbase().world(), node_and_triangle, *this, should_draw);
+	                    egbase(), node_and_triangle, *this, should_draw);
 	set_need_save(true);
 }
 
@@ -826,14 +826,14 @@
 
 		case SDLK_y:
 			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				history_->redo_action(egbase().world());
+				history_->redo_action(egbase());
 			return true;
 
 		case SDLK_z:
 			if ((code.mod & (KMOD_LCTRL | KMOD_RCTRL)) && (code.mod & (KMOD_LSHIFT | KMOD_RSHIFT)))
-				history_->redo_action(egbase().world());
+				history_->redo_action(egbase());
 			else if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				history_->undo_action(egbase().world());
+				history_->undo_action(egbase());
 			return true;
 
 		case SDLK_F1:
@@ -878,7 +878,7 @@
 				toolsize_menu.update(toolsize_menu.value());
 			}
 		}
-		egbase().mutable_map()->recalc_whole_map(egbase().world());
+		egbase().mutable_map()->recalc_whole_map(egbase());
 	}
 	tools_->current_pointer = &primary;
 	tools_->use_tool = which;
@@ -905,7 +905,7 @@
 			if (filename.empty()) {
 				loader_ui.step(_("Creating empty map…"));
 				egbase.mutable_map()->create_empty_map(
-				   egbase.world(), 64, 64, 0,
+				   egbase, 64, 64, 0,
 				   /** TRANSLATORS: Default name for new map */
 				   _("No Name"),
 				   g_options.pull_section("global").get_string(

=== modified file 'src/editor/map_generator.cc'
--- src/editor/map_generator.cc	2019-02-27 19:00:36 +0000
+++ src/editor/map_generator.cc	2019-08-23 08:59:39 +0000
@@ -132,7 +132,7 @@
 		   static_cast<ResourceAmount>(random_value / (kMaxElevation / max_amount));
 		res_val *= static_cast<ResourceAmount>(map_info_.resource_amount) + 1;
 		res_val /= 3;
-		if (map_.is_resource_valid(world, fc, res_idx)) {
+		if (map_.is_resource_valid(egbase_, fc, res_idx)) {
 			map_.initialize_resources(fc, res_idx, res_val);
 		}
 	};
@@ -657,7 +657,7 @@
 	}
 
 	//  Aftermaths...
-	map_.recalc_whole_map(egbase_.world());
+	map_.recalc_whole_map(egbase_);
 
 	// Care about players and place their start positions
 	map_.set_nrplayers(map_info_.numPlayers);
@@ -752,7 +752,7 @@
 		// Now try to find a place as near as possible to the wished
 		// starting position
 		std::vector<Coords> coords;
-		map_.find_fields(Area<FCoords>(map_.get_fcoords(playerstart), 20), &coords, functor);
+		map_.find_fields(egbase_, Area<FCoords>(map_.get_fcoords(playerstart), 20), &coords, functor);
 
 		// Take the nearest ones
 		uint32_t min_distance = std::numeric_limits<uint32_t>::max();

=== modified file 'src/editor/tools/decrease_height_tool.cc'
--- src/editor/tools/decrease_height_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/decrease_height_tool.cc	2019-08-23 08:59:39 +0000
@@ -26,9 +26,9 @@
 #include "logic/mapregion.h"
 
 /// Decreases the heights by a value. Chages surrounding nodes if necessary.
-int32_t EditorDecreaseHeightTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorDecreaseHeightTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                     const Widelands::NodeAndTriangle<>& center,
-                                                    EditorInteractive& /* parent */,
+                                                    EditorInteractive&,
                                                     EditorActionArgs* args,
                                                     Widelands::Map* map) {
 	if (args->original_heights.empty()) {
@@ -42,13 +42,13 @@
 	}
 
 	return map->change_height(
-	   world, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius),
+	   egbase, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius),
 	   -args->change_by);
 }
 
-int32_t EditorDecreaseHeightTool::handle_undo_impl(const Widelands::World& world,
+int32_t EditorDecreaseHeightTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                                    const Widelands::NodeAndTriangle<>& center,
-                                                   EditorInteractive& /* parent */,
+                                                   EditorInteractive&,
                                                    EditorActionArgs* args,
                                                    Widelands::Map* map) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
@@ -62,8 +62,7 @@
 		++i;
 	} while (mr.advance(*map));
 
-	map->recalc_for_field_area(
-	   world, Widelands::Area<Widelands::FCoords>(
+	map->recalc_for_field_area(egbase, Widelands::Area<Widelands::FCoords>(
 	             map->get_fcoords(center.node),
 	             args->sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 2));
 

=== modified file 'src/editor/tools/decrease_height_tool.h'
--- src/editor/tools/decrease_height_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/decrease_height_tool.h	2019-08-23 08:59:39 +0000
@@ -27,13 +27,13 @@
 	EditorDecreaseHeightTool() : EditorTool(*this, *this), change_by_(1) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/decrease_resources_tool.cc'
--- src/editor/tools/decrease_resources_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/decrease_resources_tool.cc	2019-08-23 08:59:39 +0000
@@ -31,9 +31,9 @@
  * Decrease the resources of the current field by the given value if
  * there is not already another resource there.
  */
-int32_t EditorDecreaseResourcesTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorDecreaseResourcesTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                        const Widelands::NodeAndTriangle<>& center,
-                                                       EditorInteractive& /* parent */,
+                                                       EditorInteractive&,
                                                        EditorActionArgs* args,
                                                        Widelands::Map* map) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
@@ -44,7 +44,7 @@
 		amount = (amount > args->change_by) ? amount - args->change_by : 0;
 
 		if (mr.location().field->get_resources() == args->current_resource &&
-		    map->is_resource_valid(world, mr.location(), args->current_resource) &&
+		    map->is_resource_valid(egbase, mr.location(), args->current_resource) &&
 		    mr.location().field->get_resources_amount() != 0) {
 
 			args->original_resource.push_back(
@@ -58,12 +58,12 @@
 	return mr.radius();
 }
 
-int32_t EditorDecreaseResourcesTool::handle_undo_impl(const Widelands::World& world,
+int32_t EditorDecreaseResourcesTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                                       const Widelands::NodeAndTriangle<>& center,
                                                       EditorInteractive& parent,
                                                       EditorActionArgs* args,
                                                       Widelands::Map* map) {
-	return parent.tools()->set_resources.handle_undo_impl(world, center, parent, args, map);
+	return parent.tools()->set_resources.handle_undo_impl(egbase, center, parent, args, map);
 }
 
 EditorActionArgs EditorDecreaseResourcesTool::format_args_impl(EditorInteractive& parent) {

=== modified file 'src/editor/tools/decrease_resources_tool.h'
--- src/editor/tools/decrease_resources_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/decrease_resources_tool.h	2019-08-23 08:59:39 +0000
@@ -28,13 +28,13 @@
 	EditorDecreaseResourcesTool() : EditorTool(*this, *this), cur_res_(0), change_by_(1) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/delete_critter_tool.cc'
--- src/editor/tools/delete_critter_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/delete_critter_tool.cc	2019-08-23 08:59:39 +0000
@@ -28,12 +28,11 @@
  * Deletes the bob at the given location
  */
 int32_t EditorDeleteCritterTool::handle_click_impl(
-   const Widelands::World&,
+   const Widelands::EditorGameBase&,
    const Widelands::NodeAndTriangle<Widelands::Coords>& center,
-   EditorInteractive& parent,
+   EditorInteractive& eia,
    EditorActionArgs* args,
    Widelands::Map* map) {
-	Widelands::EditorGameBase& egbase = parent.egbase();
 	const int32_t radius = args->sel_radius;
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 	   *map, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), radius));
@@ -41,7 +40,7 @@
 	do
 		if (Widelands::Bob* const bob = mr.location().field->get_first_bob()) {
 			args->old_bob_type.push_back(&bob->descr());
-			bob->remove(egbase);
+			bob->remove(eia.egbase());
 		} else {
 			args->old_bob_type.push_back(nullptr);
 		}
@@ -50,13 +49,13 @@
 }
 
 int32_t EditorDeleteCritterTool::handle_undo_impl(
-   const Widelands::World& world,
+   const Widelands::EditorGameBase& egbase,
    const Widelands::NodeAndTriangle<Widelands::Coords>& center,
    EditorInteractive& parent,
    EditorActionArgs* args,
    Widelands::Map* map) {
 
-	uint32_t ret = parent.tools()->place_critter.handle_undo_impl(world, center, parent, args, map);
+	uint32_t ret = parent.tools()->place_critter.handle_undo_impl(egbase, center, parent, args, map);
 	args->old_bob_type.clear();
 	return ret;
 }

=== modified file 'src/editor/tools/delete_critter_tool.h'
--- src/editor/tools/delete_critter_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/delete_critter_tool.h	2019-08-23 08:59:39 +0000
@@ -27,13 +27,13 @@
 	EditorDeleteCritterTool() : EditorTool(*this, *this) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/delete_immovable_tool.cc'
--- src/editor/tools/delete_immovable_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/delete_immovable_tool.cc	2019-08-23 08:59:39 +0000
@@ -28,18 +28,17 @@
 /**
  * Deletes the immovable at the given location
  */
-int32_t EditorDeleteImmovableTool::handle_click_impl(const Widelands::World&,
+int32_t EditorDeleteImmovableTool::handle_click_impl(const Widelands::EditorGameBase&,
                                                      const Widelands::NodeAndTriangle<>& center,
-                                                     EditorInteractive& parent,
+                                                     EditorInteractive& eia,
                                                      EditorActionArgs* args,
                                                      Widelands::Map* map) {
-	Widelands::EditorGameBase& egbase = parent.egbase();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 	   *map, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius));
 	do
 		if (upcast(Widelands::Immovable, immovable, mr.location().field->get_immovable())) {
 			args->old_immovable_types.push_back(immovable->descr().name());
-			immovable->remove(egbase);  //  Delete no buildings or stuff.
+			immovable->remove(eia.egbase());  //  Delete no buildings or stuff.
 		} else {
 			args->old_immovable_types.push_back("");
 		}
@@ -48,12 +47,12 @@
 }
 
 int32_t EditorDeleteImmovableTool::handle_undo_impl(
-   const Widelands::World& world,
+   const Widelands::EditorGameBase& egbase,
    const Widelands::NodeAndTriangle<Widelands::Coords>& center,
    EditorInteractive& parent,
    EditorActionArgs* args,
    Widelands::Map* map) {
-	return parent.tools()->place_immovable.handle_undo_impl(world, center, parent, args, map);
+	return parent.tools()->place_immovable.handle_undo_impl(egbase, center, parent, args, map);
 }
 
 EditorActionArgs EditorDeleteImmovableTool::format_args_impl(EditorInteractive& parent) {

=== modified file 'src/editor/tools/delete_immovable_tool.h'
--- src/editor/tools/delete_immovable_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/delete_immovable_tool.h	2019-08-23 08:59:39 +0000
@@ -27,13 +27,13 @@
 	EditorDeleteImmovableTool() : EditorTool(*this, *this) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/draw_tool.cc'
--- src/editor/tools/draw_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/draw_tool.cc	2019-08-23 08:59:39 +0000
@@ -30,7 +30,7 @@
 }
 
 int32_t
-EditorDrawTool::handle_click_impl(const Widelands::World& world,
+EditorDrawTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                   const Widelands::NodeAndTriangle<Widelands::Coords>& /* center */,
                                   EditorInteractive& /* parent */,
                                   EditorActionArgs* args,
@@ -38,21 +38,21 @@
 
 	for (std::list<EditorToolAction*>::iterator i = args->draw_actions.begin();
 	     i != args->draw_actions.end(); ++i) {
-		(*i)->tool.handle_click(static_cast<EditorTool::ToolIndex>((*i)->i), world, (*i)->center,
+		(*i)->tool.handle_click(static_cast<EditorTool::ToolIndex>((*i)->i), egbase, (*i)->center,
 		                        (*i)->parent, (*i)->args, &((*i)->map));
 	}
 	return args->draw_actions.size();
 }
 
 int32_t
-EditorDrawTool::handle_undo_impl(const Widelands::World& world,
+EditorDrawTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                  const Widelands::NodeAndTriangle<Widelands::Coords>& /* center */,
                                  EditorInteractive& /* parent */,
                                  EditorActionArgs* args,
                                  Widelands::Map* /* map */) {
 	for (std::list<EditorToolAction*>::reverse_iterator i = args->draw_actions.rbegin();
 	     i != args->draw_actions.rend(); ++i) {
-		(*i)->tool.handle_undo(static_cast<EditorTool::ToolIndex>((*i)->i), world, (*i)->center,
+		(*i)->tool.handle_undo(static_cast<EditorTool::ToolIndex>((*i)->i), egbase, (*i)->center,
 		                       (*i)->parent, (*i)->args, &((*i)->map));
 	}
 	return args->draw_actions.size();

=== modified file 'src/editor/tools/draw_tool.h'
--- src/editor/tools/draw_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/draw_tool.h	2019-08-23 08:59:39 +0000
@@ -29,13 +29,13 @@
 	EditorDrawTool() : EditorTool(*this, *this) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/history.cc'
--- src/editor/tools/history.cc	2019-04-03 13:22:14 +0000
+++ src/editor/tools/history.cc	2019-08-23 08:59:39 +0000
@@ -57,7 +57,7 @@
 
 // === EditorHistory === //
 
-uint32_t EditorHistory::undo_action(const Widelands::World& world) {
+uint32_t EditorHistory::undo_action(const Widelands::EditorGameBase& egbase) {
 	if (undo_stack_.empty())
 		return 0;
 
@@ -68,11 +68,11 @@
 	undo_button_.set_enabled(!undo_stack_.empty());
 	redo_button_.set_enabled(true);
 
-	return uac.tool.handle_undo(static_cast<EditorTool::ToolIndex>(uac.i), world, uac.center,
+	return uac.tool.handle_undo(static_cast<EditorTool::ToolIndex>(uac.i), egbase, uac.center,
 	                            uac.parent, uac.args, &(uac.map));
 }
 
-uint32_t EditorHistory::redo_action(const Widelands::World& world) {
+uint32_t EditorHistory::redo_action(const Widelands::EditorGameBase& egbase) {
 	if (redo_stack_.empty())
 		return 0;
 
@@ -83,14 +83,14 @@
 	undo_button_.set_enabled(true);
 	redo_button_.set_enabled(!redo_stack_.empty());
 
-	return rac.tool.handle_click(static_cast<EditorTool::ToolIndex>(rac.i), world, rac.center,
+	return rac.tool.handle_click(static_cast<EditorTool::ToolIndex>(rac.i), egbase, rac.center,
 	                             rac.parent, rac.args, &(rac.map));
 }
 
 uint32_t EditorHistory::do_action(EditorTool& tool,
                                   EditorTool::ToolIndex ind,
                                   Widelands::Map& map,
-                                  const Widelands::World& world,
+                                  const Widelands::EditorGameBase& egbase,
                                   const Widelands::NodeAndTriangle<Widelands::Coords>& center,
                                   EditorInteractive& parent,
                                   bool draw) {
@@ -125,5 +125,5 @@
 			}
 		}
 	}
-	return tool.handle_click(ind, world, center, parent, ac.args, &map);
+	return tool.handle_click(ind, egbase, center, parent, ac.args, &map);
 }

=== modified file 'src/editor/tools/history.h'
--- src/editor/tools/history.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/history.h	2019-08-23 08:59:39 +0000
@@ -42,12 +42,12 @@
 	uint32_t do_action(EditorTool& tool,
 	                   EditorTool::ToolIndex ind,
 	                   Widelands::Map& map,
-	                   const Widelands::World& world,
+	                   const Widelands::EditorGameBase& egbase,
 	                   const Widelands::NodeAndTriangle<>& center,
 	                   EditorInteractive& parent,
 	                   bool draw = false);
-	uint32_t undo_action(const Widelands::World& world);
-	uint32_t redo_action(const Widelands::World& world);
+	uint32_t undo_action(const Widelands::EditorGameBase&);
+	uint32_t redo_action(const Widelands::EditorGameBase&);
 
 private:
 	UI::Button& undo_button_;

=== modified file 'src/editor/tools/increase_height_tool.cc'
--- src/editor/tools/increase_height_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/increase_height_tool.cc	2019-08-23 08:59:39 +0000
@@ -24,9 +24,9 @@
 #include "logic/mapregion.h"
 
 /// Increases the heights by a value. Changes surrounding nodes if necessary.
-int32_t EditorIncreaseHeightTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorIncreaseHeightTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                     const Widelands::NodeAndTriangle<>& center,
-                                                    EditorInteractive& /* parent */,
+                                                    EditorInteractive&,
                                                     EditorActionArgs* args,
                                                     Widelands::Map* map) {
 	if (args->original_heights.empty()) {
@@ -40,16 +40,16 @@
 	}
 
 	return map->change_height(
-	   world, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius),
+	   egbase, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius),
 	   args->change_by);
 }
 
-int32_t EditorIncreaseHeightTool::handle_undo_impl(const Widelands::World& world,
+int32_t EditorIncreaseHeightTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                                    const Widelands::NodeAndTriangle<>& center,
                                                    EditorInteractive& parent,
                                                    EditorActionArgs* args,
                                                    Widelands::Map* map) {
-	return decrease_tool_.handle_undo_impl(world, center, parent, args, map);
+	return decrease_tool_.handle_undo_impl(egbase, center, parent, args, map);
 }
 
 EditorActionArgs EditorIncreaseHeightTool::format_args_impl(EditorInteractive& parent) {

=== modified file 'src/editor/tools/increase_height_tool.h'
--- src/editor/tools/increase_height_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/increase_height_tool.h	2019-08-23 08:59:39 +0000
@@ -33,13 +33,13 @@
 	     change_by_(1) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/increase_resources_tool.cc'
--- src/editor/tools/increase_resources_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/increase_resources_tool.cc	2019-08-23 08:59:39 +0000
@@ -23,13 +23,14 @@
 #include "logic/field.h"
 #include "logic/map_objects/world/resource_description.h"
 #include "logic/map_objects/world/terrain_description.h"
+#include "logic/map_objects/world/world.h"
 #include "logic/mapregion.h"
 
 using Widelands::TCoords;
 
-int32_t EditorIncreaseResourcesTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorIncreaseResourcesTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                        const Widelands::NodeAndTriangle<>& center,
-                                                       EditorInteractive& /* parent */,
+                                                       EditorInteractive&,
                                                        EditorActionArgs* args,
                                                        Widelands::Map* map) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
@@ -38,7 +39,7 @@
 		Widelands::ResourceAmount amount = mr.location().field->get_resources_amount();
 		Widelands::ResourceAmount max_amount =
 		   args->current_resource != Widelands::kNoResource ?
-		      world.get_resource(args->current_resource)->max_amount() :
+		      egbase.world().get_resource(args->current_resource)->max_amount() :
 		      0;
 
 		amount += args->change_by;
@@ -47,7 +48,7 @@
 
 		if ((mr.location().field->get_resources() == args->current_resource ||
 		     !mr.location().field->get_resources_amount()) &&
-		    map->is_resource_valid(world, mr.location(), args->current_resource) &&
+		    map->is_resource_valid(egbase, mr.location(), args->current_resource) &&
 		    mr.location().field->get_resources_amount() != max_amount) {
 
 			args->original_resource.push_back(
@@ -61,12 +62,12 @@
 }
 
 int32_t EditorIncreaseResourcesTool::handle_undo_impl(
-   const Widelands::World& world,
+   const Widelands::EditorGameBase& egbase,
    const Widelands::NodeAndTriangle<Widelands::Coords>& center,
    EditorInteractive& parent,
    EditorActionArgs* args,
    Widelands::Map* map) {
-	return set_tool_.handle_undo_impl(world, center, parent, args, map);
+	return set_tool_.handle_undo_impl(egbase, center, parent, args, map);
 }
 
 EditorActionArgs EditorIncreaseResourcesTool::format_args_impl(EditorInteractive& parent) {

=== modified file 'src/editor/tools/increase_resources_tool.h'
--- src/editor/tools/increase_resources_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/increase_resources_tool.h	2019-08-23 08:59:39 +0000
@@ -39,13 +39,13 @@
 	 * Increase the resources of the current field by one if there is not already
 	 * another resource there.
 	 */
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/info_tool.cc'
--- src/editor/tools/info_tool.cc	2019-05-26 17:21:15 +0000
+++ src/editor/tools/info_tool.cc	2019-08-23 08:59:39 +0000
@@ -29,11 +29,12 @@
 #include "graphic/text_layout.h"
 #include "logic/map_objects/world/editor_category.h"
 #include "logic/map_objects/world/terrain_description.h"
+#include "logic/map_objects/world/world.h"
 #include "ui_basic/multilinetextarea.h"
 #include "ui_basic/window.h"
 
 /// Show a window with information about the pointed at node and triangle.
-int32_t EditorInfoTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorInfoTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                           const Widelands::NodeAndTriangle<>& center,
                                           EditorInteractive& parent,
                                           EditorActionArgs* /* args */,
@@ -116,7 +117,7 @@
 	buf += as_heading(_("Terrain"), UI::PanelStyle::kWui);
 
 	const Widelands::Field& tf = (*map)[center.triangle.node];
-	const Widelands::TerrainDescription& ter = world.terrain_descr(
+	const Widelands::TerrainDescription& ter = egbase.world().terrain_descr(
 	   center.triangle.t == Widelands::TriangleIndex::D ? tf.terrain_d() : tf.terrain_r());
 
 	buf += as_listitem(
@@ -202,7 +203,7 @@
 		buf += as_heading(_("Resources"), UI::PanelStyle::kWui);
 		buf += as_listitem(
 		   (boost::format(pgettext("resources", "%1%x %2%")) % static_cast<unsigned int>(ramount) %
-		    world.get_resource(f.get_resources())->descname())
+		    egbase.world().get_resource(f.get_resources())->descname())
 		      .str(),
 		   font_style);
 	}

=== modified file 'src/editor/tools/info_tool.h'
--- src/editor/tools/info_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/info_tool.h	2019-08-23 08:59:39 +0000
@@ -27,7 +27,7 @@
 	EditorInfoTool() : EditorTool(*this, *this, false) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,

=== modified file 'src/editor/tools/noise_height_tool.cc'
--- src/editor/tools/noise_height_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/noise_height_tool.cc	2019-08-23 08:59:39 +0000
@@ -27,9 +27,9 @@
 #include "logic/mapregion.h"
 
 /// Sets the heights to random values. Changes surrounding nodes if necessary.
-int32_t EditorNoiseHeightTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorNoiseHeightTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                  const Widelands::NodeAndTriangle<>& center,
-                                                 EditorInteractive& /* parent */,
+                                                 EditorInteractive&,
                                                  EditorActionArgs* args,
                                                  Widelands::Map* map) {
 	if (args->original_heights.empty()) {
@@ -48,7 +48,7 @@
 	   *map, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius));
 	do {
 		max = std::max(
-		   max, map->set_height(world, mr.location(),
+		   max, map->set_height(egbase, mr.location(),
 		                        args->interval.min +
 		                           static_cast<int32_t>(static_cast<double>(args->interval.max -
 		                                                                    args->interval.min + 1) *
@@ -58,12 +58,12 @@
 }
 
 int32_t
-EditorNoiseHeightTool::handle_undo_impl(const Widelands::World& world,
+EditorNoiseHeightTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                         const Widelands::NodeAndTriangle<Widelands::Coords>& center,
                                         EditorInteractive& parent,
                                         EditorActionArgs* args,
                                         Widelands::Map* map) {
-	return set_tool_.handle_undo_impl(world, center, parent, args, map);
+	return set_tool_.handle_undo_impl(egbase, center, parent, args, map);
 }
 
 EditorActionArgs EditorNoiseHeightTool::format_args_impl(EditorInteractive& parent) {

=== modified file 'src/editor/tools/noise_height_tool.h'
--- src/editor/tools/noise_height_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/noise_height_tool.h	2019-08-23 08:59:39 +0000
@@ -30,13 +30,13 @@
 	   : EditorTool(the_set_tool, the_set_tool), set_tool_(the_set_tool), interval_(the_interval) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/place_critter_tool.cc'
--- src/editor/tools/place_critter_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/place_critter_tool.cc	2019-08-23 08:59:39 +0000
@@ -24,18 +24,19 @@
 #include "logic/field.h"
 #include "logic/map_objects/bob.h"
 #include "logic/map_objects/world/critter.h"
+#include "logic/map_objects/world/world.h"
 #include "logic/mapregion.h"
 
 /**
  * Choses an object to place randomly from all enabled
  * and places this on the current field
  */
-int32_t EditorPlaceCritterTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorPlaceCritterTool::handle_click_impl(const Widelands::EditorGameBase&,
                                                   const Widelands::NodeAndTriangle<>& center,
-                                                  EditorInteractive& parent,
+                                                  EditorInteractive& eia,
                                                   EditorActionArgs* args,
                                                   Widelands::Map* map) {
-
+	Widelands::EditorGameBase& egbase = eia.egbase();
 	if (get_nr_enabled() && args->old_bob_type.empty()) {
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 		   *map,
@@ -44,12 +45,11 @@
 			Widelands::Bob* const mbob = mr.location().field->get_first_bob();
 			args->old_bob_type.push_back((mbob ? &mbob->descr() : nullptr));
 			args->new_bob_type.push_back(dynamic_cast<const Widelands::BobDescr*>(
-			   world.get_critter_descr(get_random_enabled())));
+			   egbase.world().get_critter_descr(get_random_enabled())));
 		} while (mr.advance(*map));
 	}
 
 	if (!args->new_bob_type.empty()) {
-		Widelands::EditorGameBase& egbase = parent.egbase();
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 		   *map,
 		   Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius));
@@ -69,13 +69,13 @@
 }
 
 int32_t EditorPlaceCritterTool::handle_undo_impl(
-   const Widelands::World&,
+   const Widelands::EditorGameBase&,
    const Widelands::NodeAndTriangle<Widelands::Coords>& center,
-   EditorInteractive& parent,
+   EditorInteractive& eia,
    EditorActionArgs* args,
    Widelands::Map* map) {
+	Widelands::EditorGameBase& egbase = eia.egbase();
 	if (!args->new_bob_type.empty()) {
-		Widelands::EditorGameBase& egbase = parent.egbase();
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 		   *map,
 		   Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius));

=== modified file 'src/editor/tools/place_critter_tool.h'
--- src/editor/tools/place_critter_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/place_critter_tool.h	2019-08-23 08:59:39 +0000
@@ -28,13 +28,13 @@
 	explicit EditorPlaceCritterTool(EditorDeleteCritterTool& tool) : EditorTool(tool, tool) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/place_immovable_tool.cc'
--- src/editor/tools/place_immovable_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/place_immovable_tool.cc	2019-08-23 08:59:39 +0000
@@ -32,15 +32,15 @@
  * Choses an object to place randomly from all enabled
  * and places this on the current field
  */
-int32_t EditorPlaceImmovableTool::handle_click_impl(const Widelands::World&,
+int32_t EditorPlaceImmovableTool::handle_click_impl(const Widelands::EditorGameBase&,
                                                     const Widelands::NodeAndTriangle<>& center,
-                                                    EditorInteractive& parent,
+                                                    EditorInteractive& eia,
                                                     EditorActionArgs* args,
                                                     Widelands::Map* map) {
 	const int32_t radius = args->sel_radius;
 	if (!get_nr_enabled())
 		return radius;
-	Widelands::EditorGameBase& egbase = parent.egbase();
+	Widelands::EditorGameBase& egbase = eia.egbase();
 	if (args->old_immovable_types.empty()) {
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 		   *map, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), radius));
@@ -67,16 +67,16 @@
 }
 
 int32_t EditorPlaceImmovableTool::handle_undo_impl(
-   const Widelands::World&,
+   const Widelands::EditorGameBase&,
    const Widelands::NodeAndTriangle<Widelands::Coords>& center,
-   EditorInteractive& parent,
+   EditorInteractive& eia,
    EditorActionArgs* args,
    Widelands::Map* map) {
 	const int32_t radius = args->sel_radius;
 	if (args->old_immovable_types.empty())
 		return radius;
 
-	Widelands::EditorGameBase& egbase = parent.egbase();
+	Widelands::EditorGameBase& egbase = eia.egbase();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 	   *map, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), radius));
 	std::list<std::string>::iterator i = args->old_immovable_types.begin();

=== modified file 'src/editor/tools/place_immovable_tool.h'
--- src/editor/tools/place_immovable_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/place_immovable_tool.h	2019-08-23 08:59:39 +0000
@@ -30,13 +30,13 @@
 	explicit EditorPlaceImmovableTool(EditorDeleteImmovableTool& tool) : EditorTool(tool, tool) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/resize_tool.cc'
--- src/editor/tools/resize_tool.cc	2019-04-24 07:09:29 +0000
+++ src/editor/tools/resize_tool.cc	2019-08-23 08:59:39 +0000
@@ -23,13 +23,12 @@
 #include "logic/field.h"
 #include "logic/widelands_geometry.h"
 
-int32_t EditorResizeTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorResizeTool::handle_click_impl(const Widelands::EditorGameBase&,
                                             const Widelands::NodeAndTriangle<>& center,
-                                            EditorInteractive& parent,
+                                            EditorInteractive& eia,
                                             EditorActionArgs* args,
                                             Widelands::Map* map) {
-	Widelands::EditorGameBase& egbase = parent.egbase();
-
+	Widelands::EditorGameBase& egbase = eia.egbase();
 	args->resized.old_map_size = map->extent();
 	args->resized.port_spaces.clear();
 	args->resized.starting_positions.clear();
@@ -43,18 +42,17 @@
 	args->resized.deleted_fields =
 	   map->resize(egbase, center.node, args->new_map_size.w, args->new_map_size.h);
 
-	map->recalc_whole_map(world);
+	map->recalc_whole_map(egbase);
 	return 0;
 }
 
 int32_t
-EditorResizeTool::handle_undo_impl(const Widelands::World& world,
+EditorResizeTool::handle_undo_impl(const Widelands::EditorGameBase&,
                                    const Widelands::NodeAndTriangle<Widelands::Coords>& center,
-                                   EditorInteractive& parent,
+                                   EditorInteractive& eia,
                                    EditorActionArgs* args,
                                    Widelands::Map* map) {
-	Widelands::EditorGameBase& egbase = parent.egbase();
-
+	Widelands::EditorGameBase& egbase = eia.egbase();
 	map->resize(egbase, center.node, args->resized.old_map_size.w, args->resized.old_map_size.h);
 
 	for (const auto& it : args->resized.deleted_fields) {
@@ -82,13 +80,13 @@
 	}
 
 	for (const Widelands::Coords& c : args->resized.port_spaces) {
-		map->set_port_space(world, c, true, true);
+		map->set_port_space(egbase, c, true, true);
 	}
 	for (uint8_t i = 1; i <= map->get_nrplayers(); ++i) {
 		map->set_starting_pos(i, args->resized.starting_positions[i - 1]);
 	}
 
-	map->recalc_whole_map(world);
+	map->recalc_whole_map(egbase);
 	return 0;
 }
 

=== modified file 'src/editor/tools/resize_tool.h'
--- src/editor/tools/resize_tool.h	2019-04-24 07:09:29 +0000
+++ src/editor/tools/resize_tool.h	2019-08-23 08:59:39 +0000
@@ -31,13 +31,13 @@
 	/**
 	 * Change the map size
 	 */
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/set_height_tool.cc'
--- src/editor/tools/set_height_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_height_tool.cc	2019-08-23 08:59:39 +0000
@@ -25,9 +25,9 @@
 #include "logic/field.h"
 #include "logic/mapregion.h"
 
-int32_t EditorSetHeightTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorSetHeightTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                const Widelands::NodeAndTriangle<>& center,
-                                               EditorInteractive& /* parent */,
+                                               EditorInteractive&,
                                                EditorActionArgs* args,
                                                Widelands::Map* map) {
 	if (args->original_heights.empty()) {
@@ -40,14 +40,14 @@
 		while (mr.advance(*map));
 	}
 	return map->set_height(
-	   world, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius),
+	   egbase, Widelands::Area<Widelands::FCoords>(map->get_fcoords(center.node), args->sel_radius),
 	   args->interval);
 }
 
 int32_t
-EditorSetHeightTool::handle_undo_impl(const Widelands::World& world,
+EditorSetHeightTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                       const Widelands::NodeAndTriangle<Widelands::Coords>& center,
-                                      EditorInteractive& /* parent */,
+                                      EditorInteractive&,
                                       EditorActionArgs* args,
                                       Widelands::Map* map) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
@@ -63,7 +63,7 @@
 	} while (mr.advance(*map));
 
 	map->recalc_for_field_area(
-	   world, Widelands::Area<Widelands::FCoords>(
+	   egbase, Widelands::Area<Widelands::FCoords>(
 	             map->get_fcoords(center.node),
 	             args->sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 2));
 

=== modified file 'src/editor/tools/set_height_tool.h'
--- src/editor/tools/set_height_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_height_tool.h	2019-08-23 08:59:39 +0000
@@ -29,13 +29,13 @@
 	EditorSetHeightTool() : EditorTool(*this, *this), interval_(10, 10) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/set_origin_tool.cc'
--- src/editor/tools/set_origin_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_origin_tool.cc	2019-08-23 08:59:39 +0000
@@ -22,7 +22,7 @@
 #include "editor/editorinteractive.h"
 #include "wui/mapviewpixelconstants.h"
 
-int32_t EditorSetOriginTool::handle_click_impl(const Widelands::World&,
+int32_t EditorSetOriginTool::handle_click_impl(const Widelands::EditorGameBase&,
                                                const Widelands::NodeAndTriangle<>& center,
                                                EditorInteractive& eia,
                                                EditorActionArgs* /* args */,
@@ -34,7 +34,7 @@
 }
 
 int32_t
-EditorSetOriginTool::handle_undo_impl(const Widelands::World&,
+EditorSetOriginTool::handle_undo_impl(const Widelands::EditorGameBase&,
                                       const Widelands::NodeAndTriangle<Widelands::Coords>& center,
                                       EditorInteractive& eia,
                                       EditorActionArgs* /* args */,

=== modified file 'src/editor/tools/set_origin_tool.h'
--- src/editor/tools/set_origin_tool.h	2019-02-27 19:00:36 +0000
+++ src/editor/tools/set_origin_tool.h	2019-08-23 08:59:39 +0000
@@ -27,13 +27,13 @@
 	EditorSetOriginTool() : EditorTool(*this, *this) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& eia,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/set_port_space_tool.cc'
--- src/editor/tools/set_port_space_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_port_space_tool.cc	2019-08-23 08:59:39 +0000
@@ -47,7 +47,7 @@
 EditorUnsetPortSpaceTool::EditorUnsetPortSpaceTool() : EditorTool(*this, *this) {
 }
 
-int32_t EditorSetPortSpaceTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorSetPortSpaceTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                   const Widelands::NodeAndTriangle<>& center,
                                                   EditorInteractive&,
                                                   EditorActionArgs* args,
@@ -64,9 +64,9 @@
 	do {
 		//  check if field is valid
 		if (port_tool_nodecaps(mr.location(), *map) != NodeCaps::CAPS_NONE) {
-			map->set_port_space(world, mr.location(), true);
+			map->set_port_space(egbase, mr.location(), true);
 			Area<FCoords> a(mr.location(), 0);
-			map->recalc_for_field_area(world, a);
+			map->recalc_for_field_area(egbase, a);
 			++nr;
 		}
 	} while (mr.advance(*map));
@@ -80,17 +80,17 @@
 	return port_tool_nodecaps(fcoords, egbase.map());
 }
 
-int32_t EditorSetPortSpaceTool::handle_undo_impl(const Widelands::World& world,
+int32_t EditorSetPortSpaceTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                                  const NodeAndTriangle<Coords>& center,
                                                  EditorInteractive& parent,
                                                  EditorActionArgs* args,
                                                  Map* map) {
-	return parent.tools()->unset_port_space.handle_click_impl(world, center, parent, args, map);
+	return parent.tools()->unset_port_space.handle_click_impl(egbase, center, parent, args, map);
 }
 
-int32_t EditorUnsetPortSpaceTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorUnsetPortSpaceTool::handle_click_impl(const Widelands::EditorGameBase&,
                                                     const Widelands::NodeAndTriangle<>& center,
-                                                    EditorInteractive&,
+                                                    EditorInteractive& eia,
                                                     EditorActionArgs* args,
                                                     Map* map) {
 	assert(0 <= center.node.x);
@@ -105,9 +105,9 @@
 	do {
 		//  check if field is valid
 		if (port_tool_nodecaps(mr.location(), *map)) {
-			map->set_port_space(world, mr.location(), false);
+			map->set_port_space(eia.egbase(), mr.location(), false);
 			Area<FCoords> a(mr.location(), 0);
-			map->recalc_for_field_area(world, a);
+			map->recalc_for_field_area(eia.egbase(), a);
 			++nr;
 		}
 	} while (mr.advance(*map));
@@ -115,12 +115,12 @@
 	return nr;
 }
 
-int32_t EditorUnsetPortSpaceTool::handle_undo_impl(const Widelands::World& world,
+int32_t EditorUnsetPortSpaceTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                                    const NodeAndTriangle<Coords>& center,
                                                    EditorInteractive& parent,
                                                    EditorActionArgs* args,
                                                    Map* map) {
-	return parent.tools()->set_port_space.handle_click_impl(world, center, parent, args, map);
+	return parent.tools()->set_port_space.handle_click_impl(egbase, center, parent, args, map);
 }
 
 Widelands::NodeCaps

=== modified file 'src/editor/tools/set_port_space_tool.h'
--- src/editor/tools/set_port_space_tool.h	2019-02-27 19:00:36 +0000
+++ src/editor/tools/set_port_space_tool.h	2019-08-23 08:59:39 +0000
@@ -30,13 +30,13 @@
 public:
 	explicit EditorUnsetPortSpaceTool();
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,
@@ -54,13 +54,13 @@
 public:
 	explicit EditorSetPortSpaceTool(EditorUnsetPortSpaceTool&);
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/set_resources_tool.cc'
--- src/editor/tools/set_resources_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_resources_tool.cc	2019-08-23 08:59:39 +0000
@@ -24,11 +24,12 @@
 #include "editor/tools/increase_resources_tool.h"
 #include "logic/field.h"
 #include "logic/map_objects/world/resource_description.h"
+#include "logic/map_objects/world/world.h"
 #include "logic/mapregion.h"
 
-int32_t EditorSetResourcesTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorSetResourcesTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                   const Widelands::NodeAndTriangle<>& center,
-                                                  EditorInteractive& /* parent */,
+                                                  EditorInteractive&,
                                                   EditorActionArgs* args,
                                                   Widelands::Map* map) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
@@ -37,13 +38,13 @@
 		Widelands::ResourceAmount amount = args->set_to;
 		Widelands::ResourceAmount max_amount =
 		   args->current_resource != Widelands::kNoResource ?
-		      world.get_resource(args->current_resource)->max_amount() :
+		      egbase.world().get_resource(args->current_resource)->max_amount() :
 		      0;
 
 		if (amount > max_amount)
 			amount = max_amount;
 
-		if (map->is_resource_valid(world, mr.location(), args->current_resource)) {
+		if (map->is_resource_valid(egbase, mr.location(), args->current_resource)) {
 
 			args->original_resource.push_back(
 			   EditorActionArgs::ResourceState{mr.location(), mr.location().field->get_resources(),
@@ -56,7 +57,7 @@
 }
 
 int32_t EditorSetResourcesTool::handle_undo_impl(
-   const Widelands::World& world,
+   const Widelands::EditorGameBase& egbase,
    const Widelands::NodeAndTriangle<Widelands::Coords>& /* center */,
    EditorInteractive& /* parent */,
    EditorActionArgs* args,
@@ -64,7 +65,7 @@
 	for (const auto& res : args->original_resource) {
 		Widelands::ResourceAmount amount = res.amount;
 		Widelands::ResourceAmount max_amount =
-		   world.get_resource(args->current_resource)->max_amount();
+		   egbase.world().get_resource(args->current_resource)->max_amount();
 
 		if (amount > max_amount)
 			amount = max_amount;
@@ -86,7 +87,7 @@
 Widelands::NodeCaps resource_tools_nodecaps(const Widelands::FCoords& fcoords,
                                             const Widelands::EditorGameBase& egbase,
                                             Widelands::DescriptionIndex resource) {
-	if (egbase.map().is_resource_valid(egbase.world(), fcoords, resource)) {
+	if (egbase.map().is_resource_valid(egbase, fcoords, resource)) {
 		return fcoords.field->nodecaps();
 	}
 	return Widelands::NodeCaps::CAPS_NONE;

=== modified file 'src/editor/tools/set_resources_tool.h'
--- src/editor/tools/set_resources_tool.h	2019-02-27 19:00:36 +0000
+++ src/editor/tools/set_resources_tool.h	2019-08-23 08:59:39 +0000
@@ -35,13 +35,13 @@
 	/**
 	 * Sets the resources of the current to a fixed value
 	 */
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/set_starting_pos_tool.cc'
--- src/editor/tools/set_starting_pos_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_starting_pos_tool.cc	2019-08-23 08:59:39 +0000
@@ -59,7 +59,7 @@
 	current_player_ = 1;
 }
 
-int32_t EditorSetStartingPosTool::handle_click_impl(const Widelands::World&,
+int32_t EditorSetStartingPosTool::handle_click_impl(const Widelands::EditorGameBase&,
                                                     const Widelands::NodeAndTriangle<>& center,
                                                     EditorInteractive&,
                                                     EditorActionArgs*,

=== modified file 'src/editor/tools/set_starting_pos_tool.h'
--- src/editor/tools/set_starting_pos_tool.h	2019-02-27 19:00:36 +0000
+++ src/editor/tools/set_starting_pos_tool.h	2019-08-23 08:59:39 +0000
@@ -33,7 +33,7 @@
 struct EditorSetStartingPosTool : public EditorTool {
 	EditorSetStartingPosTool();
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>&,
 	                          EditorInteractive&,
 	                          EditorActionArgs*,

=== modified file 'src/editor/tools/set_terrain_tool.cc'
--- src/editor/tools/set_terrain_tool.cc	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_terrain_tool.cc	2019-08-23 08:59:39 +0000
@@ -24,7 +24,7 @@
 
 using Widelands::TCoords;
 
-int32_t EditorSetTerrainTool::handle_click_impl(const Widelands::World& world,
+int32_t EditorSetTerrainTool::handle_click_impl(const Widelands::EditorGameBase& egbase,
                                                 const Widelands::NodeAndTriangle<>& center,
                                                 EditorInteractive& /* parent */,
                                                 EditorActionArgs* args,
@@ -56,7 +56,7 @@
 		            radius));
 		std::list<Widelands::DescriptionIndex>::iterator i = args->terrain_type.begin();
 		do {
-			max = std::max(max, map->change_terrain(world, mr.location(), *i));
+			max = std::max(max, map->change_terrain(egbase, mr.location(), *i));
 			++i;
 		} while (mr.advance(*map));
 	}
@@ -64,7 +64,7 @@
 }
 
 int32_t
-EditorSetTerrainTool::handle_undo_impl(const Widelands::World& world,
+EditorSetTerrainTool::handle_undo_impl(const Widelands::EditorGameBase& egbase,
                                        const Widelands::NodeAndTriangle<Widelands::Coords>& center,
                                        EditorInteractive& /* parent */,
                                        EditorActionArgs* args,
@@ -82,7 +82,7 @@
 
 		std::list<Widelands::DescriptionIndex>::iterator i = args->original_terrain_type.begin();
 		do {
-			max = std::max(max, map->change_terrain(world, mr.location(), *i));
+			max = std::max(max, map->change_terrain(egbase, mr.location(), *i));
 			++i;
 		} while (mr.advance(*map));
 		return radius + max;

=== modified file 'src/editor/tools/set_terrain_tool.h'
--- src/editor/tools/set_terrain_tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/set_terrain_tool.h	2019-08-23 08:59:39 +0000
@@ -27,13 +27,13 @@
 	EditorSetTerrainTool() : EditorTool(*this, *this) {
 	}
 
-	int32_t handle_click_impl(const Widelands::World& world,
+	int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                          const Widelands::NodeAndTriangle<>& center,
 	                          EditorInteractive& parent,
 	                          EditorActionArgs* args,
 	                          Widelands::Map* map) override;
 
-	int32_t handle_undo_impl(const Widelands::World& world,
+	int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                         const Widelands::NodeAndTriangle<>& center,
 	                         EditorInteractive& parent,
 	                         EditorActionArgs* args,

=== modified file 'src/editor/tools/tool.h'
--- src/editor/tools/tool.h	2019-02-23 11:00:49 +0000
+++ src/editor/tools/tool.h	2019-08-23 08:59:39 +0000
@@ -26,7 +26,6 @@
 #include "editor/tools/action_args.h"
 #include "graphic/image.h"
 #include "logic/editor_game_base.h"
-#include "logic/map_objects/world/world.h"
 #include "logic/widelands_geometry.h"
 
 class EditorInteractive;
@@ -47,23 +46,23 @@
 
 	enum ToolIndex { First, Second, Third };
 	int32_t handle_click(ToolIndex i,
-	                     const Widelands::World& world,
+	                     const Widelands::EditorGameBase& egbase,
 	                     const Widelands::NodeAndTriangle<>& center,
 	                     EditorInteractive& parent,
 	                     EditorActionArgs* args,
 	                     Widelands::Map* map) {
 		return (i == First ? *this : i == Second ? second_ : third_)
-		   .handle_click_impl(world, center, parent, args, map);
+		   .handle_click_impl(egbase, center, parent, args, map);
 	}
 
 	int32_t handle_undo(ToolIndex i,
-	                    const Widelands::World& world,
+	                    const Widelands::EditorGameBase& egbase,
 	                    const Widelands::NodeAndTriangle<>& center,
 	                    EditorInteractive& parent,
 	                    EditorActionArgs* args,
 	                    Widelands::Map* map) {
 		return (i == First ? *this : i == Second ? second_ : third_)
-		   .handle_undo_impl(world, center, parent, args, map);
+		   .handle_undo_impl(egbase, center, parent, args, map);
 	}
 
 	const Image* get_sel(const ToolIndex i) {
@@ -83,12 +82,12 @@
 	virtual EditorActionArgs format_args_impl(EditorInteractive& parent) {
 		return EditorActionArgs(parent);
 	}
-	virtual int32_t handle_click_impl(const Widelands::World& world,
+	virtual int32_t handle_click_impl(const Widelands::EditorGameBase&,
 	                                  const Widelands::NodeAndTriangle<>&,
 	                                  EditorInteractive&,
 	                                  EditorActionArgs*,
 	                                  Widelands::Map*) = 0;
-	virtual int32_t handle_undo_impl(const Widelands::World&,
+	virtual int32_t handle_undo_impl(const Widelands::EditorGameBase&,
 	                                 const Widelands::NodeAndTriangle<>&,
 	                                 EditorInteractive&,
 	                                 EditorActionArgs*,

=== modified file 'src/editor/ui_menus/main_menu_new_map.cc'
--- src/editor/ui_menus/main_menu_new_map.cc	2019-06-25 08:03:30 +0000
+++ src/editor/ui_menus/main_menu_new_map.cc	2019-08-23 08:59:39 +0000
@@ -106,14 +106,14 @@
 	parent.cleanup_for_load();
 
 	map->create_empty_map(
-	   egbase.world(), map_size_box_.selected_width(), map_size_box_.selected_height(),
+	   egbase, map_size_box_.selected_width(), map_size_box_.selected_height(),
 	   list_.get_selected(), _("No Name"),
 	   g_options.pull_section("global").get_string("realname", pgettext("author_name", "Unknown")));
 
 	egbase.postload();
 	egbase.load_graphics(loader_ui);
 
-	map->recalc_whole_map(egbase.world());
+	map->recalc_whole_map(egbase);
 	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	2019-08-10 16:38:15 +0000
+++ src/editor/ui_menus/main_menu_random_map.cc	2019-08-23 08:59:39 +0000
@@ -485,7 +485,7 @@
 
 	MapGenerator gen(*map, map_info, egbase);
 	map->create_empty_map(
-	   egbase.world(), map_info.w, map_info.h, 0, _("No Name"),
+	   egbase, 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…"));
@@ -519,7 +519,7 @@
 	egbase.postload();
 	egbase.load_graphics(loader_ui);
 
-	map->recalc_whole_map(egbase.world());
+	map->recalc_whole_map(egbase);
 	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	2019-08-10 16:38:15 +0000
+++ src/editor/ui_menus/main_menu_save_map.cc	2019-08-23 08:59:39 +0000
@@ -314,7 +314,7 @@
 	Widelands::Map* map = egbase.mutable_map();
 
 	// Recompute seafaring tag
-	map->cleanup_port_spaces(egbase.world());
+	map->cleanup_port_spaces(egbase);
 	if (map->allows_seafaring()) {
 		map->add_tag("seafaring");
 	} else {

=== modified file 'src/logic/editor_game_base.cc'
--- src/logic/editor_game_base.cc	2019-06-23 11:41:17 +0000
+++ src/logic/editor_game_base.cc	2019-08-23 08:59:39 +0000
@@ -291,9 +291,11 @@
 		}
 	}
 
-	// Postload tribes
+	// Postload tribes and world
 	assert(tribes_);
 	tribes_->postload();
+	assert(world_);
+	world_->postload();
 
 	for (DescriptionIndex i = 0; i < tribes_->nrtribes(); i++) {
 		const TribeDescr* tribe = tribes_->get_tribe_descr(i);
@@ -333,7 +335,7 @@
 Building& EditorGameBase::warp_building(const Coords& c,
                                         PlayerNumber const owner,
                                         DescriptionIndex const idx,
-                                        Building::FormerBuildings former_buildings) {
+                                        FormerBuildings former_buildings) {
 	Player* plr = get_player(owner);
 	const TribeDescr& tribe = plr->tribe();
 	return tribe.get_building_descr(idx)->create(*this, plr, c, false, true, former_buildings);
@@ -350,7 +352,7 @@
                                                 PlayerNumber const owner,
                                                 DescriptionIndex idx,
                                                 bool loading,
-                                                Building::FormerBuildings former_buildings,
+                                                FormerBuildings former_buildings,
                                                 const BuildingSettings* settings) {
 	Player* plr = get_player(owner);
 	const TribeDescr& tribe = plr->tribe();
@@ -370,7 +372,7 @@
 Building& EditorGameBase::warp_dismantlesite(const Coords& c,
                                              PlayerNumber const owner,
                                              bool loading,
-                                             Building::FormerBuildings former_buildings) {
+                                             FormerBuildings former_buildings) {
 	Player* plr = get_player(owner);
 	const TribeDescr& tribe = plr->tribe();
 
@@ -646,7 +648,7 @@
 	//  This must reach two steps beyond the conquered area to adjust the borders
 	//  of neighbour players.
 	player_area.radius += 2;
-	map_.recalc_for_field_area(world(), player_area);
+	map_.recalc_for_field_area(*this, player_area);
 }
 
 /// Conquers the given area for that player; does the actual work.
@@ -721,7 +723,7 @@
 	// This must reach two steps beyond the conquered area to adjust the borders
 	// of neighbour players.
 	player_area.radius += 2;
-	map_.recalc_for_field_area(world(), player_area);
+	map_.recalc_for_field_area(*this, player_area);
 
 	//  Deal with player immovables in the lost area
 	//  Players are not allowed to have their immovables on their borders.
@@ -741,7 +743,7 @@
 	std::vector<PlayerImmovable*> burnlist;
 
 	//  find all immovables that need fixing
-	map_.find_immovables(area, &immovables, FindImmovablePlayerImmovable());
+	map_.find_immovables(*this, area, &immovables, FindImmovablePlayerImmovable());
 
 	for (const ImmovableFound& temp_imm : immovables) {
 		upcast(PlayerImmovable, imm, temp_imm.object);

=== modified file 'src/logic/editor_game_base.h'
--- src/logic/editor_game_base.h	2019-05-14 16:25:57 +0000
+++ src/logic/editor_game_base.h	2019-08-23 08:59:39 +0000
@@ -125,19 +125,19 @@
 	warp_building(const Coords&,
 	              PlayerNumber,
 	              DescriptionIndex,
-	              Building::FormerBuildings former_buildings = Building::FormerBuildings());
+	              FormerBuildings former_buildings = FormerBuildings());
 	Building&
 	warp_constructionsite(const Coords&,
 	                      PlayerNumber,
 	                      DescriptionIndex,
 	                      bool loading = false,
-	                      Building::FormerBuildings former_buildings = Building::FormerBuildings(),
+	                      FormerBuildings former_buildings = FormerBuildings(),
 	                      const BuildingSettings* settings = nullptr);
 	Building&
 	warp_dismantlesite(const Coords&,
 	                   PlayerNumber,
 	                   bool loading = false,
-	                   Building::FormerBuildings former_buildings = Building::FormerBuildings());
+	                   FormerBuildings former_buildings = FormerBuildings());
 	Bob& create_critter(const Coords&, DescriptionIndex bob_type_idx, Player* owner = nullptr);
 	Bob& create_critter(const Coords&, const std::string& name, Player* owner = nullptr);
 	Immovable&

=== modified file 'src/logic/game.cc'
--- src/logic/game.cc	2019-06-28 15:05:22 +0000
+++ src/logic/game.cc	2019-08-23 08:59:39 +0000
@@ -503,7 +503,7 @@
 		}
 
 		// Prepare the map, set default textures
-		mutable_map()->recalc_default_resources(world());
+		mutable_map()->recalc_default_resources(*this);
 
 		// Finally, set the scenario names and tribes to represent
 		// the correct names of the players

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2019-06-25 08:03:30 +0000
+++ src/logic/map.cc	2019-08-23 08:59:39 +0000
@@ -122,7 +122,7 @@
 and recalcs the interactive player's overlay.
 ===============
 */
-void Map::recalc_for_field_area(const World& world, const Area<FCoords> area) {
+void Map::recalc_for_field_area(const EditorGameBase& egbase, const Area<FCoords> area) {
 	assert(0 <= area.x);
 	assert(area.x < width_);
 	assert(0 <= area.y);
@@ -135,14 +135,14 @@
 		do {
 			recalc_brightness(mr.location());
 			recalc_border(mr.location());
-			recalc_nodecaps_pass1(world, mr.location());
+			recalc_nodecaps_pass1(egbase, mr.location());
 		} while (mr.advance(*this));
 	}
 
 	{  //  Second pass.
 		MapRegion<Area<FCoords>> mr(*this, area);
 		do
-			recalc_nodecaps_pass2(world, mr.location());
+			recalc_nodecaps_pass2(egbase, mr.location());
 		while (mr.advance(*this));
 	}
 }
@@ -156,7 +156,7 @@
 the overlays have completely changed.
 ===========
 */
-void Map::recalc_whole_map(const World& world) {
+void Map::recalc_whole_map(const EditorGameBase& egbase) {
 	//  Post process the map in the necessary two passes to calculate
 	//  brightness and building caps
 	FCoords f;
@@ -168,18 +168,19 @@
 			check_neighbour_heights(f, radius);
 			recalc_brightness(f);
 			recalc_border(f);
-			recalc_nodecaps_pass1(world, f);
+			recalc_nodecaps_pass1(egbase, f);
 		}
 
 	for (int16_t y = 0; y < height_; ++y)
 		for (int16_t x = 0; x < width_; ++x) {
 			f = get_fcoords(Coords(x, y));
-			recalc_nodecaps_pass2(world, f);
+			recalc_nodecaps_pass2(egbase, f);
 		}
 	recalculate_allows_seafaring();
 }
 
-void Map::recalc_default_resources(const World& world) {
+void Map::recalc_default_resources(const EditorGameBase& egbase) {
+	const World& world = egbase.world();
 	for (int16_t y = 0; y < height_; ++y)
 		for (int16_t x = 0; x < width_; ++x) {
 			FCoords f, f1;
@@ -442,7 +443,7 @@
 the given data
 ===========
 */
-void Map::create_empty_map(const World& world,
+void Map::create_empty_map(const EditorGameBase& egbase,
                            uint32_t const w,
                            uint32_t const h,
                            const Widelands::DescriptionIndex default_terrain,
@@ -467,7 +468,7 @@
 			}
 		}
 	}
-	recalc_whole_map(world);
+	recalc_whole_map(egbase);
 
 	filesystem_.reset(nullptr);
 }
@@ -871,9 +872,9 @@
 	}
 }
 
-NodeCaps Map::get_max_nodecaps(const World& world, const FCoords& fc) const {
-	NodeCaps max_caps = calc_nodecaps_pass1(world, fc, false);
-	max_caps = calc_nodecaps_pass2(world, fc, false, max_caps);
+NodeCaps Map::get_max_nodecaps(const EditorGameBase& egbase, const FCoords& fc) const {
+	NodeCaps max_caps = calc_nodecaps_pass1(egbase, fc, false);
+	max_caps = calc_nodecaps_pass2(egbase, fc, false, max_caps);
 	return static_cast<NodeCaps>(max_caps);
 }
 
@@ -891,7 +892,7 @@
 ===============
 */
 template <typename functorT>
-void Map::find_reachable(const Area<FCoords>& area,
+void Map::find_reachable(const EditorGameBase& egbase, const Area<FCoords>& area,
                          const CheckStep& checkstep,
                          functorT& functor) const {
 	std::vector<Coords> queue;
@@ -906,7 +907,7 @@
 		Pathfield& curpf = pathfields->fields[cur.field - fields_.get()];
 
 		//  handle this node
-		functor(*this, cur);
+		functor(egbase, cur);
 		curpf.cycle = pathfields->cycle;
 
 		// Get neighbours
@@ -934,10 +935,10 @@
 Functor is of the form: functor(Map &, FCoords)
 ===============
 */
-template <typename functorT> void Map::find(const Area<FCoords>& area, functorT& functor) const {
+template <typename functorT> void Map::find(const EditorGameBase& egbase, const Area<FCoords>& area, functorT& functor) const {
 	MapRegion<Area<FCoords>> mr(*this, area);
 	do
-		functor(*this, mr.location());
+		functor(egbase, mr.location());
 	while (mr.advance(*this));
 }
 
@@ -953,7 +954,7 @@
 	   : list_(list), functor_(functor), found_(0) {
 	}
 
-	void operator()(const Map&, const FCoords& cur) {
+	void operator()(const EditorGameBase&, const FCoords& cur) {
 		for (Bob* bob = cur.field->get_first_bob(); bob; bob = bob->get_next_bob()) {
 			if (list_ && std::find(list_->begin(), list_->end(), bob) != list_->end())
 				continue;
@@ -982,12 +983,12 @@
 Returns the number of objects found.
 ===============
 */
-uint32_t Map::find_bobs(Area<FCoords> const area,
+uint32_t Map::find_bobs(const EditorGameBase& egbase, Area<FCoords> const area,
                         std::vector<Bob*>* const list,
                         const FindBob& functor) const {
 	FindBobsCallback cb(list, functor);
 
-	find(area, cb);
+	find(egbase, area, cb);
 
 	return cb.found_;
 }
@@ -1004,13 +1005,13 @@
 Returns the number of objects found.
 ===============
 */
-uint32_t Map::find_reachable_bobs(Area<FCoords> const area,
+uint32_t Map::find_reachable_bobs(const EditorGameBase& egbase, Area<FCoords> const area,
                                   std::vector<Bob*>* const list,
                                   const CheckStep& checkstep,
                                   const FindBob& functor) const {
 	FindBobsCallback cb(list, functor);
 
-	find_reachable(area, checkstep, cb);
+	find_reachable(egbase, area, checkstep, cb);
 
 	return cb.found_;
 }
@@ -1027,7 +1028,7 @@
 	   : list_(list), functor_(functor), found_(0) {
 	}
 
-	void operator()(const Map&, const FCoords& cur) {
+	void operator()(const EditorGameBase&, const FCoords& cur) {
 		BaseImmovable* const imm = cur.field->get_immovable();
 
 		if (!imm)
@@ -1058,12 +1059,12 @@
 If list is not 0, found immovables are stored in list.
 ===============
 */
-uint32_t Map::find_immovables(Area<FCoords> const area,
+uint32_t Map::find_immovables(const EditorGameBase& egbase, Area<FCoords> const area,
                               std::vector<ImmovableFound>* const list,
                               const FindImmovable& functor) const {
 	FindImmovablesCallback cb(list, functor);
 
-	find(area, cb);
+	find(egbase, area, cb);
 
 	return cb.found_;
 }
@@ -1078,13 +1079,13 @@
 Returns the number of immovables we found.
 ===============
 */
-uint32_t Map::find_reachable_immovables(Area<FCoords> const area,
+uint32_t Map::find_reachable_immovables(const EditorGameBase& egbase, Area<FCoords> const area,
                                         std::vector<ImmovableFound>* const list,
                                         const CheckStep& checkstep,
                                         const FindImmovable& functor) const {
 	FindImmovablesCallback cb(list, functor);
 
-	find_reachable(area, checkstep, cb);
+	find_reachable(egbase, area, checkstep, cb);
 
 	return cb.found_;
 }
@@ -1096,14 +1097,14 @@
  *
  * \return the number of immovables found.
  */
-uint32_t Map::find_reachable_immovables_unique(const Area<FCoords> area,
+uint32_t Map::find_reachable_immovables_unique(const EditorGameBase& egbase, const Area<FCoords> area,
                                                std::vector<BaseImmovable*>& list,
                                                const CheckStep& checkstep,
                                                const FindImmovable& functor) const {
 	std::vector<ImmovableFound> duplist;
 	FindImmovablesCallback cb(&duplist, find_immovable_always_true());
 
-	find_reachable(area, checkstep, cb);
+	find_reachable(egbase, area, checkstep, cb);
 
 	for (ImmovableFound& imm_found : duplist) {
 		BaseImmovable& obj = *imm_found.object;
@@ -1129,8 +1130,8 @@
 	   : list_(list), functor_(functor), found_(0) {
 	}
 
-	void operator()(const Map& map, const FCoords& cur) {
-		if (functor_.accept(map, cur)) {
+	void operator()(const EditorGameBase& egbase, const FCoords& cur) {
+		if (functor_.accept(egbase, cur)) {
 			if (list_)
 				list_->push_back(cur);
 
@@ -1152,12 +1153,12 @@
 Note that list can be 0.
 ===============
 */
-uint32_t Map::find_fields(Area<FCoords> const area,
+uint32_t Map::find_fields(const EditorGameBase& egbase, Area<FCoords> const area,
                           std::vector<Coords>* list,
                           const FindNode& functor) const {
 	FindNodesCallback cb(list, functor);
 
-	find(area, cb);
+	find(egbase, area, cb);
 
 	return cb.found_;
 }
@@ -1171,13 +1172,13 @@
 Note that list can be 0.
 ===============
 */
-uint32_t Map::find_reachable_fields(Area<FCoords> const area,
+uint32_t Map::find_reachable_fields(const EditorGameBase& egbase, Area<FCoords> const area,
                                     std::vector<Coords>* list,
                                     const CheckStep& checkstep,
                                     const FindNode& functor) const {
 	FindNodesCallback cb(list, functor);
 
-	find_reachable(area, checkstep, cb);
+	find_reachable(egbase, area, checkstep, cb);
 
 	return cb.found_;
 }
@@ -1258,13 +1259,14 @@
 above recalc_brightness.
 ===============
 */
-void Map::recalc_nodecaps_pass1(const World& world, const FCoords& f) {
-	f.field->caps = calc_nodecaps_pass1(world, f, true);
-	f.field->max_caps = calc_nodecaps_pass1(world, f, false);
+void Map::recalc_nodecaps_pass1(const EditorGameBase& egbase, const FCoords& f) {
+	f.field->caps = calc_nodecaps_pass1(egbase, f, true);
+	f.field->max_caps = calc_nodecaps_pass1(egbase, f, false);
 }
 
-NodeCaps Map::calc_nodecaps_pass1(const World& world, const FCoords& f, bool consider_mobs) const {
+NodeCaps Map::calc_nodecaps_pass1(const EditorGameBase& egbase, const FCoords& f, bool consider_mobs) const {
 	uint8_t caps = CAPS_NONE;
+	const World& world = egbase.world();
 
 	// 1a) Get all the neighbours to make life easier
 	const FCoords tr = tr_n(f);
@@ -1362,7 +1364,7 @@
 	if (caps & MOVECAPS_WALK) {
 		//  4b) Flags must be at least 2 edges apart
 		if (consider_mobs &&
-		    find_immovables(Area<FCoords>(f, 1), nullptr, FindImmovableType(MapObjectType::FLAG)))
+		    find_immovables(egbase, Area<FCoords>(f, 1), nullptr, FindImmovableType(MapObjectType::FLAG)))
 			return static_cast<NodeCaps>(caps);
 		caps |= BUILDCAPS_FLAG;
 	}
@@ -1377,13 +1379,13 @@
 Important: flag buildability has already been checked in the first pass.
 ===============
 */
-void Map::recalc_nodecaps_pass2(const World& world, const FCoords& f) {
-	f.field->caps = calc_nodecaps_pass2(world, f, true);
+void Map::recalc_nodecaps_pass2(const EditorGameBase& egbase, const FCoords& f) {
+	f.field->caps = calc_nodecaps_pass2(egbase, f, true);
 	f.field->max_caps =
-	   calc_nodecaps_pass2(world, f, false, static_cast<NodeCaps>(f.field->max_caps));
+	   calc_nodecaps_pass2(egbase, f, false, static_cast<NodeCaps>(f.field->max_caps));
 }
 
-NodeCaps Map::calc_nodecaps_pass2(const World& world,
+NodeCaps Map::calc_nodecaps_pass2(const EditorGameBase& egbase,
                                   const FCoords& f,
                                   bool consider_mobs,
                                   NodeCaps initcaps) const {
@@ -1400,22 +1402,22 @@
 		     br.field->get_immovable()->descr().type() != MapObjectType::FLAG))
 			return static_cast<NodeCaps>(caps);
 	} else {
-		if (!(calc_nodecaps_pass1(world, br, false) & BUILDCAPS_FLAG))
+		if (!(calc_nodecaps_pass1(egbase, br, false) & BUILDCAPS_FLAG))
 			return static_cast<NodeCaps>(caps);
 	}
 
 	bool mine;
-	uint8_t buildsize = calc_buildsize(world, f, true, &mine, consider_mobs, initcaps);
+	uint8_t buildsize = calc_buildsize(egbase, f, true, &mine, consider_mobs, initcaps);
 	if (buildsize < BaseImmovable::SMALL)
 		return static_cast<NodeCaps>(caps);
 	assert(buildsize >= BaseImmovable::SMALL && buildsize <= BaseImmovable::BIG);
 
 	if (buildsize == BaseImmovable::BIG) {
-		if (calc_buildsize(world, l_n(f), false, nullptr, consider_mobs, initcaps) <
-		       BaseImmovable::BIG ||
-		    calc_buildsize(world, tl_n(f), false, nullptr, consider_mobs, initcaps) <
-		       BaseImmovable::BIG ||
-		    calc_buildsize(world, tr_n(f), false, nullptr, consider_mobs, initcaps) <
+		if (calc_buildsize(egbase, l_n(f), false, nullptr, consider_mobs, initcaps) <
+		       BaseImmovable::BIG ||
+		    calc_buildsize(egbase, tl_n(f), false, nullptr, consider_mobs, initcaps) <
+		       BaseImmovable::BIG ||
+		    calc_buildsize(egbase, tr_n(f), false, nullptr, consider_mobs, initcaps) <
 		       BaseImmovable::BIG)
 			buildsize = BaseImmovable::MEDIUM;
 	}
@@ -1489,7 +1491,7 @@
  * for the calculation. If not (calculation of maximum theoretical possible buildsize) initcaps must
  * be set.
  */
-int Map::calc_buildsize(const World& world,
+int Map::calc_buildsize(const EditorGameBase& egbase,
                         const FCoords& f,
                         bool avoidnature,
                         bool* ismine,
@@ -1509,6 +1511,7 @@
 	const FCoords tl = tl_n(f);
 	const FCoords l = l_n(f);
 
+	const World& world = egbase.world();
 	const TerrainDescription::Is terrains[6] = {world.terrain_descr(tr.field->terrain_d()).get_is(),
 	                                            world.terrain_descr(tl.field->terrain_r()).get_is(),
 	                                            world.terrain_descr(tl.field->terrain_d()).get_is(),
@@ -1540,7 +1543,7 @@
 	int buildsize = BaseImmovable::BIG;
 	if (consider_mobs) {
 		std::vector<ImmovableFound> objectlist;
-		find_immovables(Area<FCoords>(f, 1), &objectlist,
+		find_immovables(egbase, Area<FCoords>(f, 1), &objectlist,
 		                FindImmovableSize(BaseImmovable::SMALL, BaseImmovable::BIG));
 		for (uint32_t i = 0; i < objectlist.size(); ++i) {
 			const BaseImmovable* obj = objectlist[i].object;
@@ -1632,8 +1635,8 @@
 	return portdock;
 }
 
-bool Map::is_port_space_allowed(const World& world, const FCoords& fc) const {
-	return (get_max_nodecaps(world, fc) & BUILDCAPS_SIZEMASK) == BUILDCAPS_BIG &&
+bool Map::is_port_space_allowed(const EditorGameBase& egbase, const FCoords& fc) const {
+	return (get_max_nodecaps(egbase, fc) & BUILDCAPS_SIZEMASK) == BUILDCAPS_BIG &&
 	       !find_portdock(fc).empty();
 }
 
@@ -1643,10 +1646,10 @@
 }
 
 bool Map::set_port_space(
-   const World& world, const Coords& c, bool set, bool force, bool recalculate_seafaring) {
+   const EditorGameBase& egbase, const Coords& c, bool set, bool force, bool recalculate_seafaring) {
 	bool success = false;
 	if (set) {
-		success = force || is_port_space_allowed(world, get_fcoords(c));
+		success = force || is_port_space_allowed(egbase, get_fcoords(c));
 		if (success) {
 			port_spaces_.insert(c);
 			recalculate_seafaring &= !allows_seafaring();
@@ -2093,26 +2096,26 @@
 }
 
 int32_t
-Map::change_terrain(const World& world, TCoords<FCoords> const c, DescriptionIndex const terrain) {
+Map::change_terrain(const EditorGameBase& egbase, TCoords<FCoords> const c, DescriptionIndex const terrain) {
 	c.node.field->set_terrain(c.t, terrain);
 
 	// remove invalid resources if necessary
 	// check vertex to which the triangle belongs
-	if (!is_resource_valid(world, c.node, c.node.field->get_resources())) {
+	if (!is_resource_valid(egbase, c.node, c.node.field->get_resources())) {
 		clear_resources(c.node);
 	}
 
 	// always check south-east vertex
 	Widelands::FCoords f_se(c.node);
 	get_neighbour(f_se, Widelands::WALK_SE, &f_se);
-	if (!is_resource_valid(world, f_se, f_se.field->get_resources())) {
+	if (!is_resource_valid(egbase, f_se, f_se.field->get_resources())) {
 		clear_resources(f_se);
 	}
 
 	// check south-west vertex if d-Triangle is changed, check east vertex if r-Triangle is changed
 	Widelands::FCoords f_sw_e(c.node);
 	get_neighbour(f_sw_e, c.t == TriangleIndex::D ? Widelands::WALK_SW : Widelands::WALK_E, &f_sw_e);
-	if (!is_resource_valid(world, f_sw_e, f_sw_e.field->get_resources())) {
+	if (!is_resource_valid(egbase, f_sw_e, f_sw_e.field->get_resources())) {
 		clear_resources(f_sw_e);
 	}
 
@@ -2121,16 +2124,17 @@
 
 	// Changing the terrain can affect ports, which can be up to 3 fields away.
 	constexpr int kPotentiallyAffectedNeighbors = 3;
-	recalc_for_field_area(world, Area<FCoords>(c.node, kPotentiallyAffectedNeighbors));
+	recalc_for_field_area(egbase, Area<FCoords>(c.node, kPotentiallyAffectedNeighbors));
 	return kPotentiallyAffectedNeighbors;
 }
 
-bool Map::is_resource_valid(const Widelands::World& world,
+bool Map::is_resource_valid(const Widelands::EditorGameBase& egbase,
                             const Widelands::FCoords& c,
                             DescriptionIndex curres) const {
 	if (curres == Widelands::kNoResource)
 		return true;
 
+	const World& world = egbase.world();
 	Widelands::FCoords f1;
 
 	int32_t count = 0;
@@ -2156,10 +2160,10 @@
 	return count > 1;
 }
 
-void Map::ensure_resource_consistency(const World& world) {
+void Map::ensure_resource_consistency(const EditorGameBase& egbase) {
 	for (MapIndex i = 0; i < max_index(); ++i) {
 		auto fcords = get_fcoords(fields_[i]);
-		if (!is_resource_valid(world, fcords, fcords.field->get_resources())) {
+		if (!is_resource_valid(egbase, fcords, fcords.field->get_resources())) {
 			clear_resources(fcords);
 		}
 	}
@@ -2189,18 +2193,18 @@
 	initialize_resources(c, Widelands::kNoResource, 0);
 }
 
-uint32_t Map::set_height(const World& world, const FCoords fc, uint8_t const new_value) {
+uint32_t Map::set_height(const EditorGameBase& egbase, const FCoords fc, uint8_t const new_value) {
 	assert(new_value <= MAX_FIELD_HEIGHT);
 	assert(fields_.get() <= fc.field);
 	assert(fc.field < fields_.get() + max_index());
 	fc.field->height = new_value;
 	uint32_t radius = 2;
 	check_neighbour_heights(fc, radius);
-	recalc_for_field_area(world, Area<FCoords>(fc, radius));
+	recalc_for_field_area(egbase, Area<FCoords>(fc, radius));
 	return radius;
 }
 
-uint32_t Map::change_height(const World& world, Area<FCoords> area, int16_t const difference) {
+uint32_t Map::change_height(const EditorGameBase& egbase, Area<FCoords> area, int16_t const difference) {
 	{
 		MapRegion<Area<FCoords>> mr(*this, area);
 		do {
@@ -2221,11 +2225,11 @@
 		regional_radius = std::max(regional_radius, local_radius);
 	} while (mr.advance(*this));
 	area.radius += regional_radius + 2;
-	recalc_for_field_area(world, area);
+	recalc_for_field_area(egbase, area);
 	return area.radius;
 }
 
-uint32_t Map::set_height(const World& world, Area<FCoords> area, HeightInterval height_interval) {
+uint32_t Map::set_height(const EditorGameBase& egbase, Area<FCoords> area, HeightInterval height_interval) {
 	assert(height_interval.valid());
 	assert(height_interval.max <= MAX_FIELD_HEIGHT);
 	{
@@ -2262,7 +2266,7 @@
 		} while (changed);
 		area.radius = mr.radius();
 	}
-	recalc_for_field_area(world, area);
+	recalc_for_field_area(egbase, area);
 	return area.radius;
 }
 
@@ -2368,16 +2372,16 @@
 	Notifications::publish(NoteMapOptions());
 }
 
-void Map::cleanup_port_spaces(const World& world) {
+void Map::cleanup_port_spaces(const EditorGameBase& egbase) {
 	// Temporary set to avoid problems with concurrent container operations
 	PortSpacesSet clean_me_up;
 	for (const Coords& c : get_port_spaces()) {
-		if (!is_port_space_allowed(world, get_fcoords(c))) {
+		if (!is_port_space_allowed(egbase, get_fcoords(c))) {
 			clean_me_up.insert(c);
 		}
 	}
 	for (const Coords& c : clean_me_up) {
-		set_port_space(world, c, false);
+		set_port_space(egbase, c, false);
 	}
 	recalculate_allows_seafaring();
 }

=== modified file 'src/logic/map.h'
--- src/logic/map.h	2019-06-25 08:03:30 +0000
+++ src/logic/map.h	2019-08-23 08:59:39 +0000
@@ -48,7 +48,6 @@
 
 class MapLoader;
 class Objective;
-class World;
 struct BaseImmovable;
 struct MapGenerator;
 struct PathfieldManager;
@@ -164,7 +163,7 @@
 	void cleanup();
 
 	void create_empty_map  // for editor
-	   (const World& world,
+	   (const EditorGameBase&,
 	    uint32_t w = 64,
 	    uint32_t h = 64,
 	    const Widelands::DescriptionIndex default_terrain = 0,
@@ -172,8 +171,8 @@
 	    const std::string& author = pgettext("author_name", "Unknown"),
 	    const std::string& description = _("No description defined"));
 
-	void recalc_whole_map(const World& world);
-	void recalc_for_field_area(const World& world, Area<FCoords>);
+	void recalc_whole_map(const EditorGameBase&);
+	void recalc_for_field_area(const EditorGameBase&, Area<FCoords>);
 
 	/**
 	 *  If the valuable fields are empty, calculates all fields that could be conquered by a player
@@ -199,7 +198,7 @@
 	/***
 	 * Ensures that resources match their adjacent terrains.
 	 */
-	void ensure_resource_consistency(const World& world);
+	void ensure_resource_consistency(const EditorGameBase&);
 
 	/***
 	 * Recalculates all default resources.
@@ -208,7 +207,7 @@
 	 * the editor. Since there, default resources
 	 * are not shown.
 	 */
-	void recalc_default_resources(const World& world);
+	void recalc_default_resources(const EditorGameBase&);
 
 	void set_nrplayers(PlayerNumber);
 
@@ -303,31 +302,31 @@
 	void set_scenario_player_closeable(PlayerNumber, bool);
 
 	/// \returns the maximum theoretical possible nodecaps (no blocking bobs, immovables etc.)
-	NodeCaps get_max_nodecaps(const World& world, const FCoords&) const;
+	NodeCaps get_max_nodecaps(const EditorGameBase&, const FCoords&) const;
 
 	BaseImmovable* get_immovable(const Coords&) const;
-	uint32_t find_bobs(const Area<FCoords>,
+	uint32_t find_bobs(const EditorGameBase&, const Area<FCoords>,
 	                   std::vector<Bob*>* list,
 	                   const FindBob& functor = FindBobAlwaysTrue()) const;
-	uint32_t find_reachable_bobs(const Area<FCoords>,
+	uint32_t find_reachable_bobs(const EditorGameBase&, const Area<FCoords>,
 	                             std::vector<Bob*>* list,
 	                             const CheckStep&,
 	                             const FindBob& functor = FindBobAlwaysTrue()) const;
-	uint32_t find_immovables(const Area<FCoords>,
+	uint32_t find_immovables(const EditorGameBase&, const Area<FCoords>,
 	                         std::vector<ImmovableFound>* list,
 	                         const FindImmovable& = find_immovable_always_true()) const;
-	uint32_t find_reachable_immovables(const Area<FCoords>,
+	uint32_t find_reachable_immovables(const EditorGameBase&, const Area<FCoords>,
 	                                   std::vector<ImmovableFound>* list,
 	                                   const CheckStep&,
 	                                   const FindImmovable& = find_immovable_always_true()) const;
 	uint32_t
-	find_reachable_immovables_unique(const Area<FCoords>,
+	find_reachable_immovables_unique(const EditorGameBase&, const Area<FCoords>,
 	                                 std::vector<BaseImmovable*>& list,
 	                                 const CheckStep&,
 	                                 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>,
+	find_fields(const EditorGameBase&, const Area<FCoords>, std::vector<Coords>* list, const FindNode& functor) const;
+	uint32_t find_reachable_fields(const EditorGameBase&, const Area<FCoords>,
 	                               std::vector<Coords>* list,
 	                               const CheckStep&,
 	                               const FindNode&) const;
@@ -410,10 +409,10 @@
 	/// value, because it adjusts the heights of surrounding nodes in each call,
 	/// so it will be terribly slow. Use set_height for Area for that purpose
 	/// instead.
-	uint32_t set_height(const World& world, FCoords, Field::Height);
+	uint32_t set_height(const EditorGameBase&, FCoords, Field::Height);
 
 	/// Changes the height of the nodes in an Area by a difference.
-	uint32_t change_height(const World& world, Area<FCoords>, int16_t difference);
+	uint32_t change_height(const EditorGameBase&, Area<FCoords>, int16_t difference);
 
 	/// Initializes the 'initial_resources' on 'coords' to the 'resource_type'
 	/// with the given 'amount'.
@@ -442,7 +441,7 @@
 	 * the area, because this adjusts the surrounding nodes only once, after all
 	 * nodes in the area had their new height set.
 	 */
-	uint32_t set_height(const World& world, Area<FCoords>, HeightInterval height_interval);
+	uint32_t set_height(const EditorGameBase&, Area<FCoords>, HeightInterval height_interval);
 
 	/***
 	 * Changes the given triangle's terrain. This happens in the editor and might
@@ -452,14 +451,14 @@
 	 *
 	 * @return the radius of changes.
 	 */
-	int32_t change_terrain(const World& world, TCoords<FCoords>, DescriptionIndex);
+	int32_t change_terrain(const EditorGameBase&, TCoords<FCoords>, DescriptionIndex);
 
 	/***
 	 * Verify if a resource attached to a vertex has enough adjacent matching terrains to be valid.
 	 *
 	 * To qualify as valid, resources need to be surrounded by at least two matching terrains.
 	 */
-	bool is_resource_valid(const Widelands::World& world,
+	bool is_resource_valid(const Widelands::EditorGameBase&,
 	                       const Widelands::FCoords& c,
 	                       DescriptionIndex curres) const;
 
@@ -485,13 +484,13 @@
 
 	/// Checks whether the maximum theoretical possible NodeCap of the field is big,
 	/// and there is room for a port space
-	bool is_port_space_allowed(const World& world, const FCoords& fc) const;
+	bool is_port_space_allowed(const EditorGameBase&, const FCoords& fc) const;
 	bool is_port_space(const Coords& c) const;
 
 	/// If 'set', set the space at 'c' as port space, otherwise unset.
 	/// 'force' sets the port space even if it isn't viable, and is to be used for map loading only.
 	/// Returns whether the port space was set/unset successfully.
-	bool set_port_space(const World& world,
+	bool set_port_space(const EditorGameBase&,
 	                    const Widelands::Coords& c,
 	                    bool set,
 	                    bool force = false,
@@ -508,7 +507,7 @@
 	void recalculate_allows_seafaring();
 	/// Remove all port spaces that are not valid (Buildcap < big or not enough space for a
 	/// portdock).
-	void cleanup_port_spaces(const World& world);
+	void cleanup_port_spaces(const EditorGameBase&);
 
 	/// Checks whether there are any artifacts on the map
 	bool has_artifacts();
@@ -529,16 +528,16 @@
 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);
+	void recalc_nodecaps_pass1(const EditorGameBase&, const FCoords&);
+	void recalc_nodecaps_pass2(const EditorGameBase&, const FCoords& f);
 	NodeCaps
-	calc_nodecaps_pass1(const World& world, const FCoords&, bool consider_mobs = true) const;
-	NodeCaps calc_nodecaps_pass2(const World& world,
+	calc_nodecaps_pass1(const EditorGameBase&, const FCoords&, bool consider_mobs = true) const;
+	NodeCaps calc_nodecaps_pass2(const EditorGameBase&,
 	                             const FCoords&,
 	                             bool consider_mobs = true,
 	                             NodeCaps initcaps = CAPS_NONE) const;
 	void check_neighbour_heights(FCoords, uint32_t& radius);
-	int calc_buildsize(const World& world,
+	int calc_buildsize(const EditorGameBase&,
 	                   const FCoords& f,
 	                   bool avoidnature,
 	                   bool* ismine = nullptr,
@@ -546,8 +545,8 @@
 	                   NodeCaps initcaps = CAPS_NONE) const;
 	bool is_cycle_connected(const FCoords& start, uint32_t length, const WalkingDir* dirs) const;
 	template <typename functorT>
-	void find_reachable(const Area<FCoords>&, const CheckStep&, functorT&) const;
-	template <typename functorT> void find(const Area<FCoords>&, functorT&) const;
+	void find_reachable(const EditorGameBase&, const Area<FCoords>&, const CheckStep&, functorT&) const;
+	template <typename functorT> void find(const EditorGameBase&, const Area<FCoords>&, functorT&) const;
 
 	/// # of players this map supports (!= Game's number of players!)
 	PlayerNumber nrplayers_;

=== modified file 'src/logic/map_objects/bob.cc'
--- src/logic/map_objects/bob.cc	2019-05-11 13:48:12 +0000
+++ src/logic/map_objects/bob.cc	2019-08-23 08:59:39 +0000
@@ -638,7 +638,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)) {
-			const uint32_t ships_count = game.map().find_bobs(
+			const uint32_t ships_count = game.map().find_bobs(game,
 			   Widelands::Area<Widelands::FCoords>(get_position(), 0), nullptr, FindBobShip());
 			assert(ships_count > 0);
 			if (ships_count > 1) {
@@ -825,7 +825,7 @@
 bool Bob::check_node_blocked(Game& game, const FCoords& field, bool) {
 	// Battles always block movement!
 	std::vector<Bob*> soldiers;
-	game.map().find_bobs(Area<FCoords>(field, 0), &soldiers, FindBobEnemySoldier(get_owner()));
+	game.map().find_bobs(game, Area<FCoords>(field, 0), &soldiers, FindBobEnemySoldier(get_owner()));
 
 	if (!soldiers.empty()) {
 		for (Bob* temp_bob : soldiers) {

=== modified file 'src/logic/map_objects/findnode.cc'
--- src/logic/map_objects/findnode.cc	2019-02-27 19:00:36 +0000
+++ src/logic/map_objects/findnode.cc	2019-08-23 08:59:39 +0000
@@ -20,9 +20,12 @@
 #include "logic/map_objects/findnode.h"
 
 #include "base/wexception.h"
+#include "logic/editor_game_base.h"
 #include "logic/field.h"
 #include "logic/map.h"
 #include "logic/map_objects/immovable.h"
+#include "logic/map_objects/world/terrain_description.h"
+#include "logic/map_objects/world/world.h"
 
 namespace Widelands {
 
@@ -34,16 +37,16 @@
 	subfunctors.push_back(Subfunctor(findfield, negate));
 }
 
-bool FindNodeAnd::accept(const Map& map, const FCoords& coord) const {
+bool FindNodeAnd::accept(const EditorGameBase& egbase, const FCoords& coord) const {
 	for (const Subfunctor& subfunctor : subfunctors) {
-		if (subfunctor.findfield.accept(map, coord) == subfunctor.negate) {
+		if (subfunctor.findfield.accept(egbase, coord) == subfunctor.negate) {
 			return false;
 		}
 	}
 	return true;
 }
 
-bool FindNodeCaps::accept(const Map&, const FCoords& coord) const {
+bool FindNodeCaps::accept(const EditorGameBase&, const FCoords& coord) const {
 	NodeCaps nodecaps = coord.field->nodecaps();
 
 	if ((nodecaps & BUILDCAPS_SIZEMASK) < (mincaps & BUILDCAPS_SIZEMASK))
@@ -55,11 +58,12 @@
 	return true;
 }
 
-bool FindNodeSize::accept(const Map&, const FCoords& coord) const {
+bool FindNodeSize::accept(const EditorGameBase& egbase, const FCoords& coord) const {
 	if (BaseImmovable const* const immovable = coord.field->get_immovable())
 		if (immovable->get_size() > BaseImmovable::NONE)
 			return false;
 	NodeCaps const nodecaps = coord.field->nodecaps();
+	const Map& map = egbase.map();
 
 	switch (size) {
 	case sizeBuild:
@@ -74,13 +78,22 @@
 		return (nodecaps & BUILDCAPS_SIZEMASK) >= BUILDCAPS_MEDIUM;
 	case sizeBig:
 		return (nodecaps & BUILDCAPS_SIZEMASK) >= BUILDCAPS_BIG;
+	case sizeSwim:
+		return map.can_reach_by_water(coord);
+	case sizeTerraform:
+		return !(egbase.world().terrain_descr(coord.field->terrain_d()).enhancement().empty() &&
+				egbase.world().terrain_descr(coord.field->terrain_r()).enhancement().empty() &&
+				egbase.world().terrain_descr(map.tl_n(coord).field->terrain_d()).enhancement().empty() &&
+				egbase.world().terrain_descr(map.tl_n(coord).field->terrain_r()).enhancement().empty() &&
+				egbase.world().terrain_descr(map.tr_n(coord).field->terrain_d()).enhancement().empty() &&
+				egbase.world().terrain_descr(map.l_n(coord).field->terrain_r()).enhancement().empty());
 	case sizeAny:
 		return true;
 	}
 	NEVER_HERE();
 }
 
-bool FindNodeImmovableSize::accept(const Map&, const FCoords& coord) const {
+bool FindNodeImmovableSize::accept(const EditorGameBase&, const FCoords& coord) const {
 	int32_t size = BaseImmovable::NONE;
 
 	if (BaseImmovable* const imm = coord.field->get_immovable())
@@ -100,17 +113,17 @@
 	}
 }
 
-bool FindNodeImmovableAttribute::accept(const Map&, const FCoords& coord) const {
+bool FindNodeImmovableAttribute::accept(const EditorGameBase&, const FCoords& coord) const {
 	if (BaseImmovable* const imm = coord.field->get_immovable())
 		return imm->has_attribute(attribute);
 	return false;
 }
 
-bool FindNodeResource::accept(const Map&, const FCoords& coord) const {
+bool FindNodeResource::accept(const EditorGameBase&, const FCoords& coord) const {
 	return resource == coord.field->get_resources() && coord.field->get_resources_amount();
 }
 
-bool FindNodeResourceBreedable::accept(const Map& map, const FCoords& coord) const {
+bool FindNodeResourceBreedable::accept(const EditorGameBase& egbase, const FCoords& coord) const {
 	// Accept a tile that is full only if a neighbor also matches resource and
 	// is not full.
 	if (resource != coord.field->get_resources()) {
@@ -131,7 +144,7 @@
 		break;
 	}
 	for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
-		const FCoords neighb = map.get_neighbour(coord, dir);
+		const FCoords neighb = egbase.map().get_neighbour(coord, dir);
 		if (resource == neighb.field->get_resources()) {
 			switch (strictness) {
 			case AnimalBreedable::kDefault:
@@ -150,7 +163,7 @@
 	return false;
 }
 
-bool FindNodeShore::accept(const Map& map, const FCoords& coords) const {
+bool FindNodeShore::accept(const EditorGameBase& egbase, const FCoords& coords) const {
 	if (!(coords.field->nodecaps() & MOVECAPS_WALK))
 		return false;
 
@@ -169,7 +182,7 @@
 
 		// Now test all neighbours
 		for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
-			FCoords neighb = map.get_neighbour(cur, dir);
+			FCoords neighb = egbase.map().get_neighbour(cur, dir);
 			if (accepted_nodes.count(neighb.hash()) > 0 || rejected_nodes.count(neighb.hash()) > 0) {
 				// We already processed this node
 				continue;

=== modified file 'src/logic/map_objects/findnode.h'
--- src/logic/map_objects/findnode.h	2019-02-27 19:00:36 +0000
+++ src/logic/map_objects/findnode.h	2019-08-23 08:59:39 +0000
@@ -30,8 +30,8 @@
 
 enum class AnimalBreedable { kDefault, kAnimalFull };
 
+class EditorGameBase;
 struct FCoords;
-class Map;
 
 struct FindNode {
 private:
@@ -48,14 +48,14 @@
 			if (--refcount == 0)
 				delete this;
 		}
-		virtual bool accept(const Map&, const FCoords& coord) const = 0;
+		virtual bool accept(const EditorGameBase&, const FCoords& coord) const = 0;
 
 		int refcount;
 	};
 	template <typename T> struct Capsule : public BaseCapsule {
 		explicit Capsule(const T& init_op) : op(init_op) {
 		}
-		bool accept(const Map& map, const FCoords& coord) const override {
+		bool accept(const EditorGameBase& map, const FCoords& coord) const override {
 			return op.accept(map, coord);
 		}
 
@@ -85,7 +85,7 @@
 	}
 
 	// Return true if this node should be returned by find_fields()
-	bool accept(const Map& map, const FCoords& coord) const {
+	bool accept(const EditorGameBase& map, const FCoords& coord) const {
 		return capsule->accept(map, coord);
 	}
 };
@@ -94,7 +94,7 @@
 	explicit FindNodeCaps(uint8_t init_mincaps) : mincaps(init_mincaps) {
 	}
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	uint8_t mincaps;
@@ -107,7 +107,7 @@
 
 	void add(const FindNode&, bool negate = false);
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	struct Subfunctor {
@@ -130,12 +130,14 @@
 		sizeBig,
 		sizeMine,  //  can build a mine on this field
 		sizePort,  //  can build a port on this field
+		sizeSwim, // coast
+		sizeTerraform // a neighbouring triangle has enhanceable terrain
 	};
 
 	explicit FindNodeSize(Size init_size) : size(init_size) {
 	}
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	Size size;
@@ -148,7 +150,7 @@
 	explicit FindNodeImmovableSize(uint32_t init_sizes) : sizes(init_sizes) {
 	}
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	uint32_t sizes;
@@ -159,7 +161,7 @@
 	explicit FindNodeImmovableAttribute(uint32_t attrib) : attribute(attrib) {
 	}
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	uint32_t attribute;
@@ -170,7 +172,7 @@
 	explicit FindNodeResource(DescriptionIndex res) : resource(res) {
 	}
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	DescriptionIndex resource;
@@ -184,7 +186,7 @@
 	   : resource(res), strictness(br) {
 	}
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	DescriptionIndex resource;
@@ -197,7 +199,7 @@
 	explicit FindNodeShore(uint16_t f = 1) : min_fields(f) {
 	}
 
-	bool accept(const Map&, const FCoords&) const;
+	bool accept(const EditorGameBase&, const FCoords&) const;
 
 private:
 	// Minimal number of reachable swimmable fields. 1 is minimum for this to be considered "shore"

=== modified file 'src/logic/map_objects/immovable.cc'
--- src/logic/map_objects/immovable.cc	2019-05-28 17:01:30 +0000
+++ src/logic/map_objects/immovable.cc	2019-08-23 08:59:39 +0000
@@ -107,7 +107,7 @@
 	f.field->immovable = this;
 
 	if (get_size() >= SMALL) {
-		map->recalc_for_field_area(egbase.world(), Area<FCoords>(f, 2));
+		map->recalc_for_field_area(egbase, Area<FCoords>(f, 2));
 	}
 }
 
@@ -133,7 +133,7 @@
 	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));
+		map->recalc_for_field_area(egbase, Area<FCoords>(f, 2));
 	}
 }
 

=== modified file 'src/logic/map_objects/tribes/building.cc'
--- src/logic/map_objects/tribes/building.cc	2019-06-25 08:03:30 +0000
+++ src/logic/map_objects/tribes/building.cc	2019-08-23 08:59:39 +0000
@@ -45,6 +45,7 @@
 #include "logic/map_objects/tribes/tribe_descr.h"
 #include "logic/map_objects/tribes/tribes.h"
 #include "logic/map_objects/tribes/worker.h"
+#include "logic/map_objects/world/world.h"
 #include "logic/player.h"
 
 namespace Widelands {
@@ -107,6 +108,12 @@
 			throw GameDataError("size: %s", e.what());
 		}
 	}
+	if (table.has_key("built_over_immovable")) {
+		// Throws an error if no matching immovable exists
+		built_over_immovable_ = get_attribute_id(table.get_string("built_over_immovable"), false);
+	} else {
+		built_over_immovable_ = -1;
+	}
 
 	// Parse build options
 	if (table.has_key("enhancement")) {
@@ -172,12 +179,48 @@
                                 Coords const pos,
                                 bool const construct,
                                 bool loading,
-                                Building::FormerBuildings const former_buildings) const {
+                                FormerBuildings const former_buildings) const {
+	std::pair<DescriptionIndex, std::string> immovable = std::make_pair(INVALID_INDEX, "");
+	if (built_over_immovable_ >= 0) {
+		for (const auto& pair : former_buildings) {
+			if (!pair.second.empty()) {
+				const MapObjectDescr* d;
+				if (pair.second == "world") {
+					d = egbase.world().get_immovable_descr(pair.first);
+				} else if (pair.second == "tribe") {
+					d = egbase.tribes().get_immovable_descr(pair.first);
+				} else {
+					throw wexception("Invalid FormerBuildings type: %s", pair.second.c_str());
+				}
+				if (d->has_attribute(built_over_immovable_)) {
+					goto immovable_previously_found;
+				}
+			}
+		}
+		// Must be done first, because the immovable will be gone the moment the building is placed
+		const FCoords f = egbase.map().get_fcoords(pos);
+		if (f.field->get_immovable() && f.field->get_immovable()->has_attribute(built_over_immovable_)) {
+			upcast(const ImmovableDescr, imm, &f.field->get_immovable()->descr());
+			assert(imm);
+			immovable = imm->owner_type() == MapObjectDescr::OwnerType::kWorld ?
+					std::make_pair(egbase.world().get_immovable_index(imm->name()), "world") :
+					std::make_pair(egbase.tribes().safe_immovable_index(imm->name()), "tribe");
+		} else {
+			throw wexception("Attempting to build %s at %dx%d – no immovable with required attribute %i found",
+					name().c_str(), pos.x, pos.y, built_over_immovable_);
+		}
+	}
+	immovable_previously_found:
+
 	Building& b = construct ? create_constructionsite() : create_object();
 	b.position_ = pos;
 	b.set_owner(owner);
-	for (DescriptionIndex idx : former_buildings) {
-		b.old_buildings_.push_back(idx);
+	if (immovable.first != INVALID_INDEX) {
+		assert(!immovable.second.empty());
+		b.old_buildings_.push_back(immovable);
+	}
+	for (const auto& pair : former_buildings) {
+		b.old_buildings_.push_back(pair);
 	}
 	if (loading) {
 		b.Building::init(egbase);
@@ -188,8 +231,10 @@
 }
 
 bool BuildingDescr::suitability(const Map&, const FCoords& fc) const {
-	return mine_ ? fc.field->nodecaps() & Widelands::BUILDCAPS_MINE :
-	               size_ <= (fc.field->nodecaps() & Widelands::BUILDCAPS_SIZEMASK);
+	return (mine_ ? fc.field->nodecaps() & Widelands::BUILDCAPS_MINE :
+	               size_ <= (fc.field->nodecaps() & Widelands::BUILDCAPS_SIZEMASK)) &&
+           (built_over_immovable_ < 0 ||
+                   (fc.field->get_immovable() && fc.field->get_immovable()->has_attribute(built_over_immovable_)));
 }
 
 const BuildingHints& BuildingDescr::hints() const {
@@ -251,6 +296,7 @@
      leave_time_(0),
      defeating_player_(0),
      seeing_(false),
+     was_immovable_(nullptr),
      attack_target_(nullptr),
      soldier_control_(nullptr) {
 }
@@ -365,6 +411,21 @@
 		flag->attach_building(egbase, *this);
 	}
 
+	for (const auto& pair : old_buildings_) {
+		if (!pair.second.empty()) {
+			assert(!was_immovable_);
+			if (pair.second == "world") {
+				was_immovable_ = egbase.world().get_immovable_descr(pair.first);
+			} else if (pair.second == "tribe") {
+				was_immovable_ = egbase.tribes().get_immovable_descr(pair.first);
+			} else {
+				throw wexception("Invalid FormerBuildings type: %s", pair.second.c_str());
+			}
+			assert(was_immovable_);
+			break;
+		}
+	}
+
 	// Start the animation
 	start_animation(egbase, descr().get_unoccupied_animation());
 
@@ -610,6 +671,11 @@
                     const Widelands::Coords& coords,
                     const float scale,
                     RenderTarget* dst) {
+	if (was_immovable_) {
+		dst->blit_animation(point_on_dst, coords, scale, was_immovable_->main_animation(),
+				gametime - animstart_, &get_owner()->get_playercolor());
+	}
+
 	dst->blit_animation(
 	   point_on_dst, coords, scale, anim_, gametime - animstart_, &get_owner()->get_playercolor());
 

=== modified file 'src/logic/map_objects/tribes/building.h'
--- src/logic/map_objects/tribes/building.h	2019-06-23 11:41:17 +0000
+++ src/logic/map_objects/tribes/building.h	2019-08-23 08:59:39 +0000
@@ -56,13 +56,18 @@
 constexpr int32_t kPriorityNormal = 4;
 constexpr int32_t kPriorityHigh = 8;
 
+/* The value "" means that the DescriptionIndex is a normal building, as happens e.g. when enhancing a building.
+ * The value "tribe"/"world" means that the DescriptionIndex refers to an immovable of
+ * OwnerType kTribe/kWorld, as happens e.g. with amazon treetop sentry. This immovable
+ * should therefore always be painted below the building image.
+ */
+using FormerBuildings = std::vector<std::pair<DescriptionIndex, std::string>>;
+
 /*
  * Common to all buildings!
  */
 class BuildingDescr : public MapObjectDescr {
 public:
-	using FormerBuildings = std::vector<DescriptionIndex>;
-
 	BuildingDescr(const std::string& init_descname,
 	              MapObjectType type,
 	              const LuaTable& t,
@@ -169,6 +174,10 @@
 
 	uint32_t get_unoccupied_animation() const;
 
+	int32_t get_built_over_immovable() const {
+		return built_over_immovable_;
+	}
+
 protected:
 	virtual Building& create_object() const = 0;
 	Building& create_constructionsite() const;
@@ -191,6 +200,7 @@
 	   enhanced_from_;        // The building this building was enhanced from, or INVALID_INDEX
 	bool enhanced_building_;  // if it is one, it is bulldozable
 	BuildingHints hints_;     // hints (knowledge) for computer players
+	int32_t built_over_immovable_; // can be built only on nodes where an immovable with this attribute stands
 
 	// for migration, 0 is the default, meaning get_conquers() + 4
 	uint32_t vision_range_;
@@ -224,8 +234,6 @@
 		PCap_Enhancable = 1 << 2,  // can be enhanced to something
 	};
 
-	using FormerBuildings = std::vector<DescriptionIndex>;
-
 public:
 	enum class InfoStringFormat { kCensus, kStatistics, kTooltip };
 
@@ -377,6 +385,7 @@
 
 	// The former buildings names, with the current one in last position.
 	FormerBuildings old_buildings_;
+	const MapObjectDescr* was_immovable_;
 
 private:
 	std::string statistics_string_;

=== modified file 'src/logic/map_objects/tribes/constructionsite.cc'
--- src/logic/map_objects/tribes/constructionsite.cc	2019-06-23 11:41:17 +0000
+++ src/logic/map_objects/tribes/constructionsite.cc	2019-08-23 08:59:39 +0000
@@ -39,6 +39,7 @@
 #include "logic/map_objects/tribes/trainingsite.h"
 #include "logic/map_objects/tribes/tribe_descr.h"
 #include "logic/map_objects/tribes/worker.h"
+#include "logic/map_objects/world/world.h"
 #include "sound/note_sound.h"
 #include "sound/sound_handler.h"
 #include "ui_basic/window.h"
@@ -196,16 +197,23 @@
 	   NoteSound(SoundType::kAmbient, descr().creation_fx(), position_, kFxPriorityAlwaysPlay));
 	PartiallyFinishedBuilding::init(egbase);
 
-	const std::map<DescriptionIndex, uint8_t>* buildcost;
+	const std::map<DescriptionIndex, uint8_t>* buildcost = nullptr;
 	if (!old_buildings_.empty()) {
-		// Enhancement
-		DescriptionIndex was_index = old_buildings_.back();
-		const BuildingDescr* was_descr = owner().tribe().get_building_descr(was_index);
-		info_.was = was_descr;
-		buildcost = &building_->enhancement_cost();
-	} else {
+		// Enhancement and/or built over immovable
+		for (auto it = old_buildings_.end(); it != old_buildings_.begin();) {
+			--it;
+			if (it->second.empty()) {
+				const BuildingDescr* was_descr = owner().tribe().get_building_descr(it->first);
+				info_.was = was_descr;
+				buildcost = &building_->enhancement_cost();
+				break;
+			}
+		}
+	}
+	if (!buildcost) {
 		buildcost = &building_->buildcost();
 	}
+	assert(buildcost);
 
 	//  TODO(unknown): figure out whether planing is necessary
 
@@ -263,7 +271,7 @@
 	if (work_steps_ <= work_completed_) {
 		// Put the real building in place
 		DescriptionIndex becomes_idx = owner().tribe().building_index(building_->name());
-		old_buildings_.push_back(becomes_idx);
+		old_buildings_.push_back(std::make_pair(becomes_idx, ""));
 		Building& b = building_->create(egbase, get_owner(), position_, false, false, old_buildings_);
 		if (Worker* const builder = builder_.get(egbase)) {
 			builder->reset_tasks(dynamic_cast<Game&>(egbase));
@@ -330,7 +338,7 @@
 	Notifications::publish(NoteImmovable(this, NoteImmovable::Ownership::LOST));
 
 	info_.intermediates.push_back(building_);
-	old_buildings_.push_back(owner().tribe().building_index(building_->name()));
+	old_buildings_.push_back(std::make_pair(owner().tribe().building_index(building_->name()), ""));
 	building_ = owner().tribe().get_building_descr(building_->enhancement());
 	assert(building_);
 	info_.becomes = building_;
@@ -609,9 +617,13 @@
                             float scale,
                             RenderTarget* dst) {
 	uint32_t tanim = gametime - animstart_;
-	// Draw the construction site marker
 	const RGBColor& player_color = get_owner()->get_playercolor();
-	dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, anim_, tanim, &player_color);
+	if (was_immovable_) {
+		dst->blit_animation(point_on_dst, coords, scale, was_immovable_->main_animation(), tanim, &player_color);
+	} else {
+		// Draw the construction site marker
+		dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, anim_, tanim, &player_color);
+	}
 
 	// Draw the partially finished building
 

=== modified file 'src/logic/map_objects/tribes/dismantlesite.cc'
--- src/logic/map_objects/tribes/dismantlesite.cc	2019-05-26 17:21:15 +0000
+++ src/logic/map_objects/tribes/dismantlesite.cc	2019-08-23 08:59:39 +0000
@@ -76,16 +76,16 @@
                              const Coords& c,
                              Player* plr,
                              bool loading,
-                             Building::FormerBuildings& former_buildings)
+                             FormerBuildings& former_buildings)
    : PartiallyFinishedBuilding(gdescr) {
 	position_ = c;
 	set_owner(plr);
 
 	assert(!former_buildings.empty());
-	for (DescriptionIndex former_idx : former_buildings) {
-		old_buildings_.push_back(former_idx);
+	for (const auto& pair : former_buildings) {
+		old_buildings_.push_back(pair);
 	}
-	const BuildingDescr* cur_descr = owner().tribe().get_building_descr(old_buildings_.back());
+	const BuildingDescr* cur_descr = owner().tribe().get_building_descr(old_buildings_.back().first);
 	set_building(*cur_descr);
 
 	if (loading) {
@@ -95,6 +95,22 @@
 	}
 }
 
+void DismantleSite::cleanup(EditorGameBase& egbase) {
+	PartiallyFinishedBuilding::cleanup(egbase);
+
+	if (was_immovable_ && work_completed_ >= work_steps_) {
+		// Put the old immovable in place again
+		for (const auto& pair : old_buildings_) {
+			if (!pair.second.empty()) {
+				egbase.create_immovable(position_, pair.first,
+						pair.second == "world" ? MapObjectDescr::OwnerType::kWorld :
+						MapObjectDescr::OwnerType::kTribe, get_owner());
+				break;
+			}
+		}
+	}
+}
+
 /*
 ===============
 Print completion percentage.
@@ -133,9 +149,17 @@
 */
 const Buildcost DismantleSite::count_returned_wares(Building* building) {
 	Buildcost result;
-	for (DescriptionIndex former_idx : building->get_former_buildings()) {
-		const BuildingDescr* former_descr = building->owner().tribe().get_building_descr(former_idx);
-		const Buildcost& return_wares = former_idx != building->get_former_buildings().front() ?
+	DescriptionIndex first_idx = INVALID_INDEX;
+	for (const auto& pair : building->get_former_buildings()) {
+		if (pair.second.empty()) {
+			first_idx = pair.first;
+			break;
+		}
+	}
+	assert(first_idx != INVALID_INDEX);
+	for (const auto& pair : building->get_former_buildings()) {
+		const BuildingDescr* former_descr = building->owner().tribe().get_building_descr(pair.first);
+		const Buildcost& return_wares = pair.first != first_idx ?
 		                                   former_descr->returned_wares_enhanced() :
 		                                   former_descr->returned_wares();
 
@@ -236,8 +260,12 @@
 	uint32_t tanim = gametime - animstart_;
 	const RGBColor& player_color = get_owner()->get_playercolor();
 
-	// Draw the construction site marker
-	dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, anim_, tanim, &player_color);
+	if (was_immovable_) {
+		dst->blit_animation(point_on_dst, coords, scale, was_immovable_->main_animation(), tanim, &player_color);
+	} else {
+		// Draw the construction site marker
+		dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, anim_, tanim, &player_color);
+	}
 
 	// Blit bottom part of the animation according to dismantle progress
 	dst->blit_animation(point_on_dst, coords, scale, building_->get_unoccupied_animation(), tanim,

=== modified file 'src/logic/map_objects/tribes/dismantlesite.h'
--- src/logic/map_objects/tribes/dismantlesite.h	2019-05-05 14:05:07 +0000
+++ src/logic/map_objects/tribes/dismantlesite.h	2019-08-23 08:59:39 +0000
@@ -73,7 +73,7 @@
 	                       const Coords&,
 	                       Player*,
 	                       bool,
-	                       Building::FormerBuildings& former_buildings);
+	                       FormerBuildings& former_buildings);
 
 	bool burn_on_destroy() override;
 	bool init(EditorGameBase&) override;
@@ -85,6 +85,8 @@
 protected:
 	void update_statistics_string(std::string*) override;
 
+	void cleanup(EditorGameBase&) override;
+
 	uint32_t build_step_time() const override {
 		return DISMANTLESITE_STEP_TIME;
 	}

=== modified file 'src/logic/map_objects/tribes/militarysite.cc'
--- src/logic/map_objects/tribes/militarysite.cc	2019-06-23 11:41:17 +0000
+++ src/logic/map_objects/tribes/militarysite.cc	2019-08-23 08:59:39 +0000
@@ -162,7 +162,7 @@
 	       map.calc_distance(enemy.get_position(), military_site_->get_position()))
 		return;
 
-	if (map.find_bobs(Area<FCoords>(map.get_fcoords(military_site_->base_flag().get_position()), 2),
+	if (map.find_bobs(game, Area<FCoords>(map.get_fcoords(military_site_->base_flag().get_position()), 2),
 	                  nullptr, FindBobEnemySoldier(owner)))
 		return;
 
@@ -261,7 +261,7 @@
 	// In fact we do not conquer it, but place a new building of same type at
 	// the old location.
 
-	Building::FormerBuildings former_buildings = military_site_->old_buildings_;
+	FormerBuildings former_buildings = military_site_->old_buildings_;
 
 	// The enemy conquers the building
 	// In fact we do not conquer it, but place a new building of same type at
@@ -844,7 +844,7 @@
 
 	// Search in a radius of 3 (needed for big militarysites)
 	FCoords const fc = game.map().get_fcoords(get_position());
-	game.map().find_immovables(Area<FCoords>(fc, 3), &immovables);
+	game.map().find_immovables(game, Area<FCoords>(fc, 3), &immovables);
 
 	for (uint32_t i = 0; i < immovables.size(); ++i)
 		if (upcast(MilitarySite const, militarysite, immovables[i].object))

=== modified file 'src/logic/map_objects/tribes/production_program.cc'
--- src/logic/map_objects/tribes/production_program.cc	2019-05-18 11:58:43 +0000
+++ src/logic/map_objects/tribes/production_program.cc	2019-08-23 08:59:39 +0000
@@ -1519,7 +1519,7 @@
 	std::vector<ImmovableFound> immovables;
 	CheckStepWalkOn cstep(MOVECAPS_WALK, true);
 	Area<FCoords> area(map.get_fcoords(psite.base_flag().get_position()), radius);
-	if (map.find_reachable_immovables(area, &immovables, cstep, FindImmovableByDescr(descr))) {
+	if (map.find_reachable_immovables(game, area, &immovables, cstep, FindImmovableByDescr(descr))) {
 		state.objvar = immovables[0].object;
 
 		psite.working_positions_[psite.main_worker_].worker->update_task_buildingwork(game);
@@ -1532,7 +1532,7 @@
 	// 10 is custom value to make sure the "water" is at least 10 nodes big
 	fna.add(FindNodeShore(10));
 	fna.add(FindNodeImmovableSize(FindNodeImmovableSize::sizeNone));
-	if (map.find_reachable_fields(area, &fields, cstep, fna)) {
+	if (map.find_reachable_fields(game, area, &fields, cstep, fna)) {
 		// Testing received fields to get one with less immovables nearby
 		Coords best_coords = fields.back();  // Just to initialize it
 		uint32_t best_score = std::numeric_limits<uint32_t>::max();
@@ -1542,7 +1542,7 @@
 			// Counting immovables nearby
 			std::vector<ImmovableFound> found_immovables;
 			const uint32_t imm_count =
-			   map.find_immovables(Area<FCoords>(map.get_fcoords(coords), 2), &found_immovables);
+			   map.find_immovables(game, Area<FCoords>(map.get_fcoords(coords), 2), &found_immovables);
 			if (best_score > imm_count) {
 				best_score = imm_count;
 				best_coords = coords;

=== modified file 'src/logic/map_objects/tribes/ship.cc'
--- src/logic/map_objects/tribes/ship.cc	2019-05-27 14:28:34 +0000
+++ src/logic/map_objects/tribes/ship.cc	2019-08-23 08:59:39 +0000
@@ -207,7 +207,7 @@
 	FCoords position = get_position();
 	Area<FCoords> area(position, 1);
 	std::vector<Bob*> ships;
-	game.map().find_bobs(area, &ships, FindBobShip());
+	game.map().find_bobs(game, area, &ships, FindBobShip());
 
 	for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
 		if (*it == this)
@@ -406,7 +406,7 @@
 
 			// 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 ||
+			if ((map->get_max_nodecaps(game, fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
 			    map->find_portdock(fc).empty()) {
 				continue;
 			}
@@ -463,7 +463,7 @@
 
 			Area<FCoords> area(node, 0);
 			std::vector<Bob*> ships;
-			map.find_bobs(area, &ships, FindBobShip());
+			map.find_bobs(game, area, &ships, FindBobShip());
 
 			for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
 				if (*it == this)
@@ -922,9 +922,9 @@
 
 	// Make sure that we have space to squeeze in a lumberjack
 	std::vector<ImmovableFound> trees_rocks;
-	game.map().find_immovables(Area<FCoords>(game.map().get_fcoords(c), 3), &trees_rocks,
+	game.map().find_immovables(game, Area<FCoords>(game.map().get_fcoords(c), 3), &trees_rocks,
 	                           FindImmovableAttribute(MapObjectDescr::get_attribute_id("tree")));
-	game.map().find_immovables(Area<FCoords>(game.map().get_fcoords(c), 3), &trees_rocks,
+	game.map().find_immovables(game, Area<FCoords>(game.map().get_fcoords(c), 3), &trees_rocks,
 	                           FindImmovableAttribute(MapObjectDescr::get_attribute_id("rocks")));
 	for (auto& immo : trees_rocks) {
 		immo.object->remove(game);

=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc	2019-05-27 14:25:47 +0000
+++ src/logic/map_objects/tribes/soldier.cc	2019-08-23 08:59:39 +0000
@@ -781,7 +781,7 @@
 struct FindNodeOwned {
 	explicit FindNodeOwned(PlayerNumber owner) : owner_(owner) {
 	}
-	bool accept(const Map&, const FCoords& coords) const {
+	bool accept(const EditorGameBase&, const FCoords& coords) const {
 		return (coords.field->get_owned_by() == owner_);
 	}
 
@@ -926,7 +926,7 @@
 				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()),
+				if (map.find_reachable_fields(game, area, &coords, CheckStepDefault(descr().movecaps()),
 				                              FindNodeOwned(get_owner()->player_number()))) {
 					// Found home land
 					target = coords.front();
@@ -971,7 +971,7 @@
 		}
 		//  Any enemy soldier at baseflag count as defender.
 		std::vector<Bob*> soldiers;
-		map.find_bobs(Area<FCoords>(map.get_fcoords(enemy->base_flag().get_position()), 0), &soldiers,
+		map.find_bobs(game, Area<FCoords>(map.get_fcoords(enemy->base_flag().get_position()), 0), &soldiers,
 		              FindBobEnemySoldier(get_owner()));
 		defenders += soldiers.size();
 	}
@@ -1172,7 +1172,7 @@
 			// Check if any attacker is waiting us to fight
 			std::vector<Bob*> soldiers;
 			game.map().find_bobs(
-			   Area<FCoords>(get_position(), 0), &soldiers, FindBobEnemySoldier(get_owner()));
+			   game, Area<FCoords>(get_position(), 0), &soldiers, FindBobEnemySoldier(get_owner()));
 
 			for (Bob* temp_bob : soldiers) {
 				if (upcast(Soldier, temp_soldier, temp_bob)) {
@@ -1196,7 +1196,7 @@
 
 	// We are outside our building, get list of enemy soldiers attacking us
 	std::vector<Bob*> soldiers;
-	game.map().find_bobs(Area<FCoords>(get_position(), 10), &soldiers,
+	game.map().find_bobs(game, Area<FCoords>(get_position(), 10), &soldiers,
 	                     FindBobSoldierAttackingPlayer(game, *get_owner()));
 
 	if (soldiers.empty() || (get_current_health() < get_retreat_health())) {
@@ -1643,7 +1643,7 @@
 void Soldier::send_space_signals(Game& game) {
 	std::vector<Bob*> soldiers;
 
-	game.map().find_bobs(Area<FCoords>(get_position(), 1), &soldiers, FindBobSoldierOnBattlefield());
+	game.map().find_bobs(game, Area<FCoords>(get_position(), 1), &soldiers, FindBobSoldierOnBattlefield());
 
 	for (Bob* temp_soldier : soldiers) {
 		if (upcast(Soldier, soldier, temp_soldier)) {
@@ -1659,7 +1659,7 @@
 		// Let's collect all reachable attack_target sites in vicinity (militarysites mainly)
 		std::vector<BaseImmovable*> attack_targets;
 		game.map().find_reachable_immovables_unique(
-		   Area<FCoords>(get_position(), kMaxProtectionRadius), attack_targets,
+		   game, Area<FCoords>(get_position(), kMaxProtectionRadius), attack_targets,
 		   CheckStepWalkOn(descr().movecaps(), false), FindImmovableAttackTarget());
 
 		for (BaseImmovable* temp_attack_target : attack_targets) {

=== modified file 'src/logic/map_objects/tribes/warehouse.cc'
--- src/logic/map_objects/tribes/warehouse.cc	2019-06-23 11:41:17 +0000
+++ src/logic/map_objects/tribes/warehouse.cc	2019-08-23 08:59:39 +0000
@@ -86,7 +86,7 @@
 	       map.calc_distance(enemy.get_position(), warehouse_->get_position()))
 		return;
 
-	if (map.find_bobs(Area<FCoords>(map.get_fcoords(warehouse_->base_flag().get_position()), 2),
+	if (map.find_bobs(game, Area<FCoords>(map.get_fcoords(warehouse_->base_flag().get_position()), 2),
 	                  nullptr, FindBobEnemySoldier(owner)))
 		return;
 

=== modified file 'src/logic/map_objects/tribes/worker.cc'
--- src/logic/map_objects/tribes/worker.cc	2019-05-28 17:01:30 +0000
+++ src/logic/map_objects/tribes/worker.cc	2019-08-23 08:59:39 +0000
@@ -346,10 +346,10 @@
 			}
 			std::vector<ImmovableFound> list;
 			if (action.iparam2 < 0)
-				map.find_reachable_immovables(area, &list, cstep);
+				map.find_reachable_immovables(game, area, &list, cstep);
 			else
 				map.find_reachable_immovables(
-				   area, &list, cstep, FindImmovableAttribute(action.iparam2));
+				   game, area, &list, cstep, FindImmovableAttribute(action.iparam2));
 
 			for (int idx = list.size() - 1; idx >= 0; idx--) {
 				if (upcast(Immovable, imm, list[idx].object)) {
@@ -377,9 +377,9 @@
 			}
 			std::vector<Bob*> list;
 			if (action.iparam2 < 0)
-				map.find_reachable_bobs(area, &list, cstep);
+				map.find_reachable_bobs(game, area, &list, cstep);
 			else
-				map.find_reachable_bobs(area, &list, cstep, FindBobAttribute(action.iparam2));
+				map.find_reachable_bobs(game, area, &list, cstep, FindBobAttribute(action.iparam2));
 
 			for (int idx = list.size() - 1; idx >= 0; idx--) {
 				if (upcast(MapObject, bob, list[idx])) {
@@ -530,12 +530,12 @@
 	explicit FindNodeSpace(BaseImmovable* const ignoreimm) : ignoreimmovable(ignoreimm) {
 	}
 
-	bool accept(const Map& map, const FCoords& coords) const {
+	bool accept(const EditorGameBase& egbase, const FCoords& coords) const {
 		if (!(coords.field->nodecaps() & MOVECAPS_WALK))
 			return false;
 
 		for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
-			FCoords const neighb = map.get_neighbour(coords, dir);
+			FCoords const neighb = egbase.map().get_neighbour(coords, dir);
 
 			if (!(neighb.field->nodecaps() & MOVECAPS_WALK) &&
 			    neighb.field->get_immovable() != ignoreimmovable)
@@ -573,7 +573,7 @@
 	if (action.iparam3)
 		functor.add(FindNodeSpace(get_location(game)));
 
-	if (!map.find_reachable_fields(area, &list, cstep, functor)) {
+	if (!map.find_reachable_fields(game, area, &list, cstep, functor)) {
 
 		// This is default note "out of resources" sent to a player
 		FailNotificationType fail_notification_type = FailNotificationType::kDefault;
@@ -593,7 +593,7 @@
 				functorAnyFull.add(FindNodeSpace(get_location(game)));
 
 			// If there are fields full of fish, we change the type of notification
-			if (map.find_reachable_fields(area, &list, cstep, functorAnyFull)) {
+			if (map.find_reachable_fields(game, area, &list, cstep, functorAnyFull)) {
 				fail_notification_type = FailNotificationType::kFull;
 			}
 		}
@@ -920,6 +920,54 @@
 	return true;
 }
 
+bool Worker::run_terraform(Game& game, State& state, const Action&) {
+	const World& world = game.world();
+	std::map<TCoords<FCoords>, DescriptionIndex> triangles;
+	const FCoords f = get_position();
+	FCoords tln, ln, trn;
+	game.map().get_tln(f, &tln);
+	game.map().get_trn(f, &trn);
+	game.map().get_ln(f, &ln);
+
+	DescriptionIndex di = world.get_terrain_index(world.terrain_descr(f.field->terrain_r()).enhancement());
+	if (di != INVALID_INDEX) {
+		triangles.emplace(std::make_pair(TCoords<FCoords>(f, TriangleIndex::R), di));
+	}
+	di = world.get_terrain_index(world.terrain_descr(f.field->terrain_d()).enhancement());
+	if (di != INVALID_INDEX) {
+		triangles.emplace(std::make_pair(TCoords<FCoords>(f, TriangleIndex::D), di));
+	}
+	di = world.get_terrain_index(world.terrain_descr(tln.field->terrain_r()).enhancement());
+	if (di != INVALID_INDEX) {
+		triangles.emplace(std::make_pair(TCoords<FCoords>(tln, TriangleIndex::R), di));
+	}
+	di = world.get_terrain_index(world.terrain_descr(tln.field->terrain_d()).enhancement());
+	if (di != INVALID_INDEX) {
+		triangles.emplace(std::make_pair(TCoords<FCoords>(tln, TriangleIndex::D), di));
+	}
+	di = world.get_terrain_index(world.terrain_descr(ln.field->terrain_r()).enhancement());
+	if (di != INVALID_INDEX) {
+		triangles.emplace(std::make_pair(TCoords<FCoords>(ln, TriangleIndex::R), di));
+	}
+	di = world.get_terrain_index(world.terrain_descr(trn.field->terrain_d()).enhancement());
+	if (di != INVALID_INDEX) {
+		triangles.emplace(std::make_pair(TCoords<FCoords>(trn, TriangleIndex::D), di));
+	}
+
+	if (triangles.empty()) {
+		send_signal(game, "fail");
+		pop_task(game);
+		return false;
+	}
+	assert(game.mutable_map());
+	auto it = triangles.begin();
+	for (size_t rand = game.logic_rand() % triangles.size(); rand > 0; --rand) ++it;
+	game.mutable_map()->change_terrain(game, it->first, it->second);
+	++state.ivar1;
+	schedule_act(game, 10);
+	return true;
+}
+
 /**
  * Simply remove the currently selected object - make no fuss about it.
  */
@@ -2462,7 +2510,7 @@
 	std::vector<ImmovableFound> flags;
 	uint32_t vision = descr().vision_range();
 	uint32_t maxdist = 4 * vision;
-	if (map.find_immovables(Area<FCoords>(map.get_fcoords(get_position()), maxdist), &flags,
+	if (map.find_immovables(game, Area<FCoords>(map.get_fcoords(get_position()), maxdist), &flags,
 	                        FindFlagWithPlayersWarehouse(*get_owner()))) {
 		uint32_t bestdist = 0;
 		Flag* best = nullptr;
@@ -2576,7 +2624,7 @@
 		ffa.add(FindNodeImmovableSize(FindNodeImmovableSize::sizeNone), false);
 		ffa.add(FindNodeImmovableAttribute(RESI), true);
 
-		if (map.find_reachable_fields(owner_area, &list, cstep, ffa)) {
+		if (map.find_reachable_fields(game, owner_area, &list, cstep, ffa)) {
 			FCoords target;
 
 			// is center a mountain piece?
@@ -2840,7 +2888,7 @@
 		std::vector<ImmovableFound> found_sites;
 		CheckStepWalkOn csteb(MOVECAPS_WALK, true);
 		map.find_reachable_immovables(
-		   revealations, &found_sites, csteb, FindFlagOf(FindForeignMilitarysite(player)));
+		   game, revealations, &found_sites, csteb, FindFlagOf(FindForeignMilitarysite(player)));
 
 		add_sites(game, map, player, found_sites);
 
@@ -2868,7 +2916,7 @@
 	Time oldest_time = game.get_gametime();
 
 	// if some fields can be reached
-	if (map.find_reachable_fields(exploring_area, &list, cstep, ffa) > 0) {
+	if (map.find_reachable_fields(game, exploring_area, &list, cstep, ffa) > 0) {
 		// Parse randomly the reachable fields, maximum 50 iterations
 		uint8_t iterations = list.size() % 51;
 		uint8_t oldest_distance = 0;
@@ -2942,7 +2990,7 @@
 	// would fail. Therefore, the looping can be a bit silly to more knowledgeable readers.
 	for (unsigned vicinity = 1; vicinity < 4; vicinity++) {
 		Area<FCoords> exploring_area(map.get_fcoords(scoutat.scoutme), vicinity);
-		if (map.find_reachable_fields(exploring_area, &surrounding_places, cstep, fna) > 0) {
+		if (map.find_reachable_fields(game, exploring_area, &surrounding_places, cstep, fna) > 0) {
 			unsigned formax = surrounding_places.size();
 			if (3 + vicinity < formax) {
 				formax = 3 + vicinity;

=== modified file 'src/logic/map_objects/tribes/worker.h'
--- src/logic/map_objects/tribes/worker.h	2019-04-24 06:01:37 +0000
+++ src/logic/map_objects/tribes/worker.h	2019-08-23 08:59:39 +0000
@@ -256,6 +256,7 @@
 	bool run_scout(Game&, State&, const Action&);
 	bool run_playsound(Game&, State&, const Action&);
 	bool run_construct(Game&, State&, const Action&);
+	bool run_terraform(Game&, State&, const Action&);
 
 	// Forester considers multiple spaces in findspace, unlike others.
 	int16_t findspace_helper_for_forester(const Coords& pos, const Map& map, Game& game);

=== modified file 'src/logic/map_objects/tribes/worker_program.cc'
--- src/logic/map_objects/tribes/worker_program.cc	2019-05-11 13:48:12 +0000
+++ src/logic/map_objects/tribes/worker_program.cc	2019-08-23 08:59:39 +0000
@@ -75,6 +75,7 @@
 - `scout`_
 - `playsound`_
 - `construct`_
+- `terraform`_
 */
 
 const WorkerProgram::ParseMap WorkerProgram::parsemap_[] = {
@@ -95,6 +96,7 @@
    {"scout", &WorkerProgram::parse_scout},
    {"playsound", &WorkerProgram::parse_playsound},
    {"construct", &WorkerProgram::parse_construct},
+   {"terraform", &WorkerProgram::parse_terraform},
 
    {nullptr, nullptr}};
 
@@ -346,6 +348,8 @@
       * ``big``: Big building plots only.
       * ``mine``: Mining plots only.
       * ``port``: Port spaces only.
+      * ``swim``: Anything on the coast.
+      * ``terraform``: A node with terrain that can be enhanced
 
    :arg int radius: Search for map fields within the given radius around the worker.
 
@@ -439,7 +443,9 @@
 			} sizenames[] = {{"any", FindNodeSize::sizeAny},     {"build", FindNodeSize::sizeBuild},
 			                 {"small", FindNodeSize::sizeSmall}, {"medium", FindNodeSize::sizeMedium},
 			                 {"big", FindNodeSize::sizeBig},     {"mine", FindNodeSize::sizeMine},
-			                 {"port", FindNodeSize::sizePort},   {nullptr, 0}};
+			                 {"port", FindNodeSize::sizePort},   {"swim", FindNodeSize::sizeSwim},
+			                 {"terraform", FindNodeSize::sizeTerraform},
+			                 {nullptr, 0}};
 
 			int32_t index;
 
@@ -761,6 +767,28 @@
 }
 
 /* RST
+terraform
+^^^^^^^^^
+.. function:: terraform
+
+   Turns the terrain of one of the triangles around the current node into its enhancement terrain. Example::
+
+      terraform = {
+         "findspace=size:terraform radius:6",
+         "walk=coords",
+         "animate=dig 2000",
+         "terraform",
+         "return"
+      }
+*/
+void WorkerProgram::parse_terraform(Worker::Action* act, const std::vector<std::string>& cmd) {
+	if (cmd.size() > 1) {
+		throw wexception("terraform takes no arguments");
+	}
+	act->function = &Worker::run_terraform;
+}
+
+/* RST
 removeobject
 ^^^^^^^^^^^^
 .. function:: removeobject

=== modified file 'src/logic/map_objects/tribes/worker_program.h'
--- src/logic/map_objects/tribes/worker_program.h	2019-02-23 11:00:49 +0000
+++ src/logic/map_objects/tribes/worker_program.h	2019-08-23 08:59:39 +0000
@@ -91,6 +91,7 @@
 	void parse_scout(Worker::Action* act, const std::vector<std::string>& cmd);
 	void parse_playsound(Worker::Action* act, const std::vector<std::string>& cmd);
 	void parse_construct(Worker::Action* act, const std::vector<std::string>& cmd);
+	void parse_terraform(Worker::Action* act, const std::vector<std::string>& cmd);
 
 	const std::string name_;
 	const WorkerDescr& worker_;

=== modified file 'src/logic/map_objects/world/terrain_description.cc'
--- src/logic/map_objects/world/terrain_description.cc	2019-02-23 11:00:49 +0000
+++ src/logic/map_objects/world/terrain_description.cc	2019-08-23 08:59:39 +0000
@@ -113,6 +113,16 @@
 		custom_tooltips_ = table.get_table("tooltips")->array_entries<std::string>();
 	}
 
+	if (table.has_key("enhancement")) {
+		enhancement_ = table.get_string("enhancement");
+		if (enhancement_ == name_) {
+			throw GameDataError("%s: a terrain cannot be enhanced to itself", name_.c_str());
+		}
+		// Other invalid terrains will be detected in World::postload
+	} else {
+		enhancement_ = "";
+	}
+
 	if (!(0 < fertility_ && fertility_ < 1000)) {
 		throw GameDataError("%s: fertility is not in (0, 1000).", name_.c_str());
 	}
@@ -256,6 +266,10 @@
 	return fertility_;
 }
 
+const std::string& TerrainDescription::enhancement() const {
+	return enhancement_;
+}
+
 void TerrainDescription::set_minimap_color(const RGBColor& color) {
 	for (int i = -128; i < 128; i++) {
 		const int shade = 128 + i;

=== modified file 'src/logic/map_objects/world/terrain_description.h'
--- src/logic/map_objects/world/terrain_description.h	2019-04-11 05:45:55 +0000
+++ src/logic/map_objects/world/terrain_description.h	2019-08-23 08:59:39 +0000
@@ -123,6 +123,9 @@
 	/// Fertility, ranging from 0 to 1000.
 	int fertility() const;
 
+	// The terrain which certain workers can transform this terrain into.
+	const std::string& enhancement() const;
+
 	/// Additional tooptip entries for the editor
 	const std::vector<std::string>& custom_tooltips() const {
 		return custom_tooltips_;
@@ -142,6 +145,7 @@
 	int temperature_;
 	int fertility_;
 	int humidity_;
+	std::string enhancement_;
 	std::vector<std::string> texture_paths_;
 	std::vector<const Image*> textures_;
 	RGBColor minimap_colors_[256];

=== modified file 'src/logic/map_objects/world/world.cc'
--- src/logic/map_objects/world/world.cc	2019-02-23 11:00:49 +0000
+++ src/logic/map_objects/world/world.cc	2019-08-23 08:59:39 +0000
@@ -66,6 +66,18 @@
 	}
 }
 
+void World::postload() {
+	const size_t nr_t = get_nr_terrains();
+	for (size_t i = 0; i < nr_t; ++i) {
+		const TerrainDescription& t = terrain_descr(i);
+		if (!t.enhancement().empty()) {
+			if (!terrain_descr(t.enhancement())) {
+				throw GameDataError("Terrain %s: Unknown enhancement %s", t.name().c_str(), t.enhancement().c_str());
+			}
+		}
+	}
+}
+
 const DescriptionMaintainer<TerrainDescription>& World::terrains() const {
 	return *terrains_;
 }
@@ -133,6 +145,14 @@
 	return i != INVALID_INDEX ? terrains_->get_mutable(i) : nullptr;
 }
 
+DescriptionIndex World::get_terrain_index(const std::string& name) const {
+	return terrains_->get_index(name);
+}
+
+DescriptionIndex World::get_nr_terrains() const {
+	return terrains_->size();
+}
+
 DescriptionIndex World::get_critter(char const* const l) const {
 	return critters_->get_index(l);
 }

=== modified file 'src/logic/map_objects/world/world.h'
--- src/logic/map_objects/world/world.h	2019-03-01 04:19:53 +0000
+++ src/logic/map_objects/world/world.h	2019-08-23 08:59:39 +0000
@@ -48,6 +48,8 @@
 	const DescriptionMaintainer<TerrainDescription>& terrains() const;
 	TerrainDescription& terrain_descr(DescriptionIndex i) const;
 	const TerrainDescription* terrain_descr(const std::string& name) const;
+	DescriptionIndex get_terrain_index(const std::string& name) const;
+	DescriptionIndex get_nr_terrains() const;
 
 	const DescriptionMaintainer<CritterDescr>& critters() const;
 	DescriptionIndex get_critter(char const* const l) const;
@@ -89,6 +91,7 @@
 	// Load the graphics for the world. Animations are loaded on
 	// demand.
 	void load_graphics();
+	void postload();
 
 private:
 	std::unique_ptr<DescriptionMaintainer<CritterDescr>> critters_;

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc	2019-06-24 19:44:35 +0000
+++ src/logic/player.cc	2019-08-23 08:59:39 +0000
@@ -98,12 +98,12 @@
  */
 void find_former_buildings(const Tribes& tribes,
                            const Widelands::DescriptionIndex bi,
-                           Widelands::Building::FormerBuildings* former_buildings) {
+                           Widelands::FormerBuildings* former_buildings) {
 	assert(former_buildings && former_buildings->empty());
-	former_buildings->push_back(bi);
+	former_buildings->push_back(std::make_pair(bi, ""));
 
 	for (;;) {
-		Widelands::DescriptionIndex oldest_idx = former_buildings->front();
+		Widelands::DescriptionIndex oldest_idx = former_buildings->front().first;
 		const Widelands::BuildingDescr* oldest = tribes.get_building_descr(oldest_idx);
 		if (!oldest->is_enhanced()) {
 			break;
@@ -111,7 +111,7 @@
 		for (DescriptionIndex i = 0; i < tribes.nrbuildings(); ++i) {
 			const BuildingDescr* building_descr = tribes.get_building_descr(i);
 			if (building_descr->enhancement() == oldest_idx) {
-				former_buildings->insert(former_buildings->begin(), i);
+				former_buildings->insert(former_buildings->begin(), std::make_pair(i, ""));
 				break;
 			}
 		}
@@ -534,9 +534,9 @@
 }
 
 Building& Player::force_building(Coords const location,
-                                 const BuildingDescr::FormerBuildings& former_buildings) {
+                                 const FormerBuildings& former_buildings) {
 	const Map& map = egbase().map();
-	DescriptionIndex idx = former_buildings.back();
+	DescriptionIndex idx = former_buildings.back().first;
 	const BuildingDescr* descr = egbase().tribes().get_building_descr(idx);
 	terraform_for_building(egbase(), player_number(), location, descr);
 	FCoords flag_loc;
@@ -548,14 +548,14 @@
 
 Building& Player::force_csite(Coords const location,
                               DescriptionIndex b_idx,
-                              const BuildingDescr::FormerBuildings& former_buildings) {
+                              const FormerBuildings& former_buildings) {
 	EditorGameBase& eg = egbase();
 	const Map& map = eg.map();
 	const Tribes& tribes = eg.tribes();
 	const PlayerNumber pn = player_number();
 
 	if (!former_buildings.empty()) {
-		DescriptionIndex idx = former_buildings.back();
+		DescriptionIndex idx = former_buildings.back().first;
 		const BuildingDescr* descr = tribes.get_building_descr(idx);
 		terraform_for_building(eg, pn, location, descr);
 	}
@@ -577,9 +577,7 @@
 Building* Player::build(Coords c,
                         DescriptionIndex const idx,
                         bool constructionsite,
-                        BuildingDescr::FormerBuildings& former_buildings) {
-	int32_t buildcaps;
-
+                        FormerBuildings& former_buildings) {
 	// Validate building type
 	if (!tribe().has_building(idx)) {
 		return nullptr;
@@ -594,21 +592,44 @@
 	// Validate build position
 	const Map& map = egbase().map();
 	map.normalize_coords(c);
-	buildcaps = get_buildcaps(map.get_fcoords(c));
-
+	const FCoords fc = map.get_fcoords(c);
+	if (!fc.field->is_interior(player_number()) || !map.br_n(fc).field->is_interior(player_number())) {
+		return nullptr;
+	}
+	if (descr->get_size() >= BaseImmovable::BIG &&
+			!((map.l_n(fc).field->is_interior(player_number())) &&
+			(map.tr_n(fc).field->is_interior(player_number())) &&
+			(map.tl_n(fc).field->is_interior(player_number())))) {
+		return nullptr;
+	}
+
+	if (descr->get_built_over_immovable() >= 0 &&
+			!(fc.field->get_immovable() &&
+			fc.field->get_immovable()->has_attribute(descr->get_built_over_immovable()))) {
+		return nullptr;
+	}
+
+	const NodeCaps buildcaps = descr->get_built_over_immovable() < 0 ?
+			get_buildcaps(fc) : map.get_max_nodecaps(egbase(), fc);
 	if (descr->get_ismine()) {
-		if (!(buildcaps & BUILDCAPS_MINE))
+		if (!(buildcaps & BUILDCAPS_MINE)) {
 			return nullptr;
+		}
 	} else {
-		if ((buildcaps & BUILDCAPS_SIZEMASK) < descr->get_size() - BaseImmovable::SMALL + 1)
-			return nullptr;
-		if (descr->get_isport() && !(buildcaps & BUILDCAPS_PORT))
-			return nullptr;
+		if ((buildcaps & BUILDCAPS_SIZEMASK) < descr->get_size() - BaseImmovable::SMALL + 1) {
+			return nullptr;
+		}
+		if (descr->get_isport() && !(buildcaps & BUILDCAPS_PORT)) {
+			return nullptr;
+		}
+	}
+	if (!(get_buildcaps(map.br_n(fc)) & BUILDCAPS_FLAG)) {
+		return nullptr;
 	}
 
-	if (constructionsite)
+	if (constructionsite) {
 		return &egbase().warp_constructionsite(c, player_number_, idx, false, former_buildings);
-	else {
+	} else {
 		return &descr->create(egbase(), this, c, false, false, former_buildings);
 	}
 }
@@ -747,7 +768,7 @@
 	if (building->get_owner() == this &&
 	    (index_of_new_building == INVALID_INDEX ||
 	     building->descr().enhancement() == index_of_new_building)) {
-		Building::FormerBuildings former_buildings = building->get_former_buildings();
+		FormerBuildings former_buildings = building->get_former_buildings();
 		const Coords position = building->get_position();
 
 		//  Get workers and soldiers
@@ -925,7 +946,7 @@
 	const Map& map = egbase().map();
 	std::vector<BaseImmovable*> flags;
 
-	map.find_reachable_immovables_unique(Area<FCoords>(map.get_fcoords(flag.get_position()), 25),
+	map.find_reachable_immovables_unique(egbase(), Area<FCoords>(map.get_fcoords(flag.get_position()), 25),
 	                                     flags, CheckStepDefault(MOVECAPS_WALK),
 	                                     FindFlagOf(FindImmovablePlayerMilitarySite(*this)));
 

=== modified file 'src/logic/player.h'
--- src/logic/player.h	2019-05-25 10:47:18 +0000
+++ src/logic/player.h	2019-08-23 08:59:39 +0000
@@ -507,11 +507,11 @@
 	Flag* build_flag(const Coords&);   /// Build a flag if it is allowed.
 	Road& force_road(const Path&);
 	Road* build_road(const Path&);  /// Build a road if it is allowed.
-	Building& force_building(Coords, const Building::FormerBuildings&);
+	Building& force_building(Coords, const FormerBuildings&);
 	Building& force_csite(Coords,
 	                      DescriptionIndex,
-	                      const Building::FormerBuildings& = Building::FormerBuildings());
-	Building* build(Coords, DescriptionIndex, bool, Building::FormerBuildings&);
+	                      const FormerBuildings& = FormerBuildings());
+	Building* build(Coords, DescriptionIndex, bool, FormerBuildings&);
 	void bulldoze(PlayerImmovable&, bool recurse = false);
 	void flagaction(Flag&);
 	void start_stop_building(PlayerImmovable&);
@@ -698,7 +698,7 @@
 
 void find_former_buildings(const Tribes& tribes,
                            const DescriptionIndex bi,
-                           Building::FormerBuildings* former_buildings);
+                           FormerBuildings* former_buildings);
 }  // namespace Widelands
 
 #endif  // end of include guard: WL_LOGIC_PLAYER_H

=== modified file 'src/logic/playercommand.cc'
--- src/logic/playercommand.cc	2019-06-23 14:28:50 +0000
+++ src/logic/playercommand.cc	2019-08-23 08:59:39 +0000
@@ -268,7 +268,7 @@
 
 void CmdBuild::execute(Game& game) {
 	// Empty former vector since its a new csite.
-	Building::FormerBuildings former_buildings;
+	FormerBuildings former_buildings;
 	game.get_player(sender())->build(coords, bi, true, former_buildings);
 }
 

=== modified file 'src/map_io/map_bob_packet.cc'
--- src/map_io/map_bob_packet.cc	2019-06-23 10:30:26 +0000
+++ src/map_io/map_bob_packet.cc	2019-08-23 08:59:39 +0000
@@ -77,7 +77,7 @@
 	fr.open(fs, "binary/bob");
 
 	Map* map = egbase.mutable_map();
-	map->recalc_whole_map(egbase.world());  //  for movecaps checks in ReadBob
+	map->recalc_whole_map(egbase);  //  for movecaps checks in ReadBob
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
 		if (packet_version == kCurrentPacketVersion)

=== modified file 'src/map_io/map_building_packet.cc'
--- src/map_io/map_building_packet.cc	2019-02-23 11:00:49 +0000
+++ src/map_io/map_building_packet.cc	2019-08-23 08:59:39 +0000
@@ -90,7 +90,7 @@
 							if (building_type == kTypeConstructionSite) {
 								building = &egbase.warp_constructionsite(c, p, index, true);
 							} else if (building_type == kTypeDismantleSite) {
-								Building::FormerBuildings formers = {index};
+								FormerBuildings formers = {{index, ""}};
 								building = &egbase.warp_dismantlesite(c, p, true, formers);
 							} else {
 								building = &egbase.warp_building(c, p, index);

=== modified file 'src/map_io/map_buildingdata_packet.cc'
--- src/map_io/map_buildingdata_packet.cc	2019-06-23 11:41:17 +0000
+++ src/map_io/map_buildingdata_packet.cc	2019-08-23 08:59:39 +0000
@@ -56,7 +56,7 @@
 namespace Widelands {
 
 // Overall package version
-constexpr uint16_t kCurrentPacketVersion = 4;
+constexpr uint16_t kCurrentPacketVersion = 5;
 
 // Building type package versions
 constexpr uint16_t kCurrentPacketVersionDismantlesite = 1;
@@ -85,7 +85,7 @@
 
 	try {
 		uint16_t const packet_version = fr.unsigned_16();
-		if (packet_version == kCurrentPacketVersion) {
+		if (packet_version <= kCurrentPacketVersion && packet_version >= 4) {
 			while (!fr.end_of_file()) {
 				Serial const serial = fr.unsigned_32();
 				try {
@@ -144,10 +144,19 @@
 						building.leave_allow_ = nullptr;
 					}
 
-					while (fr.unsigned_8()) {
-						DescriptionIndex oldidx =
-						   building.owner().tribe().safe_building_index(fr.c_string());
-						building.old_buildings_.push_back(oldidx);
+					if (packet_version >= kCurrentPacketVersion) {
+						while (fr.unsigned_8()) {
+							DescriptionIndex oldidx =
+							   building.owner().tribe().safe_building_index(fr.c_string());
+							const std::string type(fr.c_string());
+							building.old_buildings_.push_back(std::make_pair(oldidx, type));
+						}
+					} else {
+						while (fr.unsigned_8()) {
+							DescriptionIndex oldidx =
+							   building.owner().tribe().safe_building_index(fr.c_string());
+							building.old_buildings_.push_back(std::make_pair(oldidx, ""));
+						}
 					}
 					// Only construction sites may have an empty list
 					if (building.old_buildings_.empty() && !is_a(ConstructionSite, &building)) {
@@ -905,10 +914,11 @@
 			}
 			{
 				const TribeDescr& td = building->owner().tribe();
-				for (DescriptionIndex b_idx : building->old_buildings_) {
-					const BuildingDescr* b_descr = td.get_building_descr(b_idx);
+				for (const auto& pair : building->old_buildings_) {
+					const BuildingDescr* b_descr = td.get_building_descr(pair.first);
 					fw.unsigned_8(1);
 					fw.string(b_descr->name());
+					fw.string(pair.second);
 				}
 				fw.unsigned_8(0);
 			}

=== modified file 'src/map_io/map_port_spaces_packet.cc'
--- src/map_io/map_port_spaces_packet.cc	2019-03-24 13:13:34 +0000
+++ src/map_io/map_port_spaces_packet.cc	2019-08-23 08:59:39 +0000
@@ -52,7 +52,7 @@
 			Section& s2 = prof.get_safe_section("port_spaces");
 			for (uint16_t i = 0; i < num; ++i) {
 				map->set_port_space(
-				   egbase.world(),
+				   egbase,
 				   get_safe_coords(std::to_string(static_cast<unsigned int>(i)), ext, &s2), true, true);
 			}
 		} else {

=== modified file 'src/map_io/s2map.cc'
--- src/map_io/s2map.cc	2019-04-20 05:44:37 +0000
+++ src/map_io/s2map.cc	2019-08-23 08:59:39 +0000
@@ -413,9 +413,9 @@
 
 	load_s2mf(egbase);
 
-	map_.recalc_whole_map(egbase.world());
+	map_.recalc_whole_map(egbase);
 
-	postload_set_port_spaces(egbase.world());
+	postload_set_port_spaces(egbase);
 
 	set_state(STATE_LOADED);
 
@@ -1025,7 +1025,7 @@
 	//  loading of Settlers 2 maps in the majority of cases, check all
 	//  starting positions and try to make it Widelands compatible, if its
 	//  size is too small.
-	map_.recalc_whole_map(world);  //  to initialize buildcaps
+	map_.recalc_whole_map(egbase);  //  to initialize buildcaps
 
 	const Widelands::PlayerNumber nr_players = map_.get_nrplayers();
 	log("Checking starting position for all %u players:\n", nr_players);
@@ -1042,14 +1042,14 @@
 		}
 		Widelands::FCoords fpos = map_.get_fcoords(starting_pos);
 
-		if (!(map_.get_max_nodecaps(world, fpos) & Widelands::BUILDCAPS_BIG)) {
+		if (!(map_.get_max_nodecaps(egbase, fpos) & Widelands::BUILDCAPS_BIG)) {
 			log("wrong size - trying to fix it: ");
 			bool fixed = false;
 
 			Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
 			   map_, Widelands::Area<Widelands::FCoords>(fpos, 3));
 			do {
-				if (map_.get_max_nodecaps(world, const_cast<Widelands::FCoords&>(mr.location())) &
+				if (map_.get_max_nodecaps(egbase, const_cast<Widelands::FCoords&>(mr.location())) &
 				    Widelands::BUILDCAPS_BIG) {
 					map_.set_starting_pos(p, mr.location());
 					fixed = true;
@@ -1075,10 +1075,10 @@
 
 /// Try to fix data which is incompatible between S2 and Widelands.
 /// This is only the port space locations.
-void S2MapLoader::postload_set_port_spaces(const Widelands::World& world) {
+void S2MapLoader::postload_set_port_spaces(const Widelands::EditorGameBase& egbase) {
 	// Set port spaces near desired locations if possible
 	for (const Widelands::Coords& coords : port_spaces_to_set_) {
-		bool was_set = map_.set_port_space(world, coords, true);
+		bool was_set = map_.set_port_space(egbase, coords, true);
 		const Widelands::FCoords fc = map_.get_fcoords(coords);
 		if (!was_set) {
 			// Try to set a port space at alternative location
@@ -1086,7 +1086,7 @@
 			   map_, Widelands::Area<Widelands::FCoords>(fc, 3));
 			do {
 				was_set = map_.set_port_space(
-				   world, Widelands::Coords(mr.location().x, mr.location().y), true);
+				   egbase, Widelands::Coords(mr.location().x, mr.location().y), true);
 			} while (!was_set && mr.advance(map_));
 		}
 		if (!was_set) {

=== modified file 'src/map_io/s2map.h'
--- src/map_io/s2map.h	2019-02-23 11:00:49 +0000
+++ src/map_io/s2map.h	2019-08-23 08:59:39 +0000
@@ -46,7 +46,7 @@
 
 	void load_s2mf_header(FileRead&);
 	void load_s2mf(Widelands::EditorGameBase&);
-	void postload_set_port_spaces(const Widelands::World& world);
+	void postload_set_port_spaces(const Widelands::EditorGameBase& world);
 };
 
 #endif  // end of include guard: WL_MAP_IO_S2MAP_H

=== modified file 'src/map_io/widelands_map_loader.cc'
--- src/map_io/widelands_map_loader.cc	2019-06-22 11:13:39 +0000
+++ src/map_io/widelands_map_loader.cc	2019-08-23 08:59:39 +0000
@@ -352,9 +352,9 @@
 		}
 	}  // load_type != MapLoader::LoadType::kEditor
 
-	map_.recalc_whole_map(egbase.world());
+	map_.recalc_whole_map(egbase);
 
-	map_.ensure_resource_consistency(egbase.world());
+	map_.ensure_resource_consistency(egbase);
 
 	set_state(STATE_LOADED);
 

=== modified file 'src/scripting/lua_bases.cc'
--- src/scripting/lua_bases.cc	2019-04-09 16:43:49 +0000
+++ src/scripting/lua_bases.cc	2019-08-23 08:59:39 +0000
@@ -785,7 +785,7 @@
 	}
 	DescriptionIndex building_index = tribes.building_index(name);
 
-	BuildingDescr::FormerBuildings former_buildings;
+	FormerBuildings former_buildings;
 	find_former_buildings(tribes, building_index, &former_buildings);
 	if (constructionsite) {
 		former_buildings.pop_back();

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2019-06-23 11:41:17 +0000
+++ src/scripting/lua_map.cc	2019-08-23 08:59:39 +0000
@@ -1452,7 +1452,7 @@
 // TODO(unknown): do we really want this function?
 int LuaMap::recalculate(lua_State* L) {
 	EditorGameBase& egbase = get_egbase(L);
-	egbase.mutable_map()->recalc_whole_map(egbase.world());
+	egbase.mutable_map()->recalc_whole_map(egbase);
 	return 0;
 }
 
@@ -1489,7 +1489,7 @@
 	const int y = luaL_checkint32(L, 3);
 	const bool allowed = luaL_checkboolean(L, 4);
 	const bool success = get_egbase(L).mutable_map()->set_port_space(
-	   get_egbase(L).world(), Widelands::Coords(x, y), allowed, false, true);
+	   get_egbase(L), Widelands::Coords(x, y), allowed, false, true);
 	lua_pushboolean(L, success);
 	return 1;
 }
@@ -6217,7 +6217,7 @@
 		report_error(L, "height must be <= %i", MAX_FIELD_HEIGHT);
 
 	EditorGameBase& egbase = get_egbase(L);
-	egbase.mutable_map()->set_height(egbase.world(), f, height);
+	egbase.mutable_map()->set_height(egbase, f, height);
 
 	return 0;
 }
@@ -6401,12 +6401,11 @@
 int LuaField::set_terr(lua_State* L) {
 	const char* name = luaL_checkstring(L, -1);
 	EditorGameBase& egbase = get_egbase(L);
-	const World& world = egbase.world();
-	const DescriptionIndex td = world.terrains().get_index(name);
+	const DescriptionIndex td = egbase.world().terrains().get_index(name);
 	if (td == static_cast<DescriptionIndex>(Widelands::INVALID_INDEX))
 		report_error(L, "Unknown terrain '%s'", name);
 
-	egbase.mutable_map()->change_terrain(world, TCoords<FCoords>(fcoords(L), TriangleIndex::R), td);
+	egbase.mutable_map()->change_terrain(egbase, TCoords<FCoords>(fcoords(L), TriangleIndex::R), td);
 
 	lua_pushstring(L, name);
 	return 1;
@@ -6420,12 +6419,11 @@
 int LuaField::set_terd(lua_State* L) {
 	const char* name = luaL_checkstring(L, -1);
 	EditorGameBase& egbase = get_egbase(L);
-	const World& world = egbase.world();
-	const DescriptionIndex td = world.terrains().get_index(name);
+	const DescriptionIndex td = egbase.world().terrains().get_index(name);
 	if (td == static_cast<DescriptionIndex>(INVALID_INDEX))
 		report_error(L, "Unknown terrain '%s'", name);
 
-	egbase.mutable_map()->change_terrain(world, TCoords<FCoords>(fcoords(L), TriangleIndex::D), td);
+	egbase.mutable_map()->change_terrain(egbase, TCoords<FCoords>(fcoords(L), TriangleIndex::D), td);
 
 	lua_pushstring(L, name);
 	return 1;

=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc	2019-06-25 08:03:30 +0000
+++ src/wui/fieldaction.cc	2019-08-23 08:59:39 +0000
@@ -158,7 +158,7 @@
 
 	void init();
 	void add_buttons_auto();
-	void add_buttons_build(int32_t buildcaps);
+	void add_buttons_build(int32_t buildcaps, int32_t max_nodecaps);
 	void add_buttons_road(bool flag);
 	void add_buttons_attack();
 
@@ -357,12 +357,12 @@
 			}
 		} else {
 			const int32_t buildcaps = player_ ? player_->get_buildcaps(node_) : 0;
+			const int32_t nodecaps = map_.get_max_nodecaps(ibase().egbase(), node_);
 
 			// Add house building
-			if ((buildcaps & Widelands::BUILDCAPS_SIZEMASK) ||
-			    (buildcaps & Widelands::BUILDCAPS_MINE)) {
-				assert(igbase->get_player());
-				add_buttons_build(buildcaps);
+			if (player_ && ((nodecaps & Widelands::BUILDCAPS_SIZEMASK) ||
+			    (nodecaps & Widelands::BUILDCAPS_MINE))) {
+				add_buttons_build(buildcaps, nodecaps);
 			}
 
 			// Add build actions
@@ -422,9 +422,15 @@
 Add buttons for house building.
 ===============
 */
-void FieldActionWindow::add_buttons_build(int32_t buildcaps) {
-	if (!player_)
-		return;
+void FieldActionWindow::add_buttons_build(int32_t buildcaps, int32_t max_nodecaps) {
+	if (!player_) {
+		return;
+	}
+	if (!(player_->get_buildcaps(map_.br_n(node_)) & Widelands::BUILDCAPS_FLAG) ||
+			!node_.field->is_interior(player_->player_number()) ||
+			!map_.br_n(node_).field->is_interior(player_->player_number())) {
+		return;
+	}
 	BuildGrid* bbg_house[4] = {nullptr, nullptr, nullptr, nullptr};
 	BuildGrid* bbg_mine = nullptr;
 
@@ -446,27 +452,45 @@
 			if (building_descr->needs_seafaring() && !ibase().egbase().map().allows_seafaring()) {
 				continue;
 			}
-		} else if (!building_descr->is_buildable() && !building_descr->is_enhanced())
+		} else if (!building_descr->is_buildable() && !building_descr->is_enhanced()) {
 			continue;
+		}
 
+		if (building_descr->get_built_over_immovable() >= 0 &&
+				!(node_.field->get_immovable() &&
+				node_.field->get_immovable()->has_attribute(building_descr->get_built_over_immovable()))) {
+			continue;
+		}
 		// Figure out if we can build it here, and in which tab it belongs
 		if (building_descr->get_ismine()) {
-			if (!(buildcaps & Widelands::BUILDCAPS_MINE))
+			if (!((building_descr->get_built_over_immovable() < 0 ?
+					buildcaps : max_nodecaps) & Widelands::BUILDCAPS_MINE)) {
 				continue;
+			}
 
 			ppgrid = &bbg_mine;
 		} else {
 			int32_t size = building_descr->get_size() - Widelands::BaseImmovable::SMALL;
 
-			if ((buildcaps & Widelands::BUILDCAPS_SIZEMASK) < size + 1)
-				continue;
-			if (building_descr->get_isport() && !(buildcaps & Widelands::BUILDCAPS_PORT))
-				continue;
+			if (((building_descr->get_built_over_immovable() < 0 ?
+					buildcaps : max_nodecaps) & Widelands::BUILDCAPS_SIZEMASK) < size + 1) {
+				continue;
+			}
+			if (building_descr->get_isport() && !(buildcaps & Widelands::BUILDCAPS_PORT)) {
+				continue;
+			}
+			if (building_descr->get_size() >= Widelands::BaseImmovable::BIG &&
+					!((map_.l_n(node_).field->is_interior(player_->player_number())) &&
+					(map_.tr_n(node_).field->is_interior(player_->player_number())) &&
+					(map_.tl_n(node_).field->is_interior(player_->player_number())))) {
+				continue;
+			}
 
-			if (building_descr->get_isport())
+			if (building_descr->get_isport()) {
 				ppgrid = &bbg_house[3];
-			else
+			} else {
 				ppgrid = &bbg_house[size];
+			}
 		}
 
 		// Allocate the tab's grid if necessary

=== modified file 'src/wui/game_debug_ui.cc'
--- src/wui/game_debug_ui.cc	2019-02-23 11:00:49 +0000
+++ src/wui/game_debug_ui.cc	2019-08-23 08:59:39 +0000
@@ -359,7 +359,7 @@
 
 	// Bobs information
 	std::vector<Widelands::Bob*> bobs;
-	map_.find_bobs(Widelands::Area<Widelands::FCoords>(coords_, 0), &bobs);
+	map_.find_bobs(egbase, Widelands::Area<Widelands::FCoords>(coords_, 0), &bobs);
 
 	// Do not clear the list. Instead parse all bobs and sync lists
 	for (uint32_t idx = 0; idx < ui_bobs_.size(); idx++) {

=== modified file 'src/wui/interactive_gamebase.cc'
--- src/wui/interactive_gamebase.cc	2019-08-13 11:12:56 +0000
+++ src/wui/interactive_gamebase.cc	2019-08-23 08:59:39 +0000
@@ -445,7 +445,7 @@
 	show_buildhelp(false);
 
 	// Recalc whole map for changed owner stuff
-	egbase().mutable_map()->recalc_whole_map(egbase().world());
+	egbase().mutable_map()->recalc_whole_map(egbase());
 
 	// Close game-relevant UI windows (but keep main menu open)
 	fieldaction_.destroy();
@@ -551,7 +551,7 @@
 	}
 
 	std::vector<Widelands::Bob*> ships;
-	if (map.find_bobs(area, &ships, Widelands::FindBobShip())) {
+	if (map.find_bobs(egbase(), area, &ships, Widelands::FindBobShip())) {
 		for (Widelands::Bob* ship : ships) {
 			if (can_see(ship->owner().player_number())) {
 				// FindBobShip should have returned only ships

=== modified file 'src/wui/watchwindow.cc'
--- src/wui/watchwindow.cc	2019-04-26 06:35:15 +0000
+++ src/wui/watchwindow.cc	2019-08-23 08:59:39 +0000
@@ -240,7 +240,7 @@
 		                           .node),
 		        2);
 		     area.radius <= 32; area.radius *= 2)
-			if (map.find_bobs(area, &bobs))
+			if (map.find_bobs(g, area, &bobs))
 				break;
 		//  Find the bob closest to us
 		float closest_dist = 0;


Follow ups