← Back to team overview

widelands-dev team mailing list archive

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

 

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

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #672248 in widelands: "duplicated animations "
  https://bugs.launchpad.net/widelands/+bug/672248

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/one_world/+merge/222708

This merges all worlds into one, converts its configuration to Lua, adds the compatibility layer to map loading needed for this.

This also regresses some issues:

- Bug 1328635 deals with terrain affinity of trees.
- Bug 1328637 deals with the hard to see road textures.
- Bug 1328640 introduces a sensible refactoring that I did not finish in this change.

I am very open for comments on the code and design, as well as suggestion to the new bugs and ways to fixing them. I would like to merge this in the next couple of weeks, so it would be great to get some feedback.
-- 
The attached diff has been truncated due to its size.
https://code.launchpad.net/~widelands-dev/widelands/one_world/+merge/222708
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/one_world into lp:widelands.
=== modified file 'campaigns/t02.wmf/scripting/mission_thread.lua'
--- campaigns/t02.wmf/scripting/mission_thread.lua	2014-03-25 06:18:48 +0000
+++ campaigns/t02.wmf/scripting/mission_thread.lua	2014-06-10 18:27:45 +0000
@@ -322,20 +322,20 @@
    end
 
    force_map_immovables{
-      { "tree3", 55, 19 },
-      { "tree7_s", 58, 19 },
-      { "tree5_m", 58, 20 },
-      { "tree7", 57, 21 },
-      { "tree4_s", 54, 22 },
-      { "tree5_s", 56, 24 },
-      { "tree1", 58, 24 },
-      { "tree7_s", 56, 25 },
-      { "tree3", 53, 27 },
-      { "tree7_s", 57, 27 },
-      { "tree1_m", 52, 29 },
-      { "tree5", 54, 30 },
-      { "tree6", 55, 30 },
-      { "tree7", 56, 30 },
+      { "spruce_summer_old", 55, 19 },
+      { "larch_summer_pole", 58, 19 },
+      { "birch_summer_mature", 58, 20 },
+      { "larch_summer_old", 57, 21 },
+      { "alder_summer_pole", 54, 22 },
+      { "birch_summer_pole", 56, 24 },
+      { "aspen_summer_old", 58, 24 },
+      { "larch_summer_pole", 56, 25 },
+      { "spruce_summer_old", 53, 27 },
+      { "larch_summer_pole", 57, 27 },
+      { "aspen_summer_mature", 52, 29 },
+      { "birch_summer_pole", 54, 30 },
+      { "beech_summer_old", 55, 30 },
+      { "larch_summer_old", 56, 30 },
       { "field2", 56, 14, "barbarians" },
       { "field0s",57, 14, "barbarians" },
       { "field2", 54, 15, "barbarians" },

=== modified file 'cmake/codecheck/rules/misused_tab'
--- cmake/codecheck/rules/misused_tab	2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/misused_tab	2014-06-10 18:27:45 +0000
@@ -3,7 +3,7 @@
 
 """
 This catches a tab that comes after the first non-whitespace character on a
-line. Tabs should only be used for indentation.  
+line. Tabs should only be used for indentation.
 """
 
 error_msg = "Tabs are only allowed before the first non-whitespace character in line."

=== modified file 'cmake/codecheck/rules/space_as_indentation'
--- cmake/codecheck/rules/space_as_indentation	2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/space_as_indentation	2014-06-10 18:27:45 +0000
@@ -3,17 +3,32 @@
 #
 
 """
-Cry when space appears as first character on a line. Indentation should be done with tabs.
-There is no reason to have spaces as the first line
+Indentation should be done with tabs, but spaces are allowed for alignment.
 
 This is not obligatory for macros, because of the Alignement of the \\ at the end
 """
 
+import re
+
 error_msg="Use tabs for indentation."
 
 strip_comments_and_strings = True
 strip_macros = True
-regexp = r"^ +"
+
+class EvalMatches( object ):
+    STARTS_WITH_SPACES = re.compile(r"^ +")
+    def __call__(self, lines, fn):
+        errors = []
+        for curline, l in enumerate(lines, 1):
+            if self.STARTS_WITH_SPACES.match(l):
+                last_char = l.rstrip()[-1] if l.rstrip() else ""
+                if last_char in ",{)":
+                    continue
+                errors.append( (fn, curline, error_msg))
+        return errors
+
+
+evaluate_matches = EvalMatches()
 
 forbidden = [
     "   if(a)\n",

=== modified file 'compile.sh'
--- compile.sh	2014-03-04 09:57:26 +0000
+++ compile.sh	2014-06-10 18:27:45 +0000
@@ -33,8 +33,8 @@
 # Definition of some local variables #
 ######################################
 var_build=0 # 0 == debug(default), 1 == release
-var_build_lang=0 # 0 = false 
-var_updater=0 # 0 = false
+var_build_lang=1 # 0 = false 
+var_updater=1 # 0 = false
 ######################################
 
 
@@ -135,7 +135,8 @@
     fi
 
     echo " "
-    cmake -DWL_PORTABLE=true .. -DCMAKE_BUILD_TYPE="${var_build_type}"
+#    cmake -DWL_PORTABLE=true .. -DCMAKE_BUILD_TYPE="${var_build_type}"
+cmake -DWL_PORTABLE=true .. -DCMAKE_BUILD_TYPE="${var_build_type}" .. -DCMAKE_CXX_COMPILER=/usr/bin/g++-4.7 -DCMAKE_C_COMPILER=/usr/bin/gcc-4.7
     make ${MAKEOPTS}
     return 0
   }
@@ -216,7 +217,7 @@
 ######################################
 set -e
 basic_check
-user_interaction
+#user_interaction
 prepare_directories_and_links
 compile_widelands
 if [ $var_build_lang -eq 1 ] ; then
@@ -224,7 +225,7 @@
 fi
 move_built_files
 cd ..
-update_script
+#update_script
 echo " "
 echo "#####################################################"
 echo "# Congratulations Widelands was successfully build. #"

=== modified file 'doc/sphinx/extract_rst.py'
--- doc/sphinx/extract_rst.py	2012-06-20 09:07:10 +0000
+++ doc/sphinx/extract_rst.py	2014-06-10 18:27:45 +0000
@@ -25,7 +25,7 @@
     Widelands. Return the base directory and the source/ directory."""
     curdir = p.abspath(p.dirname(__file__))
     source_dir = p.join(curdir, "source")
-    while not (p.exists(p.join(curdir, "tribes")) and p.exists(p.join(curdir, "worlds"))):
+    while not (p.exists(p.join(curdir, "tribes")) and p.exists(p.join(curdir, "world"))):
         curdir = p.abspath(p.join(curdir, p.pardir))
     return source_dir, curdir
 source_dir, base_dir = _find_basedir()

=== removed directory 'global/bobs'
=== removed file 'global/conf'
--- global/conf	2009-01-25 19:40:02 +0000
+++ global/conf	1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-[immovable types]
-bar-ruin00=_Ruin of a barbarian sentry
-bar-ruin01=_Ruin of a barbarian citadel
-bar-ruin02=_Ruin of a barbarian warehouse
-bar-ruin03=_Ruin of a barbarian farm
-debris00=_Debris
-debris01=_Debris
-debris02=_Debris

=== modified file 'maps/Trident of Fire.wmf/scripting/map_editing.lua'
--- maps/Trident of Fire.wmf/scripting/map_editing.lua	2014-02-22 14:33:44 +0000
+++ maps/Trident of Fire.wmf/scripting/map_editing.lua	2014-06-10 18:27:45 +0000
@@ -2,14 +2,14 @@
 function automatic_forester()
 
 local region_to_forest = map:get_field(0,0):region(23)
-	while true do 
+	while true do
 		for x,field in next,region_to_forest,f do
-			if not _fully_flooded(map:get_field(field.x,field.y)) then 
+			if not _fully_flooded(map:get_field(field.x,field.y)) then
 				if map:get_field(field.x,field.y).immovable == 	nil then
 					if (field.x + field.y) % 2 == 0 then
-						map:place_immovable("tree1_t", map:get_field(field.x,field.y))
+						map:place_immovable("aspen_summer_sapling", map:get_field(field.x,field.y))
 					else
-						map:place_immovable("tree2_t", map:get_field(field.x,field.y))
+						map:place_immovable("oak_summer_sapling", map:get_field(field.x,field.y))
 					end
 					sleep(750)
 				end
@@ -109,7 +109,7 @@
 			end
 		end
 		sleep(10*60*1000)
---		set back all eruptions		
+--		set back all eruptions
 		while fields_to_erupt.size > 0 do
 			local ff = fields_to_erupt:pop_at(1)
 			local tr_to_setback = Set:new{Triangle:new(ff._f,"d")}
@@ -163,7 +163,7 @@
    local rv = {
       _f = f,
       _td = ter_d,
-      _tr = ter_r, 
+      _tr = ter_r,
       __hash = ("%i_%i_%s_%s"):format(f.x, f.y, ter_d, ter_r),
    }
    setmetatable(rv,self)
@@ -178,5 +178,3 @@
 	end
 	return t1
 end
-
-

=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2013-07-26 19:16:51 +0000
+++ src/ai/ai_help_structs.h	2014-06-10 18:27:45 +0000
@@ -29,6 +29,8 @@
 #include "logic/game.h"
 #include "logic/map.h"
 #include "logic/player.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 
 namespace Widelands {
 
@@ -76,19 +78,19 @@
 	{}
 };
 
-
 struct FindNodeWater {
-	bool accept(const Map & map, const FCoords & coord) const {
-		return
-			(map.world().terrain_descr(coord.field->terrain_d()).get_is()
-			 & TERRAIN_WATER)
-			||
-			(map.world().terrain_descr(coord.field->terrain_r()).get_is()
-			 & TERRAIN_WATER);
-	}
+	FindNodeWater(const World& world) : world_(world) {
+	}
+
+	bool accept(const Map&, const FCoords& coord) const {
+		return (world_.terrain_descr(coord.field->terrain_d()).get_is() & TerrainDescription::WATER) ||
+		       (world_.terrain_descr(coord.field->terrain_r()).get_is() & TerrainDescription::WATER);
+	}
+
+private:
+	const World& world_;  // not owned.
 };
 
-
 struct FindNodeWithFlagOrRoad {
 	Economy * economy;
 	bool accept(const Map &, FCoords) const;

=== modified file 'src/ai/ai_hints.h'
--- src/ai/ai_hints.h	2014-03-15 11:29:32 +0000
+++ src/ai/ai_hints.h	2014-06-10 18:27:45 +0000
@@ -23,7 +23,7 @@
 #include <SDL_types.h>
 #include <boost/noncopyable.hpp>
 
-struct Section;
+class Section;
 
 /// This struct is used to read out the data given in [aihints] section of a
 /// buildings conf file. It is used to tell the computer player about the

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2014-04-29 18:39:52 +0000
+++ src/ai/defaultai.cc	2014-06-10 18:27:45 +0000
@@ -42,7 +42,7 @@
 #include "logic/trainingsite.h"
 #include "logic/tribe.h"
 #include "logic/warehouse.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "profile/profile.h"
 #include "upcast.h"
 
@@ -238,7 +238,7 @@
 
 	// collect information about the different buildings our tribe can construct
 	Building_Index const nr_buildings = tribe->get_nrbuildings();
-	const World & world = game().map().world();
+	const World & world = game().world();
 	for (Building_Index i = 0; i < nr_buildings; ++i) {
 		const Building_Descr & bld = *tribe->get_building_descr(i);
 		const std::string & building_name = bld.name();
@@ -512,7 +512,7 @@
 		field.consumers_nearby.clear();
 		field.consumers_nearby.resize(wares.size());
 		std::vector<Coords> water_list;
-		FindNodeWater find_water;
+		FindNodeWater find_water(game().world());
 		map.find_fields(Area<FCoords>(field.coords, 4), &water_list, find_water);
 		field.water_nearby = water_list.size();
 

=== modified file 'src/description_maintainer.h'
--- src/description_maintainer.h	2014-04-21 09:19:14 +0000
+++ src/description_maintainer.h	2014-06-10 18:27:45 +0000
@@ -20,11 +20,13 @@
 #ifndef DESCR_MAINTAINER_H
 #define DESCR_MAINTAINER_H
 
-#include <cassert>
 #include <map>
 #include <memory>
+#include <string>
 #include <vector>
 
+#include "wexception.h"
+
 // Used to have a typesafe maintainer for description classes.
 template <typename T> struct DescriptionMaintainer {
 	// Adds the 'entry', will assert() if it is already registered. Returns the
@@ -62,11 +64,13 @@
 
 template <typename T>
 int32_t DescriptionMaintainer<T>::add(T * const item) {
-	assert(exists(item->name()) == nullptr);
+	if (exists(item->name()) != nullptr) {
+		throw wexception("Tried to add %s twice.", item->name().c_str());
+	}
 	int32_t index = items_.size();
 	items_.emplace_back(item);
 	name_to_index_[item->name()] = index;
-	return index;;
+	return index;
 }
 
 template <typename T> T* DescriptionMaintainer<T>::exists(const std::string& name) const {

=== modified file 'src/economy/flag.h'
--- src/economy/flag.h	2014-04-01 18:15:56 +0000
+++ src/economy/flag.h	2014-06-10 18:27:45 +0000
@@ -53,11 +53,11 @@
 	typedef std::vector<const WareInstance *> Wares;
 
 	friend class Economy;
-	friend struct Router;
 	friend class FlagQueue;
+	friend class Map_Flagdata_Data_Packet; // has to read/write this to a file
 	friend struct Map_Ware_Data_Packet;     // has to look at pending wares
 	friend struct Map_Waredata_Data_Packet; // has to look at pending wares
-	friend struct Map_Flagdata_Data_Packet; // has to read/write this to a file
+	friend struct Router;
 
 	Flag(); /// empty flag for savegame loading
 	Flag(Editor_Game_Base &, Player & owner, Coords); /// create a new flag

=== modified file 'src/economy/road.h'
--- src/economy/road.h	2014-04-01 18:15:56 +0000
+++ src/economy/road.h	2014-06-10 18:27:45 +0000
@@ -46,8 +46,8 @@
  * road.
  */
 struct Road : public PlayerImmovable {
-	friend struct Map_Roaddata_Data_Packet; // For saving
-	friend struct Map_Road_Data_Packet; // For init()
+	friend class Map_Roaddata_Data_Packet; // For saving
+	friend class Map_Road_Data_Packet; // For init()
 
 	static bool IsRoadDescr(Map_Object_Descr const *);
 

=== modified file 'src/economy/test/test_road.cc'
--- src/economy/test/test_road.cc	2014-02-22 18:04:02 +0000
+++ src/economy/test/test_road.cc	2014-06-10 18:27:45 +0000
@@ -27,6 +27,10 @@
 #include "logic/instances.h"
 #include "logic/player.h"
 
+namespace Widelands {
+class World;
+}  // namespace Widelands
+
 using namespace Widelands;
 
 /******************/
@@ -41,7 +45,7 @@
 struct TestingMap : public Map {
 	TestingMap(int const w, int const h) : Map() {set_size(w, h);}
 
-	virtual void recalc_for_field_area(Area<FCoords>) override {}
+	virtual void recalc_for_field_area(const World&, Area<FCoords>) override {}
 
 };
 
@@ -102,4 +106,3 @@
 }
 
 BOOST_AUTO_TEST_SUITE_END()
-

=== modified file 'src/economy/wares_queue.h'
--- src/economy/wares_queue.h	2014-04-21 10:00:16 +0000
+++ src/economy/wares_queue.h	2014-06-10 18:27:45 +0000
@@ -32,7 +32,6 @@
 struct Map_Map_Object_Saver;
 class Player;
 class Request;
-class WaresQueue;
 class Worker;
 
 /**

=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2014-05-27 11:01:15 +0000
+++ src/editor/editorinteractive.cc	2014-06-10 18:27:45 +0000
@@ -37,6 +37,8 @@
 #include "logic/map.h"
 #include "logic/player.h"
 #include "logic/tribe.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/world.h"
 #include "map_io/widelands_map_loader.h"
 #include "profile/profile.h"
 #include "scoped_timer.h"
@@ -109,8 +111,10 @@
 	m_toggle_minimap.sigclicked.connect(boost::bind(&Editor_Interactive::toggle_minimap, this));
 	m_toggle_buildhelp.sigclicked.connect(boost::bind(&Editor_Interactive::toggle_buildhelp, this));
 	m_toggle_player_menu.sigclicked.connect(boost::bind(&Editor_Interactive::toggle_playermenu, this));
-	m_undo.sigclicked.connect(boost::bind(&Editor_History::undo_action, &m_history));
-	m_redo.sigclicked.connect(boost::bind(&Editor_History::redo_action, &m_history));
+	m_undo.sigclicked.connect(
+	   boost::bind(&Editor_History::undo_action, &m_history, boost::cref(egbase().world())));
+	m_redo.sigclicked.connect(
+	   boost::bind(&Editor_History::redo_action, &m_history, boost::cref(egbase().world())));
 
 	m_toolbar.set_layout_toplevel(true);
 	m_toolbar.add(&m_toggle_main_menu,       UI::Box::AlignLeft);
@@ -154,17 +158,14 @@
 
 	//  Resources: we do not calculate default resources, therefore we do not
 	//  expect to meet them here.
-	const Widelands::World    &    world           = map.world();
-	OverlayManager        &       overlay_manager = map.overlay_manager();
-	Widelands::Extent        const extent          = map.extent();
+	OverlayManager& overlay_manager = map.overlay_manager();
+	Widelands::Extent const extent = map.extent();
 	iterate_Map_FCoords(map, extent, fc) {
 		if (uint8_t const amount = fc.field->get_resources_amount()) {
-			const std::string & immname =
-			    world.get_resource(fc.field->get_resources())->get_editor_pic
-			    (amount);
+			const std::string& immname =
+			   egbase().world().get_resource(fc.field->get_resources())->get_editor_pic(amount);
 			if (immname.size())
-				overlay_manager.register_overlay
-				(fc, g_gr->images().get(immname), 4);
+				overlay_manager.register_overlay(fc, g_gr->images().get(immname), 4);
 		}
 	}
 
@@ -182,36 +183,30 @@
 	egbase().cleanup_for_load();
 	m_history.reset();
 
-	std::unique_ptr<Widelands::Map_Loader> const ml(map.get_correct_loader(filename));
+	std::unique_ptr<Widelands::Map_Loader> ml(map.get_correct_loader(filename));
 	if (not ml.get())
 		throw warning
 			(_("Unsupported format"),
 			 _("Widelands could not load the file \"%s\". The file format seems to be incompatible."),
 			 filename.c_str());
+	ml->preload_map(true);
 
 	UI::ProgressWindow loader_ui("pics/editor.jpg");
 	std::vector<std::string> tipstext;
 	tipstext.push_back("editor");
+
+	m_history.reset();
+
 	GameTips editortips(loader_ui, tipstext);
 
-	{
-		std::string const old_world_name = map.get_world_name();
-		ml->preload_map(true);
-		if (strcmp(map.get_world_name(), old_world_name.c_str()))
-			change_world();
-	}
 	load_all_tribes(&egbase(), &loader_ui);
 
 	// Create the players. TODO SirVer this must be managed better
 	loader_ui.step(_("Creating players"));
 	iterate_player_numbers(p, map.get_nrplayers()) {
-		egbase().add_player
-		(p, 0, map.get_scenario_player_tribe(p),
-		 map.get_scenario_player_name(p));
+		egbase().add_player(p, 0, map.get_scenario_player_tribe(p), map.get_scenario_player_name(p));
 	}
 
-	loader_ui.step(_("Loading world data"));
-	ml->load_world();
 	ml->load_map_complete(egbase(), true);
 	loader_ui.step(_("Loading graphics..."));
 	egbase().load_graphics(loader_ui);
@@ -278,7 +273,7 @@
 void Editor_Interactive::map_clicked(bool should_draw) {
 	m_history.do_action
 		(tools.current(),
-		 tools.use_tool, egbase().map(),
+		 tools.use_tool, egbase().map(), egbase().world(),
 	     get_sel_pos(), *this, should_draw);
 	need_complete_redraw();
 	set_need_save(true);
@@ -468,14 +463,14 @@
 
 		case SDLK_z:
 			if ((code.mod & (KMOD_LCTRL | KMOD_RCTRL)) && (code.mod & (KMOD_LSHIFT | KMOD_RSHIFT)))
-				m_history.redo_action();
+				m_history.redo_action(egbase().world());
 			else if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				m_history.undo_action();
+				m_history.undo_action(egbase().world());
 			handled = true;
 			break;
 		case SDLK_y:
 			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				m_history.redo_action();
+				m_history.redo_action(egbase().world());
 			handled = true;
 			break;
 		default:
@@ -511,8 +506,7 @@
 		//  A new tool has been selected. Remove all registered overlay callback
 		//  functions.
 		map.overlay_manager().remove_overlay_callback_function();
-		map.recalc_whole_map();
-
+		map.recalc_whole_map(egbase().world());
 	}
 	tools.current_pointer = &primary;
 	tools.use_tool        = which;
@@ -578,17 +572,7 @@
 	return false;
 }
 
-
-void Editor_Interactive::change_world() {
-	m_history.reset();
-	delete m_terrainmenu  .window;
-	delete m_immovablemenu.window;
-	delete m_bobmenu      .window;
-	delete m_resourcesmenu.window;
-}
-
-
-void Editor_Interactive::run_editor(const std::string & filename, const std::string& script_to_run) {
+void Editor_Interactive::run_editor(const std::string& filename, const std::string& script_to_run) {
 	Widelands::Editor_Game_Base editor(nullptr);
 	Editor_Interactive eia(editor);
 	editor.set_ibase(&eia); // TODO get rid of this
@@ -603,10 +587,12 @@
 			editor.set_map(&map);
 			if (filename.empty()) {
 				loader_ui.step("Creating empty map...");
-				map.create_empty_map
-				(64, 64, "greenland", _("No Name"),
-				 g_options.pull_section("global").get_string
-				 ("realname", _("Unknown")));
+				map.create_empty_map(
+				   editor.world(),
+				   64,
+				   64,
+				   _("No Name"),
+				   g_options.pull_section("global").get_string("realname", _("Unknown")));
 
 				load_all_tribes(&editor, &loader_ui);
 

=== modified file 'src/editor/editorinteractive.h'
--- src/editor/editorinteractive.h	2014-04-20 20:02:13 +0000
+++ src/editor/editorinteractive.h	2014-06-10 18:27:45 +0000
@@ -81,7 +81,6 @@
 			place_bob(delete_bob),
 			increase_resources(decrease_resources, set_resources),
 			set_port_space(unset_port_space)
-
 		{}
 		Editor_Tool & current() const {return *current_pointer;}
 		typedef std::vector<Editor_Tool *> Tool_Vector;
@@ -121,10 +120,6 @@
 	bool is_player_tribe_referenced(Widelands::Player_Number);
 	void set_need_save(bool const t) {m_need_save = t;}
 
-	/// Must be called when the world is changed. Takes care of closing the tool
-	/// menus that are showing elements from the old world.
-	void change_world();
-
 private:
 	void toggle_buildhelp();
 	void tool_menu_btn();

=== modified file 'src/editor/tools/editor_decrease_height_tool.cc'
--- src/editor/tools/editor_decrease_height_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_decrease_height_tool.cc	2014-06-10 18:27:45 +0000
@@ -27,12 +27,11 @@
 #include "logic/mapregion.h"
 
 /// Decreases the heights by a value. Chages surrounding nodes if necessary.
-int32_t Editor_Decrease_Height_Tool::handle_click_impl
-	(Widelands::Map & map,
-	Widelands::Node_and_Triangle<> center,
-	Editor_Interactive & /* parent */,
-	Editor_Action_Args & args)
-{
+int32_t Editor_Decrease_Height_Tool::handle_click_impl(Widelands::Map& map,
+                                                       const Widelands::World& world,
+                                                       Widelands::Node_and_Triangle<> center,
+                                                       Editor_Interactive& /* parent */,
+                                                       Editor_Action_Args& args) {
 	if (args.origHights.empty()) {
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 		(map,
@@ -42,15 +41,15 @@
 		while (mr.advance(map));
 	}
 
-	return
-	    map.change_height
-	    (Widelands::Area<Widelands::FCoords>
-	     (map.get_fcoords(center.node), args.sel_radius),
-	     -args.change_by);
+	return map.change_height(
+	   world,
+	   Widelands::Area<Widelands::FCoords>(map.get_fcoords(center.node), args.sel_radius),
+	   -args.change_by);
 }
 
 int32_t Editor_Decrease_Height_Tool::handle_undo_impl
 	(Widelands::Map & map,
+	 const Widelands::World& world,
 	Widelands::Node_and_Triangle<> center,
 	Editor_Interactive & /* parent */,
 	Editor_Action_Args & args)
@@ -65,10 +64,10 @@
 		mr.location().field->set_height(*i); ++i;
 	} while (mr.advance(map));
 
-	map.recalc_for_field_area
-		(Widelands::Area<Widelands::FCoords>
-			(map.get_fcoords(center.node),
-				args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 2));
+	map.recalc_for_field_area(world,
+	                          Widelands::Area<Widelands::FCoords>(
+	                             map.get_fcoords(center.node),
+	                             args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 2));
 
 	return mr.radius() + 1;
 }
@@ -79,5 +78,3 @@
 	a.change_by = m_change_by;
 	return a;
 }
-
-

=== modified file 'src/editor/tools/editor_decrease_height_tool.h'
--- src/editor/tools/editor_decrease_height_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_decrease_height_tool.h	2014-06-10 18:27:45 +0000
@@ -27,11 +27,15 @@
 	Editor_Decrease_Height_Tool() : Editor_Tool(*this, *this), m_change_by(1) {}
 
 	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
+		(Widelands::Map & map,
+		 const Widelands::World& world,
+		 Widelands::Node_and_Triangle<> center,
 		 Editor_Interactive & parent, Editor_Action_Args & args) override;
 
 	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
+		(Widelands::Map & map,
+		 const Widelands::World& world,
+		 Widelands::Node_and_Triangle<> center,
 		 Editor_Interactive & parent, Editor_Action_Args & args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;

=== modified file 'src/editor/tools/editor_decrease_resources_tool.cc'
--- src/editor/tools/editor_decrease_resources_tool.cc	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_decrease_resources_tool.cc	2014-06-10 18:27:45 +0000
@@ -26,7 +26,8 @@
 #include "logic/field.h"
 #include "logic/mapregion.h"
 #include "logic/widelands_geometry.h"
-#include "logic/world.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/world.h"
 #include "wui/overlay_manager.h"
 
 
@@ -34,12 +35,12 @@
  * Decrease the resources of the current field by one if
  * there is not already another resource there.
 */
-int32_t Editor_Decrease_Resources_Tool::handle_click_impl
-	(Widelands::Map           &           map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive         &         /* parent */,
-	Editor_Action_Args         &         args)
-{
+int32_t
+Editor_Decrease_Resources_Tool::handle_click_impl(Widelands::Map& map,
+                                                  const Widelands::World& world,
+                                                  Widelands::Node_and_Triangle<> const center,
+                                                  Editor_Interactive& /* parent */,
+                                                  Editor_Action_Args& args) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
 	Widelands::Area<Widelands::FCoords>
@@ -55,14 +56,11 @@
 		args.orgResT.push_back(res);
 		args.orgRes.push_back(mr.location().field->get_resources_amount());
 
-		if
-		(res == args.cur_res
-		        and
-		        Editor_Change_Resource_Tool_Callback(mr.location(), map, args.cur_res))
-		{
+		if (res == args.cur_res &&
+		    Editor_Change_Resource_Tool_Callback(mr.location(), map, world, args.cur_res)) {
 			//  Ok, we're doing something. First remove the current overlays.
 			std::string str =
-			    map.world().get_resource(res)->get_editor_pic
+			    world.get_resource(res)->get_editor_pic
 			    (mr.location().field->get_resources_amount());
 			const Image* pic = g_gr->images().get(str);
 			map.overlay_manager().remove_overlay(mr.location(), pic);
@@ -73,24 +71,24 @@
 				mr.location().field->set_resources(args.cur_res, amount);
 				mr.location().field->set_starting_res_amount(amount);
 				//  set new overlay
-				str = map.world().get_resource(args.cur_res)->get_editor_pic(amount);
+				str = world.get_resource(args.cur_res)->get_editor_pic(amount);
 				pic = g_gr->images().get(str);
 				map.overlay_manager().register_overlay(mr.location(), pic, 4);
-				map.recalc_for_field_area
-				(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+				map.recalc_for_field_area(
+				   world, Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}
 		}
 	} while (mr.advance(map));
 	return mr.radius();
 }
 
-int32_t Editor_Decrease_Resources_Tool::handle_undo_impl
-	(Widelands::Map & map,
-	Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent,
-	Editor_Action_Args & args)
-{
-	return parent.tools.set_resources.handle_undo_impl(map, center, parent, args);
+int32_t Editor_Decrease_Resources_Tool::handle_undo_impl(
+   Widelands::Map& map,
+   const Widelands::World& world,
+   Widelands::Node_and_Triangle<Widelands::Coords> center,
+   Editor_Interactive& parent,
+   Editor_Action_Args& args) {
+	return parent.tools.set_resources.handle_undo_impl(map, world, center, parent, args);
 }
 
 Editor_Action_Args Editor_Decrease_Resources_Tool::format_args_impl(Editor_Interactive & parent)

=== modified file 'src/editor/tools/editor_decrease_resources_tool.h'
--- src/editor/tools/editor_decrease_resources_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_decrease_resources_tool.h	2014-06-10 18:27:45 +0000
@@ -21,7 +21,6 @@
 #define EDITOR_DECREASE_RESOURCES_TOOL_H
 
 #include "editor/tools/editor_tool.h"
-#include "logic/world.h"
 
 ///  Decreases the resources of a node by a value.
 struct Editor_Decrease_Resources_Tool : public Editor_Tool {
@@ -29,13 +28,17 @@
 		: Editor_Tool(*this, *this), m_cur_res(0), m_change_by(1)
 	{}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 
@@ -52,7 +55,7 @@
 
 private:
 	Widelands::Resource_Index m_cur_res;
-	int32_t                   m_change_by;
+	int32_t m_change_by;
 };
 
 #endif

=== modified file 'src/editor/tools/editor_delete_bob_tool.cc'
--- src/editor/tools/editor_delete_bob_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_delete_bob_tool.cc	2014-06-10 18:27:45 +0000
@@ -27,10 +27,12 @@
 /**
  * Deletes the bob at the given location
 */
-int32_t Editor_Delete_Bob_Tool::handle_click_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
+int32_t
+Editor_Delete_Bob_Tool::handle_click_impl(Widelands::Map& map,
+                                          const Widelands::World&,
+                                          Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                          Editor_Interactive& parent,
+                                          Editor_Action_Args& args) {
 	Widelands::Editor_Game_Base & egbase = parent.egbase();
 	const int32_t radius = args.sel_radius;
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
@@ -48,12 +50,14 @@
 	return radius + 2;
 }
 
-int32_t Editor_Delete_Bob_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
+int32_t
+Editor_Delete_Bob_Tool::handle_undo_impl(Widelands::Map& map,
+                                         const Widelands::World& world,
+                                         Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                         Editor_Interactive& parent,
+                                         Editor_Action_Args& args) {
 
-	uint32_t ret = parent.tools.place_bob.handle_undo_impl(map, center, parent, args);
+	uint32_t ret = parent.tools.place_bob.handle_undo_impl(map, world, center, parent, args);
 	args.obob_type.clear();
 	return ret;
 }
@@ -62,5 +66,3 @@
 {
 	return Editor_Tool::format_args_impl(parent);
 }
-
-

=== modified file 'src/editor/tools/editor_delete_bob_tool.h'
--- src/editor/tools/editor_delete_bob_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_delete_bob_tool.h	2014-06-10 18:27:45 +0000
@@ -26,13 +26,17 @@
 struct Editor_Delete_Bob_Tool : public Editor_Tool {
 	Editor_Delete_Bob_Tool() : Editor_Tool(*this, *this) {}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_delete_immovable_tool.cc'
--- src/editor/tools/editor_delete_immovable_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_delete_immovable_tool.cc	2014-06-10 18:27:45 +0000
@@ -28,12 +28,11 @@
 /**
  * Deletes the immovable at the given location
 */
-int32_t Editor_Delete_Immovable_Tool::handle_click_impl
-	(Widelands::Map           &           map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive       &           parent,
-	 Editor_Action_Args       &           args)
-{
+int32_t Editor_Delete_Immovable_Tool::handle_click_impl(Widelands::Map& map,
+                                                        const Widelands::World&,
+                                                        Widelands::Node_and_Triangle<> const center,
+                                                        Editor_Interactive& parent,
+                                                        Editor_Action_Args& args) {
 	Widelands::Editor_Game_Base & egbase = parent.egbase();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
@@ -54,15 +53,16 @@
 	return mr.radius() + 2;
 }
 
-int32_t Editor_Delete_Immovable_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
-	return parent.tools.place_immovable.handle_undo_impl(map, center, parent, args);
+int32_t Editor_Delete_Immovable_Tool::handle_undo_impl(
+   Widelands::Map& map,
+   const Widelands::World& world,
+   Widelands::Node_and_Triangle<Widelands::Coords> center,
+   Editor_Interactive& parent,
+   Editor_Action_Args& args) {
+	return parent.tools.place_immovable.handle_undo_impl(map, world, center, parent, args);
 }
 
 Editor_Action_Args Editor_Delete_Immovable_Tool::format_args_impl(Editor_Interactive & parent)
 {
 	return Editor_Tool::format_args_impl(parent);
 }
-

=== modified file 'src/editor/tools/editor_delete_immovable_tool.h'
--- src/editor/tools/editor_delete_immovable_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_delete_immovable_tool.h	2014-06-10 18:27:45 +0000
@@ -26,13 +26,17 @@
 struct Editor_Delete_Immovable_Tool : public Editor_Tool {
 	Editor_Delete_Immovable_Tool() : Editor_Tool(*this, *this) {}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_draw_tool.cc'
--- src/editor/tools/editor_draw_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_draw_tool.cc	2014-06-10 18:27:45 +0000
@@ -36,10 +36,12 @@
 	args.draw_actions.push_back(new Editor_Tool_Action(ac));
 }
 
-int32_t Editor_Draw_Tool::handle_click_impl
-	(Widelands::Map & /* map */, Widelands::Node_and_Triangle<Widelands::Coords> /* center */,
-	Editor_Interactive & /* parent */, Editor_Action_Args & args)
-{
+int32_t
+Editor_Draw_Tool::handle_click_impl(Widelands::Map& /* map */,
+                                    const Widelands::World& world,
+                                    Widelands::Node_and_Triangle<Widelands::Coords> /* center */,
+                                    Editor_Interactive& /* parent */,
+                                    Editor_Action_Args& args) {
 
 	for
 		(std::list<Editor_Tool_Action *>::iterator i = args.draw_actions.begin();
@@ -48,15 +50,17 @@
 	{
 		(*i)->tool.handle_click
 			(static_cast<Editor_Tool::Tool_Index>((*i)->i),
-				(*i)->map, (*i)->center, (*i)->parent, *((*i)->args));
+				(*i)->map, world, (*i)->center, (*i)->parent, *((*i)->args));
 	}
 	return args.draw_actions.size();
 }
 
-int32_t Editor_Draw_Tool::handle_undo_impl
-	(Widelands::Map & /* map */, Widelands::Node_and_Triangle<Widelands::Coords> /* center */,
-	Editor_Interactive & /* parent */, Editor_Action_Args & args)
-{
+int32_t
+Editor_Draw_Tool::handle_undo_impl(Widelands::Map& /* map */,
+                                   const Widelands::World& world,
+                                   Widelands::Node_and_Triangle<Widelands::Coords> /* center */,
+                                   Editor_Interactive& /* parent */,
+                                   Editor_Action_Args& args) {
 	for
 		(std::list<Editor_Tool_Action *>::reverse_iterator i = args.draw_actions.rbegin();
 	        i != args.draw_actions.rend();
@@ -64,7 +68,7 @@
 	{
 		(*i)->tool.handle_undo
 		(static_cast<Editor_Tool::Tool_Index>((*i)->i),
-			(*i)->map, (*i)->center, (*i)->parent, *((*i)->args));
+			(*i)->map, world, (*i)->center, (*i)->parent, *((*i)->args));
 	}
 	return args.draw_actions.size();
 }

=== modified file 'src/editor/tools/editor_draw_tool.h'
--- src/editor/tools/editor_draw_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_draw_tool.h	2014-06-10 18:27:45 +0000
@@ -28,13 +28,17 @@
 struct Editor_Draw_Tool : public Editor_Tool {
 	Editor_Draw_Tool() : Editor_Tool(*this, *this) {}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 
@@ -47,4 +51,3 @@
 };
 
 #endif
-

=== modified file 'src/editor/tools/editor_history.cc'
--- src/editor/tools/editor_history.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_history.cc	2014-06-10 18:27:45 +0000
@@ -55,8 +55,7 @@
 
 // === Editor_History === //
 
-uint32_t Editor_History::undo_action()
-{
+uint32_t Editor_History::undo_action(const Widelands::World& world) {
 	if (undo_stack.empty())
 		return 0;
 
@@ -67,14 +66,15 @@
 	m_undo_button.set_enabled(!undo_stack.empty());
 	m_redo_button.set_enabled(true);
 
-	return
-		uac.tool.handle_undo
-		(static_cast<Editor_Tool::Tool_Index>(uac.i),
-		 uac.map, uac.center, uac.parent, *uac.args);
+	return uac.tool.handle_undo(static_cast<Editor_Tool::Tool_Index>(uac.i),
+	                            uac.map,
+	                            world,
+	                            uac.center,
+	                            uac.parent,
+	                            *uac.args);
 }
 
-uint32_t Editor_History::redo_action()
-{
+uint32_t Editor_History::redo_action(const Widelands::World& world) {
 	if (redo_stack.empty())
 		return 0;
 
@@ -85,20 +85,21 @@
 	m_undo_button.set_enabled(true);
 	m_redo_button.set_enabled(!redo_stack.empty());
 
-	return
-		rac.tool.handle_click
-		(static_cast<Editor_Tool::Tool_Index>(rac.i),
-		 rac.map, rac.center, rac.parent, *rac.args);
+	return rac.tool.handle_click(static_cast<Editor_Tool::Tool_Index>(rac.i),
+	                             rac.map,
+	                             world,
+	                             rac.center,
+	                             rac.parent,
+	                             *rac.args);
 }
 
-uint32_t Editor_History::do_action
-	(Editor_Tool & tool,
-	Editor_Tool::Tool_Index ind,
-	Widelands::Map & map,
-	const Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent,
-	bool draw)
-{
+uint32_t Editor_History::do_action(Editor_Tool& tool,
+                                   Editor_Tool::Tool_Index ind,
+                                   Widelands::Map& map,
+                                   const Widelands::World& world,
+                                   const Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                   Editor_Interactive& parent,
+                                   bool draw) {
 	Editor_Tool_Action ac
 		(tool, static_cast<uint32_t>(ind),
 		 map, center, parent, tool.format_args(ind, parent));
@@ -130,7 +131,7 @@
 		m_undo_button.set_enabled(true);
 		m_redo_button.set_enabled(false);
 	}
-	return tool.handle_click(ind, map, center, parent, *ac.args);
+	return tool.handle_click(ind, map, world, center, parent, *ac.args);
 }
 
 
@@ -141,4 +142,3 @@
 	m_undo_button.set_enabled(false);
 	m_redo_button.set_enabled(false);
 }
-

=== modified file 'src/editor/tools/editor_history.h'
--- src/editor/tools/editor_history.h	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_history.h	2014-06-10 18:27:45 +0000
@@ -39,12 +39,15 @@
 	Editor_History(UI::Button & undo, UI::Button & redo):
 		m_undo_button(undo), m_redo_button(redo) {};
 
-	uint32_t do_action
-		(Editor_Tool & tool, Editor_Tool::Tool_Index ind, Widelands::Map & map,
-		 Widelands::Node_and_Triangle<> const center,
-		 Editor_Interactive & parent, bool draw = false);
-	uint32_t undo_action();
-	uint32_t redo_action();
+	uint32_t do_action(Editor_Tool& tool,
+	                   Editor_Tool::Tool_Index ind,
+	                   Widelands::Map& map,
+	                   const Widelands::World& world,
+	                   Widelands::Node_and_Triangle<> const center,
+	                   Editor_Interactive& parent,
+	                   bool draw = false);
+	uint32_t undo_action(const Widelands::World& world);
+	uint32_t redo_action(const Widelands::World& world);
 
 	/// Must be called after every change of map, world, or ... to avoid undo errors
 	void reset();
@@ -64,4 +67,3 @@
 
 
 #endif
-

=== modified file 'src/editor/tools/editor_increase_height_tool.cc'
--- src/editor/tools/editor_increase_height_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_increase_height_tool.cc	2014-06-10 18:27:45 +0000
@@ -25,36 +25,34 @@
 #include "logic/mapregion.h"
 
 /// Increases the heights by a value. Chages surrounding nodes if necessary.
-int32_t Editor_Increase_Height_Tool::handle_click_impl
-	(Widelands::Map & map,
-	Widelands::Node_and_Triangle<> center,
-	Editor_Interactive & /* parent */,
-	Editor_Action_Args & args)
-{
+int32_t Editor_Increase_Height_Tool::handle_click_impl(Widelands::Map& map,
+                                                       const Widelands::World& world,
+                                                       Widelands::Node_and_Triangle<> center,
+                                                       Editor_Interactive& /* parent */,
+                                                       Editor_Action_Args& args) {
 	if (args.origHights.empty()) {
-		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
+		   map,
+		   Widelands::Area<Widelands::FCoords>(
+		      map.get_fcoords(center.node),
+		      args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
 		do {
 			args.origHights.push_back(mr.location().field->get_height());
 		} while (mr.advance(map));
 	}
 
-	return
-	    map.change_height
-	    (Widelands::Area<Widelands::FCoords>
-	     (map.get_fcoords(center.node), args.sel_radius),
-	     args.change_by);
+	return map.change_height(
+	   world,
+	   Widelands::Area<Widelands::FCoords>(map.get_fcoords(center.node), args.sel_radius),
+	   args.change_by);
 }
 
-int32_t Editor_Increase_Height_Tool::handle_undo_impl
-	(Widelands::Map & map,
-	Widelands::Node_and_Triangle<> center,
-	Editor_Interactive & parent,
-	Editor_Action_Args & args)
-{
-	return m_decrease_tool.handle_undo_impl(map, center, parent, args);
+int32_t Editor_Increase_Height_Tool::handle_undo_impl(Widelands::Map& map,
+                                                      const Widelands::World& world,
+                                                      Widelands::Node_and_Triangle<> center,
+                                                      Editor_Interactive& parent,
+                                                      Editor_Action_Args& args) {
+	return m_decrease_tool.handle_undo_impl(map, world, center, parent, args);
 }
 
 Editor_Action_Args Editor_Increase_Height_Tool::format_args_impl(Editor_Interactive & parent)

=== modified file 'src/editor/tools/editor_increase_height_tool.h'
--- src/editor/tools/editor_increase_height_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_increase_height_tool.h	2014-06-10 18:27:45 +0000
@@ -34,13 +34,17 @@
 		m_change_by(1)
 	{}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_increase_resources_tool.cc'
--- src/editor/tools/editor_increase_resources_tool.cc	2014-05-27 11:01:15 +0000
+++ src/editor/tools/editor_increase_resources_tool.cc	2014-06-10 18:27:45 +0000
@@ -23,39 +23,55 @@
 #include "graphic/graphic.h"
 #include "logic/field.h"
 #include "logic/mapregion.h"
-#include "logic/world.h"
-#include "logic/worlddata.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 #include "wui/overlay_manager.h"
 
 using Widelands::TCoords;
 
+namespace  {
+
+int32_t resource_value(const Widelands::TerrainDescription& terrain,
+                       const Widelands::Resource_Index resource) {
+	if (!terrain.is_resource_valid(resource)) {
+		return -1;
+	}
+	if (terrain.get_is() & Widelands::TerrainDescription::UNPASSABLE) {
+		return 8;
+	}
+	return 1;
+}
+
+}  // namespace
+
+
 int32_t Editor_Change_Resource_Tool_Callback
-	(const TCoords<Widelands::FCoords>& c, Widelands::Map& map, int32_t const curres)
+	(const TCoords<Widelands::FCoords>& c, Widelands::Map& map,
+	 const Widelands::World& world, int32_t const curres)
 {
-	Widelands::World & world = map.world();
 	Widelands::FCoords f(c, &map[c]);
 
 	Widelands::FCoords f1;
 	int32_t count = 0;
 
 	//  this field
-	count += world.terrain_descr(f.field->terrain_r()).resource_value(curres);
-	count += world.terrain_descr(f.field->terrain_d()).resource_value(curres);
-
+	count += resource_value(world.terrain_descr(f.field->terrain_r()), curres);
+	count += resource_value(world.terrain_descr(f.field->terrain_d()), curres);
 
 	//  If one of the neighbours is unpassable, count its resource stronger.
 	//  top left neigbour
 	map.get_neighbour(f, Widelands::WALK_NW, &f1);
-	count += world.terrain_descr(f1.field->terrain_r()).resource_value(curres);
-	count += world.terrain_descr(f1.field->terrain_d()).resource_value(curres);
+	count += resource_value(world.terrain_descr(f1.field->terrain_r()), curres);
+	count += resource_value(world.terrain_descr(f1.field->terrain_d()), curres);
 
 	//  top right neigbour
 	map.get_neighbour(f, Widelands::WALK_NE, &f1);
-	count += world.terrain_descr(f1.field->terrain_d()).resource_value(curres);
+	count += resource_value(world.terrain_descr(f1.field->terrain_d()), curres);
 
 	//  left neighbour
 	map.get_neighbour(f, Widelands::WALK_W, &f1);
-	count += world.terrain_descr(f1.field->terrain_r()).resource_value(curres);
+	count += resource_value(world.terrain_descr(f1.field->terrain_r()), curres);
 
 	return count <= 3 ? 0 : f.field->nodecaps();
 }
@@ -68,23 +84,21 @@
 there is not already another resource there.
 ===========
 */
-int32_t Editor_Increase_Resources_Tool::handle_click_impl
-	(Widelands::Map           &           map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive         &         /* parent */,
-	Editor_Action_Args         &         args)
-{
-	const Widelands::World & world = map.world();
+int32_t
+Editor_Increase_Resources_Tool::handle_click_impl(Widelands::Map& map,
+                                                  const Widelands::World& world,
+                                                  Widelands::Node_and_Triangle<> const center,
+                                                  Editor_Interactive& /* parent */,
+                                                  Editor_Action_Args& args) {
 	OverlayManager & overlay_manager = map.overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 		(map,
 			Widelands::Area<Widelands::FCoords>
 				(map.get_fcoords(center.node), args.sel_radius));
 	do {
-		int32_t res        = mr.location().field->get_resources();
-		int32_t amount     = mr.location().field->get_resources_amount();
-		int32_t max_amount =
-		    map.get_world()->get_resource(args.cur_res)->get_max_amount();
+		int32_t res = mr.location().field->get_resources();
+		int32_t amount = mr.location().field->get_resources_amount();
+		int32_t max_amount = world.get_resource(args.cur_res)->max_amount();
 
 		amount += args.change_by;
 		if (amount > max_amount)
@@ -96,7 +110,7 @@
 		if
 		((res == args.cur_res or not mr.location().field->get_resources_amount())
 		        and
-		        Editor_Change_Resource_Tool_Callback(mr.location(), map, args.cur_res))
+		        Editor_Change_Resource_Tool_Callback(mr.location(), map, world, args.cur_res))
 		{
 			//  Ok, we're doing something. First remove the current overlays.
 			const Image* pic =
@@ -115,20 +129,21 @@
 				pic = g_gr->images().get
 				        (world.get_resource(args.cur_res)->get_editor_pic(amount));
 				overlay_manager.register_overlay(mr.location(), pic, 4);
-				map.recalc_for_field_area
-				(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+				map.recalc_for_field_area(
+				   world, Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}
 		}
 	} while (mr.advance(map));
 	return mr.radius();
 }
 
-int32_t Editor_Increase_Resources_Tool::handle_undo_impl
-	(Widelands::Map & map,
-	Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
-	return m_set_tool.handle_undo_impl(map, center, parent, args);
+int32_t Editor_Increase_Resources_Tool::handle_undo_impl(
+   Widelands::Map& map,
+   const Widelands::World& world,
+   Widelands::Node_and_Triangle<Widelands::Coords> center,
+   Editor_Interactive& parent,
+   Editor_Action_Args& args) {
+	return m_set_tool.handle_undo_impl(map, world, center, parent, args);
 }
 
 Editor_Action_Args Editor_Increase_Resources_Tool::format_args_impl(Editor_Interactive & parent)

=== modified file 'src/editor/tools/editor_increase_resources_tool.h'
--- src/editor/tools/editor_increase_resources_tool.h	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_increase_resources_tool.h	2014-06-10 18:27:45 +0000
@@ -26,22 +26,26 @@
 
 /// Increases the resources of a node by a value.
 struct Editor_Increase_Resources_Tool : public Editor_Tool {
-	Editor_Increase_Resources_Tool
-	(Editor_Decrease_Resources_Tool & the_decrease_tool,
-	 Editor_Set_Resources_Tool    &   the_set_to_tool)
-		:
-		Editor_Tool(the_decrease_tool, the_set_to_tool),
-		m_decrease_tool(the_decrease_tool), m_set_tool(the_set_to_tool),
-		m_change_by(1), m_cur_res(0)
-	{}
-
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
-
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	Editor_Increase_Resources_Tool(Editor_Decrease_Resources_Tool& the_decrease_tool,
+	                               Editor_Set_Resources_Tool& the_set_to_tool)
+	   : Editor_Tool(the_decrease_tool, the_set_to_tool),
+	     m_decrease_tool(the_decrease_tool),
+	     m_set_tool(the_set_to_tool),
+	     m_change_by(1),
+	     m_cur_res(0) {
+	}
+
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
+
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 
@@ -63,12 +67,14 @@
 
 private:
 	Editor_Decrease_Resources_Tool & m_decrease_tool;
-	Editor_Set_Resources_Tool    &   m_set_tool;
-	int32_t                              m_change_by;
+	Editor_Set_Resources_Tool& m_set_tool;
+	int32_t m_change_by;
 	Widelands::Resource_Index m_cur_res;
 };
 
-int32_t Editor_Change_Resource_Tool_Callback
-	(const Widelands::TCoords<Widelands::FCoords>&, Widelands::Map&, int32_t);
+int32_t Editor_Change_Resource_Tool_Callback(const Widelands::TCoords<Widelands::FCoords>& c,
+                                             Widelands::Map& map,
+                                             const Widelands::World& world,
+                                             int32_t const curres);
 
 #endif

=== modified file 'src/editor/tools/editor_info_tool.cc'
--- src/editor/tools/editor_info_tool.cc	2014-03-09 10:28:39 +0000
+++ src/editor/tools/editor_info_tool.cc	2014-06-10 18:27:45 +0000
@@ -26,18 +26,17 @@
 #include "editor/editorinteractive.h"
 #include "i18n.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/terrain_description.h"
+#include "logic/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 Editor_Info_Tool::handle_click_impl
-	(Widelands::Map            &         map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive         &         parent,
-	Editor_Action_Args         &         /* args */)
-{
-	const Widelands::World & world = map.world();
+int32_t Editor_Info_Tool::handle_click_impl(Widelands::Map& map,
+								  const Widelands::World& world,
+								  Widelands::Node_and_Triangle<> center,
+								  Editor_Interactive& parent,
+								  Editor_Action_Args& /* args */) {
 	UI::Window * const w =
 	    new UI::Window
 	(&parent, "field_information", 30, 30, 400, 200,
@@ -97,9 +96,8 @@
 	buf += std::string("\n") + _("Terrain:") + "\n";
 
 	const Widelands::Field         & tf  = map[center.triangle];
-	const Widelands::Terrain_Descr & ter = world.terrain_descr
-	                                       (center.triangle.t == Widelands::TCoords<>::D ?
-	                                        tf.terrain_d() : tf.terrain_r());
+	const Widelands::TerrainDescription& ter = world.terrain_descr(
+	   center.triangle.t == Widelands::TCoords<>::D ? tf.terrain_d() : tf.terrain_r());
 
 	buf += std::string("• ") + (boost::format(_("Name: %s")) % ter.descname()).str() + "\n";
 	buf += std::string("• ") + (boost::format(_("Texture Number: %i")) % ter.get_texture()).str() + "\n";
@@ -134,12 +132,6 @@
 	buf += std::string("• ") + (boost::format(_("Author: %s")) % map.get_author()).str() + "\n";
 	buf += std::string("• ") + (boost::format(_("Descr: %s")) % map.get_description()).str() + "\n";
 
-	// *** World info
-	buf += std::string("\n") + _("World:") + "\n";
-	buf += std::string("• ") + (boost::format(_("Name: %s")) % world.get_name()).str() + "\n";
-	buf += std::string("• ") + (boost::format(_("Author: %s")) % world.get_author()).str() + "\n";
-	buf += std::string("• ") + (boost::format(_("Descr: %s")) % world.get_descr()).str() + "\n";
-
 	multiline_textarea->set_text(buf.c_str());
 
 	return 0;

=== modified file 'src/editor/tools/editor_info_tool.h'
--- src/editor/tools/editor_info_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_info_tool.h	2014-06-10 18:27:45 +0000
@@ -24,13 +24,18 @@
 
 /// A simple tool to show information about the clicked node.
 struct Editor_Info_Tool : public Editor_Tool {
-	Editor_Info_Tool() : Editor_Tool(*this, *this, false) {}
-
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
-
-	char const * get_sel_impl() const override {return "pics/fsel_editor_info.png";}
+	Editor_Info_Tool() : Editor_Tool(*this, *this, false) {
+	}
+
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
+
+	char const* get_sel_impl() const override {
+		return "pics/fsel_editor_info.png";
+	}
 };
 
 #endif

=== modified file 'src/editor/tools/editor_make_infrastructure_tool.cc'
--- src/editor/tools/editor_make_infrastructure_tool.cc	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_make_infrastructure_tool.cc	2014-06-10 18:27:45 +0000
@@ -46,12 +46,11 @@
  *
  * Obviously, this function ignores the sel radius
 */
-int32_t Editor_Make_Infrastructure_Tool::handle_click_impl
-	(Widelands::Map &,
-	Widelands::Node_and_Triangle<> const,
-	Editor_Interactive         &         parent,
-	Editor_Action_Args         &         /* args */)
-{
+int32_t Editor_Make_Infrastructure_Tool::handle_click_impl(Widelands::Map&,
+                                                           const Widelands::World&,
+                                                           Widelands::Node_and_Triangle<> const,
+                                                           Editor_Interactive& parent,
+                                                           Editor_Action_Args& /* args */) {
 	show_field_action
 	(&parent, parent.egbase().get_player(m_player), &m_registry);
 

=== modified file 'src/editor/tools/editor_make_infrastructure_tool.h'
--- src/editor/tools/editor_make_infrastructure_tool.h	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_make_infrastructure_tool.h	2014-06-10 18:27:45 +0000
@@ -23,6 +23,10 @@
 #include "editor/tools/editor_tool.h"
 #include "ui_basic/unique_window.h"
 
+namespace Widelands {
+class Editor_Game_Base;
+}  // namespace Widelands
+
 /**
  * This places immovables on the map
  * \TODO Implement undo for this tool
@@ -35,9 +39,11 @@
 	Widelands::Player_Number get_player() const
 		{return m_player;}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
 	const char * get_sel_impl() const override
 		{return "pics/fsel.png";} //  Standard sel icon, most complex tool of all

=== modified file 'src/editor/tools/editor_noise_height_tool.cc'
--- src/editor/tools/editor_noise_height_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_noise_height_tool.cc	2014-06-10 18:27:45 +0000
@@ -27,12 +27,11 @@
 #include "logic/mapregion.h"
 
 /// Sets the heights to random values. Changes surrounding nodes if necessary.
-int32_t Editor_Noise_Height_Tool::handle_click_impl
-	(Widelands::Map           &           map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive         &         /* parent */,
-	Editor_Action_Args & args)
-{
+int32_t Editor_Noise_Height_Tool::handle_click_impl(Widelands::Map& map,
+                                                    const Widelands::World& world,
+                                                    Widelands::Node_and_Triangle<> const center,
+                                                    Editor_Interactive& /* parent */,
+                                                    Editor_Action_Args& args) {
 	if (args.origHights.empty()) {
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 		(map,
@@ -50,27 +49,25 @@
 	 Widelands::Area<Widelands::FCoords>
 	 (map.get_fcoords(center.node), args.sel_radius));
 	do {
-		max =
-		    std::max
-		    (max,
-		     map.set_height
-		     (mr.location(),
-		      args.m_interval.min
-		      +
-		      static_cast<int32_t>
-		      (static_cast<double>
-		       (args.m_interval.max - args.m_interval.min + 1) * rand()
-		       /
-		       (RAND_MAX + 1.0))));
+		max = std::max(
+		   max,
+		   map.set_height(world,
+		                  mr.location(),
+		                  args.m_interval.min +
+		                     static_cast<int32_t>(
+		                        static_cast<double>(args.m_interval.max - args.m_interval.min + 1) *
+		                        rand() / (RAND_MAX + 1.0))));
 	} while (mr.advance(map));
 	return mr.radius() + max;
 }
 
-int32_t Editor_Noise_Height_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
-	return m_set_tool.handle_undo_impl(map, center, parent, args);
+int32_t
+Editor_Noise_Height_Tool::handle_undo_impl(Widelands::Map& map,
+                                           const Widelands::World& world,
+                                           Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                           Editor_Interactive& parent,
+                                           Editor_Action_Args& args) {
+	return m_set_tool.handle_undo_impl(map, world, center, parent, args);
 }
 
 Editor_Action_Args Editor_Noise_Height_Tool::format_args_impl(Editor_Interactive & parent)
@@ -79,4 +76,3 @@
 	a.m_interval = m_interval;
 	return a;
 }
-

=== modified file 'src/editor/tools/editor_noise_height_tool.h'
--- src/editor/tools/editor_noise_height_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_noise_height_tool.h	2014-06-10 18:27:45 +0000
@@ -34,13 +34,17 @@
 		m_interval(the_interval)
 	{}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_place_bob_tool.cc'
--- src/editor/tools/editor_place_bob_tool.cc	2014-03-31 20:21:27 +0000
+++ src/editor/tools/editor_place_bob_tool.cc	2014-06-10 18:27:45 +0000
@@ -24,17 +24,17 @@
 #include "logic/editor_game_base.h"
 #include "logic/field.h"
 #include "logic/mapregion.h"
+#include "logic/world/world.h"
 
 /**
  * Choses an object to place randomly from all enabled
  * and places this on the current field
 */
-int32_t Editor_Place_Bob_Tool::handle_click_impl
-	(Widelands::Map           &           map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive       &           parent,
-	 Editor_Action_Args       &           args)
-{
+int32_t Editor_Place_Bob_Tool::handle_click_impl(Widelands::Map& map,
+                                                 const Widelands::World& world,
+                                                 Widelands::Node_and_Triangle<> const center,
+                                                 Editor_Interactive& parent,
+                                                 Editor_Action_Args& args) {
 
 	if (get_nr_enabled() && args.obob_type.empty()) {
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
@@ -44,7 +44,7 @@
 		do {
 			Widelands::Bob * const mbob = mr.location().field->get_first_bob();
 			args.obob_type.push_back((mbob ? &mbob->descr() : nullptr));
-			args.nbob_type.push_back(map.world().get_bob_descr(get_random_enabled()));
+			args.nbob_type.push_back(world.get_bob_descr(get_random_enabled()));
 		} while (mr.advance(map));
 	}
 
@@ -69,10 +69,12 @@
 		return 0;
 }
 
-int32_t Editor_Place_Bob_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
+int32_t
+Editor_Place_Bob_Tool::handle_undo_impl(Widelands::Map& map,
+                                        const Widelands::World&,
+                                        Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                        Editor_Interactive& parent,
+                                        Editor_Action_Args& args) {
 	if (not args.nbob_type.empty()) {
 		Widelands::Editor_Game_Base & egbase = parent.egbase();
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr

=== modified file 'src/editor/tools/editor_place_bob_tool.h'
--- src/editor/tools/editor_place_bob_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_place_bob_tool.h	2014-06-10 18:27:45 +0000
@@ -29,13 +29,17 @@
 		: Editor_Tool(tool, tool)
 	{}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_place_immovable_tool.cc'
--- src/editor/tools/editor_place_immovable_tool.cc	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_place_immovable_tool.cc	2014-06-10 18:27:45 +0000
@@ -32,12 +32,11 @@
  * Choses an object to place randomly from all enabled
  * and places this on the current field
 */
-int32_t Editor_Place_Immovable_Tool::handle_click_impl
-	(Widelands::Map            &         map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive         &         parent,
-	Editor_Action_Args         &         args)
-{
+int32_t Editor_Place_Immovable_Tool::handle_click_impl(Widelands::Map& map,
+                                                       const Widelands::World&,
+                                                       Widelands::Node_and_Triangle<> const center,
+                                                       Editor_Interactive& parent,
+                                                       Editor_Action_Args& args) {
 	const int32_t radius = args.sel_radius;
 	if (not get_nr_enabled())
 		return radius;
@@ -74,10 +73,12 @@
 	return radius + 2;
 }
 
-int32_t Editor_Place_Immovable_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
+int32_t Editor_Place_Immovable_Tool::handle_undo_impl(
+   Widelands::Map& map,
+   const Widelands::World&,
+   Widelands::Node_and_Triangle<Widelands::Coords> center,
+   Editor_Interactive& parent,
+   Editor_Action_Args& args) {
 	const int32_t radius = args.sel_radius;
 	if (args.oimmov_types.empty())
 		return radius;
@@ -107,6 +108,3 @@
 {
 	return Editor_Tool::format_args_impl(parent);
 }
-
-
-

=== modified file 'src/editor/tools/editor_place_immovable_tool.h'
--- src/editor/tools/editor_place_immovable_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_place_immovable_tool.h	2014-06-10 18:27:45 +0000
@@ -31,13 +31,17 @@
 		: Editor_Tool(tool, tool)
 	{}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_set_height_tool.cc'
--- src/editor/tools/editor_set_height_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_set_height_tool.cc	2014-06-10 18:27:45 +0000
@@ -26,12 +26,11 @@
 #include "logic/map.h"
 #include "logic/mapregion.h"
 
-
-int32_t Editor_Set_Height_Tool::handle_click_impl
-	(Widelands::Map           &           map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive         &         /* parent */, Editor_Action_Args & args)
-{
+int32_t Editor_Set_Height_Tool::handle_click_impl(Widelands::Map& map,
+                                                  const Widelands::World& world,
+                                                  Widelands::Node_and_Triangle<> const center,
+                                                  Editor_Interactive& /* parent */,
+                                                  Editor_Action_Args& args) {
 	if (args.origHights.empty())
 	{
 		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
@@ -41,17 +40,18 @@
 		do args.origHights.push_back(mr.location().field->get_height());
 		while (mr.advance(map));
 	}
-	return
-	    map.set_height
-	    (Widelands::Area<Widelands::FCoords>
-	     (map.get_fcoords(center.node), args.sel_radius),
-	     args.m_interval);
+	return map.set_height(
+	   world,
+	   Widelands::Area<Widelands::FCoords>(map.get_fcoords(center.node), args.sel_radius),
+	   args.m_interval);
 }
 
-int32_t Editor_Set_Height_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & /* parent */, Editor_Action_Args & args)
-{
+int32_t
+Editor_Set_Height_Tool::handle_undo_impl(Widelands::Map& map,
+                                         const Widelands::World& world,
+                                         Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                         Editor_Interactive& /* parent */,
+                                         Editor_Action_Args& args) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
 	Widelands::Area<Widelands::FCoords>
@@ -65,7 +65,7 @@
 	} while (mr.advance(map));
 
 	map.recalc_for_field_area
-		(Widelands::Area<Widelands::FCoords>
+		(world, Widelands::Area<Widelands::FCoords>
 		(map.get_fcoords(center.node),
 		args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 2));
 
@@ -78,6 +78,3 @@
 	a.m_interval = m_interval;
 	return a;
 }
-
-
-

=== modified file 'src/editor/tools/editor_set_height_tool.h'
--- src/editor/tools/editor_set_height_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_set_height_tool.h	2014-06-10 18:27:45 +0000
@@ -30,13 +30,17 @@
 		: Editor_Tool(*this, *this), m_interval(10, 10)
 	{}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_set_origin_tool.cc'
--- src/editor/tools/editor_set_origin_tool.cc	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_set_origin_tool.cc	2014-06-10 18:27:45 +0000
@@ -24,12 +24,11 @@
 #include "wui/mapviewpixelconstants.h"
 #include "wui/overlay_manager.h"
 
-int32_t Editor_Set_Origin_Tool::handle_click_impl
-	(Widelands::Map           &          map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive        &          eia,
-	Editor_Action_Args        &          /* args */)
-{
+int32_t Editor_Set_Origin_Tool::handle_click_impl(Widelands::Map& map,
+                                                  const Widelands::World&,
+                                                  Widelands::Node_and_Triangle<> const center,
+                                                  Editor_Interactive& eia,
+                                                  Editor_Action_Args& /* args */) {
 	map.set_origin(center.node);
 	eia.register_overlays();
 	eia.set_rel_viewpoint
@@ -40,10 +39,12 @@
 	return 0;
 }
 
-int32_t Editor_Set_Origin_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & /* args */)
-{
+int32_t
+Editor_Set_Origin_Tool::handle_undo_impl(Widelands::Map& map,
+                                         const Widelands::World&,
+                                         Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                         Editor_Interactive& parent,
+                                         Editor_Action_Args& /* args */) {
 	Widelands::Coords nc
 		(map.get_width()  - center.node.x,
 		 map.get_height() - center.node.y);

=== modified file 'src/editor/tools/editor_set_origin_tool.h'
--- src/editor/tools/editor_set_origin_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_set_origin_tool.h	2014-06-10 18:27:45 +0000
@@ -27,13 +27,17 @@
 struct Editor_Set_Origin_Tool : public Editor_Tool {
 	Editor_Set_Origin_Tool() : Editor_Tool(*this, *this) {}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & eia, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& eia,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_set_port_space_tool.cc'
--- src/editor/tools/editor_set_port_space_tool.cc	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_set_port_space_tool.cc	2014-06-10 18:27:45 +0000
@@ -55,12 +55,11 @@
 	Editor_Tool(*this, *this)
 {}
 
-
-int32_t Editor_Set_Port_Space_Tool::handle_click_impl
-	(Map & map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive &,  Editor_Action_Args & args)
-{
+int32_t Editor_Set_Port_Space_Tool::handle_click_impl(Map& map,
+                                                      const Widelands::World& world,
+                                                      Widelands::Node_and_Triangle<> const center,
+                                                      Editor_Interactive&,
+                                                      Editor_Action_Args& args) {
 	assert(0 <= center.node.x);
 	assert(center.node.x < map.get_width());
 	assert(0 <= center.node.y);
@@ -75,7 +74,7 @@
 		if (Editor_Tool_Set_Port_Space_Callback(mr.location(), map)) {
 			map.set_port_space(mr.location(), true);
 			Area<FCoords> a(mr.location(), 0);
-			map.recalc_for_field_area(a);
+			map.recalc_for_field_area(world, a);
 			++nr;
 		}
 	} while (mr.advance(map));
@@ -83,19 +82,19 @@
 	return nr;
 }
 
-int32_t Editor_Set_Port_Space_Tool::handle_undo_impl
-	(Map & map, Node_and_Triangle< Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
-	return parent.tools.unset_port_space.handle_click_impl(map, center, parent, args);
+int32_t Editor_Set_Port_Space_Tool::handle_undo_impl(Map& map,
+                                                     const Widelands::World& world,
+                                                     Node_and_Triangle<Coords> center,
+                                                     Editor_Interactive& parent,
+                                                     Editor_Action_Args& args) {
+	return parent.tools.unset_port_space.handle_click_impl(map, world, center, parent, args);
 }
 
-
-int32_t Editor_Unset_Port_Space_Tool::handle_click_impl
-	(Map & map,
-	Node_and_Triangle<> const center,
-	Editor_Interactive &, Editor_Action_Args & args)
-{
+int32_t Editor_Unset_Port_Space_Tool::handle_click_impl(Map& map,
+                                                        const Widelands::World& world,
+                                                        Node_and_Triangle<> const center,
+                                                        Editor_Interactive&,
+                                                        Editor_Action_Args& args) {
 	assert(0 <= center.node.x);
 	assert(center.node.x < map.get_width());
 	assert(0 <= center.node.y);
@@ -110,7 +109,7 @@
 		if (Editor_Tool_Set_Port_Space_Callback(mr.location(), map)) {
 			map.set_port_space(mr.location(), false);
 			Area<FCoords> a(mr.location(), 0);
-			map.recalc_for_field_area(a);
+			map.recalc_for_field_area(world, a);
 			++nr;
 		}
 	} while (mr.advance(map));
@@ -118,10 +117,10 @@
 	return nr;
 }
 
-
-int32_t Editor_Unset_Port_Space_Tool::handle_undo_impl
-	(Map & map, Node_and_Triangle< Coords > center,
-	Editor_Interactive & parent, Editor_Action_Args & args)
-{
-	return parent.tools.set_port_space.handle_click_impl(map, center, parent, args);
+int32_t Editor_Unset_Port_Space_Tool::handle_undo_impl(Map& map,
+                                                       const Widelands::World& world,
+                                                       Node_and_Triangle<Coords> center,
+                                                       Editor_Interactive& parent,
+                                                       Editor_Action_Args& args) {
+	return parent.tools.set_port_space.handle_click_impl(map, world, center, parent, args);
 }

=== modified file 'src/editor/tools/editor_set_port_space_tool.h'
--- src/editor/tools/editor_set_port_space_tool.h	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_set_port_space_tool.h	2014-06-10 18:27:45 +0000
@@ -31,13 +31,17 @@
 public:
 	Editor_Unset_Port_Space_Tool();
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	char const * get_sel_impl() const override {return FSEL_EUPS_FILENAME;}
 };
@@ -48,13 +52,17 @@
 public:
 	Editor_Set_Port_Space_Tool(Editor_Unset_Port_Space_Tool &);
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	char const * get_sel_impl() const override {return FSEL_ESPS_FILENAME;}
 };

=== modified file 'src/editor/tools/editor_set_resources_tool.cc'
--- src/editor/tools/editor_set_resources_tool.cc	2014-05-27 11:01:15 +0000
+++ src/editor/tools/editor_set_resources_tool.cc	2014-06-10 18:27:45 +0000
@@ -25,19 +25,18 @@
 #include "graphic/graphic.h"
 #include "logic/field.h"
 #include "logic/mapregion.h"
-#include "logic/world.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/world.h"
 #include "wui/overlay_manager.h"
 
 /**
  * Sets the resources of the current to a fixed value
 */
-int32_t Editor_Set_Resources_Tool::handle_click_impl
-	(Widelands::Map           &          map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive        &          /* parent */,
-	Editor_Action_Args        &          args)
-{
-	const Widelands::World & world = map.world();
+int32_t Editor_Set_Resources_Tool::handle_click_impl(Widelands::Map& map,
+                                                     const Widelands::World& world,
+                                                     Widelands::Node_and_Triangle<> const center,
+                                                     Editor_Interactive& /* parent */,
+                                                     Editor_Action_Args& args) {
 	OverlayManager & overlay_manager = map.overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
@@ -46,7 +45,7 @@
 	do {
 		int32_t res        = mr.location().field->get_resources();
 		int32_t amount     = args.set_to;
-		int32_t max_amount = world.get_resource(args.cur_res)->get_max_amount();
+		int32_t max_amount = world.get_resource(args.cur_res)->max_amount();
 
 		if (amount < 0)
 			amount = 0;
@@ -56,7 +55,7 @@
 		args.orgResT.push_back(res);
 		args.orgRes.push_back(mr.location().field->get_resources_amount());
 
-		if (Editor_Change_Resource_Tool_Callback(mr.location(), map, args.cur_res)) {
+		if (Editor_Change_Resource_Tool_Callback(mr.location(), map, world, args.cur_res)) {
 			//  Ok, we're doing something. First remove the current overlays.
 			const Image* pic = g_gr->images().get
 				(world.get_resource(res)->get_editor_pic (mr.location().field->get_resources_amount()));
@@ -72,19 +71,19 @@
 				pic =
 				    g_gr->images().get(world.get_resource(args.cur_res)->get_editor_pic(amount));
 				overlay_manager.register_overlay(mr.location(), pic, 4);
-				map.recalc_for_field_area
-				(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+				map.recalc_for_field_area(world, Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}
 		}
 	} while (mr.advance(map));
 	return mr.radius();
 }
 
-int32_t Editor_Set_Resources_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & /* parent */, Editor_Action_Args & args)
-{
-	const Widelands::World & world = map.world();
+int32_t
+Editor_Set_Resources_Tool::handle_undo_impl(Widelands::Map& map,
+                                            const Widelands::World& world,
+                                            Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                            Editor_Interactive& /* parent */,
+                                            Editor_Action_Args& args) {
 	OverlayManager & overlay_manager = map.overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
@@ -94,7 +93,7 @@
 	do {
 		int32_t res        = mr.location().field->get_resources();
 		int32_t amount     = *ir;
-		int32_t max_amount = world.get_resource(args.cur_res)->get_max_amount();
+		int32_t max_amount = world.get_resource(args.cur_res)->max_amount();
 
 		if (amount < 0)
 			amount = 0;
@@ -115,8 +114,7 @@
 			//  set new overlay
 			pic = g_gr->images().get(world.get_resource(*it)->get_editor_pic(amount));
 			overlay_manager.register_overlay(mr.location(), pic, 4);
-			map.recalc_for_field_area
-			(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+			map.recalc_for_field_area(world, Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 		}
 		++ir;
 		++it;

=== modified file 'src/editor/tools/editor_set_resources_tool.h'
--- src/editor/tools/editor_set_resources_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_set_resources_tool.h	2014-06-10 18:27:45 +0000
@@ -21,7 +21,6 @@
 #define EDITOR_SET_RESOURCES_TOOL_H
 
 #include "editor/tools/editor_tool.h"
-#include "logic/world.h"
 
 ///  Decreases the resources of a node by a value.
 struct Editor_Set_Resources_Tool : public Editor_Tool {
@@ -29,13 +28,17 @@
 		: Editor_Tool(*this, *this), m_cur_res(0), m_set_to(0)
 	{}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 
@@ -51,7 +54,7 @@
 
 private:
 	Widelands::Resource_Index m_cur_res;
-	uint8_t                   m_set_to;
+	uint8_t m_set_to;
 };
 
 #endif

=== modified file 'src/editor/tools/editor_set_starting_pos_tool.cc'
--- src/editor/tools/editor_set_starting_pos_tool.cc	2014-05-27 11:01:15 +0000
+++ src/editor/tools/editor_set_starting_pos_tool.cc	2014-06-10 18:27:45 +0000
@@ -62,12 +62,11 @@
 	strcpy(fsel_picsname, FSEL_PIC_FILENAME);
 }
 
-
-int32_t Editor_Set_Starting_Pos_Tool::handle_click_impl
-	(Widelands::Map           &          map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive &, Editor_Action_Args &)
-{
+int32_t Editor_Set_Starting_Pos_Tool::handle_click_impl(Widelands::Map& map,
+                                                        const Widelands::World&,
+                                                        Widelands::Node_and_Triangle<> const center,
+                                                        Editor_Interactive&,
+                                                        Editor_Action_Args&) {
 	assert(0 <= center.node.x);
 	assert(center.node.x < map.get_width());
 	assert(0 <= center.node.y);

=== modified file 'src/editor/tools/editor_set_starting_pos_tool.h'
--- src/editor/tools/editor_set_starting_pos_tool.h	2014-03-09 18:32:29 +0000
+++ src/editor/tools/editor_set_starting_pos_tool.h	2014-06-10 18:27:45 +0000
@@ -34,9 +34,11 @@
 struct Editor_Set_Starting_Pos_Tool : public Editor_Tool {
 	Editor_Set_Starting_Pos_Tool();
 
-	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>,
-		 Editor_Interactive &, Editor_Action_Args &) override;
+	int32_t handle_click_impl(Widelands::Map&,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<>,
+	                          Editor_Interactive&,
+	                          Editor_Action_Args&) override;
 	char const * get_sel_impl() const override
 		{return m_current_sel_pic;}
 

=== modified file 'src/editor/tools/editor_set_terrain_tool.cc'
--- src/editor/tools/editor_set_terrain_tool.cc	2013-07-26 20:19:36 +0000
+++ src/editor/tools/editor_set_terrain_tool.cc	2014-06-10 18:27:45 +0000
@@ -25,11 +25,11 @@
 
 using Widelands::TCoords;
 
-int32_t Editor_Set_Terrain_Tool::handle_click_impl
-	(Widelands::Map           &          map,
-	Widelands::Node_and_Triangle<> const center,
-	Editor_Interactive        &          /* parent */, Editor_Action_Args & args)
-{
+int32_t Editor_Set_Terrain_Tool::handle_click_impl(Widelands::Map& map,
+                                                   const Widelands::World& world,
+                                                   Widelands::Node_and_Triangle<> const center,
+                                                   Editor_Interactive& /* parent */,
+                                                   Editor_Action_Args& args) {
 	assert
 	(center.triangle.t == TCoords<>::D or center.triangle.t == TCoords<>::R);
 	uint16_t const radius = args.sel_radius;
@@ -60,17 +60,19 @@
 		std::list<Widelands::Terrain_Index>::iterator i = args.terrainType.begin();
 		do {
 			max = std::max
-			      (max, map.change_terrain(mr.location(), *i));
+			      (max, map.change_terrain(world, mr.location(), *i));
 			++i;
 		} while (mr.advance(map));
 	}
 	return radius + max;
 }
 
-int32_t Editor_Set_Terrain_Tool::handle_undo_impl
-	(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
-	Editor_Interactive & /* parent */, Editor_Action_Args & args)
-{
+int32_t
+Editor_Set_Terrain_Tool::handle_undo_impl(Widelands::Map& map,
+                                          const Widelands::World& world,
+                                          Widelands::Node_and_Triangle<Widelands::Coords> center,
+                                          Editor_Interactive& /* parent */,
+                                          Editor_Action_Args& args) {
 	assert
 	(center.triangle.t == TCoords<>::D or center.triangle.t == TCoords<>::R);
 	uint16_t const radius = args.sel_radius;
@@ -88,7 +90,7 @@
 		std::list<Widelands::Terrain_Index>::iterator i = args.origTerrainType.begin();
 		do {
 			max = std::max
-			      (max, map.change_terrain(mr.location(), *i));
+			      (max, map.change_terrain(world, mr.location(), *i));
 			++i;
 		} while (mr.advance(map));
 		return radius + max;

=== modified file 'src/editor/tools/editor_set_terrain_tool.h'
--- src/editor/tools/editor_set_terrain_tool.h	2014-02-22 18:04:02 +0000
+++ src/editor/tools/editor_set_terrain_tool.h	2014-06-10 18:27:45 +0000
@@ -26,13 +26,17 @@
 struct Editor_Set_Terrain_Tool : public Editor_Tool, public MultiSelect {
 	Editor_Set_Terrain_Tool() : Editor_Tool(*this, *this) {}
 
-	int32_t handle_click_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_click_impl(Widelands::Map& map,
+	                          const Widelands::World& world,
+	                          Widelands::Node_and_Triangle<> center,
+	                          Editor_Interactive& parent,
+	                          Editor_Action_Args& args) override;
 
-	int32_t handle_undo_impl
-		(Widelands::Map & map, Widelands::Node_and_Triangle<> center,
-		 Editor_Interactive & parent, Editor_Action_Args & args) override;
+	int32_t handle_undo_impl(Widelands::Map& map,
+	                         const Widelands::World& world,
+	                         Widelands::Node_and_Triangle<> center,
+	                         Editor_Interactive& parent,
+	                         Editor_Action_Args& args) override;
 
 	Editor_Action_Args format_args_impl(Editor_Interactive & parent) override;
 

=== modified file 'src/editor/tools/editor_tool.h'
--- src/editor/tools/editor_tool.h	2013-09-22 18:01:36 +0000
+++ src/editor/tools/editor_tool.h	2014-06-10 18:27:45 +0000
@@ -28,7 +28,10 @@
 #include "logic/widelands_geometry.h"
 
 struct Editor_Interactive;
-namespace Widelands {class Map;}
+namespace Widelands {
+class Map;
+class World;
+}
 
 /**
  * An editor tool is a tool that can be selected in the editor. Examples are:
@@ -46,22 +49,22 @@
 	enum Tool_Index {First, Second, Third};
 	int32_t handle_click
 		(const Tool_Index i,
-		Widelands::Map & map, Widelands::Node_and_Triangle<> const center,
+		Widelands::Map & map, const Widelands::World& world, Widelands::Node_and_Triangle<> const center,
 		Editor_Interactive & parent, Editor_Action_Args & args)
 	{
 		return
 		    (i == First ? *this : i == Second ? m_second : m_third)
-		    .handle_click_impl(map, center, parent, args);
+		    .handle_click_impl(map, world, center, parent, args);
 	}
 
 	int32_t handle_undo
 		(const Tool_Index i,
-		Widelands::Map & map, Widelands::Node_and_Triangle<> const center,
+		Widelands::Map & map, const Widelands::World& world, Widelands::Node_and_Triangle<> const center,
 		Editor_Interactive & parent, Editor_Action_Args & args)
 	{
 		return
 		    (i == First ? *this : i == Second ? m_second : m_third)
-		    .handle_undo_impl(map, center, parent, args);
+		    .handle_undo_impl(map, world, center, parent, args);
 	}
 
 	const char * get_sel(const Tool_Index i) {
@@ -81,12 +84,18 @@
 	virtual Editor_Action_Args format_args_impl(Editor_Interactive & parent) {
 		return Editor_Action_Args(parent);
 	}
-	virtual int32_t handle_click_impl
-	(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &, Editor_Action_Args &)
-	= 0;
-	virtual int32_t handle_undo_impl
-	(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &, Editor_Action_Args &)
-	{return 0;} // non unduable tools don't need to implement this.
+	virtual int32_t handle_click_impl(Widelands::Map&,
+	                                  const Widelands::World& world,
+	                                  Widelands::Node_and_Triangle<>,
+	                                  Editor_Interactive&,
+	                                  Editor_Action_Args&) = 0;
+	virtual int32_t handle_undo_impl(Widelands::Map&,
+	                                 const Widelands::World&,
+	                                 Widelands::Node_and_Triangle<>,
+	                                 Editor_Interactive&,
+	                                 Editor_Action_Args&) {
+		return 0;
+	}  // non unduable tools don't need to implement this.
 	virtual const char * get_sel_impl() const = 0;
 	virtual bool operates_on_triangles() const {return false;};
 

=== added file 'src/editor/ui_menus/categorized_item_selection_menu.h'
--- src/editor/ui_menus/categorized_item_selection_menu.h	1970-01-01 00:00:00 +0000
+++ src/editor/ui_menus/categorized_item_selection_menu.h	2014-06-10 18:27:45 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef MULTI_SELECT_MENU_H
+#define MULTI_SELECT_MENU_H
+
+#include <string>
+#include <cmath>
+
+#include "description_maintainer.h"
+#include "graphic/image.h"
+#include "graphic/image_transformations.h"
+#include "i18n.h"
+#include "logic/world/editor_category.h"
+#include "ui_basic/box.h"
+#include "ui_basic/checkbox.h"
+#include "ui_basic/panel.h"
+#include "ui_basic/tabpanel.h"
+#include "ui_basic/textarea.h"
+
+template <typename DescriptionType, typename ToolType>
+class CategorizedItemSelectionMenu : public UI::Box {
+public:
+	// Creates a box with a tab panel for each category in 'categories' and
+	// populates them with the 'descriptions' ordered by the category by calling
+	// 'create_checkbox' for each of the descriptions. Calls
+	// 'select_correct_tool' whenever a selection has been made, also keeps a
+	// text label updated and updates the 'tool' with current selections. Does
+	// not take ownership.
+	CategorizedItemSelectionMenu(
+	   UI::Panel* parent,
+	   const DescriptionMaintainer<Widelands::EditorCategory>& categories,
+	   const DescriptionMaintainer<DescriptionType>& descriptions,
+	   std::function<UI::Checkbox*(UI::Panel* parent, const DescriptionType& descr)> create_checkbox,
+	   const std::function<void()> select_correct_tool,
+	   ToolType* const tool);
+
+private:
+	// Called when an item was selected.
+	void selected(int32_t, bool);
+
+	// Update the label with the currently selected object names.
+	void update_label();
+
+	const DescriptionMaintainer<DescriptionType>& descriptions_;
+	std::function<void()> select_correct_tool_;
+	bool protect_against_recursive_select_;
+	UI::Textarea current_selection_names_;
+	std::map<int, UI::Checkbox*> checkboxes_;
+	ToolType* const tool_;  // not owned
+};
+
+template <typename DescriptionType, typename ToolType>
+CategorizedItemSelectionMenu<DescriptionType, ToolType>::CategorizedItemSelectionMenu(
+   UI::Panel* parent,
+   const DescriptionMaintainer<Widelands::EditorCategory>& categories,
+   const DescriptionMaintainer<DescriptionType>& descriptions,
+   const std::function<UI::Checkbox*(UI::Panel* parent, const DescriptionType& descr)>
+      create_checkbox,
+   const std::function<void()> select_correct_tool,
+   ToolType* const tool)
+   : UI::Box(parent, 0, 0, UI::Box::Vertical),
+     descriptions_(descriptions),
+     select_correct_tool_(select_correct_tool),
+     protect_against_recursive_select_(false),
+     current_selection_names_(this, 0, 0, 0, 20, UI::Align_Center),
+     tool_(tool)
+{
+
+	UI::Tab_Panel* tab_panel = new UI::Tab_Panel(this, 0, 0, nullptr);
+	this->add(tab_panel, UI::Align_Center);
+
+	for (uint32_t category_index = 0; category_index < categories.get_nitems(); ++category_index) {
+		const Widelands::EditorCategory& category = *categories.get(category_index);
+
+		std::vector<int> item_indices;
+		for (size_t j = 0; j < descriptions_.get_nitems(); ++j) {
+			if (descriptions_.get(j)->editor_category().name() != category.name()) {
+				continue;
+			}
+			item_indices.push_back(j);
+		}
+
+		UI::Box* vertical = new UI::Box(tab_panel, 0, 0, UI::Box::Vertical);
+		const int kSpacing = 5;
+		vertical->add_space(kSpacing);
+
+		const uint32_t items_in_row =
+		   static_cast<uint32_t>(std::ceil(std::sqrt(static_cast<float>(item_indices.size()))));
+		int nitems_handled = 0;
+		UI::Box* horizontal = nullptr;
+		for (const int i : item_indices) {
+			if (nitems_handled % items_in_row == 0) {
+				horizontal = new UI::Box(vertical, 0, 0, UI::Box::Horizontal);
+				horizontal->add_space(kSpacing);
+
+				vertical->add(horizontal, UI::Align_Left);
+				vertical->add_space(kSpacing);
+			}
+			assert(horizontal != nullptr);
+
+			UI::Checkbox* cb = create_checkbox(horizontal, *descriptions_.get(i));
+			cb->set_state(tool_->is_enabled(i));
+			cb->changedto.connect(boost::bind(&CategorizedItemSelectionMenu::selected, this, i, _1));
+			checkboxes_[i] = cb;
+			horizontal->add(cb, UI::Align_Left);
+			horizontal->add_space(kSpacing);
+			++nitems_handled;
+		}
+
+		const Image* category_picture = category.picture();
+		const int kCategoryImageSize = 24;
+		if (category_picture->width() > kCategoryImageSize ||
+		    category_picture->height() > kCategoryImageSize) {
+			category_picture =
+			   ImageTransformations::resize(category_picture, kCategoryImageSize, kCategoryImageSize);
+		}
+		tab_panel->add(category.name(), category_picture, vertical, category.descname());
+	}
+	this->add(&current_selection_names_, UI::Align_Center, true);
+}
+
+template <typename DescriptionType, typename ToolType>
+void CategorizedItemSelectionMenu<DescriptionType, ToolType>::selected(const int32_t n,
+                                                                       const bool t) {
+	if (protect_against_recursive_select_)
+		return;
+
+	//  FIXME This code is erroneous. It checks the current key state. What it
+	//  FIXME needs is the key state at the time the mouse was clicked. See the
+	//  FIXME usage comment for get_key_state.
+	const bool multiselect = get_key_state(SDLK_LCTRL) | get_key_state(SDLK_RCTRL);
+	if (not t and(not multiselect or tool_->get_nr_enabled() == 1))
+		checkboxes_[n]->set_state(true);
+	else {
+		if (not multiselect) {
+			for (uint32_t i = 0; tool_->get_nr_enabled(); ++i)
+				tool_->enable(i, false);
+			//  disable all checkboxes
+			protect_against_recursive_select_ = true;
+			const int32_t size = checkboxes_.size();
+			for (int32_t i = 0; i < size; ++i) {
+				if (i != n)
+					checkboxes_[i]->set_state(false);
+			}
+			protect_against_recursive_select_ = false;
+		}
+
+		tool_->enable(n, t);
+		select_correct_tool_();
+		update_label();
+	}
+}
+
+template <typename DescriptionType, typename ToolType>
+void CategorizedItemSelectionMenu<DescriptionType, ToolType>::update_label() {
+	std::string buf = _("Current:");
+	int j = tool_->get_nr_enabled();
+	for (int i = 0; j; ++i) {
+		if (tool_->is_enabled(i)) {
+			buf += " ";
+			buf += descriptions_.get(i)->descname();
+			--j;
+		}
+	}
+	current_selection_names_.set_text(buf);
+}
+
+#endif /* end of include guard: MULTI_SELECT_MENU_H */

=== modified file 'src/editor/ui_menus/editor_main_menu_load_map.cc'
--- src/editor/ui_menus/editor_main_menu_load_map.cc	2014-04-06 16:58:10 +0000
+++ src/editor/ui_menus/editor_main_menu_load_map.cc	2014-06-10 18:27:45 +0000
@@ -30,7 +30,6 @@
 #include "io/filesystem/layered_filesystem.h"
 #include "logic/building.h"
 #include "logic/editor_game_base.h"
-#include "logic/world.h"
 #include "map_io/map_loader.h"
 #include "map_io/widelands_map_loader.h"
 #include "profile/profile.h"
@@ -88,13 +87,6 @@
 	posy += 20 + spacing;
 
 	new UI::Textarea
-		(this, posx, posy, 70, 20, _("World:"), UI::Align_CenterLeft);
-	m_world =
-		new UI::Textarea
-			(this, posx + 70, posy, 200, 20, "---", UI::Align_CenterLeft);
-	posy += 20 + spacing;
-
-	new UI::Textarea
 		(this, posx, posy, 70, 20, _("Players:"), UI::Align_CenterLeft);
 	m_nrplayers =
 		new UI::Textarea
@@ -169,20 +161,12 @@
 			map_loader->preload_map(true); //  This has worked before, no problem.
 		}
 
-		// get translated worldsname
-		std::string world(map.get_world_name());
-		std::string worldpath("worlds/" + world);
-		Profile prof((worldpath + "/conf").c_str(), nullptr, "world_" + world);
-		Section & global = prof.get_safe_section("world");
-		world = global.get_safe_string("name");
-
 		// Translate the map data
 		i18n::Textdomain td("maps");
 		m_name  ->set_text(_(map.get_name()));
 		m_author->set_text(map.get_author());
 		m_descr ->set_text
 			(_(map.get_description()) + (map.get_hint().empty() ? "" : (std::string("\n") + _(map.get_hint()))));
-		m_world ->set_text(world);
 
 		char buf[200];
 		sprintf(buf, "%i", map.get_nrplayers());
@@ -194,7 +178,6 @@
 		m_name     ->set_text("");
 		m_author   ->set_text("");
 		m_descr    ->set_text("");
-		m_world    ->set_text("");
 		m_nrplayers->set_text("");
 		m_size     ->set_text("");
 	}

=== modified file 'src/editor/ui_menus/editor_main_menu_load_map.h'
--- src/editor/ui_menus/editor_main_menu_load_map.h	2013-07-26 19:16:51 +0000
+++ src/editor/ui_menus/editor_main_menu_load_map.h	2014-06-10 18:27:45 +0000
@@ -44,7 +44,7 @@
 
 	void fill_list();
 
-	UI::Textarea * m_name, * m_author, * m_size, * m_world, * m_nrplayers;
+	UI::Textarea * m_name, * m_author, * m_size, * m_nrplayers;
 	UI::Multiline_Textarea * m_descr;
 	UI::Listselect<const char *> * m_ls;
 	UI::Button * m_ok_btn;

=== modified file 'src/editor/ui_menus/editor_main_menu_map_options.cc'
--- src/editor/ui_menus/editor_main_menu_map_options.cc	2013-07-26 20:19:36 +0000
+++ src/editor/ui_menus/editor_main_menu_map_options.cc	2014-06-10 18:27:45 +0000
@@ -72,11 +72,6 @@
 	m_nrplayers =
 		new UI::Textarea(this, posx + ta->get_w() + spacing, posy - 2, "1");
 	posy += height + spacing;
-	ta = new UI::Textarea(this, posx, posy - 2, _("World:"));
-	m_world =
-		new UI::Textarea
-			(this, posx + ta->get_w() + spacing, posy - 2, "\"Greenland\"");
-	posy += height + spacing;
 	ta = new UI::Textarea(this, posx, posy - 2, _("Author:"));
 	m_author =
 		new UI::EditBox
@@ -125,7 +120,6 @@
 	m_name  ->setText(map.get_name());
 	sprintf(buf, "%i", map.get_nrplayers());
 	m_nrplayers->set_text(buf);
-	m_world ->set_text(map.world().get_name());
 	m_descr ->set_text(map.get_description());
 }
 

=== modified file 'src/editor/ui_menus/editor_main_menu_map_options.h'
--- src/editor/ui_menus/editor_main_menu_map_options.h	2012-02-15 21:25:34 +0000
+++ src/editor/ui_menus/editor_main_menu_map_options.h	2014-06-10 18:27:45 +0000
@@ -43,7 +43,7 @@
 	void changed(int32_t);
 	void editbox_changed();
 	UI::Multiline_Editbox * m_descr;
-	UI::Textarea * m_world, * m_nrplayers, * m_size;
+	UI::Textarea * m_nrplayers, * m_size;
 	UI::EditBox * m_name, * m_author;
 	void update();
 };

=== modified file 'src/editor/ui_menus/editor_main_menu_new_map.cc'
--- src/editor/ui_menus/editor_main_menu_new_map.cc	2013-08-05 03:26:31 +0000
+++ src/editor/ui_menus/editor_main_menu_new_map.cc	2014-06-10 18:27:45 +0000
@@ -29,7 +29,7 @@
 #include "i18n.h"
 #include "logic/editor_game_base.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "profile/profile.h"
 #include "ui_basic/button.h"
 #include "ui_basic/progresswindow.h"
@@ -43,8 +43,7 @@
 	UI::Window
 		(&parent, "new_map_menu",
 		 (parent.get_w() - 140) / 2, (parent.get_h() - 150) / 2, 140, 150,
-		 _("New Map")),
-	m_currentworld(0)
+		 _("New Map"))
 {
 	char buffer[250];
 	int32_t const offsx   =  5;
@@ -101,19 +100,6 @@
 
 	posy += 20 + spacing + spacing;
 
-	Widelands::World::get_all_worlds(m_worlds);
-
-	assert(m_worlds.size());
-	while (strcmp(map.get_world_name(), m_worlds[m_currentworld].c_str()))
-		++m_currentworld;
-
-	m_world = new UI::Button
-		(this, "world",
-		 posx, posy, width, height,
-		 g_gr->images().get("pics/but1.png"),
-		 Widelands::World(m_worlds[m_currentworld].c_str()).get_name());
-	m_world->sigclicked.connect(boost::bind(&Main_Menu_New_Map::button_clicked, this, 4));
-
 	posy += height + spacing + spacing + spacing;
 
 	UI::Button * createbtn = new UI::Button
@@ -134,14 +120,6 @@
 	case 1: --m_w; break;
 	case 2: ++m_h; break;
 	case 3: --m_h; break;
-	case 4:
-		++m_currentworld;
-		if (m_currentworld == m_worlds.size())
-			m_currentworld = 0;
-		m_world->set_title
-			(Widelands::World(m_worlds[m_currentworld].c_str()).get_name
-			 	());
-		break;
 	default:
 		assert(false);
 	}
@@ -170,18 +148,16 @@
 
 	egbase.cleanup_for_load();
 
-	if (strcmp(map.get_world_name(), m_worlds[m_currentworld].c_str()))
-		eia.change_world();
-	map.create_empty_map
-		(Widelands::MAP_DIMENSIONS[m_w], Widelands::MAP_DIMENSIONS[m_h],
-		 m_worlds[m_currentworld],
-		 _("No Name"),
-		 g_options.pull_section("global").get_string("realname", _("Unknown")));
+	map.create_empty_map(egbase.world(),
+	                     Widelands::MAP_DIMENSIONS[m_w],
+	                     Widelands::MAP_DIMENSIONS[m_h],
+	                     _("No Name"),
+	                     g_options.pull_section("global").get_string("realname", _("Unknown")));
 
 	egbase.postload     ();
 	egbase.load_graphics(loader);
 
-	map.recalc_whole_map();
+	map.recalc_whole_map(egbase.world());
 
 	eia.set_need_save(true);
 	eia.need_complete_redraw();

=== modified file 'src/editor/ui_menus/editor_main_menu_new_map.h'
--- src/editor/ui_menus/editor_main_menu_new_map.h	2013-07-25 21:05:20 +0000
+++ src/editor/ui_menus/editor_main_menu_new_map.h	2014-06-10 18:27:45 +0000
@@ -40,10 +40,7 @@
 
 private:
 	UI::Textarea * m_width, * m_height;
-	UI::Button * m_world;
 	int32_t m_w, m_h;
-	std::vector<std::string>::size_type m_currentworld;
-	std::vector<std::string> m_worlds;
 
 	void button_clicked(int32_t);
 	void clicked_create_map();

=== modified file 'src/editor/ui_menus/editor_main_menu_random_map.cc'
--- src/editor/ui_menus/editor_main_menu_random_map.cc	2013-08-05 03:26:31 +0000
+++ src/editor/ui_menus/editor_main_menu_random_map.cc	2014-06-10 18:27:45 +0000
@@ -29,7 +29,7 @@
 #include "i18n.h"
 #include "logic/editor_game_base.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "map_generator.h"
 #include "profile/profile.h"
 #include "random.h"
@@ -40,15 +40,23 @@
 
 using namespace Widelands;
 
-Main_Menu_New_Random_Map::Main_Menu_New_Random_Map
-	(Editor_Interactive & parent)
-	:
-	UI::Window
-		(&parent, "random_map_menu",
-		 (parent.get_w() - 260) / 2, (parent.get_h() - 450) / 2, 260, 490,
-		 _("New Random Map")),
-	m_currentworld(0)
-{
+Main_Menu_New_Random_Map::Main_Menu_New_Random_Map(Editor_Interactive& parent) :
+	UI::Window(&parent,
+                "random_map_menu",
+                (parent.get_w() - 260) / 2,
+                (parent.get_h() - 450) / 2,
+                260,
+                490,
+                _("New Random Map")),
+     // TRANSLATORS: The next are world names for the random map generator.
+	m_world_descriptions(
+	{
+		{"greenland", _("Summer")},
+		{"winterland", _("Winter")},
+		{"desert", _("Desert")},
+		{"blackland", _("Black")},
+	}),
+	m_current_world(0) {
 	char buffer[250];
 	int32_t const offsx   =  5;
 	int32_t const offsy   =  5;
@@ -266,28 +274,17 @@
 
 	posy += height + spacing + spacing + spacing;
 
-
-
 	// ---------- Worlds ----------
-
-	Widelands::World::get_all_worlds(m_worlds);
-
-	assert(m_worlds.size());
-	while (strcmp(map.get_world_name(), m_worlds[m_currentworld].c_str()))
-		++m_currentworld;
-
 	m_world = new UI::Button
 		(this, "world",
 		 posx, posy, width, height,
 		 g_gr->images().get("pics/but1.png"),
-		 Widelands::World(m_worlds[m_currentworld].c_str()).get_name());
+		 m_world_descriptions[m_current_world].descrname);
 	m_world->sigclicked.connect
 		(boost::bind(&Main_Menu_New_Random_Map::button_clicked, this, SWITCH_WORLD));
 
 	posy += height + spacing + spacing + spacing;
 
-
-
 	// ---------- Map ID String edit ----------
 
 	new UI::Textarea(this, posx + spacing + 20, posy, _("Map ID:"));
@@ -395,11 +392,9 @@
 			m_landval -= 5;
 		break;
 	case SWITCH_WORLD:
-		++ m_currentworld;
-		if (m_currentworld == m_worlds.size())
-			m_currentworld = 0;
-		m_world->set_title
-			(Widelands::World(m_worlds[m_currentworld].c_str()).get_name());
+		++ m_current_world;
+		m_current_world %= m_world_descriptions.size();
+		m_world->set_title(m_world_descriptions[m_current_world].descrname);
 		break;
 	case SWITCH_ISLAND_MODE:
 		break;
@@ -463,16 +458,12 @@
 
 	egbase.cleanup_for_load();
 
-	if (strcmp(map.get_world_name(), m_worlds[m_currentworld].c_str()))
-		eia.change_world();
-
 	UniqueRandomMapInfo mapInfo;
 	set_map_info(mapInfo);
 
 	std::stringstream sstrm;
 	sstrm << "Random generated map\nRandom number = "
 		<< mapInfo.mapNumber << "\n"
-		<< "World = " << m_world->get_title() << "\n"
 		<< "Water = " << m_waterval << " %\n"
 		<< "Land = " << m_landval << " %\n"
 		<< "Wasteland = " << m_wastelandval << " %\n"
@@ -480,18 +471,19 @@
 		<< "ID = " << m_idEditbox->text() << "\n";
 
 	MapGenerator gen(map, mapInfo, egbase);
-	map.create_empty_map
-		(mapInfo.w, mapInfo.h,
-		 m_worlds[m_currentworld].c_str(), _("No Name"),
-		 g_options.pull_section("global").get_string("realname", _("Unknown")),
-		 sstrm.str().c_str());
+	map.create_empty_map(egbase.world(),
+	                     mapInfo.w,
+	                     mapInfo.h,
+	                     _("No Name"),
+	                     g_options.pull_section("global").get_string("realname", _("Unknown")),
+	                     sstrm.str().c_str());
 	loader.step(_("Generating random map..."));
 	gen.create_random_map();
 
 	egbase.postload     ();
 	egbase.load_graphics(loader);
 
-	map.recalc_whole_map();
+	map.recalc_whole_map(egbase.world());
 
 	eia.set_need_save(true);
 	eia.need_complete_redraw();
@@ -506,7 +498,7 @@
 
 	std::string str = m_idEditbox->text();
 
-	if (!UniqueRandomMapInfo::setFromIdString(mapInfo, str, m_worlds))
+	if (!UniqueRandomMapInfo::setFromIdString(mapInfo, str))
 		m_goButton->set_enabled(false);
 	else {
 		std::stringstream sstrm;
@@ -529,15 +521,6 @@
 
 		m_res->set_title(m_res_amounts[m_res_amount].c_str());
 
-		// Get world
-
-		m_currentworld = 0;
-		while
-			(strcmp(mapInfo.worldName.c_str(), m_worlds[m_currentworld].c_str()))
-			++m_currentworld;
-		m_world->set_title
-			(Widelands::World(m_worlds[m_currentworld].c_str()).get_name());
-
 		// Update other values in UI as well
 		button_clicked(static_cast<ButtonID>(-1));
 
@@ -587,5 +570,5 @@
 	mapInfo.resource_amount = static_cast
 		<Widelands::UniqueRandomMapInfo::Resource_Amount>
 			(m_res_amount);
-	mapInfo.worldName = m_worlds[m_currentworld];
+	mapInfo.world_name = m_world_descriptions[m_current_world].name;
 }

=== modified file 'src/editor/ui_menus/editor_main_menu_random_map.h'
--- src/editor/ui_menus/editor_main_menu_random_map.h	2013-07-25 21:05:20 +0000
+++ src/editor/ui_menus/editor_main_menu_random_map.h	2014-06-10 18:27:45 +0000
@@ -63,6 +63,13 @@
 	} ButtonID;
 
 private:
+	struct WorldDescription {
+		std::string name;
+		std::string descrname;
+	};
+
+	const std::vector<WorldDescription> m_world_descriptions;
+	int m_current_world;
 	UI::Textarea * m_width, * m_height, * m_land;
 	UI::Textarea * m_water, * m_mountains, * m_wasteland, * m_players;
 	UI::Button * m_res;
@@ -72,9 +79,7 @@
 	int32_t m_w, m_h, m_landval, m_waterval, m_wastelandval;
 	uint8_t m_pn;
 	uint32_t m_mapNumber;
-	std::vector<std::string>::size_type m_currentworld;
 	uint32_t m_res_amount;
-	std::vector<std::string> m_worlds;
 	std::vector<std::string> m_res_amounts;
 
 	UI::EditBox * m_nrEditbox;

=== modified file 'src/editor/ui_menus/editor_main_menu_save_map.cc'
--- src/editor/ui_menus/editor_main_menu_save_map.cc	2014-03-25 08:22:48 +0000
+++ src/editor/ui_menus/editor_main_menu_save_map.cc	2014-06-10 18:27:45 +0000
@@ -99,13 +99,6 @@
 	posy += 20 + spacing;
 
 	new UI::Textarea
-		(this, posx, posy, 70, 20, _("World:"), UI::Align_CenterLeft);
-	m_world =
-		new UI::Textarea
-			(this, posx + 70, posy, 200, 20, "---", UI::Align_CenterLeft);
-	posy += 20 + spacing;
-
-	new UI::Textarea
 		(this, posx, posy, 70, 20, _("Players:"), UI::Align_CenterLeft);
 	m_nrplayers =
 		new UI::Textarea
@@ -236,7 +229,6 @@
 		m_name  ->set_text(map.get_name       ());
 		m_author->set_text(map.get_author     ());
 		m_descr ->set_text(map.get_description());
-		m_world ->set_text(map.get_world_name ());
 
 		char buf[200];
 		sprintf(buf, "%i", map.get_nrplayers());
@@ -247,7 +239,6 @@
 	} else {
 		m_name     ->set_text(FileSystem::FS_Filename(name));
 		m_author   ->set_text("");
-		m_world    ->set_text("");
 		m_nrplayers->set_text("");
 		m_size     ->set_text("");
 		if (g_fs->IsDirectory(name)) {

=== modified file 'src/editor/ui_menus/editor_main_menu_save_map.h'
--- src/editor/ui_menus/editor_main_menu_save_map.h	2013-07-26 19:16:51 +0000
+++ src/editor/ui_menus/editor_main_menu_save_map.h	2014-06-10 18:27:45 +0000
@@ -50,7 +50,7 @@
 	bool save_map(std::string, bool);
 
 	UI::EditBox * m_editbox;
-	UI::Textarea * m_name, * m_author, * m_size, * m_world, * m_nrplayers;
+	UI::Textarea * m_name, * m_author, * m_size, * m_nrplayers;
 	UI::Multiline_Textarea * m_descr;
 	UI::Listselect<const char *> * m_ls;
 	UI::Button * m_ok_btn;

=== modified file 'src/editor/ui_menus/editor_player_menu.cc'
--- src/editor/ui_menus/editor_player_menu.cc	2014-05-27 11:01:15 +0000
+++ src/editor/ui_menus/editor_player_menu.cc	2014-06-10 18:27:45 +0000
@@ -354,9 +354,9 @@
 
 	//  Register callback function to make sure that only valid locations are
 	//  selected.
-	map.overlay_manager().register_overlay_callback_function
-		(boost::bind(&Editor_Tool_Set_Starting_Pos_Callback, _1, boost::ref(map)));
-	map.recalc_whole_map();
+	map.overlay_manager().register_overlay_callback_function(
+	   boost::bind(&Editor_Tool_Set_Starting_Pos_Callback, _1, boost::ref(map)));
+	map.recalc_whole_map(menu.egbase().world());
 	update();
 }
 
@@ -441,5 +441,5 @@
 	parent.tools.make_infrastructure.set_player(n);
 	overlay_manager.register_overlay_callback_function(
 	   boost::bind(&Editor_Make_Infrastructure_Tool_Callback, _1, boost::ref(egbase), n));
-	map.recalc_whole_map();
+	map.recalc_whole_map(egbase.world());
 }

=== modified file 'src/editor/ui_menus/editor_tool_change_resources_options_menu.cc'
--- src/editor/ui_menus/editor_tool_change_resources_options_menu.cc	2014-03-09 18:32:29 +0000
+++ src/editor/ui_menus/editor_tool_change_resources_options_menu.cc	2014-06-10 18:27:45 +0000
@@ -28,7 +28,8 @@
 #include "i18n.h"
 #include "logic/map.h"
 #include "logic/widelands.h"
-#include "logic/world.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/world.h"
 #include "ui_basic/button.h"
 #include "wui/overlay_manager.h"
 
@@ -124,7 +125,7 @@
 	m_change_by_decrease.set_repeating(true);
 	m_set_to_increase   .set_repeating(true);
 	m_set_to_decrease   .set_repeating(true);
-	const Widelands::World & world = parent.egbase().map().world();
+	const Widelands::World & world = parent.egbase().world();
 	Widelands::Resource_Index const nr_resources = world.get_nr_resources();
 
 	//  Find the maximal width and height for the resource pictures.
@@ -211,11 +212,11 @@
 	m_increase_tool.set_cur_res(n);
 	m_increase_tool.decrease_tool().set_cur_res(n);
 
-	Widelands::Map & map = ref_cast<Editor_Interactive, UI::Panel>(*get_parent())
-		.egbase().map();
+	Widelands::Editor_Game_Base& egbase = ref_cast<Editor_Interactive, UI::Panel>(*get_parent()).egbase();
+	Widelands::Map & map = egbase.map();
 	map.overlay_manager().register_overlay_callback_function(
-	   boost::bind(&Editor_Change_Resource_Tool_Callback, _1, boost::ref(map), n));
-	map.recalc_whole_map();
+	   boost::bind(&Editor_Change_Resource_Tool_Callback, _1, boost::ref(map), boost::ref(egbase.world()), n));
+	map.recalc_whole_map(egbase.world());
 	select_correct_tool();
 
 	update();
@@ -232,7 +233,7 @@
 	m_set_to_value.set_text(buf);
 
 	m_cur_selection.set_text
-		(ref_cast<Editor_Interactive, UI::Panel>(*get_parent()).egbase().map()
+		(ref_cast<Editor_Interactive, UI::Panel>(*get_parent()).egbase()
 		 .world().get_resource(m_increase_tool.set_tool().get_cur_res())->descname());
 	m_cur_selection.set_pos
 		(Point

=== modified file 'src/editor/ui_menus/editor_tool_menu.cc'
--- src/editor/ui_menus/editor_tool_menu.cc	2014-03-16 20:55:15 +0000
+++ src/editor/ui_menus/editor_tool_menu.cc	2014-06-10 18:27:45 +0000
@@ -143,7 +143,7 @@
 		Widelands::Map & map = parent.egbase().map();
 		map.overlay_manager().register_overlay_callback_function(
 				boost::bind(&Editor_Tool_Set_Port_Space_Callback, _1, boost::ref(map)));
-		map.recalc_whole_map();
+		map.recalc_whole_map(parent.egbase().world());
 		update();
 	}
 

=== modified file 'src/editor/ui_menus/editor_tool_place_bob_options_menu.cc'
--- src/editor/ui_menus/editor_tool_place_bob_options_menu.cc	2014-03-31 20:21:27 +0000
+++ src/editor/ui_menus/editor_tool_place_bob_options_menu.cc	2014-06-10 18:27:45 +0000
@@ -27,7 +27,7 @@
 #include "i18n.h"
 #include "logic/critter_bob.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "ui_basic/box.h"
 #include "ui_basic/button.h"
 #include "ui_basic/checkbox.h"
@@ -49,7 +49,7 @@
 m_click_recursion_protect(false)
 {
 	int32_t const space  =  5;
-	const Widelands::World & world = parent.egbase().map().world();
+	const Widelands::World & world = parent.egbase().world();
 	int32_t const nr_bobs = world.get_nr_bobs();
 	const uint32_t bobs_in_row =
 		std::max

=== modified file 'src/editor/ui_menus/editor_tool_place_immovable_options_menu.cc'
--- src/editor/ui_menus/editor_tool_place_immovable_options_menu.cc	2014-04-20 20:02:13 +0000
+++ src/editor/ui_menus/editor_tool_place_immovable_options_menu.cc	2014-06-10 18:27:45 +0000
@@ -26,7 +26,7 @@
 #include "graphic/graphic.h"
 #include "i18n.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "ui_basic/box.h"
 #include "ui_basic/button.h"
 #include "ui_basic/checkbox.h"
@@ -34,118 +34,41 @@
 #include "wlapplication.h"
 
 
-using Widelands::Immovable_Descr;
-
-Editor_Tool_Place_Immovable_Options_Menu::
-Editor_Tool_Place_Immovable_Options_Menu
-		(Editor_Interactive          & parent,
-		 Editor_Place_Immovable_Tool & pit,
-		 UI::UniqueWindow::Registry  & registry)
-:
-Editor_Tool_Options_Menu(parent, registry, 100, 100, _("Immovable Bobs")),
-m_tabpanel(this, 0, 0, g_gr->images().get("pics/but1.png")),
-m_pit     (pit),
-m_click_recursion_protect(false)
-{
-	int32_t const space  =  5;
-	const Widelands::World & world = parent.egbase().map().world();
-	const int nr_immovables = world.get_nr_immovables();
-	const uint32_t immovables_in_row = std::min
-		(static_cast<uint32_t>
-		 (ceil(sqrt(static_cast<float>(nr_immovables)))), 6U);
-
-	set_center_panel(&m_tabpanel);
-
-	uint32_t width = 0, height = 0;
-	for (int32_t j = 0; j < nr_immovables; ++j) {
-		const Immovable_Descr & descr = *world.get_immovable_descr(j);
-		const Image& pic = g_gr->animations().get_animation(descr.main_animation())
-				.representative_image(RGBColor(0, 0, 0));
-		uint16_t w = pic.width();
-		uint16_t h = pic.height();
-		if (w > width)
-			width  = w;
-		if (h > height)
-			height = h;
-	}
-
-	//box->set_inner_size((immovables_in_row)*(width+1+space)+xstart,
-	//                     (immovables_in_row)*(height+1+space)+ystart+yend);
-	const Image* tab_icon =
-		g_gr->images().get("pics/list_first_entry.png");
-
-	Point pos;
-	uint32_t cur_x = immovables_in_row;
-
-	UI::Box * box;
-	for (int i = 0; i < nr_immovables; ++cur_x, ++i) {
-		if (cur_x == immovables_in_row) {
-			cur_x = 0;
-			pos = Point(5, 15);
-			box =
-				new UI::Box
-					(&m_tabpanel, 0, 0, UI::Box::Horizontal,
-					 parent.get_inner_w() - 50, parent.get_inner_h() - 50);
-			box->set_scrolling(true);
-			m_tabpanel.add("immovables", tab_icon, box);
-		}
-		assert(box);
-
-		UI::Checkbox & cb = *new UI::Checkbox
-			(box, pos,
-			 &g_gr->animations().get_animation(world.get_immovable_descr(i)->main_animation())
-				.representative_image(RGBColor(0, 0, 0)), world.get_immovable_descr(i)->descname());
-		cb.set_desired_size(width, height);
-		cb.set_state(m_pit.is_enabled(i));
-		cb.changedto.connect
-			(boost::bind(&Editor_Tool_Place_Immovable_Options_Menu::clicked, this, i, _1));
-		m_checkboxes.push_back(&cb);
-		box->add(&cb, UI::Align_Left);
-		box->add_space(space);
-		pos.x += width + 1 + space;
-	}
-
-	m_tabpanel.activate(0);
-}
-
-/**
- * Cleanup
- */
-Editor_Tool_Place_Immovable_Options_Menu::
-~Editor_Tool_Place_Immovable_Options_Menu
-	()
-{}
-
-/**
- * Called when one of the state boxes is toggled
-*/
-void Editor_Tool_Place_Immovable_Options_Menu::clicked(int32_t n, bool t)
-{
-	if (m_click_recursion_protect)
-		return;
-
-	//  FIXME This code is erroneous. It checks the current key state. What it
-	//  FIXME needs is the key state at the time the mouse was clicked. See the
-	//  FIXME usage comment for get_key_state.
-	const bool multiselect =
-		get_key_state(SDLK_LCTRL) | get_key_state(SDLK_RCTRL);
-	if (not t and (not multiselect or m_pit.get_nr_enabled() == 1))
-		m_checkboxes[n]->set_state(true);
-	else {
-		if (not multiselect) {
-			for (uint32_t i = 0; m_pit.get_nr_enabled(); ++i)
-				m_pit.enable(i, false);
-			//  Disable all checkboxes
-			const int32_t size = m_checkboxes.size();
-			m_click_recursion_protect = true;
-			for (int32_t i = 0; i < size; ++i) {
-				if (i != n)
-					m_checkboxes[i]->set_state(false);
-			}
-			m_click_recursion_protect = false;
-		}
-
-		m_pit.enable(n, t);
-		select_correct_tool();
-	}
+namespace {
+
+using namespace Widelands;
+
+UI::Checkbox* create_immovable_checkbox(UI::Panel* parent, const Immovable_Descr& immovable_descr) {
+	const Image& pic =
+	   g_gr->animations().get_animation(immovable_descr.main_animation()).representative_image(
+	      RGBColor(0, 0, 0));
+	UI::Checkbox* cb = new UI::Checkbox(parent, Point(0, 0), &pic, immovable_descr.descname());
+	const int kMinClickableArea = 24;
+	cb->set_desired_size(std::max<int>(pic.width(), kMinClickableArea),
+	                     std::max<int>(pic.height(), kMinClickableArea));
+	return cb;
+}
+
+}  // namespace
+
+Editor_Tool_Place_Immovable_Options_Menu::Editor_Tool_Place_Immovable_Options_Menu(
+   Editor_Interactive& parent,
+   Editor_Place_Immovable_Tool& tool,
+   UI::UniqueWindow::Registry& registry)
+   : Editor_Tool_Options_Menu(parent, registry, 0, 0, _("Immovable Select")) {
+	const Widelands::World& world = parent.egbase().world();
+	multi_select_menu_.reset(
+	   new CategorizedItemSelectionMenu<Widelands::Immovable_Descr, Editor_Place_Immovable_Tool>(
+	      this,
+	      world.editor_immovable_categories(),
+	      world.immovables(),
+	      [this](UI::Panel* cb_parent, const Immovable_Descr& immovable_descr) {
+		      return create_immovable_checkbox(cb_parent, immovable_descr);
+		   },
+	      [this] { select_correct_tool(); },
+	      &tool));
+	set_center_panel(multi_select_menu_.get());
+}
+
+Editor_Tool_Place_Immovable_Options_Menu::~Editor_Tool_Place_Immovable_Options_Menu() {
 }

=== modified file 'src/editor/ui_menus/editor_tool_place_immovable_options_menu.h'
--- src/editor/ui_menus/editor_tool_place_immovable_options_menu.h	2013-07-26 20:19:36 +0000
+++ src/editor/ui_menus/editor_tool_place_immovable_options_menu.h	2014-06-10 18:27:45 +0000
@@ -22,28 +22,21 @@
 
 #include <vector>
 
+#include "editor/ui_menus/categorized_item_selection_menu.h"
 #include "editor/ui_menus/editor_tool_options_menu.h"
-#include "ui_basic/tabpanel.h"
+#include "editor/tools/editor_place_immovable_tool.h"
 
 struct Editor_Interactive;
-struct Editor_Place_Immovable_Tool;
-namespace UI {struct Checkbox;}
 
-struct Editor_Tool_Place_Immovable_Options_Menu :
-	public Editor_Tool_Options_Menu
-{
-	Editor_Tool_Place_Immovable_Options_Menu
-		(Editor_Interactive          &,
-		 Editor_Place_Immovable_Tool &,
-		 UI::UniqueWindow::Registry  &);
+struct Editor_Tool_Place_Immovable_Options_Menu : public Editor_Tool_Options_Menu {
+	Editor_Tool_Place_Immovable_Options_Menu(Editor_Interactive&,
+	                                         Editor_Place_Immovable_Tool&,
+	                                         UI::UniqueWindow::Registry&);
 	virtual ~Editor_Tool_Place_Immovable_Options_Menu();
 
 private:
-	std::vector<UI::Checkbox *> m_checkboxes;
-	UI::Tab_Panel m_tabpanel;
-	Editor_Place_Immovable_Tool & m_pit;
-	void clicked(int32_t, bool);
-	bool m_click_recursion_protect;
+	std::unique_ptr<CategorizedItemSelectionMenu<Widelands::Immovable_Descr, Editor_Place_Immovable_Tool>>
+	multi_select_menu_;
 };
 
 #endif

=== modified file 'src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc'
--- src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc	2014-04-21 10:47:03 +0000
+++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc	2014-06-10 18:27:45 +0000
@@ -30,188 +30,103 @@
 #include "graphic/texture.h"
 #include "i18n.h"
 #include "logic/map.h"
-#include "logic/world.h"
-#include "logic/worlddata.h"
-#include "ui_basic/button.h"
+#include "logic/world/editor_category.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 #include "ui_basic/checkbox.h"
 #include "ui_basic/panel.h"
-#include "wlapplication.h"
-
-Editor_Tool_Set_Terrain_Options_Menu:: Editor_Tool_Set_Terrain_Options_Menu
-	(Editor_Interactive         & parent,
-	 Editor_Set_Terrain_Tool    & tool,
-	 UI::UniqueWindow::Registry & registry)
-	:
-	Editor_Tool_Options_Menu(parent, registry, 0, 0, _("Terrain Select")),
-	m_cur_selection         (this, 0, 0, 0, 20, UI::Align_Center),
-	m_tool                  (tool),
-	m_select_recursion_protect(false)
-{
-	Widelands::World & world = parent.egbase().map().world();
-	Widelands::Terrain_Index const nr_terrains = world.get_nr_terrains();
-	const uint32_t terrains_in_row = static_cast<uint32_t>
-		(ceil(sqrt(static_cast<float>(nr_terrains))));
-
-	static const int32_t check[] = {
-		0,                                            //  "green"
-		TERRAIN_DRY,                                  //  "dry"
-		TERRAIN_DRY|TERRAIN_MOUNTAIN,                 //  "mountain"
-		TERRAIN_DRY|TERRAIN_UNPASSABLE,               //  "unpassable"
-		TERRAIN_ACID|TERRAIN_DRY|TERRAIN_UNPASSABLE,  //  "dead" or "acid"
-		TERRAIN_UNPASSABLE|TERRAIN_DRY|TERRAIN_WATER,
-	};
-
-	m_checkboxes.resize(nr_terrains);
-
-	const Image* green =
-		g_gr->images().get("pics/terrain_green.png");
-	const Image* water =
-		g_gr->images().get("pics/terrain_water.png");
-	const Image* mountain =
-		g_gr->images().get("pics/terrain_mountain.png");
-	const Image* dead =
-		g_gr->images().get("pics/terrain_dead.png");
-	const Image* unpassable =
-		g_gr->images().get("pics/terrain_unpassable.png");
-	const Image* dry =
-		g_gr->images().get("pics/terrain_dry.png");
-
-	static const int small_pich = 20;
-	static const int small_picw = 20;
-
-	uint32_t cur_x = 0;
-	Point pos(hmargin(), vmargin());
-	for (size_t checkfor = 0; checkfor < 6; ++checkfor) {
-		for (Widelands::Terrain_Index i  = 0; i < nr_terrains; ++i) {
-			const uint8_t ter_is = world.get_ter(i).get_is();
-			if (ter_is != check[checkfor])
-				continue;
-
-			if (cur_x == terrains_in_row) {
-				cur_x = 0;
-				pos.x  = hmargin();
-				pos.y += TEXTURE_HEIGHT + vspacing();
-			}
-
-			Surface* surf = Surface::create(64, 64);
-			const Image* tex = g_gr->images().get
-				(g_gr->get_maptexture_data(world.terrain_descr(i).get_texture())->get_texture_image());
-			surf->blit(Point(0, 0), tex->surface(), Rect(0, 0, tex->width(), tex->height()), CM_Solid);
-
-			Point pt(1, 64 - small_pich - 1);
-
-			//  check is green
-			if (ter_is == 0) {
-				surf->blit(pt, green->surface(), Rect(0, 0, green->width(), green->height()));
-				pt.x += small_picw + 1;
-			} else {
-				if (ter_is & TERRAIN_WATER) {
-					surf->blit(pt, water->surface(), Rect(0, 0, water->width(), water->height()));
-					pt.x += small_picw + 1;
-				}
-				if (ter_is & TERRAIN_MOUNTAIN) {
-					surf->blit(pt, mountain->surface(), Rect(0, 0, mountain->width(), mountain->height()));
-					pt.x += small_picw + 1;
-				}
-				if (ter_is & TERRAIN_ACID) {
-					surf->blit(pt, dead->surface(), Rect(0, 0, dead->width(), dead->height()));
-					pt.x += small_picw + 1;
-				}
-				if (ter_is & TERRAIN_UNPASSABLE) {
-					surf->blit(pt, unpassable->surface(), Rect(0, 0, unpassable->width(), unpassable->height()));
-					pt.x += small_picw + 1;
-				}
-				if (ter_is & TERRAIN_DRY)
-					surf->blit(pt, dry->surface(), Rect(0, 0, dry->width(), dry->height()));
-			}
-			// Make sure we delete this later on.
-			offscreen_images_.push_back(new_in_memory_image("dummy_hash", surf));
-
-			UI::Checkbox & cb = *new UI::Checkbox(this, pos, offscreen_images_.back());
-			cb.set_size(TEXTURE_WIDTH + 1, TEXTURE_HEIGHT + 1);
-			cb.set_state(m_tool.is_enabled(i));
-			cb.changedto.connect
-				(boost::bind(&Editor_Tool_Set_Terrain_Options_Menu::selected, this, i, _1));
-			m_checkboxes[i] = &cb;
-
-			pos.x += TEXTURE_WIDTH + hspacing();
-			++cur_x;
-		}
-	}
-	pos.y += TEXTURE_HEIGHT + vspacing();
-
-	set_inner_size
-		(terrains_in_row * (TEXTURE_WIDTH + hspacing()) +
-		 2 * hmargin() - hspacing(),
-		 pos.y + m_cur_selection.get_h() + vmargin());
-	pos.x = get_inner_w() / 2;
-	m_cur_selection.set_pos(pos);
-
-	std::string buf = _("Current:");
-	uint32_t j = m_tool.get_nr_enabled();
-	for (Widelands::Terrain_Index i = 0; j; ++i)
-		if (m_tool.is_enabled(i)) {
-			buf += " ";
-			buf += world.get_ter(i).descname();
-			--j;
-		}
-	m_cur_selection.set_text(buf);
-}
-
-
-Editor_Tool_Set_Terrain_Options_Menu::~Editor_Tool_Set_Terrain_Options_Menu()
-{
-	for (const Image* pic : offscreen_images_)
-		delete pic;
-	offscreen_images_.clear();
-}
-
-void Editor_Tool_Set_Terrain_Options_Menu::selected
-	(int32_t const n, bool const t)
-{
-	if (m_select_recursion_protect)
-		return;
-
-	//  FIXME This code is erroneous. It checks the current key state. What it
-	//  FIXME needs is the key state at the time the mouse was clicked. See the
-	//  FIXME usage comment for get_key_state.
-	const bool multiselect =
-		get_key_state(SDLK_LCTRL) | get_key_state(SDLK_RCTRL);
-	if (not t and (not multiselect or m_tool.get_nr_enabled() == 1))
-		m_checkboxes[n]->set_state(true);
-	else {
-		if (not multiselect) {
-			for (uint32_t i = 0; m_tool.get_nr_enabled(); ++i)
-				m_tool.enable(i, false);
-			//  disable all checkboxes
-			m_select_recursion_protect = true;
-			const int32_t size = m_checkboxes.size();
-			for (int32_t i = 0; i < size; ++i) {
-				if (i != n)
-					m_checkboxes[i]->set_state(false);
-			}
-			m_select_recursion_protect = false;
-		}
-
-		m_tool.enable(n, t);
-		select_correct_tool();
-
-		std::string buf = _("Current:");
-		const Widelands::World & world =
-			ref_cast<Editor_Interactive, UI::Panel>(*get_parent())
-			.egbase().map().world();
-		uint32_t j = m_tool.get_nr_enabled();
-		for (Widelands::Terrain_Index i = 0; j; ++i)
-			if (m_tool.is_enabled(i)) {
-				buf += " ";
-				buf += world.get_ter(i).descname();
-				--j;
-			}
-
-		m_cur_selection.set_text(buf.c_str());
-		m_cur_selection.set_pos
-			(Point
-			 	((get_inner_w() - m_cur_selection.get_w()) / 2,
-			 	 m_cur_selection.get_y()));
-	}
+#include "ui_basic/tabpanel.h"
+
+namespace {
+
+using namespace Widelands;
+
+static const int32_t check[] = {
+   TerrainDescription::GREEN,                                 //  "green"
+   TerrainDescription::DRY,                                   //  "dry"
+   TerrainDescription::DRY | TerrainDescription::MOUNTAIN,    //  "mountain"
+   TerrainDescription::DRY | TerrainDescription::UNPASSABLE,  //  "unpassable"
+   TerrainDescription::ACID | TerrainDescription::DRY |
+      TerrainDescription::UNPASSABLE,  //  "dead" or "acid"
+   TerrainDescription::UNPASSABLE | TerrainDescription::DRY | TerrainDescription::WATER,
+   -1,  // end marker
+};
+
+UI::Checkbox* create_terrain_checkbox(UI::Panel* parent,
+                                      const TerrainDescription& terrain_descr,
+                                      std::vector<std::unique_ptr<const Image>>* offscreen_images) {
+	const Image* green = g_gr->images().get("pics/terrain_green.png");
+	const Image* water = g_gr->images().get("pics/terrain_water.png");
+	const Image* mountain = g_gr->images().get("pics/terrain_mountain.png");
+	const Image* dead = g_gr->images().get("pics/terrain_dead.png");
+	const Image* unpassable = g_gr->images().get("pics/terrain_unpassable.png");
+	const Image* dry = g_gr->images().get("pics/terrain_dry.png");
+
+	constexpr int kSmallPicHeight = 20;
+	constexpr int kSmallPicWidth = 20;
+	for (size_t checkfor = 0; check[checkfor] >= 0; ++checkfor) {
+		const TerrainDescription::Type ter_is = terrain_descr.get_is();
+		if (ter_is != check[checkfor])
+			continue;
+
+		Surface* surf = Surface::create(TEXTURE_WIDTH, TEXTURE_HEIGHT);
+		const Image* tex = g_gr->images().get(
+		   g_gr->get_maptexture_data(terrain_descr.get_texture())->get_texture_image());
+		surf->blit(Point(0, 0), tex->surface(), Rect(0, 0, tex->width(), tex->height()), CM_Solid);
+		Point pt(1, TEXTURE_HEIGHT - kSmallPicHeight - 1);
+
+		if (ter_is == TerrainDescription::GREEN) {
+			surf->blit(pt, green->surface(), Rect(0, 0, green->width(), green->height()));
+			pt.x += kSmallPicWidth + 1;
+		} else {
+			if (ter_is & TerrainDescription::WATER) {
+				surf->blit(pt, water->surface(), Rect(0, 0, water->width(), water->height()));
+				pt.x += kSmallPicWidth + 1;
+			}
+			if (ter_is & TerrainDescription::MOUNTAIN) {
+				surf->blit(pt, mountain->surface(), Rect(0, 0, mountain->width(), mountain->height()));
+				pt.x += kSmallPicWidth + 1;
+			}
+			if (ter_is & TerrainDescription::ACID) {
+				surf->blit(pt, dead->surface(), Rect(0, 0, dead->width(), dead->height()));
+				pt.x += kSmallPicWidth + 1;
+			}
+			if (ter_is & TerrainDescription::UNPASSABLE) {
+				surf->blit(
+				   pt, unpassable->surface(), Rect(0, 0, unpassable->width(), unpassable->height()));
+				pt.x += kSmallPicWidth + 1;
+			}
+			if (ter_is & TerrainDescription::DRY)
+				surf->blit(pt, dry->surface(), Rect(0, 0, dry->width(), dry->height()));
+		}
+		// Make sure we delete this later on.
+		offscreen_images->emplace_back(new_in_memory_image("dummy_hash", surf));
+		break;
+	}
+
+	UI::Checkbox* cb = new UI::Checkbox(parent, Point(0, 0), offscreen_images->back().get());
+	cb->set_desired_size(TEXTURE_WIDTH + 1, TEXTURE_HEIGHT + 1);
+	return cb;
+}
+
+}  // namespace
+
+Editor_Tool_Set_Terrain_Options_Menu::Editor_Tool_Set_Terrain_Options_Menu(
+   Editor_Interactive& parent, Editor_Set_Terrain_Tool& tool, UI::UniqueWindow::Registry& registry)
+   : Editor_Tool_Options_Menu(parent, registry, 0, 0, _("Terrain Select")) {
+	const Widelands::World& world = parent.egbase().world();
+	multi_select_menu_.reset(
+	   new CategorizedItemSelectionMenu<Widelands::TerrainDescription, Editor_Set_Terrain_Tool>(
+	      this,
+	      world.editor_terrain_categories(),
+	      world.terrains(),
+	      [this](UI::Panel* cb_parent, const TerrainDescription& terrain_descr) {
+		      return create_terrain_checkbox(cb_parent, terrain_descr, &offscreen_images_);
+		   },
+	      [this] { select_correct_tool(); },
+	      &tool));
+	set_center_panel(multi_select_menu_.get());
+}
+
+Editor_Tool_Set_Terrain_Options_Menu::~Editor_Tool_Set_Terrain_Options_Menu() {
 }

=== modified file 'src/editor/ui_menus/editor_tool_set_terrain_options_menu.h'
--- src/editor/ui_menus/editor_tool_set_terrain_options_menu.h	2013-07-26 20:19:36 +0000
+++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.h	2014-06-10 18:27:45 +0000
@@ -20,32 +20,28 @@
 #ifndef EDITOR_TOOL_SET_TERRAIN_TOOL_H
 #define EDITOR_TOOL_SET_TERRAIN_TOOL_H
 
+#include <map>
+#include <memory>
 #include <vector>
 
+#include "editor/ui_menus/categorized_item_selection_menu.h"
 #include "editor/ui_menus/editor_tool_options_menu.h"
+#include "logic/world/terrain_description.h"
 #include "ui_basic/textarea.h"
 
-
 struct Editor_Interactive;
 struct Editor_Set_Terrain_Tool;
-namespace UI {struct Checkbox;}
 
 struct Editor_Tool_Set_Terrain_Options_Menu : public Editor_Tool_Options_Menu {
-	Editor_Tool_Set_Terrain_Options_Menu
-		(Editor_Interactive         &,
-		 Editor_Set_Terrain_Tool    &,
-		 UI::UniqueWindow::Registry &);
+	Editor_Tool_Set_Terrain_Options_Menu(Editor_Interactive&,
+	                                     Editor_Set_Terrain_Tool&,
+	                                     UI::UniqueWindow::Registry&);
 	virtual ~Editor_Tool_Set_Terrain_Options_Menu();
 
 private:
-	// When we are using an offscreen surface, we have to delete it,
-	// when we are closed. So we keep a pointer around.
-	std::vector<const Image*>  offscreen_images_;
-	UI::Textarea                m_cur_selection;
-	Editor_Set_Terrain_Tool   & m_tool;
-	void selected(int32_t, bool);
-	std::vector<UI::Checkbox *> m_checkboxes;
-	bool m_select_recursion_protect;
+	std::unique_ptr<CategorizedItemSelectionMenu<Widelands::TerrainDescription, Editor_Set_Terrain_Tool>>
+	multi_select_menu_;
+	std::vector<std::unique_ptr<const Image>>  offscreen_images_;
 };
 
 

=== modified file 'src/game_io/game_game_class_data_packet.cc'
--- src/game_io/game_game_class_data_packet.cc	2014-05-11 07:38:01 +0000
+++ src/game_io/game_game_class_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -38,7 +38,7 @@
 		uint16_t const packet_version = fr.Unsigned16();
 		if (packet_version <= CURRENT_PACKET_VERSION) {
 			fr.Signed16(); // This used to be game speed
-			game.m_gametime = fr.Unsigned32();
+			game.gametime_ = fr.Unsigned32();
 		} else
 			throw game_data_error
 				("unknown/unhandled version %u", packet_version);
@@ -70,7 +70,7 @@
 
 	// EDITOR GAME CLASS
 	// Write gametime
-	fw.Unsigned32(game.m_gametime);
+	fw.Unsigned32(game.gametime_);
 
 	// We do not care for players, since they were set
 	// on game initialization to match Map::scenario_player_[names|tribes]

=== modified file 'src/game_io/game_map_data_packet.cc'
--- src/game_io/game_map_data_packet.cc	2014-03-24 21:47:08 +0000
+++ src/game_io/game_map_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -44,7 +44,6 @@
 	m_wml = new WL_Map_Loader(fs.MakeSubFileSystem("map"), &game.map());
 
 	m_wml->preload_map(true);
-	m_wml->load_world();
 
 	//  DONE, mapfs gets deleted by WidelandsMapLoader.
 

=== modified file 'src/game_io/game_preload_data_packet.cc'
--- src/game_io/game_preload_data_packet.cc	2014-04-14 06:17:25 +0000
+++ src/game_io/game_preload_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -105,13 +105,8 @@
 	}
 	s.set_int(PLAYERS_AMOUNT_KEY_V4, game.player_manager()->get_number_of_players());
 
-	std::string bg(map.get_background());
-	if (bg.empty())
-		bg = map.get_world_name();
-	s.set_string("background", bg);
-
+	s.set_string("background", map.get_background());
 	s.set_string("win_condition", game.get_win_condition_displayname());
-
 	prof.write("preload", false, fs);
 
 	// Write minimap image

=== modified file 'src/graphic/animation.cc'
--- src/graphic/animation.cc	2014-04-21 10:47:03 +0000
+++ src/graphic/animation.cc	2014-06-10 18:27:45 +0000
@@ -43,8 +43,9 @@
 #include "io/filesystem/layered_filesystem.h"
 #include "log.h"
 #include "logic/bob.h"
-#include "logic/instances.h"  // For Map_Object_Descr.
+#include "logic/instances.h"
 #include "profile/profile.h"
+#include "scripting/lua_table.h"
 #include "sound/sound_handler.h"
 #include "wexception.h"
 
@@ -54,6 +55,16 @@
 
 namespace  {
 
+// Parses an array { 12, 23 } into a point.
+void get_point(const LuaTable& table, Point* p) {
+	std::vector<int> pts = table.array_entries<int>();
+	if (pts.size() != 2) {
+		throw wexception("Expected 2 entries, but got %" PRIuS ".", pts.size());
+	}
+	p->x = pts[0];
+	p->y = pts[1];
+}
+
 /**
  * An Image Implementation that draws a static animation into a surface.
  */
@@ -96,7 +107,8 @@
 class NonPackedAnimation : public Animation {
 public:
 	virtual ~NonPackedAnimation() {}
-	NonPackedAnimation(const string& directory, Section & s);
+	NonPackedAnimation(const string& directory, Section & section);
+	NonPackedAnimation(const LuaTable& table);
 
 	// Implements Animation.
 	virtual uint16_t width() const override;
@@ -121,106 +133,129 @@
 	uint32_t frametime_;
 	Point hotspot_;
 	bool hasplrclrs_;
-	std::string picnametempl_;
+	std::vector<std::string> image_files_;
+	std::vector<std::string> pc_mask_image_files_;
 
 	vector<const Image*> frames_;
 	vector<const Image*> pcmasks_;
 
-	/// mapping of soundeffect name to frame number, indexed by frame number .
-	map<uint32_t, string> sfx_cues;
+	// name of sound effect that will be played at frame 0.
+	// TODO(sirver): this should be done using playFX in a program instead of
+	// binding it to the animation.
+	string sound_effect_;
 };
 
-NonPackedAnimation::NonPackedAnimation(const string& directory, Section& s)
+NonPackedAnimation::NonPackedAnimation(const string& directory, Section& section)
 		: frametime_(FRAME_LENGTH),
 		  hasplrclrs_(false) {
-	// Read mapping from frame numbers to sound effect names and load effects
-	while (Section::Value * const v = s.get_next_val("sfx")) {
-		char * parameters = v->get_string(), * endp;
-		string fx_name;
-		unsigned long long int const value = strtoull(parameters, &endp, 0);
-		const uint32_t frame_number = value;
-		try {
-			if (endp == parameters or frame_number != value)
-				throw wexception("expected %s but found \"%s\"", "frame number", parameters);
-			parameters = endp;
-			force_skip(parameters);
-
-			fx_name = string(directory) + "/" + string(parameters);
-			g_sound_handler.load_fx_if_needed(directory, parameters, fx_name);
-			map<uint32_t, string>::const_iterator const it =
-				sfx_cues.find(frame_number);
-			if (it != sfx_cues.end())
-				throw wexception
-					("redefinition for frame %u to \"%s\" (previously defined to "
-					 "\"%s\")",
-					 frame_number, parameters, it->second.c_str());
-		} catch (const _wexception & e) {
-			throw wexception("sfx: %s", e.what());
-		}
-		sfx_cues[frame_number] = fx_name;
+	// If this animation has a sound effect associated, try to load it now.
+	const std::string sfx = section.get_string("sfx", "");
+	if (!sfx.empty()) {
+			sound_effect_ = string(directory) + "/" + sfx;
+			g_sound_handler.load_fx_if_needed(directory, sfx, sound_effect_);
 	}
 
-	int32_t const fps = s.get_int("fps");
+	int32_t const fps = section.get_int("fps");
 	if (fps < 0)
 		throw wexception("fps is %i, must be non-negative", fps);
 	if (fps > 0)
 		frametime_ = 1000 / fps;
 
-	hotspot_ = s.get_Point("hotspot");
+	hotspot_ = section.get_Point("hotspot");
 
 	//  In the filename template, the last sequence of '?' characters (if any)
 	//  is replaced with a number, for example the template "idle_??" is
 	//  replaced with "idle_00". Then the code looks if there is a PNG with that
 	//  name, increments the number and continues . on until it can not find any
 	//  file. Then it is assumed that there are no more frames in the animation.
-	if (char const * const pics = s.get_string("pics")) {
-		picnametempl_ = directory + pics;
+	string picnametempl;
+	if (char const * const pics = section.get_string("pics")) {
+		picnametempl = directory + pics;
 	} else {
-		picnametempl_ = directory + s.get_name();
+		picnametempl = directory + section.get_name();
 	}
 	// Strip the .png extension if it has one.
-	boost::replace_all(picnametempl_, ".png", "");
-}
+	boost::replace_all(picnametempl, ".png", "");
 
-void NonPackedAnimation::load_graphics() {
-	NumberGlob glob(picnametempl_);
+	NumberGlob glob(picnametempl);
 	string filename_wo_ext;
 	while (glob.next(&filename_wo_ext)) {
 		const string filename = filename_wo_ext + ".png";
 		if (!g_fs->FileExists(filename))
 			break;
-
-		const Image* image = g_gr->images().get(filename);
-		if
-			(frames_.size() &&
-			 (frames_[0]->width() != image->width() or frames_[0]->height() != image->height()))
-					throw wexception
-						("wrong size: (%u, %u), should be (%u, %u) like the first frame",
-						 image->width(), image->height(), frames_[0]->width(), frames_[0]->height());
-		frames_.push_back(image);
-
-		//TODO Do not load playercolor mask as opengl texture or use it as
-		//     opengl texture.
+		image_files_.push_back(filename);
+
 		const string pc_filename = filename_wo_ext + "_pc.png";
 		if (g_fs->FileExists(pc_filename)) {
 			hasplrclrs_ = true;
-			const Image* pc_image = g_gr->images().get(pc_filename);
-			if (frames_[0]->width() != pc_image->width() or frames_[0]->height() != pc_image->height())
-				throw wexception
-					("playercolor mask has wrong size: (%u, %u), should "
-					 "be (%u, %u) like the animation frame",
-					 pc_image->width(), pc_image->height(), frames_[0]->width(), frames_[0]->height());
-			pcmasks_.push_back(pc_image);
-		}
-	}
-
-	if (frames_.empty())
-		throw wexception("animation %s has no frames", picnametempl_.c_str());
-
-	if (pcmasks_.size() and pcmasks_.size() != frames_.size())
+			pc_mask_image_files_.push_back(pc_filename);
+		}
+	}
+}
+
+NonPackedAnimation::NonPackedAnimation(const LuaTable& table)
+		: frametime_(FRAME_LENGTH),
+		  hasplrclrs_(false) {
+	// TODO(sirver): the LuaTable constructor has no support for player_colors right now.
+	get_point(*table.get_table("hotspot"), &hotspot_);
+
+	if (table.has_key("sound_effect")) {
+		std::unique_ptr<LuaTable> sound_effects = table.get_table("sound_effect");
+
+		const std::string name = sound_effects->get_string("name");
+		const std::string directory = sound_effects->get_string("directory");
+		sound_effect_ = directory + "/" + name;
+		g_sound_handler.load_fx_if_needed(directory, name, sound_effect_);
+	}
+
+	image_files_ = table.get_table("pictures")->array_entries<std::string>();
+	if (image_files_.empty()) {
+		throw wexception("Animation without pictures.");
+	} else if (image_files_.size() == 1) {
+		if (table.has_key("fps")) {
+			throw wexception("Animation with one picture must not have 'fps'.");
+		}
+	} else {
+		frametime_ = 1000 / get_positive_int(table, "fps");
+	}
+}
+
+void NonPackedAnimation::load_graphics() {
+	if (image_files_.empty())
+		throw wexception("animation without pictures.");
+
+	if (pc_mask_image_files_.size() and pc_mask_image_files_.size() != image_files_.size())
 		throw wexception
 			("animation has %" PRIuS " frames but playercolor mask has %" PRIuS " frames",
-			 frames_.size(), pcmasks_.size());
+			 image_files_.size(), pc_mask_image_files_.size());
+
+	for (const std::string& filename : image_files_) {
+		const Image* image = g_gr->images().get(filename);
+		if (frames_.size() &&
+		    (frames_[0]->width() != image->width() or frames_[0]->height() != image->height())) {
+			throw wexception("wrong size: (%u, %u), should be (%u, %u) like the first frame",
+			                 image->width(),
+			                 image->height(),
+			                 frames_[0]->width(),
+			                 frames_[0]->height());
+		}
+		frames_.push_back(image);
+	}
+
+	for (const std::string& filename : pc_mask_image_files_) {
+		// TODO Do not load playercolor mask as opengl texture or use it as
+		//     opengl texture.
+		const Image* pc_image = g_gr->images().get(filename);
+		if (frames_[0]->width() != pc_image->width() or frames_[0]->height() != pc_image->height()) {
+			throw wexception("playercolor mask has wrong size: (%u, %u), should "
+			                 "be (%u, %u) like the animation frame",
+			                 pc_image->width(),
+			                 pc_image->height(),
+			                 frames_[0]->width(),
+			                 frames_[0]->height());
+		}
+		pcmasks_.push_back(pc_image);
+	}
 }
 
 uint16_t NonPackedAnimation::width() const {
@@ -260,12 +295,14 @@
 	return get_frame(0, nullptr);
 }
 
-void NonPackedAnimation::trigger_soundfx
-	(uint32_t time, uint32_t stereo_position) const {
+void NonPackedAnimation::trigger_soundfx(uint32_t time, uint32_t stereo_position) const {
+	if (sound_effect_.empty()) {
+		return;
+	}
 	const uint32_t framenumber = time / frametime_ % nr_frames();
-	const map<uint32_t, string>::const_iterator sfx_cue = sfx_cues.find(framenumber);
-	if (sfx_cue != sfx_cues.end())
-		g_sound_handler.play_fx(sfx_cue->second, stereo_position, 1);
+	if (framenumber == 0) {
+		g_sound_handler.play_fx(sound_effect_, stereo_position, 1);
+	}
 }
 
 void NonPackedAnimation::blit
@@ -403,6 +440,11 @@
 	return m_animations.size();
 }
 
+uint32_t AnimationManager::load(const LuaTable& table) {
+	m_animations.push_back(new NonPackedAnimation(table));
+	return m_animations.size();
+}
+
 const Animation& AnimationManager::get_animation(uint32_t id) const
 {
 	if (!id || id > m_animations.size())

=== modified file 'src/graphic/animation.h'
--- src/graphic/animation.h	2014-04-06 15:46:29 +0000
+++ src/graphic/animation.h	2014-06-10 18:27:45 +0000
@@ -31,9 +31,10 @@
 #include "rect.h"
 
 class Image;
+class LuaTable;
+class Section;
 class Surface;
 struct RGBColor;
-struct Section;
 
 /**
  * Representation of an Animation in the game. An animation is a looping set of
@@ -103,6 +104,7 @@
 	 * \param s             conffile section to search for data on this animation
 	*/
 	uint32_t load(const std::string & directory, Section& s);
+	uint32_t load(const LuaTable& table);
 
 	/// Returns the animation with the given ID or throws an exception if it is
 	/// unknown.

=== modified file 'src/graphic/diranimations.h'
--- src/graphic/diranimations.h	2014-03-16 20:55:15 +0000
+++ src/graphic/diranimations.h	2014-06-10 18:27:45 +0000
@@ -28,12 +28,12 @@
 
 namespace Widelands {struct Map_Object_Descr;}
 
-struct Profile;
-struct Section;
+class Profile;
+class Section;
 
 /// Manages a set of 6 animations, one for each possible direction.
 struct DirAnimations {
-	explicit DirAnimations
+	DirAnimations
 		(uint32_t dir1 = 0, uint32_t dir2 = 0, uint32_t dir3 = 0,
 		 uint32_t dir4 = 0, uint32_t dir5 = 0, uint32_t dir6 = 0);
 
@@ -48,6 +48,9 @@
 	uint32_t get_animation(Widelands::Direction const dir) const {
 		return m_animations[dir - 1];
 	}
+	void set_animation(const Widelands::Direction dir, const uint32_t anim) {
+		m_animations[dir - 1] = anim;
+	}
 
 	static DirAnimations Null() {
 		return DirAnimations(0); // Since real animation IDs are positive, this is safe

=== modified file 'src/graphic/graphic.cc'
--- src/graphic/graphic.cc	2014-05-10 16:56:38 +0000
+++ src/graphic/graphic.cc	2014-06-10 18:27:45 +0000
@@ -313,6 +313,9 @@
 
 	m_sdl_screen = sdlsurface;
 	m_rendertarget.reset(new RenderTarget(screen_.get()));
+
+	pic_road_normal_.reset(image_loader_->load("world/pics/roadt_normal.png"));
+	pic_road_busy_.reset(image_loader_->load("world/pics/roadt_busy.png"));
 }
 
 bool Graphic::check_fallback_settings_in_effect()
@@ -321,7 +324,7 @@
 }
 
 void Graphic::cleanup() {
-	flush_maptextures();
+	m_maptextures.clear();
 	surface_cache_->flush();
 	// TODO: this should really not be needed, but currently is :(
 	if (UI::g_fh)
@@ -525,34 +528,9 @@
 	png_destroy_write_struct(&png_ptr, &info_ptr);
 }
 
-void Graphic::flush_maptextures()
-{
-	for (Texture* texture : m_maptextures)
-		delete texture;
-	m_maptextures.clear();
-}
-
-/**
- * Creates a terrain texture.
- *
- * fnametempl is a filename with possible wildcard characters '?'. The function
- * fills the wildcards with decimal numbers to get the different frames of a
- * texture animation. For example, if fnametempl is "foo_??.png", it tries
- * "foo_00.png", "foo_01.png" etc...
- * frametime is in milliseconds.
- * \return 0 if the texture couldn't be loaded.
- * \note Terrain textures are not reused, even if fnametempl matches.
-*/
-uint32_t Graphic::get_maptexture(const string& fnametempl, uint32_t frametime)
-{
-	try {
-		m_maptextures.push_back
-			(new Texture(fnametempl, frametime, *m_sdl_screen->format));
-	} catch (exception& e) {
-		log("Failed to load maptexture %s: %s\n", fnametempl.c_str(), e.what());
-		return 0;
-	}
-
+uint32_t Graphic::new_maptexture(const std::vector<std::string>& texture_files, const uint32_t frametime)
+{
+	m_maptextures.emplace_back(new Texture(texture_files, frametime, *m_sdl_screen->format));
 	return m_maptextures.size(); // ID 1 is at m_maptextures[0]
 }
 
@@ -567,16 +545,6 @@
 }
 
 /**
- * reset that the map texture have been animated
- */
-void Graphic::reset_texture_animation_reminder()
-{
-	for (uint32_t i = 0; i < m_maptextures.size(); ++i) {
-		m_maptextures[i]->reset_was_animated();
-	}
-}
-
-/**
  * Save a screenshot to the given file.
 */
 void Graphic::screenshot(const string& fname) const
@@ -617,24 +585,9 @@
 Texture * Graphic::get_maptexture_data(uint32_t id)
 {
 	--id; // ID 1 is at m_maptextures[0]
-	if (id < m_maptextures.size())
-		return m_maptextures[id];
-	else
-		return nullptr;
-}
-
-
-/**
- * Sets the name of the current world and loads the fitting road and edge textures
- */
-void Graphic::set_world(string worldname) {
-	char buf[255];
-
-	// Load the road textures
-	snprintf(buf, sizeof(buf), "worlds/%s/pics/roadt_normal.png", worldname.c_str());
-	pic_road_normal_.reset(image_loader_->load(buf));
-	snprintf(buf, sizeof(buf), "worlds/%s/pics/roadt_busy.png", worldname.c_str());
-	pic_road_busy_.reset(image_loader_->load(buf));
+
+	assert(id < m_maptextures.size());
+	return m_maptextures[id].get();
 }
 
 /**

=== modified file 'src/graphic/graphic.h'
--- src/graphic/graphic.h	2014-03-16 20:55:15 +0000
+++ src/graphic/graphic.h	2014-06-10 18:27:45 +0000
@@ -109,15 +109,14 @@
 
 	void save_png(const Image*, StreamWrite*) const;
 
-	void flush_maptextures();
-	uint32_t get_maptexture(const std::string& fnametempl, uint32_t frametime);
+	// Creates a new Texture() with the given 'frametime' and using the given
+	// 'texture_files' as the images for it and returns it id.
+	uint32_t new_maptexture(const std::vector<std::string>& texture_files, uint32_t frametime);
 	void animate_maptextures(uint32_t time);
-	void reset_texture_animation_reminder();
 
 	void screenshot(const std::string& fname) const;
 	Texture * get_maptexture_data(uint32_t id);
 
-	void set_world(std::string);
 	Surface& get_road_texture(int32_t roadtex);
 
 	const GraphicCaps& caps() const {return m_caps;}
@@ -171,7 +170,7 @@
 	std::unique_ptr<Surface> pic_road_normal_;
 	std::unique_ptr<Surface> pic_road_busy_;
 
-	std::vector<Texture *> m_maptextures;
+	std::vector<std::unique_ptr<Texture>> m_maptextures;
 };
 
 extern Graphic * g_gr;

=== modified file 'src/graphic/render/gamerenderer_gl.cc'
--- src/graphic/render/gamerenderer_gl.cc	2014-05-11 07:38:01 +0000
+++ src/graphic/render/gamerenderer_gl.cc	2014-06-10 18:27:45 +0000
@@ -29,6 +29,8 @@
 #include "io/fileread.h"
 #include "logic/editor_game_base.h"
 #include "logic/player.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 #include "wui/mapviewpixelconstants.h"
 #include "wui/mapviewpixelfunctions.h"
 #include "wui/overlay_manager.h"
@@ -49,9 +51,9 @@
 {
 }
 
-const GLSurfaceTexture * GameRendererGL::get_dither_edge_texture(const Widelands::World & world)
+const GLSurfaceTexture * GameRendererGL::get_dither_edge_texture()
 {
-	const std::string fname = world.basedir() + "/pics/edge.png";
+	const std::string fname = "world/pics/edge.png";
 	const std::string cachename = std::string("gltex#") + fname;
 
 	if (Surface* surface = g_gr->surfaces().get(cachename))
@@ -117,6 +119,12 @@
 
 void GameRendererGL::draw()
 {
+	const World & world = m_egbase->world();
+	if (m_terrain_freq.size() < world.terrains().get_nitems()) {
+		m_terrain_freq.resize(world.terrains().get_nitems());
+		m_terrain_edge_freq.resize(world.terrains().get_nitems());
+	}
+
 	m_surface = dynamic_cast<GLSurface *>(m_dst->get_surface());
 	if (!m_surface)
 		return;
@@ -242,8 +250,6 @@
 		m_patch_vertices_size = reqsize;
 	}
 
-	if (m_terrain_freq.size() < 16)
-		m_terrain_freq.resize(16);
 	m_terrain_freq.assign(m_terrain_freq.size(), 0);
 
 	collect_terrain_base(true);
@@ -273,8 +279,7 @@
 
 void GameRendererGL::draw_terrain_base()
 {
-	const Map & map = m_egbase->map();
-	const World & world = map.world();
+	const World & world = m_egbase->world();
 
 	glMatrixMode(GL_TEXTURE);
 	glLoadIdentity();
@@ -313,8 +318,7 @@
 	(bool onlyscan, Terrain_Index ter, const Coords & edge1, const Coords & edge2, const Coords & opposite)
 {
 	if (onlyscan) {
-		if (ter >= m_terrain_edge_freq.size())
-			m_terrain_edge_freq.resize(ter + 1);
+		assert(ter < m_terrain_edge_freq.size());
 		m_terrain_edge_freq[ter] += 1;
 	} else {
 		static const float TyZero = 1.0 / TEXTURE_HEIGHT;
@@ -340,7 +344,7 @@
 void GameRendererGL::collect_terrain_dither(bool onlyscan)
 {
 	const Map & map = m_egbase->map();
-	const World & world = map.world();
+	const World & world = m_egbase->world();
 
 	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
 		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
@@ -354,12 +358,12 @@
 			Terrain_Index ter_rr = map.r_n(fcoords).field->get_terrains().d;
 			Terrain_Index ter_l = map.l_n(fcoords).field->get_terrains().r;
 			Terrain_Index ter_dd = map.bl_n(fcoords).field->get_terrains().r;
-			int32_t lyr_d = world.get_ter(ter_d).dither_layer();
-			int32_t lyr_r = world.get_ter(ter_r).dither_layer();
-			int32_t lyr_u = world.get_ter(ter_u).dither_layer();
-			int32_t lyr_rr = world.get_ter(ter_rr).dither_layer();
-			int32_t lyr_l = world.get_ter(ter_l).dither_layer();
-			int32_t lyr_dd = world.get_ter(ter_dd).dither_layer();
+			int32_t lyr_d = world.terrain_descr(ter_d).dither_layer();
+			int32_t lyr_r = world.terrain_descr(ter_r).dither_layer();
+			int32_t lyr_u = world.terrain_descr(ter_u).dither_layer();
+			int32_t lyr_rr = world.terrain_descr(ter_rr).dither_layer();
+			int32_t lyr_l = world.terrain_descr(ter_l).dither_layer();
+			int32_t lyr_dd = world.terrain_descr(ter_dd).dither_layer();
 
 			Coords f(fx, fy);
 			Coords rn(fx + 1, fy);
@@ -408,8 +412,6 @@
 {
 	static_assert(sizeof(dithervertex) == 32, "assert(sizeof(dithervertex) == 32) failed.");
 
-	if (m_terrain_edge_freq.size() < 16)
-		m_terrain_edge_freq.resize(16);
 	m_terrain_edge_freq.assign(m_terrain_edge_freq.size(), 0);
 
 	collect_terrain_dither(true);
@@ -439,9 +441,6 @@
 
 void GameRendererGL::draw_terrain_dither()
 {
-	const Map & map = m_egbase->map();
-	const World & world = map.world();
-
 	if (m_edge_vertices_size == 0)
 		return;
 
@@ -456,7 +455,7 @@
 	glClientActiveTextureARB(GL_TEXTURE1_ARB);
 	glTexCoordPointer(2, GL_FLOAT, sizeof(dithervertex), &m_edge_vertices[0].edgex);
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	GLuint edge = get_dither_edge_texture(world)->get_gl_texture();
+	GLuint edge = get_dither_edge_texture()->get_gl_texture();
 	glBindTexture(GL_TEXTURE_2D, edge);
 	glEnable(GL_TEXTURE_2D);
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
@@ -478,7 +477,7 @@
 
 		const Texture & texture =
 				*g_gr->get_maptexture_data
-					(world.terrain_descr(ter).get_texture());
+					(m_egbase->world().terrain_descr(ter).get_texture());
 		glBindTexture(GL_TEXTURE_2D, texture.getTexture());
 		glDrawArrays
 			(GL_TRIANGLES,

=== modified file 'src/graphic/render/gamerenderer_gl.h'
--- src/graphic/render/gamerenderer_gl.h	2014-02-22 18:04:02 +0000
+++ src/graphic/render/gamerenderer_gl.h	2014-06-10 18:27:45 +0000
@@ -30,7 +30,7 @@
 namespace Widelands {
 struct Coords;
 struct FCoords;
-struct World;
+class World;
 }
 
 class GLSurface;
@@ -65,7 +65,7 @@
 		uint32_t pad[1];
 	};
 
-	const GLSurfaceTexture * get_dither_edge_texture(const Widelands::World & world);
+	const GLSurfaceTexture * get_dither_edge_texture();
 
 	void draw() override;
 	void prepare_terrain_base();

=== modified file 'src/graphic/render/gamerenderer_sdl.cc'
--- src/graphic/render/gamerenderer_sdl.cc	2013-07-26 20:19:36 +0000
+++ src/graphic/render/gamerenderer_sdl.cc	2014-06-10 18:27:45 +0000
@@ -24,6 +24,8 @@
 #include "logic/field.h"
 #include "logic/map.h"
 #include "logic/player.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 #include "wui/overlay_manager.h"
 
 
@@ -66,7 +68,7 @@
 		m_dst->get_surface()->fill_rect(m_dst->get_rect(), RGBAColor(0, 0, 0, 255));
 
 	const Map & map = m_egbase->map();
-	const World & world = map.world();
+	const World & world = m_egbase->world();
 	uint32_t const mapwidth = map.get_width();
 
 #define get_terrain_texture(ter) \

=== modified file 'src/graphic/render/minimaprenderer.cc'
--- src/graphic/render/minimaprenderer.cc	2013-10-13 15:03:08 +0000
+++ src/graphic/render/minimaprenderer.cc	2014-06-10 18:27:45 +0000
@@ -31,6 +31,8 @@
 #include "logic/field.h"
 #include "logic/map.h"
 #include "logic/player.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 #include "upcast.h"
 #include "wui/mapviewpixelconstants.h"
 #include "wui/mapviewpixelfunctions.h"
@@ -66,7 +68,7 @@
 		pixelcolor =
 			g_gr->
 			get_maptexture_data
-				(egbase.map().world()
+				(egbase.world()
 				 .terrain_descr(f.field->terrain_d()).get_texture())
 			->get_minimap_color(f.field->get_brightness()) | format.Amask;
 	}
@@ -91,10 +93,7 @@
 
 		if (upcast(PlayerImmovable const, immovable, f.field->get_immovable())) {
 			if ((flags & MiniMap::Roads) and dynamic_cast<Road const *>(immovable)) {
-				if (!(flags & MiniMap::Owner) && !strcmp(egbase.map().get_world_name(), "winterland"))
-						pixelcolor = blend_color(format, pixelcolor, 255, 127, 0);
-				else //ownership layer displayed or greenland
-						pixelcolor = blend_color(format, pixelcolor, 255, 255, 255);
+				pixelcolor = blend_color(format, pixelcolor, 255, 255, 255);
 			}
 
 			if
@@ -104,14 +103,7 @@
 				  and
 				  dynamic_cast<Widelands::Building const *>(immovable)))
 			{
-				if (!(flags & MiniMap::Owner) && !strcmp(egbase.map().get_world_name(), "winterland"))
-					pixelcolor =
-						SDL_MapRGB
-							(&const_cast<SDL_PixelFormat &>(format), 255, 127, 0);
-				else //ownership layer displayed or greenland
-					pixelcolor =
-						SDL_MapRGB
-							(&const_cast<SDL_PixelFormat &>(format), 255, 255, 255);
+				pixelcolor = SDL_MapRGB(&const_cast<SDL_PixelFormat&>(format), 255, 255, 255);
 			}
 		}
 	}

=== modified file 'src/graphic/texture.cc'
--- src/graphic/texture.cc	2014-05-10 16:56:38 +0000
+++ src/graphic/texture.cc	2014-06-10 18:27:45 +0000
@@ -37,62 +37,39 @@
  * Currently it converts a 16 bit image to a 8 bit texture. This should
  * be changed to load a 8 bit file directly, however.
  */
-Texture::Texture(const string& fnametmpl, uint32_t frametime, const SDL_PixelFormat& format)
-	: m_pixels   (nullptr),
-		m_curframe (nullptr),
-		m_frame_num(0),
-		m_nrframes (0),
-		m_frametime(frametime),
-		m_was_animated(false)
-{
-	// Load the images one by one
-	char fname[256];
-
-	for (;;) {
-		int32_t nr = m_nrframes;
-
-		// create the file name by reverse-scanning for '?' and replacing
-		snprintf(fname, sizeof(fname), "%s", fnametmpl.c_str());
-		char * p = fname + strlen(fname);
-		while (p > fname) {
-			if (*--p != '?')
-				continue;
-
-			*p = '0' + (nr % 10);
-			nr = nr / 10;
+Texture::Texture(const std::vector<std::string>& texture_files,
+                 const uint32_t frametime,
+                 const SDL_PixelFormat& format)
+   : m_colormap(nullptr),
+     m_pixels(nullptr),
+     m_curframe(nullptr),
+     m_frame_num(0),
+     m_nrframes(0),
+     m_frametime(frametime) {
+	if (texture_files.empty()) {
+		throw wexception("No images for texture.");
+	}
+
+	for (const std::string& fname : texture_files) {
+		if (!g_fs->FileExists(fname)) {
+			throw wexception("Could not find %s.", fname.c_str());
 		}
 
-		if (nr) // cycled up to maximum possible frame number
-			break;
-
-		if (!g_fs->FileExists(fname))
-			break;
-
 		SDL_Surface * surf;
-
 		m_texture_image = fname;
-
 		FileRead fr;
-
 		fr.Open(*g_fs, fname);
 
 		surf = IMG_Load_RW(SDL_RWFromMem(fr.Data(0), fr.GetSize()), 1);
-
 		if (!surf) {
-			log
-				("WARNING: Failed to load texture frame %s: %s\n",
-				 fname, IMG_GetError());
-			break;
+			throw wexception("WARNING: Failed to load texture frame %s: %s\n", fname.c_str(), IMG_GetError());
 		}
-
 		if (surf->w != TEXTURE_WIDTH || surf->h != TEXTURE_HEIGHT) {
 			SDL_FreeSurface(surf);
-			log
-				("WARNING: %s: texture must be %ix%i pixels big\n",
-				 fname,
-				 TEXTURE_WIDTH,
-				 TEXTURE_HEIGHT);
-			break;
+			throw wexception("WARNING: %s: texture must be %ix%i pixels big\n",
+			                 fname.c_str(),
+			                 TEXTURE_WIDTH,
+			                 TEXTURE_HEIGHT);
 		}
 
 		if (g_opengl) {
@@ -138,7 +115,7 @@
 			} else {
 				SDL_Color pal[256];
 
-				log("WARNING: %s: using 332 default palette\n", fname);
+				log("WARNING: %s: using 332 default palette\n", fname.c_str());
 
 				for (int32_t r = 0; r < 8; ++r)
 					for (int32_t g = 0; g < 8; ++g)
@@ -192,7 +169,7 @@
 	}
 
 	if (!m_nrframes)
-		throw wexception("%s: texture has no frames", fnametmpl.c_str());
+		throw wexception("Texture has no frames");
 }
 
 
@@ -220,13 +197,7 @@
 void Texture::animate(uint32_t time)
 {
 	m_frame_num = (time / m_frametime) % m_nrframes;
-
 	if (g_opengl)
 		return;
-
-	uint8_t * const lastframe = m_curframe;
-
 	m_curframe = &m_pixels[TEXTURE_WIDTH * TEXTURE_HEIGHT * m_frame_num];
-	if (lastframe != m_curframe)
-		m_was_animated = true;
 }

=== modified file 'src/graphic/texture.h'
--- src/graphic/texture.h	2014-03-17 12:25:49 +0000
+++ src/graphic/texture.h	2014-06-10 18:27:45 +0000
@@ -39,8 +39,9 @@
 * changed to load 8 bit bitmaps directly.
 */
 struct Texture {
-	Texture
-		(const std::string& fnametempl, uint32_t frametime, const SDL_PixelFormat&);
+	Texture(const std::vector<std::string>& texture_files,
+	        uint32_t frametime,
+	        const SDL_PixelFormat&);
 	~Texture();
 
 	const std::string & get_texture_image() const {return m_texture_image;}
@@ -52,8 +53,6 @@
 	uint32_t get_minimap_color(char shade);
 
 	void animate(uint32_t time);
-	void reset_was_animated() {m_was_animated = false;}
-	bool was_animated() const {return m_was_animated;}
 	uint32_t getTexture() const
 		{return m_glFrames.at(m_frame_num)->get_gl_texture();}
 
@@ -66,7 +65,6 @@
 	std::string m_texture_image;
 	uint32_t    m_nrframes;
 	uint32_t    m_frametime;
-	bool        m_was_animated;
 	std::vector<std::unique_ptr<GLSurfaceTexture>> m_glFrames;
 };
 

=== modified file 'src/io/filesystem/disk_filesystem.cc'
--- src/io/filesystem/disk_filesystem.cc	2014-05-10 16:56:38 +0000
+++ src/io/filesystem/disk_filesystem.cc	2014-06-10 18:27:45 +0000
@@ -391,8 +391,9 @@
 
 		length = size;
 	} catch (...) {
-		if (file)
+		if (file) {
 			fclose(file);
+		}
 		free(data);
 		throw;
 	}

=== modified file 'src/logic/bob.cc'
--- src/logic/bob.cc	2014-05-11 07:38:01 +0000
+++ src/logic/bob.cc	2014-06-10 18:27:45 +0000
@@ -21,10 +21,11 @@
 
 #include <cstdlib>
 
+#include <stdint.h>
+
 #include "backtrace.h"
 #include "economy/route.h"
 #include "economy/transfer.h"
-#include "graphic/graphic.h"
 #include "graphic/rendertarget.h"
 #include "io/fileread.h"
 #include "io/filewrite.h"
@@ -49,6 +50,12 @@
 
 namespace Widelands {
 
+BobDescr::BobDescr(const std::string& init_name,
+                  const std::string& init_descname,
+                  Tribe_Descr const* tribe)
+   : Map_Object_Descr(init_name, init_descname), owner_tribe_(tribe) {
+}
+
 /**
  * Only tribe bobs have a vision range, since it would be irrelevant
  * for world bobs.
@@ -59,42 +66,15 @@
  */
 uint32_t BobDescr::vision_range() const
 {
-	if (m_owner_tribe) {
+	if (owner_tribe_) {
 		if (upcast(const Ship_Descr, ship, this))
 			return ship->vision_range();
-		return m_owner_tribe->get_bob_vision_range();
+		return owner_tribe_->get_bob_vision_range();
 	}
 
 	return 0;
 }
 
-
-BobDescr::BobDescr
-	(char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 Tribe_Descr const * const tribe)
-	:
-	Map_Object_Descr(_name, _descname),
-	m_owner_tribe(tribe)
-{
-	{ //  global options
-		Section & idle_s = prof.get_safe_section("idle");
-
-		add_animation("idle", g_gr->animations().load(directory, idle_s));
-	}
-
-	// Parse attributes
-	while (Section::Value const * val = global_s.get_next_val("attrib")) {
-		uint32_t const attrib = get_attribute_id(val->get_string());
-
-		if (attrib < Map_Object::HIGHEST_FIXED_ATTRIBUTE)
-			throw game_data_error("bad attribute \"%s\"", val->get_string());
-
-		add_attribute(attrib);
-	}
-}
-
-
 /**
  * Create a bob of this type
  */

=== modified file 'src/logic/bob.h'
--- src/logic/bob.h	2014-05-11 07:38:01 +0000
+++ src/logic/bob.h	2014-06-10 18:27:45 +0000
@@ -29,7 +29,7 @@
 #include "point.h"
 #include "port.h"
 
-struct Profile;
+class Profile;
 
 namespace Widelands {
 class Map;
@@ -55,21 +55,15 @@
 public:
 	friend struct Map_Bobdata_Data_Packet;
 
-	BobDescr(char const* name,
-	      char const* descname,
-	      const std::string& directory,
-	      Profile&,
-	      Section& global_s,
-	      Tribe_Descr const*);
+	BobDescr(const std::string& init_name,
+	         const std::string& init_descname,
+	         Tribe_Descr const* tribe);
 
 	virtual ~BobDescr() {};
 	Bob& create(Editor_Game_Base&, Player* owner, const Coords&) const;
-	bool is_world_bob() const {
-		return not m_owner_tribe;
-	}
 
 	Tribe_Descr const* get_owner_tribe() const {
-		return m_owner_tribe;
+		return owner_tribe_;
 	}
 
 	virtual uint32_t movecaps() const {
@@ -80,7 +74,8 @@
 protected:
 	virtual Bob& create_object() const = 0;
 
-	const Tribe_Descr* const m_owner_tribe;  //  0 if world bob
+private:
+	const Tribe_Descr* const owner_tribe_;  //  nullptr if world bob
 };
 
 /**
@@ -248,7 +243,6 @@
 	void set_position(Editor_Game_Base &, const Coords &);
 	const FCoords & get_position() const {return m_position;}
 	Bob * get_next_bob() const {return m_linknext;}
-	bool is_world_bob() const {return descr().is_world_bob();}
 
 	uint32_t vision_range() const {return descr().vision_range();}
 

=== modified file 'src/logic/buildcost.h'
--- src/logic/buildcost.h	2014-05-11 07:38:01 +0000
+++ src/logic/buildcost.h	2014-06-10 18:27:45 +0000
@@ -26,7 +26,7 @@
 
 class FileRead;
 class FileWrite;
-struct Section;
+class Section;
 
 namespace Widelands {
 

=== modified file 'src/logic/building.h'
--- src/logic/building.h	2014-05-11 07:38:01 +0000
+++ src/logic/building.h	2014-06-10 18:27:45 +0000
@@ -38,7 +38,7 @@
 namespace UI {class Window;}
 struct BuildingHints;
 class Interactive_GameBase;
-struct Profile;
+class Profile;
 class Image;
 
 namespace Widelands {
@@ -160,7 +160,7 @@
 
 class Building : public PlayerImmovable {
 	friend struct Building_Descr;
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 
 	MO_DESCR(Building_Descr)
 

=== modified file 'src/logic/constructionsite.h'
--- src/logic/constructionsite.h	2014-04-06 10:50:39 +0000
+++ src/logic/constructionsite.h	2014-06-10 18:27:45 +0000
@@ -59,7 +59,7 @@
 };
 
 class ConstructionSite : public Partially_Finished_Building {
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 
 	static const uint32_t CONSTRUCTIONSITE_STEP_TIME = 30000;
 

=== modified file 'src/logic/critter_bob.cc'
--- src/logic/critter_bob.cc	2014-05-11 07:38:01 +0000
+++ src/logic/critter_bob.cc	2014-06-10 18:27:45 +0000
@@ -21,6 +21,9 @@
 
 #include <cstdio>
 
+#include <stdint.h>
+
+#include "graphic/graphic.h"
 #include "helper.h"
 #include "io/fileread.h"
 #include "io/filewrite.h"
@@ -29,57 +32,67 @@
 #include "logic/game.h"
 #include "logic/game_data_error.h"
 #include "logic/tribe.h"
+#include "logic/world/world.h"
+#include "map_io/one_world_legacy_lookup_table.h"
 #include "profile/profile.h"
+#include "scripting/lua_table.h"
 #include "wexception.h"
 
 
 namespace Widelands {
 
-const Critter_BobProgram::ParseMap Critter_BobProgram::s_parsemap[] = {
-	{"remove",            &Critter_BobProgram::parse_remove},
-	{nullptr,                   nullptr}
-};
-
-
-void Critter_BobProgram::parse(Parser * const parser, char const * const name)
-{
-	Section & program_s = parser->prof->get_safe_section(name);
-
+namespace {
+
+// Parses program lines in a section into a vector of strings.
+std::vector<std::string> section_to_strings(Section* section) {
+	std::vector<std::string> return_value;
 	for (uint32_t idx = 0;; ++idx) {
+		char buffer[32];
+		snprintf(buffer, sizeof(buffer), "%i", idx);
+		char const* const string = section->get_string(buffer, nullptr);
+		if (!string)
+			break;
+		return_value.emplace_back(string);
+	}
+	// Check for line numbering problems
+	if (section->get_num_values() != return_value.size())
+		throw wexception("Line numbers appear to be wrong");
+	return return_value;
+}
+
+// Sets the dir animations in 'anims' with the animations
+// '<prefix>_(ne|e|se|sw|w|nw)' which must be defined in 'mo'.
+void assign_diranimation(DirAnimations* anims, Map_Object_Descr& mo, const std::string& prefix) {
+	static char const* const dirstrings[6] = {"ne", "e", "se", "sw", "w", "nw"};
+	for (int32_t dir = 1; dir <= 6; ++dir) {
+		anims->set_animation(dir, mo.get_animation(prefix + std::string("_") + dirstrings[dir - 1]));
+	}
+}
+
+}  // namespace
+
+void Critter_BobProgram::parse(const std::vector<std::string>& lines) {
+	for (const std::string& line : lines) {
 		try {
-			char buffer[32];
-
-			snprintf(buffer, sizeof(buffer), "%i", idx);
-			char const * const string = program_s.get_string(buffer, nullptr);
-			if (!string)
-				break;
-
-			const std::vector<std::string> cmd(split_string(string, " \t\r\n"));
+			const std::vector<std::string> cmd(split_string(line, " \t\r\n"));
 			if (cmd.empty())
 				continue;
 
-			//  find the appropriate parser
 			Critter_BobAction act;
-			uint32_t mapidx;
-
-			for (mapidx = 0; s_parsemap[mapidx].name; ++mapidx)
-				if (cmd[0] == s_parsemap[mapidx].name)
-					break;
-
-			if (!s_parsemap[mapidx].name)
+			if (cmd[0] == "remove") {
+				if (cmd.size() != 1)
+					throw wexception("Usage: remove");
+				act.function = &Critter_Bob::run_remove;
+			} else {
 				throw wexception("unknown command type \"%s\"", cmd[0].c_str());
-
-			(this->*s_parsemap[mapidx].function)(&act, parser, cmd);
+			}
 
 			m_actions.push_back(act);
-		} catch (const std::exception & e) {
-			throw wexception("Line %i: %s", idx, e.what());
+		}
+		catch (const std::exception& e) {
+			throw wexception("Line '%s': %s", line.c_str(), e.what());
 		}
 	}
-
-	// Check for line numbering problems
-	if (program_s.get_num_values() != m_actions.size())
-		throw wexception("Line numbers appear to be wrong");
 }
 
 /*
@@ -99,15 +112,6 @@
 
 ==============================
 */
-void Critter_BobProgram::parse_remove
-	(Critter_BobAction * act, Parser *, const std::vector<std::string> & cmd)
-{
-	if (cmd.size() != 1)
-		throw wexception("Usage: remove");
-
-	act->function = &Critter_Bob::run_remove;
-}
-
 bool Critter_Bob::run_remove
 	(Game & game, State & state, const Critter_BobAction &)
 {
@@ -126,14 +130,27 @@
 ===========================================================================
 */
 
-Critter_Bob_Descr::Critter_Bob_Descr
-	(char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 Tribe_Descr const * const _tribe)
-	:
-	BobDescr(_name, _descname, directory, prof, global_s, _tribe),
-	m_swimming(global_s.get_bool("swimming", false))
-{
+Critter_Bob_Descr::Critter_Bob_Descr(char const* const _name,
+                                     char const* const _descname,
+                                     const std::string& directory,
+                                     Profile& prof,
+                                     Section& global_s,
+                                     Tribe_Descr const* const _tribe)
+   : BobDescr(_name, _descname, _tribe) {
+	{ //  global options
+		Section & idle_s = prof.get_safe_section("idle");
+		add_animation("idle", g_gr->animations().load(directory, idle_s));
+	}
+
+	// Parse attributes
+	{
+		std::vector<std::string> attributes;
+		while (Section::Value const* val = global_s.get_next_val("attrib")) {
+			attributes.emplace_back(val->get_string());
+		}
+		add_attributes(attributes, std::set<uint32_t>());
+	}
+
 	char defaultpics[256];
 	snprintf(defaultpics, sizeof(defaultpics), "%s_walk_!!_??.png", _name);
 	m_walk_anims.parse(*this, directory, prof, "walk", false, defaultpics);
@@ -147,14 +164,10 @@
 		try {
 			if (m_programs.count(program_name))
 				throw wexception("this program has already been declared");
-			Critter_BobProgram::Parser parser;
-
-			parser.descr = this;
-			parser.directory = directory;
-			parser.prof = &prof;
 
 			prog = new Critter_BobProgram(v->get_string());
-			prog->parse(&parser, v->get_string());
+			std::vector<std::string> lines(section_to_strings(&prof.get_safe_section(program_name)));
+			prog->parse(lines);
 			m_programs[program_name] = prog;
 		} catch (const std::exception & e) {
 			delete prog;
@@ -164,12 +177,44 @@
 	}
 }
 
+Critter_Bob_Descr::Critter_Bob_Descr(const LuaTable& table)
+   : BobDescr(table.get_string("name"),
+              table.get_string("descname"),
+              nullptr)  // Can only handle world critters.
+{
+	{
+		std::unique_ptr<LuaTable> anims(table.get_table("animations"));
+		for (const std::string& animation : anims->keys<std::string>()) {
+			add_animation(animation, g_gr->animations().load(*anims->get_table(animation)));
+		}
+		assign_diranimation(&m_walk_anims, *this, "walk");
+	}
+
+	add_attributes(
+	   table.get_table("attributes")->array_entries<std::string>(), std::set<uint32_t>());
+
+	std::unique_ptr<LuaTable> programs = table.get_table("programs");
+	for (const std::string& program_name : programs->keys<std::string>()) {
+		try {
+			std::unique_ptr<Critter_BobProgram> prog(new Critter_BobProgram(program_name));
+			prog->parse(programs->get_table(program_name)->array_entries<std::string>());
+			m_programs[program_name] = prog.release();
+		} catch (const std::exception& e) {
+			throw wexception("Parse error in program %s: %s", program_name.c_str(), e.what());
+		}
+	}
+}
 
 Critter_Bob_Descr::~Critter_Bob_Descr() {
 	container_iterate_const(Programs, m_programs, i)
 		delete i.current->second;
 }
 
+bool Critter_Bob_Descr::is_swimming() const {
+	const static uint32_t swimming_attribute = get_attribute_id("swimming");
+	return has_attribute(swimming_attribute);
+}
+
 
 /*
 ===============
@@ -350,10 +395,10 @@
 	return critter.descr().get_program(name);
 }
 
-
-Map_Object::Loader * Critter_Bob::load
-	(Editor_Game_Base & egbase, Map_Map_Object_Loader & mol, FileRead & fr)
-{
+Map_Object::Loader* Critter_Bob::load(Editor_Game_Base& egbase,
+                                      Map_Map_Object_Loader& mol,
+                                      FileRead& fr,
+                                      const OneWorldLegacyLookupTable& lookup_table) {
 	std::unique_ptr<Loader> loader(new Loader);
 
 	try {
@@ -361,24 +406,25 @@
 
 		uint8_t const version = fr.Unsigned8();
 		if (1 <= version && version <= CRITTER_SAVEGAME_VERSION) {
-			std::string owner = fr.CString();
-			std::string name = fr.CString();
+			const std::string owner = fr.CString();
+			std::string critter_name = fr.CString();
 			const Critter_Bob_Descr * descr = nullptr;
 
 			if (owner == "world") {
-				descr = dynamic_cast<const Critter_Bob_Descr *>
-					(egbase.map().world().get_bob_descr(name));
+				critter_name = lookup_table.lookup_critter(critter_name);
+				descr =
+				   dynamic_cast<const Critter_Bob_Descr*>(egbase.world().get_bob_descr(critter_name));
 			} else {
 				egbase.manually_load_tribe(owner);
 
 				if (const Tribe_Descr * tribe = egbase.get_tribe(owner))
 					descr = dynamic_cast<const Critter_Bob_Descr *>
-						(tribe->get_bob_descr(name));
+						(tribe->get_bob_descr(critter_name));
 			}
 
 			if (!descr)
 				throw game_data_error
-					("undefined critter %s/%s", owner.c_str(), name.c_str());
+					("undefined critter %s/%s", owner.c_str(), critter_name.c_str());
 
 			loader->init(egbase, mol, descr->create_object());
 			loader->load(fr);

=== modified file 'src/logic/critter_bob.h'
--- src/logic/critter_bob.h	2014-03-31 20:21:27 +0000
+++ src/logic/critter_bob.h	2014-06-10 18:27:45 +0000
@@ -23,6 +23,9 @@
 #include "logic/bob.h"
 #include "graphic/diranimations.h"
 
+class LuaTable;
+class OneWorldLegacyLookupTable;
+
 namespace Widelands {
 
 struct Critter_BobAction;
@@ -35,12 +38,13 @@
 	Critter_Bob_Descr
 		(char const * name, char const * descname,
 		 const std::string & directory, Profile &, Section & global_s,
-		 Tribe_Descr const *);
+		 const Tribe_Descr *);
+	Critter_Bob_Descr(const LuaTable&);
 	virtual ~Critter_Bob_Descr();
 
 	Bob & create_object() const override;
 
-	bool is_swimming() const {return m_swimming;}
+	bool is_swimming() const;
 	uint32_t movecaps() const override;
 	const DirAnimations & get_walk_anims() const {return m_walk_anims;}
 
@@ -48,7 +52,6 @@
 
 private:
 	DirAnimations m_walk_anims;
-	bool          m_swimming;
 	typedef std::map<std::string, Critter_BobProgram *> Programs;
 	Programs      m_programs;
 };
@@ -70,16 +73,11 @@
 	void start_task_program(Game &, const std::string & name);
 	const std::string & descname() const {return descr().descname();}
 
-private:
-	void roam_update   (Game &, State &);
-	void program_update(Game &, State &);
-
-	bool run_remove(Game &, State &, const Critter_BobAction &);
-
-	static Task const taskRoam;
-	static Task const taskProgram;
-
-	// saving and loading
+	virtual void save(Editor_Game_Base &, Map_Map_Object_Saver &, FileWrite &) override;
+
+	static Map_Object::Loader*
+	load(Editor_Game_Base&, Map_Map_Object_Loader&, FileRead&, const OneWorldLegacyLookupTable& lookup_table);
+
 protected:
 	struct Loader : Bob::Loader {
 		Loader();
@@ -88,11 +86,15 @@
 		virtual const BobProgramBase * get_program(const std::string & name) override;
 	};
 
-public:
-	virtual void save(Editor_Game_Base &, Map_Map_Object_Saver &, FileWrite &) override;
-
-	static Map_Object::Loader * load
-		(Editor_Game_Base &, Map_Map_Object_Loader &, FileRead &);
+private:
+	void roam_update   (Game &, State &);
+	void program_update(Game &, State &);
+
+	bool run_remove(Game &, State &, const Critter_BobAction &);
+
+	static Task const taskRoam;
+	static Task const taskProgram;
+
 };
 
 }

=== modified file 'src/logic/critter_bob_program.h'
--- src/logic/critter_bob_program.h	2014-02-22 18:04:02 +0000
+++ src/logic/critter_bob_program.h	2014-06-10 18:27:45 +0000
@@ -43,16 +43,6 @@
 };
 
 struct Critter_BobProgram : public BobProgramBase {
-	struct Parser {
-		Critter_Bob_Descr * descr;
-		std::string         directory;
-		Profile           * prof;
-	};
-
-	typedef
-		void (Critter_BobProgram::*parse_t)
-			(Critter_BobAction *, Parser *, const std::vector<std::string> & cmd);
-
 	Critter_BobProgram(const std::string & name) : m_name(name) {}
 	virtual ~Critter_BobProgram() {}
 
@@ -63,24 +53,11 @@
 		return m_actions[idx];
 	}
 
-	void parse(Parser *, char const * name);
-
-private:
-	struct ParseMap {
-		const char * name;
-		parse_t      function;
-	};
-
-private:
-	void parse_remove
-		(Critter_BobAction *, Parser *, const std::vector<std::string> & cmd);
+	void parse(const std::vector<std::string>& lines);
 
 private:
 	std::string                    m_name;
 	std::vector<Critter_BobAction> m_actions;
-
-private:
-	static const ParseMap          s_parsemap[];
 };
 
 }

=== modified file 'src/logic/dismantlesite.h'
--- src/logic/dismantlesite.h	2014-02-22 18:04:02 +0000
+++ src/logic/dismantlesite.h	2014-06-10 18:27:45 +0000
@@ -51,7 +51,7 @@
 };
 
 class DismantleSite : public Partially_Finished_Building {
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 
 	static const uint32_t DISMANTLESITE_STEP_TIME = 45000;
 

=== modified file 'src/logic/editor_game_base.cc'
--- src/logic/editor_game_base.cc	2014-04-20 20:02:13 +0000
+++ src/logic/editor_game_base.cc	2014-06-10 18:27:45 +0000
@@ -40,8 +40,10 @@
 #include "logic/tribe.h"
 #include "logic/ware_descr.h"
 #include "logic/worker.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "rgbcolor.h"
+#include "scoped_timer.h"
+#include "scripting/lua_table.h"
 #include "scripting/scripting.h"
 #include "sound/sound_handler.h"
 #include "ui_basic/progresswindow.h"
@@ -60,33 +62,31 @@
 ============
 */
 Editor_Game_Base::Editor_Game_Base(LuaInterface * lua_interface) :
-m_gametime          (0),
-m_lua               (lua_interface),
-m_player_manager    (new Players_Manager(*this)),
-m_ibase             (nullptr),
-m_map               (nullptr),
-m_lasttrackserial   (0)
+gametime_          (0),
+lua_               (lua_interface),
+player_manager_    (new Players_Manager(*this)),
+ibase_             (nullptr),
+map_               (nullptr),
+lasttrackserial_   (0)
 {
-	if (not m_lua) // TODO SirVer: this is sooo ugly, I can't say
-		m_lua = new LuaEditorInterface(this);
+	if (not lua_) // TODO SirVer: this is sooo ugly, I can't say
+		lua_.reset(new LuaEditorInterface(this));
 
-	g_sound_handler.m_egbase = this;
+	g_sound_handler.egbase_ = this;
 
 }
 
 
 Editor_Game_Base::~Editor_Game_Base() {
-	delete m_map;
-	delete m_player_manager.release();
+	delete map_;
+	delete player_manager_.release();
 
-	container_iterate_const(Tribe_Vector, m_tribes, i)
+	container_iterate_const(Tribe_Vector, tribes_, i)
 		delete *i.current;
 
-	delete m_lua;
-
 	if (g_gr) { // dedicated does not use the sound_handler
-		assert(this == g_sound_handler.m_egbase);
-		g_sound_handler.m_egbase = nullptr;
+		assert(this == g_sound_handler.egbase_);
+		g_sound_handler.egbase_ = nullptr;
 	}
 }
 
@@ -96,6 +96,31 @@
 	// by a given number of milliseconds
 }
 
+const World& Editor_Game_Base::world() const {
+	// Const casts are evil, but this is essentially lazy evaluation and the
+	// caller should really not modify this.
+	return *const_cast<Editor_Game_Base*>(this)->mutable_world();
+}
+
+World* Editor_Game_Base::mutable_world() {
+	if (!world_) {
+		// Lazy initialization of World. We need to create the pointer to the
+		// world immediately though, because the lua scripts need to have access
+		// to world through this method already.
+		ScopedTimer timer("Loading the world took %ums");
+		world_.reset(new World());
+
+		try {
+			lua_->run_script("world/init.lua");
+		}
+		catch (const _wexception& e) {
+			log("Could not read world information: %s", e.what());
+			throw;
+		}
+	}
+	return world_.get();
+}
+
 void Editor_Game_Base::receive(const NoteImmovable & note)
 {
 	note.pi->owner().receive(note);
@@ -108,11 +133,11 @@
 
 void Editor_Game_Base::receive(const NoteFieldTransformed & note)
 {
-	Widelands::Map_Index const i = note.fc.field - &(*m_map)[0];
+	Widelands::Map_Index const i = note.fc.field - &(*map_)[0];
 
-	iterate_players_existing(p, m_map->get_nrplayers(), *this, plr)
+	iterate_players_existing(p, map_->get_nrplayers(), *this, plr)
 		if (plr->vision(i) > 1) // player currently sees field?
-			plr->rediscover_node(*m_map, (*m_map)[0], note.fc);
+			plr->rediscover_node(*map_, (*map_)[0], note.fc);
 }
 
 Interactive_GameBase* Editor_Game_Base::get_igbase()
@@ -122,7 +147,7 @@
 
 /// @see PlayerManager class
 void Editor_Game_Base::remove_player(Player_Number plnum) {
-	m_player_manager->remove_player(plnum);
+	player_manager_->remove_player(plnum);
 }
 
 /// @see PlayerManager class
@@ -134,7 +159,7 @@
 	 TeamNumber                team)
 {
 	return
-		m_player_manager->add_player
+		player_manager_->add_player
 			(player_number, initialization_index, tribe,
 			name, team);
 }
@@ -143,39 +168,38 @@
 const Tribe_Descr & Editor_Game_Base::manually_load_tribe
 	(const std::string & tribe)
 {
-	container_iterate_const(Tribe_Vector, m_tribes, i)
+	container_iterate_const(Tribe_Vector, tribes_, i)
 		if ((*i.current)->name() == tribe)
 			return **i.current;
 
-	if (not map().get_world())
-		map().load_world();
-	assert(map().get_world());
 	Tribe_Descr & result = *new Tribe_Descr(tribe, *this);
 	//resize the configuration of our wares if they won't fit in the current window (12 = info label size)
 	int number = (g_gr->get_yres() - 270) / (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + 12);
 	result.resize_ware_orders(number);
-	m_tribes.push_back(&result);
+	tribes_.push_back(&result);
 	return result;
 }
 
 Player* Editor_Game_Base::get_player(const int32_t n) const
 {
-	return m_player_manager->get_player(n);
+	return player_manager_->get_player(n);
 }
 
 Player& Editor_Game_Base::player(const int32_t n) const
 {
-	return m_player_manager->player(n);
+	return player_manager_->player(n);
 }
 
 
 
 /// Returns a tribe description from the internally loaded list
-const Tribe_Descr * Editor_Game_Base::get_tribe(const char * const tribe) const
+const Tribe_Descr * Editor_Game_Base::get_tribe(const std::string& tribename) const
 {
-	container_iterate_const(Tribe_Vector, m_tribes, i)
-		if (not strcmp((*i.current)->name().c_str(), tribe))
-			return *i.current;
+	for (const Tribe_Descr* tribe : tribes_) {
+		if (tribe->name() == tribename) {
+			return tribe;
+		}
+	}
 	return nullptr;
 }
 
@@ -206,19 +230,14 @@
  * to the Editor_Game_Base object.
  */
 void Editor_Game_Base::set_map(Map * const new_map) {
-	assert(new_map != m_map);
+	assert(new_map != map_);
 	assert(new_map);
 
-	delete m_map;
-
-	m_map = new_map;
-
-	// if this map is already completely loaded, we better inform g_gr about the change of the world
-	// to (re)load the correct road textures.
-	if (g_gr && strcmp(m_map->get_world_name(), ""))
-		g_gr->set_world(m_map->get_world_name());
-
-	NoteReceiver<NoteFieldTransformed>::connect(*m_map);
+	delete map_;
+
+	map_ = new_map;
+
+	NoteReceiver<NoteFieldTransformed>::connect(*map_);
 }
 
 
@@ -241,10 +260,10 @@
 
 	// Postload tribes
 	id = 0;
-	while (id < m_tribes.size()) {
+	while (id < tribes_.size()) {
 		for (pid = 1; pid <= MAX_PLAYERS; ++pid)
 			if (const Player * const plr = get_player(pid))
-				if (&plr->tribe() == m_tribes[id])
+				if (&plr->tribe() == tribes_[id])
 					break;
 
 		if
@@ -253,11 +272,11 @@
 			 not dynamic_cast<const Game *>(this))
 		{ // if this is editor, load the tribe anyways
 			// the tribe is used, postload it
-			m_tribes[id]->postload(*this);
+			tribes_[id]->postload(*this);
 			++id;
 		} else {
-			delete m_tribes[id]; // the tribe is no longer used, remove it
-			m_tribes.erase(m_tribes.begin() + id);
+			delete tribes_[id]; // the tribe is no longer used, remove it
+			tribes_.erase(tribes_.begin() + id);
 		}
 	}
 
@@ -274,10 +293,7 @@
 {
 	loader_ui.step(_("Loading world data"));
 
-	g_gr->set_world(m_map->get_world_name());
-	m_map->load_graphics(); // especially loads world data
-
-	container_iterate_const(Tribe_Vector, m_tribes, i) {
+	container_iterate_const(Tribe_Vector, tribes_, i) {
 		loader_ui.stepf(_("Loading tribes"));
 		(*i.current)->load_graphics();
 	}
@@ -366,7 +382,7 @@
 		(tribe ?
 		 tribe->get_bob_descr(idx)
 		 :
-		 m_map->get_world()->get_bob_descr(idx));
+		 world().get_bob_descr(idx));
 
 	return create_bob(c, descr, owner);
 }
@@ -378,7 +394,7 @@
 	const BobDescr * descr =
 		tribe ?
 		tribe->get_bob_descr(name) :
-		m_map->get_world()->get_bob_descr(name);
+		world().get_bob_descr(name);
 
 	if (!descr)
 		throw wexception
@@ -405,7 +421,7 @@
 		(tribe ?
 		 tribe->get_immovable_descr(idx)
 		 :
-		 m_map->world().get_immovable_descr(idx));
+		 world().get_immovable_descr(idx));
 	assert(&descr);
 	inform_players_about_immovable
 		(Map::get_index(c, map().get_width()), &descr);
@@ -419,7 +435,7 @@
 		tribe ?
 		tribe->get_immovable_index(name.c_str())
 		:
-		m_map->get_world()->get_immovable_index(name.c_str());
+		world().get_immovable_index(name.c_str());
 	if (idx < 0)
 		throw wexception
 			("Editor_Game_Base::create_immovable(%i, %i): %s is not defined for "
@@ -450,13 +466,13 @@
 */
 uint32_t Editor_Game_Base::add_trackpointer(void * const ptr)
 {
-	++m_lasttrackserial;
+	++lasttrackserial_;
 
-	if (!m_lasttrackserial)
+	if (!lasttrackserial_)
 		throw wexception("Dude, you play too long. Track serials exceeded.");
 
-	m_trackpointers[m_lasttrackserial] = ptr;
-	return m_lasttrackserial;
+	trackpointers_[lasttrackserial_] = ptr;
+	return lasttrackserial_;
 }
 
 
@@ -468,9 +484,9 @@
 */
 void * Editor_Game_Base::get_trackpointer(uint32_t const serial)
 {
-	std::map<uint32_t, void *>::iterator it = m_trackpointers.find(serial);
+	std::map<uint32_t, void *>::iterator it = trackpointers_.find(serial);
 
-	if (it != m_trackpointers.end())
+	if (it != trackpointers_.end())
 		return it->second;
 
 	return nullptr;
@@ -485,7 +501,7 @@
 */
 void Editor_Game_Base::remove_trackpointer(uint32_t serial)
 {
-	m_trackpointers.erase(serial);
+	trackpointers_.erase(serial);
 }
 
 /**
@@ -496,10 +512,11 @@
 void Editor_Game_Base::cleanup_for_load()
 {
 	cleanup_objects(); /// Clean all the stuff up, so we can load.
-	m_player_manager->cleanup();
-
-	if (m_map)
-		m_map->cleanup();
+
+	player_manager_->cleanup();
+
+	if (map_)
+		map_->cleanup();
 }
 
 
@@ -652,7 +669,7 @@
 	//  This must reach one step beyond the conquered area to adjust the borders
 	//  of neighbour players.
 	++player_area.radius;
-	map().recalc_for_field_area(player_area);
+	map().recalc_for_field_area(world(), player_area);
 }
 
 
@@ -755,7 +772,7 @@
 	//  This must reach one step beyond the conquered area to adjust the borders
 	//  of neighbour players.
 	++player_area.radius;
-	map().recalc_for_field_area(player_area);
+	map().recalc_for_field_area(world(), player_area);
 }
 
 /// Makes sure that buildings cannot exist outside their owner's territory.

=== modified file 'src/logic/editor_game_base.h'
--- src/logic/editor_game_base.h	2014-04-20 20:02:13 +0000
+++ src/logic/editor_game_base.h	2014-06-10 18:27:45 +0000
@@ -69,11 +69,11 @@
 	virtual ~Editor_Game_Base();
 
 	void set_map(Map *);
-	Map & map() const {return *m_map;}
-	Map * get_map() {return m_map;}
-	Map & get_map() const {return *m_map;}
-	const Object_Manager & objects() const {return m_objects;}
-	Object_Manager       & objects()       {return m_objects;}
+	Map & map() const {return *map_;}
+	Map * get_map() {return map_;}
+	Map & get_map() const {return *map_;}
+	const Object_Manager & objects() const {return objects_;}
+	Object_Manager       & objects()       {return objects_;}
 
 	// logic handler func
 	virtual void think();
@@ -117,8 +117,8 @@
 	Immovable & create_immovable
 		(Coords, const std::string & name, Tribe_Descr const *);
 
-	int32_t get_gametime() const {return m_gametime;}
-	Interactive_Base * get_ibase() const {return m_ibase;}
+	int32_t get_gametime() const {return gametime_;}
+	Interactive_Base * get_ibase() const {return ibase_;}
 
 	// safe system for storing pointers to non-Map_Object C++ objects
 	// unlike objects in the Object_Manager, these pointers need not be
@@ -132,11 +132,8 @@
 	const Tribe_Descr & manually_load_tribe(Player_Number const p) {
 		return manually_load_tribe(map().get_scenario_player_tribe(p));
 	}
-	// Get a tribe from the loaded list, when available
-	Tribe_Descr const * get_tribe(const char * tribe) const;
-	Tribe_Descr const * get_tribe(const std::string & name) const {
-		return get_tribe(name.c_str());
-	}
+	// Get a tribe from the loaded list, when known or nullptr.
+	Tribe_Descr const * get_tribe(const std::string & name) const;
 
 	void inform_players_about_ownership(Map_Index, Player_Number);
 	void inform_players_about_immovable(Map_Index, Map_Object_Descr const *);
@@ -157,33 +154,40 @@
 
 	// next function is used to update the current gametime,
 	// for queue runs e.g.
-	int32_t & get_game_time_pointer() {return m_gametime;}
-	void set_ibase(Interactive_Base * const b) {m_ibase = b;}
+	int32_t & get_game_time_pointer() {return gametime_;}
+	void set_ibase(Interactive_Base * const b) {ibase_ = b;}
 
 	/// Lua frontend, used to run Lua scripts
-	LuaInterface & lua() {return *m_lua;}
+	LuaInterface & lua() {return *lua_;}
 
-	Players_Manager* player_manager() {return m_player_manager.get();}
+	Players_Manager* player_manager() {return player_manager_.get();}
 
 	Interactive_GameBase * get_igbase();
 
+	// Returns the world.
+	const World& world() const;
+
+	// Returns the world that can be modified. Prefer world() whenever possible.
+	World* mutable_world();
+
 private:
 	// FIXME -- SDL returns time as uint32. Why do I have int32 ? Please comment or change this to uint32.
-	int32_t m_gametime;
-	Object_Manager             m_objects;
-
-	LuaInterface             * m_lua;
-	std::unique_ptr<Players_Manager> m_player_manager;
+	int32_t gametime_;
+	Object_Manager objects_;
+
+	std::unique_ptr<LuaInterface> lua_;
+	std::unique_ptr<Players_Manager> player_manager_;
+
+	std::unique_ptr<World> world_;
+	Interactive_Base* ibase_;
+	Map* map_;
+
+	uint32_t lasttrackserial_;
+	std::map<uint32_t, void*> trackpointers_;
 
 protected:
-	typedef std::vector<Tribe_Descr *> Tribe_Vector;
-	Tribe_Vector           m_tribes;
-private:
-	Interactive_Base         * m_ibase;
-	Map                      * m_map;
-
-	uint32_t                       m_lasttrackserial;
-	std::map<uint32_t, void *>     m_trackpointers;
+	typedef std::vector<Tribe_Descr*> Tribe_Vector;
+	Tribe_Vector tribes_;
 
 private:
 	/// \param preferred_player

=== modified file 'src/logic/field.h'
--- src/logic/field.h	2014-03-31 20:21:27 +0000
+++ src/logic/field.h	2014-06-10 18:27:45 +0000
@@ -28,7 +28,6 @@
 #include "logic/roadtype.h"
 #include "logic/widelands.h"
 #include "logic/widelands_geometry.h"
-#include "logic/world.h"
 
 namespace Widelands {
 
@@ -48,8 +47,8 @@
 // Making it a struct doesn't add anything. struct is used interchangeably with
 // class all around the code
 
-struct Terrain_Descr;
 class Bob;
+class TerrainDescription;
 struct BaseImmovable;
 
 // Field is used so often, make sure it is as small as possible.
@@ -74,8 +73,10 @@
 	typedef uint8_t Height;
 	typedef uint8_t Resource_Amount;
 
-	struct Terrains         {Terrain_Index   d : 4, r : 4;};
-	static_assert(sizeof(Terrains) == 1, "assert(sizeof(Terrains) == 1) failed.");
+	struct Terrains {
+		Terrain_Index d, r;
+	};
+	static_assert(sizeof(Terrains) == 2, "assert(sizeof(Terrains) == 2) failed.");
 	struct Resources        {Resource_Index  d : 4, r : 4;};
 	static_assert(sizeof(Resources) == 1, "assert(sizeof(Resources) == 1) failed.");
 	struct Resource_Amounts {Resource_Amount d : 4, r : 4;};
@@ -232,7 +233,11 @@
 #pragma pack(pop)
 
 // Check that Field is tightly packed.
-static_assert(sizeof(Field) <= sizeof(void *) * 2 + 10, "Field is not tightly packed.");
+#ifndef WIN32
+static_assert(sizeof(Field) == sizeof(void *) * 2 + 10, "Field is not tightly packed.");
+#else
+static_assert(sizeof(Field) <= sizeof(void *) * 2 + 11, "Field is not tightly packed.");
+#endif
 }
 
 #endif

=== modified file 'src/logic/findbob.h'
--- src/logic/findbob.h	2014-02-22 18:04:02 +0000
+++ src/logic/findbob.h	2014-06-10 18:27:45 +0000
@@ -24,6 +24,7 @@
 
 namespace Widelands {
 
+class Player;
 
 struct FindBobAttribute : public FindBob {
 	FindBobAttribute(uint32_t const attrib) : m_attrib(attrib) {}

=== modified file 'src/logic/game.cc'
--- src/logic/game.cc	2014-05-11 07:38:01 +0000
+++ src/logic/game.cc	2014-06-10 18:27:45 +0000
@@ -228,10 +228,6 @@
 	std::string const background = map().get_background();
 	if (background.size() > 0)
 		loaderUI.set_background(background);
-	else
-		loaderUI.set_background(map().get_world_name());
-	loaderUI.step (_("Loading a world"));
-	maploader->load_world();
 
 	// We have to create the players here.
 	Player_Number const nr_players = map().get_nrplayers();
@@ -292,8 +288,6 @@
 	if (loaderUI) {
 		if (background.size() > 0)
 			loaderUI->set_background(background);
-		else
-			loaderUI->set_background(map().get_world_name());
 		loaderUI->step(_("Configuring players"));
 	}
 	std::vector<PlayerSettings> shared;
@@ -334,6 +328,7 @@
 	// Check for win_conditions
 	if (!settings.scenario) {
 		std::unique_ptr<LuaTable> table(lua().run_script(settings.win_condition_script));
+		table->do_not_warn_about_unaccessed_keys();
 		m_win_condition_displayname = table->get_string("name");
 		std::unique_ptr<LuaCoroutine> cr = table->get_coroutine("func");
 		enqueue_command(new Cmd_LuaCoroutine(get_gametime() + 100, cr.release()));
@@ -500,7 +495,7 @@
 				(map().get_starting_pos(get_ipl()->player_number()));
 
 		// Prepare the map, set default textures
-		map().recalc_default_resources();
+		map().recalc_default_resources(world());
 
 		// Finally, set the scenario names and tribes to represent
 		// the correct names of the players
@@ -646,9 +641,9 @@
 	m_state = gs_notrunning;
 
 	Editor_Game_Base::cleanup_for_load();
-	container_iterate_const(std::vector<Tribe_Descr *>, m_tribes, i)
+	container_iterate_const(std::vector<Tribe_Descr *>, tribes_, i)
 		delete *i.current;
-	m_tribes.clear();
+	tribes_.clear();
 	cmdqueue().flush();
 
 	// Statistics
@@ -1032,8 +1027,9 @@
 	// game, call the corresponding Lua function
 	std::unique_ptr<LuaTable> hook = lua().get_hook("custom_statistic");
 	if (hook) {
+		hook->do_not_warn_about_unaccessed_keys();
 		iterate_players_existing(p, nr_plrs, *this, plr) {
-			std::unique_ptr<LuaCoroutine> cr = hook->get_coroutine("calculator");
+			std::unique_ptr<LuaCoroutine> cr(hook->get_coroutine("calculator"));
 			cr->push_arg(plr);
 			cr->resume(&custom_statistic[p - 1]);
 		}

=== modified file 'src/logic/immovable.cc'
--- src/logic/immovable.cc	2014-05-11 07:38:01 +0000
+++ src/logic/immovable.cc	2014-06-10 18:27:45 +0000
@@ -21,6 +21,7 @@
 
 #include <cstdio>
 
+#include <boost/algorithm/string.hpp>
 #include <boost/format.hpp>
 #include <config.h>
 
@@ -42,7 +43,10 @@
 #include "logic/tribe.h"
 #include "logic/widelands_geometry_io.h"
 #include "logic/worker.h"
+#include "logic/world/world.h"
+#include "map_io/one_world_legacy_lookup_table.h"
 #include "profile/profile.h"
+#include "scripting/lua_table.h"
 #include "sound/sound_handler.h"
 #include "text_layout.h"
 #include "upcast.h"
@@ -51,6 +55,23 @@
 
 namespace Widelands {
 
+namespace  {
+
+BaseImmovable::Size string_to_size(const std::string& size) {
+	if (size == "none")
+		return BaseImmovable::NONE;
+	if (size == "small")
+		return BaseImmovable::SMALL;
+	if (size == "medium")
+		return BaseImmovable::MEDIUM;
+	if (size == "big")
+		return BaseImmovable::BIG;
+	throw game_data_error("Unknown size %s.", size.c_str());
+}
+
+}  // namespace
+
+
 BaseImmovable::BaseImmovable(const Map_Object_Descr & mo_descr) :
 Map_Object(&mo_descr)
 {}
@@ -80,7 +101,7 @@
 	f.field->immovable = this;
 
 	if (get_size() >= SMALL)
-		map.recalc_for_field_area(Area<FCoords>(f, 2));
+		map.recalc_for_field_area(egbase.world(), Area<FCoords>(f, 2));
 }
 
 /**
@@ -99,7 +120,7 @@
 	egbase.inform_players_about_immovable(f.field - &map[0], nullptr);
 
 	if (get_size() >= SMALL)
-		map.recalc_for_field_area(Area<FCoords>(f, 2));
+		map.recalc_for_field_area(egbase.world(), Area<FCoords>(f, 2));
 }
 
 
@@ -111,40 +132,78 @@
 ==============================================================================
 */
 
-
-ImmovableProgram::ImmovableProgram
-	(const std::string    & directory,
-	 Profile              & prof,
-	 const std::string    & _name,
-	 Immovable_Descr      & immovable)
-	: m_name(_name)
-{
-	Section & program_s = prof.get_safe_section(_name.c_str());
-	while (Section::Value * const v = program_s.get_next_val()) {
-		Action * action;
-		if      (not strcmp(v->get_name(), "animate"))
-			action = new ActAnimate  (v->get_string(), immovable, directory, prof);
-		else if (not strcmp(v->get_name(), "transform"))
+ImmovableProgram::ImmovableProgram(const std::string& directory,
+                                   Profile& prof,
+                                   const std::string& _name,
+                                   Immovable_Descr& immovable)
+   : m_name(_name) {
+	Section& program_s = prof.get_safe_section(_name.c_str());
+	while (Section::Value* const v = program_s.get_next_val()) {
+		Action* action;
+		if (not strcmp(v->get_name(), "animate")) {
+			bool reached_end;
+			char * full_line = v->get_string();
+			char * const animation_name = match(full_line, reached_end);
+			if (!immovable.is_animation_known(animation_name)) {
+				immovable.add_animation(
+				   animation_name,
+				   g_gr->animations().load(directory, prof.get_safe_section(animation_name)));
+			}
+			action = new ActAnimate(v->get_string(), immovable);
+		} else if (not strcmp(v->get_name(), "transform")) {
 			action = new ActTransform(v->get_string(), immovable);
-		else if (not strcmp(v->get_name(), "grow"))
+		} else if (not strcmp(v->get_name(), "grow")) {
 			action = new ActGrow(v->get_string(), immovable);
-		else if (not strcmp(v->get_name(), "remove"))
-			action = new ActRemove   (v->get_string(), immovable);
-		else if (not strcmp(v->get_name(), "seed"))
-			action = new ActSeed     (v->get_string(), immovable);
-		else if (not strcmp(v->get_name(), "playFX"))
-			action = new ActPlayFX   (directory, v->get_string(), immovable);
-		else if (not strcmp(v->get_name(), "construction"))
+		} else if (not strcmp(v->get_name(), "remove")) {
+			action = new ActRemove(v->get_string(), immovable);
+		} else if (not strcmp(v->get_name(), "seed")) {
+			action = new ActSeed(v->get_string(), immovable);
+		} else if (not strcmp(v->get_name(), "playFX")) {
+			action = new ActPlayFX(directory, v->get_string(), immovable);
+		} else if (not strcmp(v->get_name(), "construction")) {
 			action = new ActConstruction(v->get_string(), immovable, directory, prof);
-		else
-			throw game_data_error
-				("unknown command type \"%s\"", v->get_name());
-		m_actions.push_back(action);
-	}
-	if (m_actions.empty())
-		throw game_data_error("no actions");
-}
-
+		} else {
+			throw game_data_error("unknown command type \"%s\"", v->get_name());
+		}
+		m_actions.push_back(action);
+	}
+	if (m_actions.empty())
+		throw game_data_error("no actions");
+}
+
+ImmovableProgram::ImmovableProgram(const std::string& init_name,
+                                   const std::vector<std::string>& lines,
+											  Immovable_Descr* immovable)
+   : m_name(init_name) {
+	for (const std::string& line : lines) {
+		std::vector<std::string> parts;
+		boost::split(parts, line, boost::is_any_of("="));
+		if (parts.size() != 2) {
+			throw game_data_error("invalid line: %s.", line.c_str());
+		}
+		std::unique_ptr<char []> arguments(new char[parts[1].size() + 1]);
+		strncpy(arguments.get(), parts[1].c_str(), parts[1].size() + 1);
+
+		Action* action;
+		if (parts[0] == "animate") {
+			action = new ActAnimate(arguments.get(), *immovable);
+		} else if (parts[0] == "transform") {
+			action = new ActTransform(arguments.get(), *immovable);
+		} else if (parts[0] == "grow") {
+			action = new ActGrow(arguments.get(), *immovable);
+		} else if (parts[0] == "remove") {
+			action = new ActRemove(arguments.get(), *immovable);
+		} else if (parts[0] == "seed") {
+			action = new ActSeed(arguments.get(), *immovable);
+		} else {
+			throw game_data_error(
+			   "unknown or (here)not support command type \"%s\"", parts[0].c_str());
+		}
+		m_actions.push_back(action);
+	}
+	if (m_actions.empty())
+		throw game_data_error("no actions");
+}
 
 /*
 ==============================================================================
@@ -156,28 +215,16 @@
 
 /**
  * Parse an immovable from its conf file.
- *
- * Section [global]:
- * picture (default = $NAME_00.png): name of picture used in editor
- * size = none|small|medium|big (default = none): influences build options
- *
- * Section [program] (optional)
- * step = animation [animation name] [duration]
- *        transform [immovable name]
- *
- * Default:
- * 0=animation idle -1
-*/
+ */
 Immovable_Descr::Immovable_Descr
 	(char const * const _name, char const * const _descname,
 	 const std::string & directory, Profile & prof, Section & global_s,
-	 const World & world, Tribe_Descr const * const owner_tribe)
+	 Tribe_Descr const * const owner_tribe)
 :
 	Map_Object_Descr(_name, _descname),
 	m_size          (BaseImmovable::NONE),
 	m_owner_tribe   (owner_tribe)
 {
-
 	if (char const * const string = global_s.get_string("size"))
 		try {
 			if      (!strcasecmp(string, "small"))
@@ -194,17 +241,15 @@
 			throw game_data_error("size: %s", e.what());
 		}
 
-
-	//  parse attributes
-	while (Section::Value const * const v = global_s.get_next_val("attrib")) {
-		uint32_t attrib = get_attribute_id(v->get_string());
-		if (attrib < Map_Object::HIGHEST_FIXED_ATTRIBUTE)
-			if (attrib != Map_Object::RESI)
-				throw game_data_error("bad attribute \"%s\"", v->get_string());
-		add_attribute(attrib);
+	// parse attributes
+	{
+		std::vector<std::string> attributes;
+		while (Section::Value const * const v = global_s.get_next_val("attrib")) {
+			attributes.emplace_back(v->get_string());
+		}
+		add_attributes(attributes, {Map_Object::RESI});
 	}
 
-
 	//  parse the programs
 	while (Section::Value const * const v = global_s.get_next_val("program")) {
 		std::string program_name = v->get_string();
@@ -214,7 +259,7 @@
 		try {
 			if (m_programs.count(program_name))
 				throw game_data_error("this program has already been declared");
-			m_programs[program_name.c_str()] =
+			m_programs[program_name] =
 				new ImmovableProgram(directory, prof, program_name, *this);
 		} catch (const std::exception & e) {
 			throw game_data_error
@@ -222,63 +267,63 @@
 		}
 	}
 
-	if (m_programs.find("program") == m_programs.end()) { //  default program
-		char parameters[] = "idle";
-		m_programs["program"] =
-			new ImmovableProgram
-				("program",
-				 new ImmovableProgram::ActAnimate
-				 	(parameters, *this, directory, prof));
-	}
-
-	uint8_t * it = m_terrain_affinity;
-	memset(it, 0, sizeof(m_terrain_affinity));
-	if
-		(Section * const terrain_affinity_s =
-		 	prof.get_section("terrain affinity"))
-	{
-		memset(it, 0, sizeof(m_terrain_affinity));
-		for (int i = 0; i < world.get_nr_terrains(); ++i, ++it) {
-			char const * const terrain_type_name =
-				world.get_ter(i).name().c_str();
-			try {
-				uint32_t const value =
-					terrain_affinity_s->get_natural(terrain_type_name, 0);
-				if ((*it = value) != value)
-					throw game_data_error
-						("expected %s but found %u", "0 .. 255", value);
-				if (terrain_affinity_s->get_next_val(terrain_type_name))
-					throw game_data_error("duplicated");
-			} catch (const _wexception & e) {
-				throw game_data_error
-					("[terrain affinity] %s: %s", terrain_type_name, e.what());
-			}
-		}
-		if (owner_tribe) {
-			//  Tribe immovables may have entries for other worlds.
-			while (Section::Value * const v = terrain_affinity_s->get_next_val())
-				try {
-					uint32_t const value = v->get_natural();
-					if ((*it = value) != value)
-						throw game_data_error
-						("expected %s but found %u", "0 .. 255", value);
-					if (terrain_affinity_s->get_next_val(v->get_name()))
-						throw game_data_error("duplicated");
-				} catch (const _wexception & e) {
-					throw game_data_error
-						("[terrain affinity] \"%s\" (not in current world): %s",
-						 v->get_name(), e.what());
-				}
-		}
-	} else
-		memset(it, 255, sizeof(m_terrain_affinity));
+	make_sure_default_program_is_there();
 
 	if (owner_tribe) {
-		if (Section * buildcost_s = prof.get_section("buildcost"))
+		// shipconstruction has a cost associated.
+		if (Section * buildcost_s = prof.get_section("buildcost")) {
 			m_buildcost.parse(*owner_tribe, *buildcost_s);
-	}
-}
-
+		}
+	}
+}
+
+Immovable_Descr::Immovable_Descr(const LuaTable& table, const World& world)
+   : Map_Object_Descr(table.get_string("name"), table.get_string("descname")),
+     m_size(BaseImmovable::NONE),
+     m_owner_tribe(nullptr)  // Can only parse world immovables for now.
+{
+	m_size = string_to_size(table.get_string("size"));
+	add_attributes(table.get_table("attributes")->array_entries<std::string>(), {Map_Object::RESI});
+
+	std::unique_ptr<LuaTable> anims(table.get_table("animations"));
+	for (const std::string& animation : anims->keys<std::string>()) {
+		add_animation(animation, g_gr->animations().load(*anims->get_table(animation)));
+	}
+
+	std::unique_ptr<LuaTable> programs = table.get_table("programs");
+	for (const std::string& program_name : programs->keys<std::string>()) {
+		try {
+			m_programs[program_name] = new ImmovableProgram(
+			   program_name, programs->get_table(program_name)->array_entries<std::string>(), this);
+		} catch (const std::exception& e) {
+			throw wexception("Error in program %s: %s", program_name.c_str(), e.what());
+		}
+	}
+
+	int editor_category =
+	   world.editor_immovable_categories().get_index(table.get_string("editor_category"));
+	if (editor_category < 0) {
+		throw game_data_error("Unknown editor_category: %s\n",
+		                      table.get_string("editor_category").c_str());
+	}
+	editor_category_ = world.editor_immovable_categories().get(editor_category);
+
+	make_sure_default_program_is_there();
+}
+
+const EditorCategory& Immovable_Descr::editor_category() const {
+	return *editor_category_;
+}
+
+
+void Immovable_Descr::make_sure_default_program_is_there() {
+	if (m_programs.find("program") == m_programs.end()) {  //  default program
+		assert(is_animation_known("idle"));
+		char parameters[] = "idle";
+		m_programs["program"] = new ImmovableProgram(
+		   "program", new ImmovableProgram::ActAnimate(parameters, *this));
+	}
+}
 
 /**
  * Cleanup
@@ -449,26 +494,10 @@
 	schedule_act(game, 1);
 }
 
-uint32_t Immovable_Descr::terrain_suitability
-	(FCoords const f, const Map & map) const
-{
-	uint32_t result = 0;
-	//  Neighbours
-	FCoords const tr = map.tr_n(f);
-	FCoords const tl = map.tl_n(f);
-	FCoords const  l = map. l_n(f);
-
-	result += m_terrain_affinity[tr.field->terrain_d()];
-	result += m_terrain_affinity[tl.field->terrain_r()];
-	result += m_terrain_affinity[tl.field->terrain_d()];
-	result += m_terrain_affinity [l.field->terrain_r()];
-	result += m_terrain_affinity [f.field->terrain_d()];
-	result += m_terrain_affinity [f.field->terrain_r()];
-
-	return result;
+uint32_t Immovable_Descr::terrain_suitability(FCoords const, const Map&) const {
+	return 6 * 255;
 }
 
-
 /**
  * Run program timer.
 */
@@ -610,8 +639,8 @@
 	} catch (const Map_Object_Descr::Animation_Nonexistent &) {
 		imm.m_anim = imm.descr().main_animation();
 		log
-			("Warning: Animation \"%s\" not found, using animation %s).\n",
-			 animname, imm.descr().get_animation_name(imm.m_anim).c_str());
+			("Warning: (%s) Animation \"%s\" not found, using animation %s).\n",
+			 imm.name().c_str(), animname, imm.descr().get_animation_name(imm.m_anim).c_str());
 	}
 	imm.m_animstart = fr.Signed32();
 	if (version >= 4) {
@@ -728,39 +757,40 @@
 }
 
 Map_Object::Loader * Immovable::load
-	(Editor_Game_Base & egbase, Map_Map_Object_Loader & mol, FileRead & fr)
+	(Editor_Game_Base & egbase, Map_Map_Object_Loader & mol,
+	 FileRead & fr, const OneWorldLegacyLookupTable& lookup_table)
 {
 	std::unique_ptr<Loader> loader(new Loader);
 
 	try {
 		// The header has been peeled away by the caller
-
 		uint8_t const version = fr.Unsigned8();
 		if (1 <= version and version <= IMMOVABLE_SAVEGAME_VERSION) {
 
 			const std::string owner_name = fr.CString();
-			const std::string name = fr.CString();
+			const std::string old_name = fr.CString();
 			Immovable * imm = nullptr;
 
 			if (owner_name != "world") { //  It is a tribe immovable.
 				egbase.manually_load_tribe(owner_name);
 
 				if (Tribe_Descr const * const tribe = egbase.get_tribe(owner_name)) {
-					int32_t const idx = tribe->get_immovable_index(name);
+					int32_t const idx = tribe->get_immovable_index(old_name);
 					if (idx != -1)
 						imm = new Immovable(*tribe->get_immovable_descr(idx));
 					else
 						throw game_data_error
 							("tribe %s does not define immovable type \"%s\"",
-							 owner_name.c_str(), name.c_str());
+							 owner_name.c_str(), old_name.c_str());
 				} else
 					throw wexception("unknown tribe %s", owner_name.c_str());
 			} else { //  world immovable
-				const World & world = egbase.map().world();
-				int32_t const idx = world.get_immovable_index(name.c_str());
+				const World & world = egbase.world();
+				const std::string new_name = lookup_table.lookup_immovable(old_name);
+				int32_t const idx = world.get_immovable_index(new_name.c_str());
 				if (idx == -1)
 					throw wexception
-						("world does not define immovable type \"%s\"", name.c_str());
+						("world does not define immovable type \"%s\"", new_name.c_str());
 
 				imm = new Immovable(*world.get_immovable_descr(idx));
 			}
@@ -779,22 +809,15 @@
 
 ImmovableProgram::Action::~Action() {}
 
-
-ImmovableProgram::ActAnimate::ActAnimate
-	(char * parameters, Immovable_Descr & descr,
-	 const std::string & directory, Profile & prof)
-{
+ImmovableProgram::ActAnimate::ActAnimate(char* parameters, Immovable_Descr& descr) {
 	try {
 		bool reached_end;
 		char * const animation_name = match(parameters, reached_end);
-		if (descr.is_animation_known(animation_name))
-			m_id = descr.get_animation(animation_name);
-		else {
-			m_id =
-				g_gr->animations().load(directory, prof.get_safe_section(animation_name));
+		if (!descr.is_animation_known(animation_name)) {
+			throw game_data_error("Unknown animation: %s.", animation_name);
+		}
+		m_id = descr.get_animation(animation_name);
 
-			descr.add_animation(animation_name, m_id);
-		}
 		if (not reached_end) { //  The next parameter is the duration.
 			char * endp;
 			long int const value = strtol(parameters, &endp, 0);

=== modified file 'src/logic/immovable.h'
--- src/logic/immovable.h	2014-05-10 16:47:03 +0000
+++ src/logic/immovable.h	2014-06-10 18:27:45 +0000
@@ -25,7 +25,9 @@
 #include "logic/instances.h"
 #include "logic/widelands_geometry.h"
 
-struct Profile;
+class LuaTable;
+class OneWorldLegacyLookupTable;
+class Profile;
 
 namespace Widelands {
 
@@ -33,9 +35,9 @@
 class Map;
 class WareInstance;
 class Worker;
+class World;
 struct Flag;
 struct Tribe_Descr;
-struct World;
 
 /**
  * BaseImmovable is the base for all non-moving objects (immovables such as
@@ -48,7 +50,7 @@
  * For more information, see the Map::recalc_* functions.
  */
 struct BaseImmovable : public Map_Object {
-	enum {
+	enum Size {
 		NONE = 0, ///< not robust (i.e. removable by building something over it)
 		SMALL,    ///< small building or robust map element, including trees
 		MEDIUM,   ///< medium size building
@@ -93,7 +95,9 @@
 	Immovable_Descr
 		(char const * name, char const * descname,
 		 const std::string & directory, Profile &, Section & global_s,
-		 const World & world, Tribe_Descr const * const);
+		 Tribe_Descr const * const);
+	Immovable_Descr(const LuaTable&, const World&);
+
 	~Immovable_Descr();
 
 	int32_t get_size() const {return m_size;}
@@ -108,6 +112,9 @@
 
 	const Buildcost & buildcost() const {return m_buildcost;}
 
+	// Returns the editor category.
+	const EditorCategory& editor_category() const;
+
 protected:
 	int32_t     m_size;
 	Programs    m_programs;
@@ -121,7 +128,10 @@
 	Buildcost m_buildcost;
 
 private:
-	uint8_t m_terrain_affinity[16];
+	EditorCategory* editor_category_;  // not owned.
+
+	// Adds a default program if none was defined.
+	void make_sure_default_program_is_there();
 };
 
 class Immovable : public BaseImmovable {
@@ -240,7 +250,7 @@
 
 	virtual void save(Editor_Game_Base &, Map_Map_Object_Saver &, FileWrite &) override;
 	static Map_Object::Loader * load
-		(Editor_Game_Base &, Map_Map_Object_Loader &, FileRead &);
+		(Editor_Game_Base &, Map_Map_Object_Loader &, FileRead &, const OneWorldLegacyLookupTable& lookup_table);
 
 private:
 	void increment_program_pointer();

=== modified file 'src/logic/immovable_program.h'
--- src/logic/immovable_program.h	2014-02-22 18:04:02 +0000
+++ src/logic/immovable_program.h	2014-06-10 18:27:45 +0000
@@ -32,7 +32,7 @@
 #include "logic/buildcost.h"
 #include "logic/immovable.h"
 
-struct Profile;
+class Profile;
 
 namespace Widelands {
 
@@ -61,9 +61,7 @@
 	/// will not be stopped by this command. It will run until another animation
 	/// is started.)
 	struct ActAnimate : public Action {
-		ActAnimate
-			(char * parameters, Immovable_Descr &,
-			 const std::string & directory, Profile &);
+		ActAnimate(char * parameters, Immovable_Descr &);
 		virtual void execute(Game &, Immovable &) const override;
 		uint32_t animation() const {return m_id;}
 	private:
@@ -180,12 +178,18 @@
 		m_actions.push_back(action);
 	}
 
+	// Create an immovable program from a number of lines.
+	ImmovableProgram(const std::string& init_name,
+	                 const std::vector<std::string>& lines,
+	                 Immovable_Descr* immovable);
+
 	/// Create a program by parsing a conf-file section.
 	ImmovableProgram
 		(const std::string    & directory,
 		 Profile              &,
 		 const std::string    & name,
 		 Immovable_Descr      &);
+
 	~ImmovableProgram() {
 		container_iterate_const(Actions, m_actions, i)
 			delete *i.current;

=== modified file 'src/logic/instances.cc'
--- src/logic/instances.cc	2014-05-11 07:38:01 +0000
+++ src/logic/instances.cc	2014-06-10 18:27:45 +0000
@@ -283,6 +283,18 @@
 		m_attributes.push_back(attr);
 }
 
+void Map_Object_Descr::add_attributes(const std::vector<std::string>& attributes,
+                                      const std::set<uint32_t>& allowed_special) {
+	for (const std::string& attribute : attributes) {
+		uint32_t const attrib = get_attribute_id(attribute);
+		if (attrib < Map_Object::HIGHEST_FIXED_ATTRIBUTE) {
+			if (!allowed_special.count(attrib)) {
+				throw game_data_error("bad attribute \"%s\"", attribute.c_str());
+			}
+		}
+		add_attribute(attrib);
+	}
+}
 
 /**
  * Lookup an attribute by name. If the attribute name hasn't been encountered

=== modified file 'src/logic/instances.h'
--- src/logic/instances.h	2014-05-11 07:38:01 +0000
+++ src/logic/instances.h	2014-06-10 18:27:45 +0000
@@ -22,6 +22,7 @@
 
 #include <cstring>
 #include <map>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -43,6 +44,7 @@
 
 namespace Widelands {
 
+class EditorCategory;
 class Map_Map_Object_Loader;
 class Player;
 struct Path;
@@ -52,9 +54,9 @@
  * link them together
  */
 struct Map_Object_Descr : boost::noncopyable {
-	Map_Object_Descr(char const * const _name, char const * const _descname)
-		: m_name(_name), m_descname(_descname)
-	{}
+	Map_Object_Descr(const std::string& init_name, const std::string& init_descname)
+	   : m_name(init_name), m_descname(init_descname) {
+	}
 	virtual ~Map_Object_Descr() {m_anims.clear();}
 
 	const std::string &     name() const {return m_name;}
@@ -83,9 +85,11 @@
 	void add_animation(const std::string & name, uint32_t anim);
 
 protected:
+	// Add all the special attributes to the attribute list. Only the 'allowed_special'
+	// attributes are allowed to appear - i.e. resi are fine for immovables.
+	void add_attributes(const std::vector<std::string>& attributes, const std::set<uint32_t>& allowed_special);
 	void add_attribute(uint32_t attr);
 
-
 private:
 	typedef std::map<std::string, uint32_t> Anims;
 	typedef std::map<std::string, uint32_t> AttribMap;

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2014-05-27 11:01:15 +0000
+++ src/logic/map.cc	2014-06-10 18:27:45 +0000
@@ -39,7 +39,7 @@
 #include "logic/player.h"
 #include "logic/soldier.h"
 #include "logic/tribe.h"
-#include "logic/worlddata.h"
+#include "logic/world/world.h"
 #include "map_generator.h"
 #include "map_io/widelands_map_loader.h"
 #include "s2map.h"
@@ -70,10 +70,8 @@
 m_scenario_types (NO_SCENARIO),
 m_width          (0),
 m_height         (0),
-m_world          (nullptr),
 m_pathfieldmgr   (new PathfieldManager)
 {
-	m_worldname[0] = '\0';
 }
 
 
@@ -108,7 +106,7 @@
 and recalcs the interactive player's overlay.
 ===============
 */
-void Map::recalc_for_field_area(const Area<FCoords> area) {
+void Map::recalc_for_field_area(const World& world, const Area<FCoords> area) {
 	assert(0 <= area.x);
 	assert(area.x < m_width);
 	assert(0 <= area.y);
@@ -120,15 +118,15 @@
 	{ //  First pass.
 		MapRegion<Area<FCoords> > mr(*this, area);
 		do {
-			recalc_brightness     (mr.location());
-			recalc_border         (mr.location());
-			recalc_nodecaps_pass1(mr.location());
+			recalc_brightness(mr.location());
+			recalc_border(mr.location());
+			recalc_nodecaps_pass1(world, mr.location());
 		} while (mr.advance(*this));
 	}
 
 	{ //  Second pass.
 		MapRegion<Area<FCoords> > mr(*this, area);
-		do recalc_nodecaps_pass2(mr.location()); while (mr.advance(*this));
+		do recalc_nodecaps_pass2(world, mr.location()); while (mr.advance(*this));
 	}
 
 	{ //  Now only recaluclate the overlays.
@@ -148,7 +146,7 @@
 the overlays have completely changed.
 ===========
 */
-void Map::recalc_whole_map()
+void Map::recalc_whole_map(const World& world)
 {
 	assert(m_overlay_manager);
 
@@ -163,13 +161,13 @@
 			check_neighbour_heights(f, radius);
 			recalc_brightness     (f);
 			recalc_border         (f);
-			recalc_nodecaps_pass1  (f);
+			recalc_nodecaps_pass1  (world, f);
 		}
 
 	for (Y_Coordinate y = 0; y < m_height; ++y)
 		for (X_Coordinate x = 0; x < m_width; ++x) {
 			f = get_fcoords(Coords(x, y));
-			recalc_nodecaps_pass2(f);
+			recalc_nodecaps_pass2(world, f);
 		}
 
 	//  Now only recaluclate the overlays.
@@ -185,8 +183,7 @@
  * the editor. Since there, default resources
  * are not shown.
  */
-void Map::recalc_default_resources() {
-	const World & w = world();
+void Map::recalc_default_resources(const World& world) {
 	for (Y_Coordinate y = 0; y < m_height; ++y)
 		for (X_Coordinate x = 0; x < m_width; ++x) {
 			FCoords f, f1;
@@ -199,14 +196,14 @@
 
 			//  this node
 			{
-				const Terrain_Descr & terr = w.terrain_descr(f.field->terrain_r());
-				++m[terr.get_default_resources()];
-				amount += terr.get_default_resources_amount();
+				const TerrainDescription & terr = world.terrain_descr(f.field->terrain_r());
+				++m[terr.get_default_resource()];
+				amount += terr.get_default_resource_amount();
 			}
 			{
-				const Terrain_Descr & terd = w.terrain_descr(f.field->terrain_d());
-				++m[terd.get_default_resources()];
-				amount += terd.get_default_resources_amount();
+				const TerrainDescription & terd = world.terrain_descr(f.field->terrain_d());
+				++m[terd.get_default_resource()];
+				amount += terd.get_default_resource_amount();
 			}
 
 			//  If one of the neighbours is unpassable, count its resource
@@ -214,20 +211,20 @@
 			//  top left neigbour
 			get_neighbour(f, WALK_NW, &f1);
 			{
-				const Terrain_Descr& terr = w.terrain_descr(f1.field->terrain_r());
-				const int8_t resr = terr.get_default_resources();
-				const int default_amount = terr.get_default_resources_amount();
-				if ((terr.get_is() & TERRAIN_UNPASSABLE) && default_amount > 0)
+				const TerrainDescription& terr = world.terrain_descr(f1.field->terrain_r());
+				const int8_t resr = terr.get_default_resource();
+				const int default_amount = terr.get_default_resource_amount();
+				if ((terr.get_is() & TerrainDescription::UNPASSABLE) && default_amount > 0)
 					m[resr] += 3;
 				else
 					++m[resr];
 				amount += default_amount;
 			}
 			{
-				const Terrain_Descr & terd = w.terrain_descr(f1.field->terrain_d());
-				const int8_t resd = terd.get_default_resources();
-				const int default_amount = terd.get_default_resources_amount();
-				if ((terd.get_is() & TERRAIN_UNPASSABLE) && default_amount > 0)
+				const TerrainDescription& terd = world.terrain_descr(f1.field->terrain_d());
+				const int8_t resd = terd.get_default_resource();
+				const int default_amount = terd.get_default_resource_amount();
+				if ((terd.get_is() & TerrainDescription::UNPASSABLE) && default_amount > 0)
 					m[resd] += 3;
 				else
 					++m[resd];
@@ -237,24 +234,26 @@
 			//  top right neigbour
 			get_neighbour(f, WALK_NE, &f1);
 			{
-				const Terrain_Descr& terd = w.terrain_descr(f1.field->terrain_d());
-				const int8_t resd = terd.get_default_resources();
-				const int default_amount = terd.get_default_resources_amount();
-				if ((terd.get_is() & TERRAIN_UNPASSABLE) && default_amount > 0)
+				const TerrainDescription& terd = world.terrain_descr(f1.field->terrain_d());
+				const int8_t resd = terd.get_default_resource();
+				const int default_amount = terd.get_default_resource_amount();
+				if ((terd.get_is() & TerrainDescription::UNPASSABLE) && default_amount > 0)
 					m[resd] += 3;
-				else ++m[resd];
+				else
+					++m[resd];
 				amount += default_amount;
 			}
 
 			//  left neighbour
 			get_neighbour(f, WALK_W, &f1);
 			{
-				const Terrain_Descr & terr = w.terrain_descr(f1.field->terrain_r());
-				const int8_t resr = terr.get_default_resources();
-				const int default_amount = terr.get_default_resources_amount();
-				if ((terr.get_is() & TERRAIN_UNPASSABLE) && default_amount > 0)
+				const TerrainDescription& terr = world.terrain_descr(f1.field->terrain_r());
+				const int8_t resr = terr.get_default_resource();
+				const int default_amount = terr.get_default_resource_amount();
+				if ((terr.get_is() & TerrainDescription::UNPASSABLE) && default_amount > 0)
 					m[resr] += 3;
-				else ++m[resr];
+				else
+					++m[resr];
 				amount += default_amount;
 			}
 
@@ -292,8 +291,6 @@
 	m_width = m_height = 0;
 
 	m_fields.reset();
-	delete m_world;
-	m_world = nullptr;
 
 	m_starting_pos.clear();
 	m_scenario_tribes.clear();
@@ -318,14 +315,11 @@
 ===========
 */
 void Map::create_empty_map
-	(uint32_t const w, uint32_t const h,
-	 const std::string & worldname,
+	(const World& world, uint32_t const w, uint32_t const h,
 	 char const * const name,
 	 char const * const author,
 	 char const * const description)
 {
-	set_world_name(worldname.c_str());
-	load_world();
 	set_size(w, h);
 	set_name       (name);
 	set_author     (author);
@@ -350,7 +344,7 @@
 			field->set_terrains(default_terrains);
 		}
 	}
-	recalc_whole_map();
+	recalc_whole_map(world);
 }
 
 
@@ -573,11 +567,6 @@
 	m_hint = string;
 }
 
-void Map::set_world_name(char const * const string)
-{
-	snprintf(m_worldname, sizeof(m_worldname), "%s", string);
-}
-
 void Map::set_background(char const * const string)
 {
 	if (string)
@@ -590,28 +579,9 @@
 	m_tags.insert(tag);
 }
 
-/*
-===============
-load the corresponding world. This should only happen
-once during initial load.
-===============
-*/
-void Map::load_world()
-{
-	if (!m_world)
-		m_world = new World(m_worldname);
-}
-
-/// Load data for the graphics subsystem.
-void Map::load_graphics()
-{
-	m_world->load_graphics();
-}
-
-
-NodeCaps Map::get_max_nodecaps(FCoords & fc) {
-	NodeCaps caps = _calc_nodecaps_pass1(fc, false);
-	caps = _calc_nodecaps_pass2(fc, false, caps);
+NodeCaps Map::get_max_nodecaps(const World& world, FCoords & fc) {
+	NodeCaps caps = _calc_nodecaps_pass1(world, fc, false);
+	caps = _calc_nodecaps_pass2(world, fc, false, caps);
 	return caps;
 }
 
@@ -1036,11 +1006,11 @@
 above recalc_brightness.
 ===============
 */
-void Map::recalc_nodecaps_pass1(FCoords const f) {
-	f.field->caps = _calc_nodecaps_pass1(f, true);
+void Map::recalc_nodecaps_pass1(const World& world, FCoords const f) {
+	f.field->caps = _calc_nodecaps_pass1(world, f, true);
 }
 
-NodeCaps Map::_calc_nodecaps_pass1(FCoords const f, bool consider_mobs) {
+NodeCaps Map::_calc_nodecaps_pass1(const World& world, FCoords const f, bool consider_mobs) {
 	uint8_t caps = CAPS_NONE;
 
 	// 1a) Get all the neighbours to make life easier
@@ -1048,46 +1018,44 @@
 	const FCoords tl = tl_n(f);
 	const FCoords  l =  l_n(f);
 
-	const World & w = world();
-
-	uint8_t const tr_d_terrain_is =
-		w.terrain_descr(tr.field->terrain_d()).get_is();
-	uint8_t const tl_r_terrain_is =
-		w.terrain_descr(tl.field->terrain_r()).get_is();
-	uint8_t const tl_d_terrain_is =
-		w.terrain_descr(tl.field->terrain_d()).get_is();
-	uint8_t const  l_r_terrain_is =
-		w.terrain_descr (l.field->terrain_r()).get_is();
-	uint8_t const  f_d_terrain_is =
-		w.terrain_descr (f.field->terrain_d()).get_is();
-	uint8_t const  f_r_terrain_is =
-		w.terrain_descr (f.field->terrain_r()).get_is();
+	const TerrainDescription::Type tr_d_terrain_is =
+		world.terrain_descr(tr.field->terrain_d()).get_is();
+	const TerrainDescription::Type tl_r_terrain_is =
+		world.terrain_descr(tl.field->terrain_r()).get_is();
+	const TerrainDescription::Type tl_d_terrain_is =
+		world.terrain_descr(tl.field->terrain_d()).get_is();
+	const TerrainDescription::Type  l_r_terrain_is =
+		world.terrain_descr (l.field->terrain_r()).get_is();
+	const TerrainDescription::Type  f_d_terrain_is =
+		world.terrain_descr (f.field->terrain_d()).get_is();
+	const TerrainDescription::Type  f_r_terrain_is =
+		world.terrain_descr (f.field->terrain_r()).get_is();
 
 	//  1b) Collect some information about the neighbours
 	uint8_t cnt_unpassable = 0;
 	uint8_t cnt_water = 0;
 	uint8_t cnt_acid = 0;
 
-	if  (tr_d_terrain_is & TERRAIN_UNPASSABLE) ++cnt_unpassable;
-	if  (tl_r_terrain_is & TERRAIN_UNPASSABLE) ++cnt_unpassable;
-	if  (tl_d_terrain_is & TERRAIN_UNPASSABLE) ++cnt_unpassable;
-	if   (l_r_terrain_is & TERRAIN_UNPASSABLE) ++cnt_unpassable;
-	if   (f_d_terrain_is & TERRAIN_UNPASSABLE) ++cnt_unpassable;
-	if   (f_r_terrain_is & TERRAIN_UNPASSABLE) ++cnt_unpassable;
-
-	if  (tr_d_terrain_is & TERRAIN_WATER)      ++cnt_water;
-	if  (tl_r_terrain_is & TERRAIN_WATER)      ++cnt_water;
-	if  (tl_d_terrain_is & TERRAIN_WATER)      ++cnt_water;
-	if   (l_r_terrain_is & TERRAIN_WATER)      ++cnt_water;
-	if   (f_d_terrain_is & TERRAIN_WATER)      ++cnt_water;
-	if   (f_r_terrain_is & TERRAIN_WATER)      ++cnt_water;
-
-	if  (tr_d_terrain_is & TERRAIN_ACID)       ++cnt_acid;
-	if  (tl_r_terrain_is & TERRAIN_ACID)       ++cnt_acid;
-	if  (tl_d_terrain_is & TERRAIN_ACID)       ++cnt_acid;
-	if   (l_r_terrain_is & TERRAIN_ACID)       ++cnt_acid;
-	if   (f_d_terrain_is & TERRAIN_ACID)       ++cnt_acid;
-	if   (f_r_terrain_is & TERRAIN_ACID)       ++cnt_acid;
+	if  (tr_d_terrain_is & TerrainDescription::UNPASSABLE) ++cnt_unpassable;
+	if  (tl_r_terrain_is & TerrainDescription::UNPASSABLE) ++cnt_unpassable;
+	if  (tl_d_terrain_is & TerrainDescription::UNPASSABLE) ++cnt_unpassable;
+	if   (l_r_terrain_is & TerrainDescription::UNPASSABLE) ++cnt_unpassable;
+	if   (f_d_terrain_is & TerrainDescription::UNPASSABLE) ++cnt_unpassable;
+	if   (f_r_terrain_is & TerrainDescription::UNPASSABLE) ++cnt_unpassable;
+
+	if  (tr_d_terrain_is & TerrainDescription::WATER)      ++cnt_water;
+	if  (tl_r_terrain_is & TerrainDescription::WATER)      ++cnt_water;
+	if  (tl_d_terrain_is & TerrainDescription::WATER)      ++cnt_water;
+	if   (l_r_terrain_is & TerrainDescription::WATER)      ++cnt_water;
+	if   (f_d_terrain_is & TerrainDescription::WATER)      ++cnt_water;
+	if   (f_r_terrain_is & TerrainDescription::WATER)      ++cnt_water;
+
+	if  (tr_d_terrain_is & TerrainDescription::ACID)       ++cnt_acid;
+	if  (tl_r_terrain_is & TerrainDescription::ACID)       ++cnt_acid;
+	if  (tl_d_terrain_is & TerrainDescription::ACID)       ++cnt_acid;
+	if   (l_r_terrain_is & TerrainDescription::ACID)       ++cnt_acid;
+	if   (f_d_terrain_is & TerrainDescription::ACID)       ++cnt_acid;
+	if   (f_r_terrain_is & TerrainDescription::ACID)       ++cnt_acid;
 
 
 	//  2) Passability
@@ -1147,11 +1115,11 @@
 Important: flag buildability has already been checked in the first pass.
 ===============
 */
-void Map::recalc_nodecaps_pass2(const FCoords & f) {
-	f.field->caps = _calc_nodecaps_pass2(f, true);
+void Map::recalc_nodecaps_pass2(const World& world, const FCoords & f) {
+	f.field->caps = _calc_nodecaps_pass2(world, f, true);
 }
 
-NodeCaps Map::_calc_nodecaps_pass2(FCoords const f, bool consider_mobs, NodeCaps initcaps) {
+NodeCaps Map::_calc_nodecaps_pass2(const World& world, FCoords const f, bool consider_mobs, NodeCaps initcaps) {
 	uint8_t caps = consider_mobs ? f.field->caps : static_cast<uint8_t>(initcaps);
 
 	// NOTE  This dependency on the bottom-right neighbour is the reason
@@ -1166,21 +1134,21 @@
 			(!br.field->get_immovable() || br.field->get_immovable()->get_type() != Map_Object::FLAG))
 			return static_cast<NodeCaps>(caps);
 	} else {
-		if (!(_calc_nodecaps_pass1(br, false) & BUILDCAPS_FLAG))
+		if (!(_calc_nodecaps_pass1(world, br, false) & BUILDCAPS_FLAG))
 			return static_cast<NodeCaps>(caps);
 	}
 
 	bool mine;
-	uint8_t buildsize = calc_buildsize(f, true, &mine, consider_mobs, initcaps);
+	uint8_t buildsize = calc_buildsize(world, 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(l_n(f),  false, nullptr, consider_mobs, initcaps) < BaseImmovable::BIG ||
-			 calc_buildsize(tl_n(f), false, nullptr, consider_mobs, initcaps) < BaseImmovable::BIG ||
-			 calc_buildsize(tr_n(f), false, nullptr, consider_mobs, initcaps) < BaseImmovable::BIG)
+			(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) < BaseImmovable::BIG)
 			buildsize = BaseImmovable::MEDIUM;
 	}
 
@@ -1258,7 +1226,7 @@
  * for the calculation. If not (calculation of maximum theoretical possible buildsize) initcaps must be set.
  */
 int Map::calc_buildsize
-	(const FCoords & f, bool avoidnature, bool * ismine, bool consider_mobs, NodeCaps initcaps)
+	(const World& world, const FCoords & f, bool avoidnature, bool * ismine, bool consider_mobs, NodeCaps initcaps)
 {
 	if (consider_mobs) {
 		if (!(f.field->get_caps() & MOVECAPS_WALK))
@@ -1275,24 +1243,22 @@
 	const FCoords tl = tl_n(f);
 	const FCoords  l =  l_n(f);
 
-	const World & w = world();
-
-	uint8_t terrains[6] = {
-		w.terrain_descr(tr.field->terrain_d()).get_is(),
-		w.terrain_descr(tl.field->terrain_r()).get_is(),
-		w.terrain_descr(tl.field->terrain_d()).get_is(),
-		w.terrain_descr (l.field->terrain_r()).get_is(),
-		w.terrain_descr (f.field->terrain_d()).get_is(),
-		w.terrain_descr (f.field->terrain_r()).get_is()
+	const TerrainDescription::Type 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(),
+		world.terrain_descr (l.field->terrain_r()).get_is(),
+		world.terrain_descr (f.field->terrain_d()).get_is(),
+		world.terrain_descr (f.field->terrain_r()).get_is()
 	};
 
 	uint32_t cnt_mountain = 0;
 	uint32_t cnt_dry = 0;
 	for (uint32_t i = 0; i < 6; ++i) {
-		if (terrains[i] & TERRAIN_WATER)
+		if (terrains[i] & TerrainDescription::WATER)
 			return BaseImmovable::NONE;
-		if (terrains[i] & TERRAIN_MOUNTAIN) ++cnt_mountain;
-		if (terrains[i] & TERRAIN_DRY) ++cnt_dry;
+		if (terrains[i] & TerrainDescription::MOUNTAIN) ++cnt_mountain;
+		if (terrains[i] & TerrainDescription::DRY) ++cnt_dry;
 	}
 
 	if (cnt_mountain == 6) {
@@ -1873,30 +1839,30 @@
 ===========
 */
 int32_t Map::change_terrain
-	(TCoords<FCoords> const c, Terrain_Index const terrain)
+	(const World& world, TCoords<FCoords> const c, Terrain_Index const terrain)
 {
 	c.field->set_terrain(c.t, terrain);
 
 	NoteSender<NoteFieldTransformed>::send(NoteFieldTransformed(c));
 
-	recalc_for_field_area(Area<FCoords>(c, 2));
+	recalc_for_field_area(world, Area<FCoords>(c, 2));
 
 	return 2;
 }
 
 
-uint32_t Map::set_height(const FCoords fc, uint8_t const new_value) {
+uint32_t Map::set_height(const World& world, const FCoords fc, uint8_t const new_value) {
 	assert(new_value <= MAX_FIELD_HEIGHT);
 	assert(m_fields.get() <= fc.field);
 	assert            (fc.field < m_fields.get() + max_index());
 	fc.field->height = new_value;
 	uint32_t radius = 2;
 	check_neighbour_heights(fc, radius);
-	recalc_for_field_area(Area<FCoords>(fc, radius));
+	recalc_for_field_area(world, Area<FCoords>(fc, radius));
 	return radius;
 }
 
-uint32_t Map::change_height(Area<FCoords> area, int16_t const difference) {
+uint32_t Map::change_height(const World& world, Area<FCoords> area, int16_t const difference) {
 	{
 		MapRegion<Area<FCoords> > mr(*this, area);
 		do {
@@ -1923,12 +1889,12 @@
 		regional_radius = std::max(regional_radius, local_radius);
 	} while (mr.advance(*this));
 	area.radius += regional_radius + 2;
-	recalc_for_field_area(area);
+	recalc_for_field_area(world, area);
 	return area.radius;
 }
 
 uint32_t Map::set_height
-	(Area<FCoords> area, interval<Field::Height> height_interval)
+	(const World& world, Area<FCoords> area, interval<Field::Height> height_interval)
 {
 	assert(height_interval.valid());
 	assert(height_interval.max <= MAX_FIELD_HEIGHT);
@@ -1965,7 +1931,7 @@
 		} while (changed);
 		area.radius = mr.radius();
 	}
-	recalc_for_field_area(area);
+	recalc_for_field_area(world, area);
 	return area.radius;
 }
 

=== modified file 'src/logic/map.h'
--- src/logic/map.h	2014-05-27 11:01:15 +0000
+++ src/logic/map.h	2014-06-10 18:27:45 +0000
@@ -21,19 +21,20 @@
 #define MAP_H
 
 #include <cstring>
+#include <map>
 #include <memory>
 #include <set>
 #include <string>
 #include <vector>
 
 #include "economy/itransport_cost_calculator.h"
-#include "i18n.h"
 #include "interval.h"
 #include "logic/field.h"
 #include "logic/map_revision.h"
 #include "logic/notification.h"
+#include "logic/objective.h"
+#include "logic/walkingdir.h"
 #include "logic/widelands_geometry.h"
-#include "logic/world.h"
 #include "random.h"
 
 class FileSystem;
@@ -43,14 +44,12 @@
 
 namespace Widelands {
 
-class Map;
 class Map_Loader;
 class Objective;
-class Player;
+class World;
 struct BaseImmovable;
 struct MapGenerator;
 struct PathfieldManager;
-struct World;
 
 #define WLMF_SUFFIX ".wmf"
 #define S2MF_SUFFIX ".swd"
@@ -122,17 +121,16 @@
 	public NoteSender<NoteFieldTransformed>
 {
 public:
+	friend class Editor;
 	friend class Editor_Game_Base;
 	friend class Map_Loader;
+	friend class Map_Version_Data_Packet;
 	friend struct ::S2_Map_Loader;
-	friend struct WL_Map_Loader;
-	friend struct Map_Elemental_Data_Packet;
-	friend struct Map_Extradata_Data_Packet;
-	friend struct Map_Version_Data_Packet;
-	friend class Editor;
 	friend struct Main_Menu_New_Map;
+	friend struct MapAStarBase;
 	friend struct MapGenerator;
-	friend struct MapAStarBase;
+	friend struct Map_Elemental_Data_Packet;
+	friend struct WL_Map_Loader;
 
 	typedef std::set<Coords, Coords::ordering_functor> PortSpacesSet;
 	typedef std::map<std::string, std::unique_ptr<Objective>> Objectives;
@@ -164,17 +162,17 @@
 
 	void cleanup();
 
-	void create_empty_map // for editor
-		(uint32_t w = 64, uint32_t h = 64,
-		 const std::string & worldname   =   "greenland",
-		 char        const * name        = _("No Name"),
-		 char        const * author      = _("Unknown"),
-		 char        const * description = _("no description defined"));
+	void create_empty_map  // for editor
+	   (const World& world,
+		 uint32_t w = 64,
+	    uint32_t h = 64,
+	    char const* name = _("No Name"),
+	    char const* author = _("Unknown"),
+	    char const* description = _("no description defined"));
 
-	void load_graphics();
-	void recalc_whole_map();
-	virtual void recalc_for_field_area(Area<FCoords>);
-	void recalc_default_resources();
+	void recalc_whole_map(const World& world);
+	virtual void recalc_for_field_area(const World& world, Area<FCoords>);
+	void recalc_default_resources(const World& world);
 
 	void set_nrplayers(Player_Number);
 
@@ -186,7 +184,6 @@
 
 	void set_filename   (char const *);
 	void set_author     (char const *);
-	void set_world_name (char const *);
 	void set_name       (char const *);
 	void set_description(char const *);
 	void set_hint       (std::string);
@@ -204,7 +201,6 @@
 	const char * get_name()        const {return m_name;}
 	const char * get_description() const {return m_description;}
 	std::string  get_hint()        const {return m_hint;}
-	const char * get_world_name()  const {return m_worldname;}
 	const std::string & get_background() const {return m_background;}
 	typedef std::set<std::string> Tags;
 	const Tags & get_tags() const {return m_tags;}
@@ -215,8 +211,6 @@
 	Extent extent() const {return Extent(m_width, m_height);}
 	X_Coordinate get_width   () const {return m_width;}
 	Y_Coordinate get_height  () const {return m_height;}
-	World & world() const {return *m_world;}
-	World * get_world() const {return m_world;}
 
 	//  The next few functions are only valid when the map is loaded as a
 	//  scenario.
@@ -230,7 +224,7 @@
 	void set_scenario_player_closeable(Player_Number, bool);
 
 	/// \returns the maximum theoretical possible nodecaps (no blocking bobs, etc.)
-	NodeCaps get_max_nodecaps(FCoords &);
+	NodeCaps get_max_nodecaps(const World& world, FCoords &);
 
 	BaseImmovable * get_immovable(Coords) const;
 	uint32_t find_bobs
@@ -337,10 +331,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(FCoords, Field::Height);
+	uint32_t set_height(const World& world, FCoords, Field::Height);
 
 	/// Changes the height of the nodes in an Area by a difference.
-	uint32_t change_height(Area<FCoords>, int16_t difference);
+	uint32_t change_height(const World& world, Area<FCoords>, int16_t difference);
 
 	/**
 	 * Ensures that the height of each node within radius from fc is in
@@ -355,10 +349,10 @@
 	 * 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(Area<FCoords>, interval<Field::Height> height_interval);
+	uint32_t set_height(const World& world, Area<FCoords>, interval<Field::Height> height_interval);
 
 	//  change terrain of a triangle, recalculate buildcaps
-	int32_t change_terrain(TCoords<FCoords>, Terrain_Index);
+	int32_t change_terrain(const World& world, TCoords<FCoords>, Terrain_Index);
 
 	// The objectives that are defined in this map if it is a scenario.
 	const Objectives& objectives() const {
@@ -384,7 +378,6 @@
 	void set_size(uint32_t w, uint32_t h);
 
 private:
-	void load_world();
 	void recalc_border(FCoords);
 
 	/// # of players this map supports (!= Game's number of players!)
@@ -398,10 +391,8 @@
 	char        m_name         [61];
 	char        m_description[1024];
 	std::string m_hint;
-	char        m_worldname  [1024];
 	std::string m_background;
 	Tags        m_tags;
-	World     * m_world;           //  world type
 	std::vector<Coords> m_starting_pos;    //  players' starting positions
 
 	std::unique_ptr<Field[]> m_fields;
@@ -421,13 +412,16 @@
 	Objectives objectives_;
 
 	void recalc_brightness(FCoords);
-	void recalc_nodecaps_pass1(FCoords);
-	void recalc_nodecaps_pass2(const FCoords & f);
-	NodeCaps _calc_nodecaps_pass1(FCoords, bool consider_mobs = true);
-	NodeCaps _calc_nodecaps_pass2(FCoords, bool consider_mobs = true, NodeCaps initcaps = CAPS_NONE);
+	void recalc_nodecaps_pass1(const World& world, FCoords);
+	void recalc_nodecaps_pass2(const World& world, const FCoords & f);
+	NodeCaps _calc_nodecaps_pass1(const World& world, FCoords, bool consider_mobs = true);
+	NodeCaps _calc_nodecaps_pass2(const World& world,
+	                              FCoords,
+	                              bool consider_mobs = true,
+	                              NodeCaps initcaps = CAPS_NONE);
 	void check_neighbour_heights(FCoords, uint32_t & radius);
 	int calc_buildsize
-		(const Widelands::FCoords& f, bool avoidnature, bool * ismine = nullptr,
+		(const World& world, const FCoords& f, bool avoidnature, bool * ismine = nullptr,
 		 bool consider_mobs = true, NodeCaps initcaps = CAPS_NONE);
 	bool is_cycle_connected
 		(const FCoords & start, uint32_t length, const WalkingDir * dirs);

=== modified file 'src/logic/mapastar.cc'
--- src/logic/mapastar.cc	2013-07-26 20:19:36 +0000
+++ src/logic/mapastar.cc	2014-06-10 18:27:45 +0000
@@ -19,6 +19,7 @@
 
 #include "logic/mapastar.h"
 
+#include "logic/instances.h"
 #include "logic/path.h"
 
 namespace Widelands {

=== modified file 'src/logic/message_queue.h'
--- src/logic/message_queue.h	2014-02-22 18:04:02 +0000
+++ src/logic/message_queue.h	2014-06-10 18:27:45 +0000
@@ -31,7 +31,7 @@
 namespace Widelands {
 
 struct MessageQueue : boost::noncopyable, private std::map<Message_Id, Message *> {
-	friend struct Map_Players_Messages_Data_Packet;
+	friend class Map_Players_Messages_Data_Packet;
 	// Make typedefs public so that this looks like proper
 	// STL container to templated algorithms.
 	typedef std::map<Message_Id, Message *> _Mybase;

=== modified file 'src/logic/militarysite.h'
--- src/logic/militarysite.h	2014-04-18 16:31:54 +0000
+++ src/logic/militarysite.h	2014-06-10 18:27:45 +0000
@@ -28,7 +28,7 @@
 namespace Widelands {
 
 class Soldier;
-struct World;
+class World;
 
 struct MilitarySite_Descr : public ProductionSite_Descr {
 	MilitarySite_Descr
@@ -61,7 +61,7 @@
 class MilitarySite :
 	public ProductionSite, public SoldierControl, public Attackable
 {
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 	MO_DESCR(MilitarySite_Descr);
 
 public:

=== modified file 'src/logic/partially_finished_building.h'
--- src/logic/partially_finished_building.h	2014-04-06 10:50:39 +0000
+++ src/logic/partially_finished_building.h	2014-06-10 18:27:45 +0000
@@ -35,7 +35,7 @@
 dismantlesites.
 */
 class Partially_Finished_Building : public Building {
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 	friend struct Map_Building_Data_Packet;
 
 public:

=== modified file 'src/logic/player.h'
--- src/logic/player.h	2014-04-21 09:19:14 +0000
+++ src/logic/player.h	2014-06-10 18:27:45 +0000
@@ -71,9 +71,9 @@
 	friend class Editor_Game_Base;
 	friend struct Game_Player_Info_Data_Packet;
 	friend struct Game_Player_Economies_Data_Packet;
-	friend struct Map_Buildingdata_Data_Packet;
-	friend struct Map_Players_View_Data_Packet;
-	friend struct Map_Exploration_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
+	friend class Map_Players_View_Data_Packet;
+	friend class Map_Exploration_Data_Packet;
 
 	Player
 		(Editor_Game_Base &,
@@ -155,11 +155,7 @@
 		{
 			//  Must be initialized because the rendering code is accessing it
 			//  even for triangles that the player does not see (it is the
-			//  darkening that actually hides the ground from the user). This is
-			//  important for worlds where the number of terrain types is not
-			//  maximal (16), so that an uninitialized terrain index could cause a
-			//  not found error in
-			//  DescriptionMaintainer<Terrain_Descr>::get(Terrain_Index).
+			//  darkening that actually hides the ground from the user).
 			terrains.d = terrains.r = 0;
 
 			time_triangle_last_surveyed[0] = Never();

=== modified file 'src/logic/production_program.cc'
--- src/logic/production_program.cc	2014-04-21 10:00:16 +0000
+++ src/logic/production_program.cc	2014-06-10 18:27:45 +0000
@@ -42,6 +42,8 @@
 #include "logic/trainingsite.h"
 #include "logic/tribe.h"
 #include "logic/worker_program.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/world.h"
 #include "profile/profile.h"
 #include "sound/sound_handler.h"
 #include "upcast.h"

=== modified file 'src/logic/production_program.h'
--- src/logic/production_program.h	2014-05-11 07:38:01 +0000
+++ src/logic/production_program.h	2014-06-10 18:27:45 +0000
@@ -36,7 +36,7 @@
 #include "logic/tattribute.h"
 #include "logic/widelands.h"
 
-struct Profile;
+class Profile;
 
 namespace Widelands {
 
@@ -46,7 +46,7 @@
 class ProductionSite;
 struct Tribe_Descr;
 class Worker;
-struct World;
+class World;
 
 /// Ordered sequence of actions (at least 1). Has a name.
 struct ProductionProgram {

=== modified file 'src/logic/productionsite.cc'
--- src/logic/productionsite.cc	2014-04-21 10:00:16 +0000
+++ src/logic/productionsite.cc	2014-06-10 18:27:45 +0000
@@ -37,7 +37,7 @@
 #include "logic/soldier.h"
 #include "logic/tribe.h"
 #include "logic/warelist.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "profile/profile.h"
 #include "upcast.h"
 #include "wexception.h"

=== modified file 'src/logic/productionsite.h'
--- src/logic/productionsite.h	2014-04-18 16:31:54 +0000
+++ src/logic/productionsite.h	2014-06-10 18:27:45 +0000
@@ -94,7 +94,7 @@
 };
 
 class ProductionSite : public Building {
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 	friend struct ProductionProgram::ActReturn;
 	friend struct ProductionProgram::ActReturn::Workers_Need_Experience;
 	friend struct ProductionProgram::ActCall;

=== modified file 'src/logic/ship.cc'
--- src/logic/ship.cc	2014-05-11 07:38:01 +0000
+++ src/logic/ship.cc	2014-06-10 18:27:45 +0000
@@ -50,8 +50,12 @@
 	(const char * given_name, const char * gdescname,
 	 const std::string & directory, Profile & prof, Section & global_s,
 	 const Tribe_Descr & gtribe)
-: BobDescr(given_name, gdescname, directory, prof, global_s, &gtribe)
+: BobDescr(given_name, gdescname, &gtribe)
 {
+	{ //  global options
+		Section & idle_s = prof.get_safe_section("idle");
+		add_animation("idle", g_gr->animations().load(directory, idle_s));
+	}
 	m_sail_anims.parse(*this, directory, prof, "sail");
 
 	Section * sinking_s = prof.get_section("sinking");
@@ -354,7 +358,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(fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG
+					((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG
 					 ||
 					 map.find_portdock(fc).empty())
 				{

=== modified file 'src/logic/trainingsite.h'
--- src/logic/trainingsite.h	2014-04-18 16:31:54 +0000
+++ src/logic/trainingsite.h	2014-06-10 18:27:45 +0000
@@ -28,7 +28,7 @@
 
 namespace Widelands {
 
-struct World;
+class World;
 
 struct TrainingSite_Descr : public ProductionSite_Descr {
 	TrainingSite_Descr
@@ -98,7 +98,7 @@
  *        contains soldiers!
  */
 class TrainingSite : public ProductionSite, public SoldierControl {
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 	MO_DESCR(TrainingSite_Descr);
 	friend struct ::TrainingSite_Window;
 

=== modified file 'src/logic/tribe.cc'
--- src/logic/tribe.cc	2014-05-10 17:07:11 +0000
+++ src/logic/tribe.cc	2014-06-10 18:27:45 +0000
@@ -43,7 +43,8 @@
 #include "logic/trainingsite.h"
 #include "logic/warehouse.h"
 #include "logic/worker.h"
-#include "logic/world.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/world.h"
 #include "parse_map_object_types.h"
 #include "profile/profile.h"
 #include "scripting/lua_table.h"
@@ -95,12 +96,12 @@
 					 	(*this, _name, _descname, path, prof, global_s));
 			PARSE_MAP_OBJECT_TYPES_END;
 
-			const World& world = egbase.map().world();
+			const World& world = egbase.world();
 
 			PARSE_MAP_OBJECT_TYPES_BEGIN("immovable")
 				m_immovables.add
 					(new Immovable_Descr
-					 	(_name, _descname, path, prof, global_s, world, this));
+					 	(_name, _descname, path, prof, global_s, this));
 			PARSE_MAP_OBJECT_TYPES_END;
 
 #define PARSE_WORKER_TYPES(name, descr_type)                                  \
@@ -287,6 +288,7 @@
 				     filter(g_fs->ListDirectory(path + "scripting"),
 				            [](const string& fn) {return boost::ends_with(fn, ".lua");})) {
 					std::unique_ptr<LuaTable> t = egbase.lua().run_script(script);
+					t->do_not_warn_about_unaccessed_keys();
 
 					m_initializations.resize(m_initializations.size() + 1);
 					Initialization& init = m_initializations.back();
@@ -358,6 +360,7 @@
 				     filter(g_fs->ListDirectory(path),
 				            [](const string& fn) {return boost::ends_with(fn, ".lua");})) {
 					std::unique_ptr<LuaTable> t = lua.run_script(script);
+					t->do_not_warn_about_unaccessed_keys();
 					info->initializations.push_back(
 					   TribeBasicInfo::Initialization(script, t->get_string("name")));
 				}
@@ -429,7 +432,7 @@
 ==============
 */
 uint32_t Tribe_Descr::get_resource_indicator
-	(Resource_Descr const * const res, uint32_t const amount) const
+	(ResourceDescription const * const res, uint32_t const amount) const
 {
 	if (not res or not amount) {
 		int32_t idx = get_immovable_index("resi_none");
@@ -460,7 +463,7 @@
 
 	int32_t bestmatch =
 		static_cast<int32_t>
-			((static_cast<float>(amount) / res->get_max_amount())
+			((static_cast<float>(amount) / res->max_amount())
 			 *
 			 num_indicators);
 	if (bestmatch > num_indicators)
@@ -468,8 +471,8 @@
 			("Amount of %s is %i but max amount is %i",
 			 res->name().c_str(),
 			 amount,
-			 res->get_max_amount());
-	if (static_cast<int32_t>(amount) < res->get_max_amount())
+			 res->max_amount());
+	if (static_cast<int32_t>(amount) < res->max_amount())
 		bestmatch += 1; // Resi start with 1, not 0
 
 	snprintf

=== modified file 'src/logic/tribe.h'
--- src/logic/tribe.h	2014-05-11 07:38:01 +0000
+++ src/logic/tribe.h	2014-06-10 18:27:45 +0000
@@ -35,14 +35,14 @@
 
 namespace Widelands {
 
+class Editor_Game_Base;
+class ResourceDescription;
 class Warehouse;
 class Worker_Descr;
+class World;
 struct Building_Descr;
-class Editor_Game_Base;
 struct Event;
 struct WareDescr;
-struct Resource_Descr;
-struct World;
 
 /*
 Tribes
@@ -53,11 +53,6 @@
 Two players can choose the same tribe.
 */
 struct Tribe_Descr : boost::noncopyable {
-	enum {
-		OK = 0,
-		ERR_WRONGVERSION
-	};
-
 	Tribe_Descr(const std::string & name, Editor_Game_Base &);
 
 	//  Static function to check for tribes.
@@ -197,7 +192,7 @@
 	uint32_t get_bob_vision_range() const {return m_bob_vision_range;}
 
 	uint32_t get_resource_indicator
-		(const Resource_Descr * const res, const uint32_t amount) const;
+		(const ResourceDescription * const res, const uint32_t amount) const;
 
 	void postload(Editor_Game_Base &);
 	void load_graphics();

=== modified file 'src/logic/ware_descr.h'
--- src/logic/ware_descr.h	2014-05-11 07:38:01 +0000
+++ src/logic/ware_descr.h	2014-06-10 18:27:45 +0000
@@ -27,8 +27,8 @@
 
 #include "logic/instances.h"
 
-struct Profile;
-struct Section;
+class Profile;
+class Section;
 class Image;
 
 #define WARE_MENU_PIC_WIDTH   24  //< Default width for ware's menu icons

=== modified file 'src/logic/warehouse.h'
--- src/logic/warehouse.h	2014-05-11 07:38:01 +0000
+++ src/logic/warehouse.h	2014-06-10 18:27:45 +0000
@@ -28,7 +28,7 @@
 #include "wexception.h"
 
 class Interactive_Player;
-struct Profile;
+class Profile;
 
 namespace Widelands {
 
@@ -68,7 +68,7 @@
 
 class Warehouse : public Building, public Attackable, public SoldierControl {
 	friend class PortDock;
-	friend struct Map_Buildingdata_Data_Packet;
+	friend class Map_Buildingdata_Data_Packet;
 
 	MO_DESCR(Warehouse_Descr);
 

=== modified file 'src/logic/widelands.h'
--- src/logic/widelands.h	2014-04-21 09:19:14 +0000
+++ src/logic/widelands.h	2014-06-10 18:27:45 +0000
@@ -49,7 +49,7 @@
  */
 typedef uint8_t TeamNumber;
 
-typedef uint8_t  Terrain_Index;   /// 4 bits used, so 0 .. 15.
+typedef uint8_t  Terrain_Index;
 typedef uint8_t  Resource_Index;  /// 4 bits used, so 0 .. 15.
 typedef uint8_t  Resource_Amount; /// 4 bits used, so 0 .. 15.
 

=== added file 'src/logic/widelands_streamread.h.THIS'
--- src/logic/widelands_streamread.h.THIS	1970-01-01 00:00:00 +0000
+++ src/logic/widelands_streamread.h.THIS	2014-06-10 18:27:45 +0000
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2007-2011 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef WIDELANDS_STREAMREAD_H
+#define WIDELANDS_STREAMREAD_H
+
+#include <cassert>
+
+#include "io/streamread.h"
+#include "logic/widelands.h"
+#include "logic/widelands_geometry.h"
+
+namespace Widelands {
+
+struct Building_Descr;
+class Editor_Game_Base;
+struct Immovable_Descr;
+struct Tribe_Descr;
+class World;
+
+/// A StreamRead that can read Widelands-specific types. It has no extra data
+/// members. Therefore it is binary compatible with StreamRead, so any
+/// ::StreamRead can be used as a Widelands::StreamRead to read
+/// Widelands-specific types.
+class StreamRead : public ::StreamRead {
+public:
+	struct direction_is_null : public _data_error {
+		direction_is_null
+			()
+			:
+			_data_error
+				("direction is 0 but must be one of {1 (northeast), 2 (east), 3 "
+				 "(southeast), 4 (southwest), 5 (west), 6 (northwest)}")
+		{}
+	};
+	struct direction_invalid : public _data_error {
+		direction_invalid
+			(Direction const D)
+			:
+			_data_error
+				("direction is %u but must be one of {0 (idle), 1 (northeast), 2 "
+				 "(east), 3 (southeast), 4 (southwest), 5 (west), 6 (northwest)}",
+				 D),
+			direction(D)
+		{}
+		Direction direction;
+	};
+	struct exceeded_max_index : public _data_error {
+		exceeded_max_index
+			(Map_Index const Max, Map_Index const I)
+			:
+			_data_error
+				("index is %u but max index is only %u",
+				 I, Max),
+			max(Max), i(I)
+		{}
+		Map_Index const max, i;
+	};
+	struct exceeded_width : public _data_error {
+		exceeded_width
+			(uint16_t const W, const X_Coordinate X)
+			:
+			_data_error
+				("x coordinate is %i but width is only %u",
+				 X, W),
+			w(W), x(X)
+		{}
+		uint16_t     const w;
+		X_Coordinate const x;
+	};
+	struct exceeded_height : public _data_error {
+		exceeded_height
+			(uint16_t const H, const Y_Coordinate Y)
+			:
+			_data_error
+				("y coordinate is %i but height is only %u",
+				 Y, H),
+			h(H), y(Y)
+		{}
+		uint16_t     h;
+		Y_Coordinate y;
+	};
+	struct player_nonexistent          : public _data_error {
+		player_nonexistent
+			(Player_Number const N, Player_Number const P)
+			:
+			_data_error
+				("player number is %u but there are only %u players",
+				 P, N),
+			nr_players(N), player_number(P)
+		{}
+		Player_Number nr_players, player_number;
+	};
+	struct tribe_nonexistent           : public _data_error {
+		tribe_nonexistent
+			(char const * const Name)
+			:
+			_data_error
+				("tribe \"%s\" does not exist",
+				 Name),
+			name(Name) {}
+		char const * const name;
+	};
+	struct tribe_immovable_nonexistent : public _data_error {
+		tribe_immovable_nonexistent
+			(const std::string & Tribename, const std::string & Name)
+			:
+			_data_error
+				("tribe %s does not define immovable type \"%s\"",
+				 Tribename.c_str(), Name.c_str()),
+			tribename(Tribename), name(Name)
+		{}
+		virtual ~tribe_immovable_nonexistent() throw () {}
+		std::string tribename;
+		std::string name;
+	};
+	struct world_immovable_nonexistent : public _data_error {
+		world_immovable_nonexistent(char const* const Name)
+		   : _data_error("world does not define immovable type \"%s\"", Name),
+		     name(Name) {
+		}
+		char const* const name;
+	};
+	struct building_nonexistent : public _data_error {
+		building_nonexistent
+			(const std::string & Tribename, char const * const Name)
+			:
+			_data_error
+				("tribe %s does not define building type \"%s\"",
+				 Tribename.c_str(), Name),
+			tribename(Tribename), name(Name)
+		{}
+		const std::string & tribename;
+		char        const * const name;
+	};
+
+	/// Read a Direction from the file. Use this when the result can only be a
+	/// direction.
+	///
+	/// \throws direction_is_null if the direction is 0.
+	/// \throws direction_invalid if direction is > 6.
+	Direction Direction8();
+
+	/// Read a Direction from the file. Use this when the result can only be a
+	/// direction or 0 (none).
+	///
+	/// \throws direction_invalid if direction is > 6.
+	Direction Direction8_allow_null();
+
+	Map_Index Map_Index32(Map_Index max);
+
+	/// Read a Coords from the file. Use this when the result can only be a
+	/// coordinate pair referring to a node.
+	///
+	/// \throws width_exceeded  if extent.w is <= the x coordinate.
+	/// \throws height_exceeded if extent.h is <= the y coordinate.
+	/// Both coordinates are read from the file before checking and possibly
+	/// throwing, so in case such an exception is thrown, it is guaranteed that
+	/// the whole coordinate pair has been read.
+	Coords Coords32(const Extent &);
+
+	/// Like Coords32 but the result can have the special value indicating
+	/// invalidity, as defined by Coords::Null.
+	Coords Coords32_allow_null(const Extent &);
+
+	Coords Coords32(); /// Unchecked reading.
+
+	Area<Coords, uint16_t> Area48(const Extent &);
+
+	Player_Number Player_Number8() {return Unsigned8();}
+
+	/// Read a Player_Number from the file. Use this when the result can only be
+	/// the number of an existing player.
+	///
+	/// \throws player_nonexistent when the player number is 0 or
+	/// nr_players < the player number.
+	Player_Number Player_Number8              (Player_Number nr_players);
+
+	/// Read a Player_Number from the file. Use this when the result can only be
+	/// the number of an existing player or 0 (neutral).
+	///
+	/// \throws player_nonexistent when nr_players < the player number.
+	Player_Number Player_Number8_allow_null(Player_Number nr_players);
+
+	/// Reads a CString and interprets it as the name of a tribe.
+	///
+	/// \returns a pointer to the tribe description.
+	///
+	/// \throws Tribe_Nonexistent if the there is no tribe with that name.
+	const Tribe_Descr     & Tribe           (const Editor_Game_Base &);
+
+	/// Reads a CString and interprets it as the name of a tribe.
+	///
+	/// \returns 0 if the name is empty, otherwise a pointer to the tribe
+	/// description.
+	///
+	/// \throws Tribe_Nonexistent if the name is not empty and there is no tribe
+	/// with that name.
+	Tribe_Descr     const * Tribe_allow_null(const Editor_Game_Base &);
+
+	/// Reads a CString and interprets t as the name of an immovable type.
+	///
+	/// \returns a reference to the immovable type description.
+	///
+	/// \throws Immovable_Nonexistent if there is no imovable type with that
+	/// name in the World.
+	const Immovable_Descr & Immovable_Type  (const World            &);
+
+	/// Reads a CString and interprets t as the name of an immovable type.
+	///
+	/// \returns a reference to the immovable type description.
+	///
+	/// \throws Immovable_Nonexistent if there is no imovable type with that
+	/// name in the tribe.
+	const Immovable_Descr & Immovable_Type  (const Tribe_Descr      &);
+
+	/// Reads a CString and interprets t as the name of an immovable type.
+	///
+	/// \returns a reference to the building type description.
+	///
+	/// \throws Building_Nonexistent if there is no building type with that
+	/// name in the tribe.
+	const Building_Descr  & Building_Type   (const Tribe_Descr      &);
+
+	/// Calls Tribe(const Editor_Game_Base &) to read a tribe and then reads a
+	/// CString and interprets it as the name of a building type in that tribe.
+	///
+	/// \returns a reference to the building type description.
+	const Building_Descr  & Building_Type   (const Editor_Game_Base &);
+
+	/// Calls Tribe_allow_null(const Editor_Game_Base &). If it returns a tribe,
+	/// Immovable_Type(const Tribe_Descr &) is called with that tribe and the
+	/// result is returned. Otherwise Immovable_Type(const World &) is called
+	/// and the result is returned.
+	const Immovable_Descr & Immovable_Type  (const Editor_Game_Base &);
+};
+
+inline Direction StreamRead::Direction8() {
+	uint8_t const d = Unsigned8();
+	if (d == 0)
+		throw direction_is_null();
+	if (6 < d)
+		throw direction_invalid(d);
+	return d;
+}
+
+inline Direction StreamRead::Direction8_allow_null() {
+	uint8_t const d = Unsigned8();
+	if (6 < d)
+		throw direction_invalid(d);
+	return d;
+}
+
+inline Map_Index StreamRead::Map_Index32(Map_Index const max) {
+	uint32_t const i = Unsigned32();
+	if (max <= i)
+		throw exceeded_max_index(max, i);
+	return i;
+}
+
+inline Coords StreamRead::Coords32(const Extent & extent) {
+	uint16_t const x = Unsigned16();
+	uint16_t const y = Unsigned16();
+	if (extent.w <= x)
+		throw exceeded_width (extent.w, x);
+	if (extent.h <= y)
+		throw exceeded_height(extent.h, y);
+	return Coords(x, y);
+}
+
+inline Coords StreamRead::Coords32_allow_null(const Extent & extent) {
+	uint16_t const x = Unsigned16();
+	uint16_t const y = Unsigned16();
+	const Coords result(x, y);
+	if (result) {
+		if (extent.w <= x)
+			throw exceeded_width (extent.w, x);
+		if (extent.h <= y)
+			throw exceeded_height(extent.h, y);
+	}
+	return result;
+}
+
+inline Coords StreamRead::Coords32() {
+	uint16_t const x = Unsigned16();
+	uint16_t const y = Unsigned16();
+	return Coords(x, y);
+}
+
+inline Area<Coords, uint16_t> StreamRead::Area48(const Extent & extent) {
+	Coords   const c =   Coords32(extent);
+	uint16_t const r = Unsigned16();
+	return Area<Coords, uint16_t>(c, r);
+}
+
+inline Player_Number StreamRead::Player_Number8_allow_null
+	(Player_Number const nr_players)
+{
+	Player_Number const p = Player_Number8();
+	if (nr_players < p)
+		throw player_nonexistent(nr_players, p);
+	return p;
+}
+
+inline Player_Number StreamRead::Player_Number8(Player_Number const nr_players)
+{
+	Player_Number const p = Player_Number8_allow_null(nr_players);
+	if (p == 0)
+		throw player_nonexistent(nr_players, 0);
+	return p;
+}
+
+}
+
+#endif

=== added file 'src/logic/widelands_streamread_inlines.h.THIS'
--- src/logic/widelands_streamread_inlines.h.THIS	1970-01-01 00:00:00 +0000
+++ src/logic/widelands_streamread_inlines.h.THIS	2014-06-10 18:27:45 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2008 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef WIDELANDS_STREAMREAD_INLINES_H
+#define WIDELANDS_STREAMREAD_INLINES_H
+
+#include "logic/immovable.h"
+#include "logic/widelands_streamread.h"
+#include "logic/world/world.h"
+
+namespace Widelands {
+
+inline const Tribe_Descr & StreamRead::Tribe
+	(const Editor_Game_Base & egbase)
+{
+	char const * const name = CString();
+	if (Tribe_Descr const * const result = egbase.get_tribe(name))
+		return *result;
+	else
+		throw tribe_nonexistent(name);
+}
+
+inline Tribe_Descr const * StreamRead::Tribe_allow_null
+	(const Editor_Game_Base & egbase)
+{
+	char const * const name = CString();
+	if (*name)
+		if (Tribe_Descr const * const result = egbase.get_tribe(name))
+			return result;
+		else
+			throw tribe_nonexistent(name);
+	else
+		return nullptr;
+}
+
+inline const Immovable_Descr & StreamRead::Immovable_Type
+	(const World & world)
+{
+	char const * const name = CString();
+	int32_t const index = world.get_immovable_index(name);
+	if (index == -1)
+		throw world_immovable_nonexistent(name);
+	return *world.get_immovable_descr(index);
+}
+
+inline const Immovable_Descr & StreamRead::Immovable_Type
+	(const Editor_Game_Base & egbase)
+{
+	if (Tribe_Descr const * const tribe = Tribe_allow_null(egbase))
+		return Immovable_Type(*tribe);
+	else
+		return Immovable_Type(egbase.world());
+}
+
+inline const Building_Descr  & StreamRead::Building_Type
+	(const Tribe_Descr & tribe)
+{
+	char const * const name = CString();
+	Building_Index const index = tribe.building_index(name);
+	if (index == INVALID_INDEX)
+		throw building_nonexistent(tribe.name(), name);
+	return *tribe.get_building_descr(index);
+}
+
+inline const Building_Descr & StreamRead::Building_Type
+	(const Editor_Game_Base & egbase)
+{
+	return Building_Type(Tribe(egbase));
+}
+
+}
+
+#endif

=== modified file 'src/logic/worker.cc'
--- src/logic/worker.cc	2014-05-11 07:38:01 +0000
+++ src/logic/worker.cc	2014-06-10 18:27:45 +0000
@@ -48,6 +48,9 @@
 #include "logic/tribe.h"
 #include "logic/warehouse.h"
 #include "logic/worker_program.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 #include "map_io/widelands_map_map_object_loader.h"
 #include "map_io/widelands_map_map_object_saver.h"
 #include "profile/profile.h"
@@ -106,7 +109,7 @@
 
 	//Make sure that the specified resource is available in this world
 	Resource_Index const res =
-		map.get_world()->get_resource(action.sparam1.c_str());
+		game.world().get_resource(action.sparam1.c_str());
 	if (static_cast<int8_t>(res) == -1) //  FIXME ARGH!!
 		throw game_data_error
 			(_
@@ -211,7 +214,7 @@
 
 	//Make sure that the specified resource is available in this world
 	Resource_Index const res =
-		map.get_world()->get_resource(action.sparam1.c_str());
+		game.world().get_resource(action.sparam1.c_str());
 	if (static_cast<int8_t>(res) == -1) //  FIXME ARGH!!
 		throw game_data_error
 			(_
@@ -344,7 +347,7 @@
 
 	state.ivar2 =
 		state.svar1 == "world" ?
-		game.map().world().get_bob(bob.c_str())
+		game.world().get_bob(bob.c_str())
 		:
 		descr ().tribe().get_bob(bob.c_str());
 
@@ -540,7 +543,7 @@
 {
 	std::vector<Coords> list;
 	Map & map = game.map();
-	World * const w = &map.world();
+	const World& world = game.world();
 
 	CheckStepDefault cstep(descr().movecaps());
 
@@ -552,10 +555,10 @@
 		if (action.iparam4)
 			functor.add
 				(FindNodeResourceBreedable
-				 	(w->get_resource(action.sparam1.c_str())));
+				 	(world.get_resource(action.sparam1.c_str())));
 		else
 			functor.add
-				(FindNodeResource(w->get_resource(action.sparam1.c_str())));
+				(FindNodeResource(world.get_resource(action.sparam1.c_str())));
 	}
 
 	if (action.iparam5 > -1)
@@ -601,7 +604,7 @@
 	if (res_type == "stone") res_type = "granit";
 
 	// Translate the Resource name (if it is defined by the world)
-	const World & world = game.map().world();
+	const World & world = game.world();
 	int32_t residx = world.get_resource(res_type.c_str());
 	if (residx != -1)
 		res_type = world.get_resource(residx)->descname();
@@ -807,10 +810,10 @@
 		if (list.size() == 1) {
 			state.svar1 = "world";
 			immovable = list[0];
-			state.ivar2 = map.world().get_immovable_index(immovable.c_str());
+			state.ivar2 = game.world().get_immovable_index(immovable.c_str());
 			if (state.ivar2 > 0) {
 				Immovable_Descr const * imm =
-					map.world().get_immovable_descr(state.ivar2);
+					game.world().get_immovable_descr(state.ivar2);
 				uint32_t suits = imm->terrain_suitability(fpos, map);
 				// Remove existing, if this immovable suits better
 				if (suits > terrain_suitability) {
@@ -939,23 +942,25 @@
 	const Map & map = game.map();
 	const FCoords position = map.get_fcoords(get_position());
 	BaseImmovable const * const imm = position.field->get_immovable();
-	const World & world = map.world();
+	const World & world = game.world();
 
 	if (imm && imm->get_size() > BaseImmovable::NONE) {
 		//NoLog("  Field is no longer empty\n");
 	} else if
-		(const Resource_Descr * const rdescr =
+		(const ResourceDescription * const rdescr =
 		 	world.get_resource(position.field->get_resources()))
 	{
 		// Geologist also sends a message notifying the player
-		if (rdescr->is_detectable() && position.field->get_resources_amount()) {
+		if (rdescr->detectable() && position.field->get_resources_amount()) {
 			char message[1024];
-			snprintf
-				(message, sizeof(message),
-				 "<rt image=%sresources/%s_1f.png>"
-				 "<p font-size=14 font-face=DejaVuSerif>%s</p></rt>",
-				 world.basedir().c_str(), rdescr->name().c_str(),
-				 _("A geologist found resources."));
+			// TODO(sirver): this is very wrong: It assumes a directory layout
+			// that might not be around forever.
+			snprintf(message,
+			         sizeof(message),
+			         "<rt image=world/resources/%s_1f.png>"
+			         "<p font-size=14 font-face=DejaVuSerif>%s</p></rt>",
+			         rdescr->name().c_str(),
+			         _("A geologist found resources."));
 
 			//  We should add a message to the player's message queue - but only,
 			//  if there is not already a similar one in list.
@@ -977,7 +982,7 @@
 			(position,
 			 t.get_resource_indicator
 			 	(rdescr,
-			 	 rdescr->is_detectable() ?
+			 	 rdescr->detectable() ?
 			 	 position.field->get_resources_amount() : 0),
 			 &t);
 	}
@@ -2664,7 +2669,7 @@
 
 	//
 	Map & map = game.map();
-	const World & world = map.world();
+	const World & world = game.world();
 	Area<FCoords> owner_area
 		(map.get_fcoords
 		 	(ref_cast<Flag, PlayerImmovable>(*get_location(game)).get_position()),
@@ -2701,11 +2706,11 @@
 			bool is_center_mountain =
 				(world.terrain_descr(owner_area.field->terrain_d()).get_is()
 				 &
-				 TERRAIN_MOUNTAIN)
+				 TerrainDescription::MOUNTAIN)
 				|
 				(world.terrain_descr(owner_area.field->terrain_r()).get_is()
 				 &
-				 TERRAIN_MOUNTAIN);
+				 TerrainDescription::MOUNTAIN);
 			// Only run towards fields that are on a mountain (or not)
 			// depending on position of center
 			bool is_target_mountain;
@@ -2718,11 +2723,11 @@
 				is_target_mountain =
 					(world.terrain_descr(target.field->terrain_d()).get_is()
 					 &
-					 TERRAIN_MOUNTAIN)
+					 TerrainDescription::MOUNTAIN)
 					|
 					(world.terrain_descr(target.field->terrain_r()).get_is()
 					 &
-					 TERRAIN_MOUNTAIN);
+					 TerrainDescription::MOUNTAIN);
 				if (i == 0)
 					i = list.size();
 				--i;

=== modified file 'src/logic/worker.h'
--- src/logic/worker.h	2014-04-21 09:19:14 +0000
+++ src/logic/worker.h	2014-06-10 18:27:45 +0000
@@ -89,7 +89,6 @@
 	const Image* icon() const {return descr().icon();}
 	Ware_Index becomes() const {return descr().becomes();}
 	Ware_Index worker_index() const {return descr().worker_index();}
-	const Tribe_Descr * get_tribe() const {return descr().get_tribe();}
 	const Tribe_Descr & tribe() const {return descr().tribe();}
 	const std::string & descname() const {return descr().descname();}
 

=== modified file 'src/logic/worker_descr.cc'
--- src/logic/worker_descr.cc	2014-04-21 10:00:16 +0000
+++ src/logic/worker_descr.cc	2014-06-10 18:27:45 +0000
@@ -23,6 +23,7 @@
 #include "helper.h"
 #include "i18n.h"
 #include "logic/carrier.h"
+#include "logic/game_data_error.h"
 #include "logic/nodecaps.h"
 #include "logic/soldier.h"
 #include "logic/tribe.h"
@@ -40,7 +41,7 @@
 	 const std::string & directory, Profile & prof, Section & global_s,
 	 const Tribe_Descr & _tribe)
 	:
-	BobDescr(_name, _descname, directory, prof, global_s, &_tribe),
+	BobDescr(_name, _descname, &_tribe),
 	m_helptext(global_s.get_string("help", "")),
 	m_ware_hotspot(global_s.get_Point("ware_hotspot", Point(0, 15))),
 	m_icon_fname(directory + "/menu.png"),
@@ -49,6 +50,11 @@
 	m_level_experience(-1),
 	m_becomes (INVALID_INDEX)
 {
+	{ //  global options
+		Section & idle_s = prof.get_safe_section("idle");
+		add_animation("idle", g_gr->animations().load(directory, idle_s));
+	}
+
 	add_attribute(Map_Object::WORKER);
 
 	m_default_target_quantity =
@@ -132,6 +138,11 @@
 	}
 }
 
+const Tribe_Descr& Worker_Descr::tribe() const {
+	const Tribe_Descr* owner_tribe = get_owner_tribe();
+	assert(owner_tribe != nullptr);
+	return *owner_tribe;
+}
 
 /**
  * Load graphics (other than animations).

=== modified file 'src/logic/worker_descr.h'
--- src/logic/worker_descr.h	2014-05-11 07:38:01 +0000
+++ src/logic/worker_descr.h	2014-06-10 18:27:45 +0000
@@ -65,8 +65,9 @@
 		return m_buildcost;
 	}
 
-	const Tribe_Descr * get_tribe() const {return m_owner_tribe;}
-	const Tribe_Descr & tribe() const {return *m_owner_tribe;}
+	// The tribe in which this worker is defined.
+	const Tribe_Descr & tribe() const;
+
 	std::string helptext() const {return m_helptext;}
 	Point get_ware_hotspot() const {return m_ware_hotspot;}
 

=== modified file 'src/logic/worker_program.cc'
--- src/logic/worker_program.cc	2014-04-21 09:19:14 +0000
+++ src/logic/worker_program.cc	2014-06-10 18:27:45 +0000
@@ -502,8 +502,8 @@
 /**
  * plant \<immmovable type\> \<immovable type\> ... [unless object]
  *
- * Plant one of the given immovables on the current position.
- * Decision is made with inclusion of the terrain affinity.
+ * Plant one of the given immovables on the current position taking into
+ * account the fertility of the area.
  *
  * sparamv  list of object names
  * iparam1  one of plantXXX

=== added directory 'src/logic/world'
=== added file 'src/logic/world/editor_category.cc'
--- src/logic/world/editor_category.cc	1970-01-01 00:00:00 +0000
+++ src/logic/world/editor_category.cc	2014-06-10 18:27:45 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "logic/world/editor_category.h"
+
+#include "graphic/graphic.h"
+#include "scripting/lua_table.h"
+
+namespace Widelands {
+
+EditorCategory::EditorCategory(const LuaTable& table)
+   : name_(table.get_string("name")),
+     descname_(table.get_string("descname")),
+     image_file_(table.get_string("picture")) {
+}
+
+const std::string& EditorCategory::name() const {
+	return name_;
+}
+
+const std::string& EditorCategory::descname() const {
+	return descname_;
+}
+
+const Image* EditorCategory::picture() const {
+	const Image* image = g_gr->images().get(image_file_);
+	assert(image);
+	return image;
+}
+
+}  // namespace Widelands

=== added file 'src/logic/world/editor_category.h'
--- src/logic/world/editor_category.h	1970-01-01 00:00:00 +0000
+++ src/logic/world/editor_category.h	2014-06-10 18:27:45 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef EDITOR_CATEGORY_H
+#define EDITOR_CATEGORY_H
+
+#include <string>
+
+#include <boost/noncopyable.hpp>
+
+class Image;
+class LuaTable;
+
+namespace Widelands {
+
+// Represents a category for grouping items in the Editor, so purely a UI
+// distinction and not a logical one.
+class EditorCategory : boost::noncopyable {
+public:
+	EditorCategory(const LuaTable& table);
+
+	// Internal name.
+	const std::string& name() const;
+
+	// User facing (translated) name.
+	const std::string& descname() const;
+
+	// The menu image for the category.
+	const Image* picture() const;
+
+private:
+	const std::string name_;
+	const std::string descname_;
+	const std::string image_file_;
+};
+
+}  // namespace Widelands
+
+#endif /* end of include guard: EDITOR_CATEGORY_H */

=== added file 'src/logic/world/map_gen.cc'
--- src/logic/world/map_gen.cc	1970-01-01 00:00:00 +0000
+++ src/logic/world/map_gen.cc	2014-06-10 18:27:45 +0000
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "logic/world/map_gen.h"
+
+#include <string>
+#include <vector>
+
+#include "helper.h"
+#include "logic/game_data_error.h"
+#include "logic/world/world.h"
+#include "profile/profile.h"
+#include "scripting/lua_table.h"
+
+namespace Widelands {
+
+MapGenBobCategory::MapGenBobCategory(const LuaTable& table) {
+	immovables_ = table.get_table("immovables")->array_entries<std::string>();
+	critters_ = table.get_table("critters")->array_entries<std::string>();
+}
+
+const MapGenBobCategory*
+MapGenLandResource::getBobCategory(MapGenAreaInfo::MapGenTerrainType terrType) const {
+	switch (terrType) {
+	case MapGenAreaInfo::ttLandCoast:
+		return land_coast_bob_category_;
+	case MapGenAreaInfo::ttLandLand:
+		return land_inner_bob_category_;
+	case MapGenAreaInfo::ttLandUpper:
+		return land_upper_bob_category_;
+	case MapGenAreaInfo::ttWastelandInner:
+		return wasteland_inner_bob_category_;
+	case MapGenAreaInfo::ttWastelandOuter:
+		return wasteland_outer_bob_category_;
+	default:
+		return nullptr;
+	};
+	return nullptr;
+}
+
+MapGenLandResource::MapGenLandResource(const LuaTable& table, MapGenInfo& mapGenInfo) {
+	weight_ = get_uint(table, "weight");
+
+	immovable_density_ = static_cast<uint8_t>(get_uint(table, "immovable_density"));
+	critter_density_ = static_cast<uint8_t>(get_uint(table, "critter_density"));
+
+	const auto& do_assign = [&table, &mapGenInfo](
+	   const std::string& key, const MapGenBobCategory** our_pointer) {
+		const std::string value = table.get_string(key);
+		if (value.empty()) {
+			*our_pointer = nullptr;
+			return;
+		}
+		*our_pointer = mapGenInfo.getBobCategory(value);
+	};
+
+	do_assign("land_coast_bobs", &land_coast_bob_category_);
+	do_assign("land_inner_bobs", &land_inner_bob_category_);
+	do_assign("land_upper_bobs", &land_upper_bob_category_);
+	do_assign("wasteland_inner_bobs", &wasteland_inner_bob_category_);
+	do_assign("wasteland_outer_bobs", &wasteland_outer_bob_category_);
+}
+
+MapGenAreaInfo::MapGenAreaInfo(const LuaTable& table,
+                               const World& world,
+                               MapGenAreaType const areaType) {
+	weight_ = get_positive_int(table, "weight");
+
+	const auto& read_terrains = [this, &table, &world](
+	   const std::string& key, std::vector<Terrain_Index>* list) {
+		const std::vector<std::string> terrains = table.get_table(key)->array_entries<std::string>();
+
+		for (const std::string& terrain : terrains) {
+			const Terrain_Index tix = world.terrains().get_index(terrain);
+			list->push_back(tix);
+		}
+	};
+
+	switch (areaType) {
+	case atWater:
+		read_terrains("ocean_terrains", &terrains1_);
+		read_terrains("shelf_terrains", &terrains2_);
+		read_terrains("shallow_terrains", &terrains3_);
+		break;
+	case atLand:
+		read_terrains("coast_terrains", &terrains1_);
+		read_terrains("land_terrains", &terrains2_);
+		read_terrains("upper_terrains", &terrains3_);
+		break;
+	case atMountains:
+		read_terrains("mountainfoot_terrains", &terrains1_);
+		read_terrains("mountain_terrains", &terrains2_);
+		read_terrains("snow_terrains", &terrains3_);
+		break;
+	case atWasteland:
+		read_terrains("inner_terrains", &terrains1_);
+		read_terrains("outer_terrains", &terrains2_);
+		break;
+	default:
+		throw wexception("bad areaType");
+	}
+}
+
+size_t MapGenAreaInfo::getNumTerrains(MapGenTerrainType const terrType) const {
+	switch (terrType) {
+	case ttWaterOcean:
+		return terrains1_.size();
+	case ttWaterShelf:
+		return terrains2_.size();
+	case ttWaterShallow:
+		return terrains3_.size();
+
+	case ttLandCoast:
+		return terrains1_.size();
+	case ttLandLand:
+		return terrains2_.size();
+	case ttLandUpper:
+		return terrains3_.size();
+
+	case ttWastelandInner:
+		return terrains1_.size();
+	case ttWastelandOuter:
+		return terrains2_.size();
+
+	case ttMountainsFoot:
+		return terrains1_.size();
+	case ttMountainsMountain:
+		return terrains2_.size();
+	case ttMountainsSnow:
+		return terrains3_.size();
+
+	default:
+		return 0;
+	}
+}
+
+Terrain_Index MapGenAreaInfo::getTerrain(MapGenTerrainType const terrType,
+                                         uint32_t const index) const {
+	switch (terrType) {
+	case ttWaterOcean:
+		return terrains1_[index];
+	case ttWaterShelf:
+		return terrains2_[index];
+	case ttWaterShallow:
+		return terrains3_[index];
+
+	case ttLandCoast:
+		return terrains1_[index];
+	case ttLandLand:
+		return terrains2_[index];
+	case ttLandUpper:
+		return terrains3_[index];
+
+	case ttWastelandInner:
+		return terrains1_[index];
+	case ttWastelandOuter:
+		return terrains2_[index];
+
+	case ttMountainsFoot:
+		return terrains1_[index];
+	case ttMountainsMountain:
+		return terrains2_[index];
+	case ttMountainsSnow:
+		return terrains3_[index];
+
+	default:
+		return 0;
+	}
+}
+
+uint32_t MapGenInfo::getSumLandWeight() const {
+	if (land_weight_valid_)
+		return land_weight_;
+
+	uint32_t sum = 0;
+	for (uint32_t ix = 0; ix < getNumAreas(MapGenAreaInfo::atLand); ++ix)
+		sum += getArea(MapGenAreaInfo::atLand, ix).getWeight();
+	land_weight_ = sum;
+	land_weight_valid_ = true;
+
+	return land_weight_;
+}
+
+const MapGenLandResource& MapGenInfo::getLandResource(size_t index) const {
+	return land_resources_[index];
+}
+
+size_t MapGenInfo::getNumLandResources() const {
+	return land_resources_.size();
+}
+
+uint32_t MapGenInfo::getSumLandResourceWeight() const {
+	if (sum_bob_area_weights_valid_)
+		return sum_bob_area_weights_;
+
+	uint32_t sum = 0;
+	for (uint32_t ix = 0; ix < land_resources_.size(); ++ix)
+		sum += land_resources_[ix].getWeight();
+	sum_bob_area_weights_ = sum;
+	sum_bob_area_weights_valid_ = true;
+
+	return sum_bob_area_weights_;
+}
+
+size_t MapGenInfo::getNumAreas(MapGenAreaInfo::MapGenAreaType const areaType) const {
+	switch (areaType) {
+	case MapGenAreaInfo::atWater:
+		return water_areas_.size();
+	case MapGenAreaInfo::atLand:
+		return land_areas_.size();
+	case MapGenAreaInfo::atMountains:
+		return mountain_areas_.size();
+	case MapGenAreaInfo::atWasteland:
+		return wasteland_areas_.size();
+	default:
+		throw wexception("invalid MapGenAreaType %u", areaType);
+	}
+}
+
+const MapGenAreaInfo& MapGenInfo::getArea(MapGenAreaInfo::MapGenAreaType const areaType,
+                                          uint32_t const index) const {
+	switch (areaType) {
+	case MapGenAreaInfo::atWater:
+		return water_areas_.at(index);
+	case MapGenAreaInfo::atLand:
+		return land_areas_.at(index);
+	case MapGenAreaInfo::atMountains:
+		return mountain_areas_.at(index);
+	case MapGenAreaInfo::atWasteland:
+		return wasteland_areas_.at(index);
+	default:
+		throw wexception("invalid MapGenAreaType %u", areaType);
+	}
+}
+
+const MapGenBobCategory* MapGenInfo::getBobCategory(const std::string& bobCategory) const {
+	if (bob_categories_.find(bobCategory) == bob_categories_.end())
+		throw wexception("invalid MapGenBobCategory %s", bobCategory.c_str());
+	// Ugly workaround because at is not defined for some systems
+	// and operator[] does not fare well with constants
+	return &bob_categories_.find(bobCategory)->second;
+}
+
+MapGenInfo::MapGenInfo(const LuaTable& table, const World& world) {
+	land_weight_valid_ = false;
+	sum_bob_area_weights_valid_ = false;
+
+	{  //  find out about the general heights
+		std::unique_ptr<LuaTable> heights(table.get_table("heights"));
+		ocean_height_ = get_uint(*heights, "ocean");
+		shelf_height_ = get_uint(*heights, "shelf");
+		shallow_height_ = get_uint(*heights, "shallow");
+		coast_height_ = get_uint(*heights, "coast");
+		upperland_height_ = get_uint(*heights, "upperland");
+		mountainfoot_height_ = get_uint(*heights, "mountainfoot");
+		mountain_height_ = get_uint(*heights, "mountain");
+		snow_height_ = get_uint(*heights, "snow");
+		summit_height_ = get_uint(*heights, "summit");
+	}
+
+	//  read the areas.
+	{
+		std::unique_ptr<LuaTable> areas(table.get_table("areas"));
+
+		const auto read_area = [&world, &areas](const std::string& area_name,
+		                                        const MapGenAreaInfo::MapGenAreaType area_type,
+		                                        std::vector<MapGenAreaInfo>* area_vector) {
+			std::unique_ptr<LuaTable> area(areas->get_table(area_name));
+			std::vector<std::unique_ptr<LuaTable>> entries =
+			   area->array_entries<std::unique_ptr<LuaTable>>();
+			for (std::unique_ptr<LuaTable>& entry : entries) {
+				entry->get_string("name");  // name is only for debugging really. Touch it so LuaTable
+				                            // will not complain.
+				area_vector->push_back(MapGenAreaInfo(*entry, world, area_type));
+			}
+		};
+
+		read_area("water", MapGenAreaInfo::atWater, &water_areas_);
+		read_area("land", MapGenAreaInfo::atLand, &land_areas_);
+		read_area("wasteland", MapGenAreaInfo::atWasteland, &wasteland_areas_);
+		read_area("mountains", MapGenAreaInfo::atMountains, &mountain_areas_);
+	}
+
+	// read the bobs.
+	{
+		std::unique_ptr<LuaTable> bobs(table.get_table("bob_categories"));
+
+		for (std::unique_ptr<LuaTable>& entry : bobs->array_entries<std::unique_ptr<LuaTable>>()) {
+			bob_categories_.insert(
+			   std::make_pair(entry->get_string("name"), MapGenBobCategory(*entry)));
+			MapGenBobCategory& category = bob_categories_.at(entry->get_string("name"));
+
+			for (size_t jx = 0; jx < category.num_immovables(); jx++)
+				if (world.get_immovable_index(category.get_immovable(jx).c_str()) < 0)
+					throw wexception("unknown immovable %s", category.get_immovable(jx).c_str());
+
+			for (size_t jx = 0; jx < category.num_critters(); jx++)
+				if (world.get_bob(category.get_critter(jx).c_str()) < 0)
+					throw wexception("unknown moveable %s", category.get_critter(jx).c_str());
+		}
+	}
+
+	// read the land resources.
+	{
+		std::unique_ptr<LuaTable> land_resources(table.get_table("land_resources"));
+
+		for (std::unique_ptr<LuaTable>& entry :
+		     land_resources->array_entries<std::unique_ptr<LuaTable>>()) {
+			entry->get_string(
+			   "name");  // name is only for debugging really. Touch it so LuaTable will not complain.
+			land_resources_.push_back(MapGenLandResource(*entry, *this));
+		}
+	}
+
+	if (getNumAreas(MapGenAreaInfo::atWater) < 1)
+		throw game_data_error("missing a water area");
+
+	if (getNumAreas(MapGenAreaInfo::atWater) < 1)
+		throw game_data_error("too many water areas (>3)");
+
+	if (getNumAreas(MapGenAreaInfo::atLand) < 1)
+		throw game_data_error("missing a land area");
+
+	if (getNumAreas(MapGenAreaInfo::atLand) > 3)
+		throw game_data_error("too many land areas (>3)");
+
+	if (getNumAreas(MapGenAreaInfo::atWasteland) < 1)
+		throw game_data_error("missing a wasteland area");
+
+	if (getNumAreas(MapGenAreaInfo::atWasteland) > 2)
+		throw game_data_error("too many wasteland areas (>2)");
+
+	if (getNumAreas(MapGenAreaInfo::atMountains) < 1)
+		throw game_data_error("missing a mountain area");
+
+	if (getNumAreas(MapGenAreaInfo::atMountains) < 1)
+		throw game_data_error("too many mountain areas (>1)");
+
+	if (getArea(MapGenAreaInfo::atWater, 0).getNumTerrains(MapGenAreaInfo::ttWaterOcean) < 1)
+		throw game_data_error("missing a water/ocean terrain type");
+
+	if (getArea(MapGenAreaInfo::atWater, 0).getNumTerrains(MapGenAreaInfo::ttWaterShelf) < 1)
+		throw game_data_error("missing a water/shelf terrain type");
+
+	if (getArea(MapGenAreaInfo::atWater, 0).getNumTerrains(MapGenAreaInfo::ttWaterShallow) < 1)
+		throw game_data_error("is missing a water/shallow terrain type");
+
+	if (getArea(MapGenAreaInfo::atLand, 0).getNumTerrains(MapGenAreaInfo::ttLandCoast) < 1)
+		throw game_data_error("missing a land/coast terrain type");
+
+	if (getArea(MapGenAreaInfo::atLand, 0).getNumTerrains(MapGenAreaInfo::ttLandLand) < 1)
+		throw game_data_error("missing a land/land terrain type");
+
+	if (getArea(MapGenAreaInfo::atMountains, 0).getNumTerrains(MapGenAreaInfo::ttMountainsFoot) < 1)
+		throw game_data_error("missing a mountain/foot terrain type");
+
+	if (getArea(MapGenAreaInfo::atMountains, 0).getNumTerrains(MapGenAreaInfo::ttMountainsMountain) <
+	    1)
+		throw game_data_error("missing a monutain/mountain terrain type");
+
+	if (getArea(MapGenAreaInfo::atMountains, 0).getNumTerrains(MapGenAreaInfo::ttMountainsSnow) < 1)
+		throw game_data_error("missing a mountain/snow terrain type");
+
+	if (getArea(MapGenAreaInfo::atWasteland, 0).getNumTerrains(MapGenAreaInfo::ttWastelandInner) < 1)
+		throw game_data_error("missing a land/coast terrain type");
+
+	if (getArea(MapGenAreaInfo::atWasteland, 0).getNumTerrains(MapGenAreaInfo::ttWastelandOuter) < 1)
+		throw game_data_error("missing a land/land terrain type");
+}
+
+}  // namespace Widelands

=== added file 'src/logic/world/map_gen.h'
--- src/logic/world/map_gen.h	1970-01-01 00:00:00 +0000
+++ src/logic/world/map_gen.h	2014-06-10 18:27:45 +0000
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef MAP_GEN_H
+#define MAP_GEN_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "logic/world/terrain_description.h"
+
+class LuaTable;
+
+namespace Widelands {
+
+class World;
+struct MapGenInfo;
+
+/// Holds world and area specific information for the map generator.
+/// Areas are: Water, Land, Wasteland and Mountains.
+struct MapGenAreaInfo {
+	enum MapGenAreaType {
+		atWater,
+		atLand,
+		atWasteland,
+		atMountains
+	};
+
+	enum MapGenTerrainType {
+		ttWaterOcean,
+		ttWaterShelf,
+		ttWaterShallow,
+
+		ttLandCoast,
+		ttLandLand,
+		ttLandUpper,
+
+		ttWastelandInner,
+		ttWastelandOuter,
+
+		ttMountainsFoot,
+		ttMountainsMountain,
+		ttMountainsSnow
+	};
+
+	MapGenAreaInfo(const LuaTable& table, const World& world, MapGenAreaType areaType);
+
+	size_t getNumTerrains(MapGenTerrainType) const;
+	Terrain_Index getTerrain(MapGenTerrainType terrType, uint32_t index) const;
+	uint32_t getWeight() const {return weight_;}
+
+private:
+	std::vector<Terrain_Index>  terrains1_; //  ocean, coast, inner or foot
+	std::vector<Terrain_Index>  terrains2_; //  shelf, land, outer or mountain
+	std::vector<Terrain_Index>  terrains3_; //  shallow, upper, snow
+
+	uint32_t weight_;
+	MapGenAreaType areaType_;
+};
+
+struct MapGenBobCategory {
+	MapGenBobCategory(const LuaTable& table);
+
+	size_t num_immovables() const {return immovables_.size();}
+	size_t num_critters() const {return critters_.size();}
+
+	const std::string & get_immovable(size_t index) const {
+		return immovables_[index];
+	};
+	const std::string & get_critter(size_t index) const {
+		return critters_[index];
+	};
+
+private:
+	std::vector<std::string> immovables_;
+	std::vector<std::string> critters_;
+};
+
+struct MapGenLandResource {
+	MapGenLandResource(const LuaTable& table, MapGenInfo& mapGenInfo);
+
+	uint32_t getWeight() const {return weight_;};
+	const MapGenBobCategory * getBobCategory
+		(MapGenAreaInfo::MapGenTerrainType terrType) const;
+
+	uint8_t getImmovableDensity() const {return immovable_density_;};
+	uint8_t getMoveableDensity() const {return critter_density_;};
+
+private:
+	uint32_t        weight_;
+	uint8_t         immovable_density_; // In percent
+	uint8_t         critter_density_;  // In percent
+	const MapGenBobCategory * land_coast_bob_category_;
+	const MapGenBobCategory * land_inner_bob_category_;
+	const MapGenBobCategory * land_upper_bob_category_;
+	const MapGenBobCategory * wasteland_inner_bob_category_;
+	const MapGenBobCategory * wasteland_outer_bob_category_;
+};
+
+/** struct MapGenInfo
+  *
+  * This class holds world specific information for the map generator.
+  * This info is usually read from the file "mapgeninfo" of a world.
+  */
+struct MapGenInfo {
+	MapGenInfo(const LuaTable& table, const World& world);
+
+	size_t getNumAreas(MapGenAreaInfo::MapGenAreaType areaType) const;
+	const MapGenAreaInfo & getArea
+		(MapGenAreaInfo::MapGenAreaType const areaType, uint32_t const index)
+		const;
+	const MapGenBobCategory * getBobCategory(const std::string & bobCategory) const;
+
+	uint8_t getWaterOceanHeight  () const {return ocean_height_;}
+	uint8_t getWaterShelfHeight  () const {return shelf_height_;}
+	uint8_t getWaterShallowHeight() const {return shallow_height_;}
+	uint8_t getLandCoastHeight   () const {return coast_height_;}
+	uint8_t getLandUpperHeight   () const {return upperland_height_;}
+	uint8_t getMountainFootHeight() const {return mountainfoot_height_;}
+	uint8_t getMountainHeight    () const {return mountain_height_;}
+	uint8_t getSnowHeight        () const {return snow_height_;}
+	uint8_t getSummitHeight      () const {return summit_height_;}
+
+	uint32_t getSumLandWeight() const;
+
+	size_t getNumLandResources() const;
+	const MapGenLandResource & getLandResource(size_t index) const;
+	uint32_t getSumLandResourceWeight() const;
+
+private:
+	std::vector<MapGenAreaInfo> water_areas_;
+	std::vector<MapGenAreaInfo> land_areas_;
+	std::vector<MapGenAreaInfo> wasteland_areas_;
+	std::vector<MapGenAreaInfo> mountain_areas_;
+
+	std::vector<MapGenLandResource>           land_resources_;
+	std::map<std::string, MapGenBobCategory> bob_categories_;
+
+	uint8_t ocean_height_;
+	uint8_t shelf_height_;
+	uint8_t shallow_height_;
+	uint8_t coast_height_;
+	uint8_t upperland_height_;
+	uint8_t mountainfoot_height_;
+	uint8_t snow_height_;
+	uint8_t mountain_height_;
+	uint8_t summit_height_;
+
+	mutable int32_t  land_weight_;
+	mutable bool land_weight_valid_;
+
+	mutable int32_t sum_bob_area_weights_;
+	mutable bool sum_bob_area_weights_valid_;
+
+};
+
+}  // namespace Widelands
+
+#endif /* end of include guard: MAP_GEN_H */

=== added file 'src/logic/world/resource_description.cc'
--- src/logic/world/resource_description.cc	1970-01-01 00:00:00 +0000
+++ src/logic/world/resource_description.cc	2014-06-10 18:27:45 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "logic/world/resource_description.h"
+
+#include "helper.h"
+#include "log.h"
+#include "logic/game_data_error.h"
+#include "profile/profile.h"
+#include "scripting/lua_table.h"
+
+namespace Widelands {
+
+ResourceDescription::ResourceDescription(const LuaTable& table)
+   : name_(table.get_string("name")),
+     descname_(table.get_string("descname")),
+     detectable_(table.get_bool("detectable")),
+     max_amount_(table.get_int("max_amount")) {
+
+	std::unique_ptr<LuaTable> st = table.get_table("editor_pictures");
+	const std::set<int> keys = st->keys<int>();
+	for (int upper_limit : keys) {
+		ResourceDescription::EditorPicture editor_picture = {st->get_string(upper_limit), upper_limit};
+		editor_pictures_.push_back(editor_picture);
+	}
+	if (editor_pictures_.empty()) {
+		throw game_data_error("Resource %s has no editor_pictures.", name_.c_str());
+	}
+}
+
+const std::string & ResourceDescription::get_editor_pic
+	(uint32_t const amount) const
+{
+	uint32_t bestmatch = 0;
+
+	assert(editor_pictures_.size());
+
+	for (uint32_t i = 1; i < editor_pictures_.size(); ++i) {
+		const int32_t diff1 =
+			editor_pictures_[bestmatch].upper_limit - static_cast<int32_t>(amount);
+		const int32_t diff2 =
+			editor_pictures_[i].upper_limit - static_cast<int32_t>(amount);
+
+		// This is a catch-all for high amounts
+		if (editor_pictures_[i].upper_limit < 0)
+		{
+			if (diff1 < 0) {
+				bestmatch = i;
+				continue;
+			}
+
+			continue;
+		}
+
+		// This is lower than the actual amount
+		if (diff2 < 0)
+		{
+			if (editor_pictures_[bestmatch].upper_limit < 0)
+				continue;
+
+			if (diff1 < diff2) {
+				bestmatch = i; // still better than previous best match
+				continue;
+			}
+
+			continue;
+		}
+
+		// This is higher than the actual amount
+		if
+			(editor_pictures_[bestmatch].upper_limit < 0     ||
+			 diff2                               < diff1 ||
+			 diff1                               < 0)
+		{
+			bestmatch = i;
+			continue;
+		}
+	}
+
+	//noLog("Resource(%s): Editor_Pic '%s' for amount = %u\n",
+	//name_.c_str(), editor_pictures_[bestmatch].picname.c_str(), amount);
+
+	return editor_pictures_[bestmatch].picname;
+}
+
+const std::string& ResourceDescription::name() const {
+	return name_;
+}
+
+const std::string& ResourceDescription::descname() const {
+	return descname_;
+}
+
+bool ResourceDescription::detectable() const {
+	return detectable_;
+}
+
+int32_t ResourceDescription::max_amount() const {
+	return max_amount_;
+}
+
+
+}  // namespace Widelands

=== added file 'src/logic/world/resource_description.h'
--- src/logic/world/resource_description.h	1970-01-01 00:00:00 +0000
+++ src/logic/world/resource_description.h	2014-06-10 18:27:45 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef RESOURCE_DESCRIPTION_H
+#define RESOURCE_DESCRIPTION_H
+
+#include <string>
+#include <vector>
+
+#include <boost/noncopyable.hpp>
+
+#include "logic/widelands.h"
+
+class LuaTable;
+
+namespace Widelands {
+
+class ResourceDescription : boost::noncopyable {
+public:
+	struct EditorPicture {
+		std::string picname;
+		int upper_limit;
+	};
+
+	ResourceDescription(const LuaTable& table);
+
+	// Returns the in engine name of this resource.
+	const std::string& name() const;
+
+	// Returns the name of this resource for users. Usually translated.
+	const std::string& descname() const;
+
+	// Returns if this resource is detectable by a geologist.
+	bool detectable() const;
+
+	// Returns the maximum amount that can be in a field for this resource.
+	int32_t max_amount() const;
+
+	// Returns the path to the image that should be used in the editor to
+	// represent an 'amount' of this resource.
+	const std::string& get_editor_pic(uint32_t amount) const;
+
+private:
+	const std::string name_;
+	const std::string descname_;
+	const bool detectable_;
+	const int32_t max_amount_;
+	std::vector<EditorPicture> editor_pictures_;
+};
+
+}  // namespace Widelands
+
+#endif /* end of include guard: RESOURCE_DESCRIPTION_H */

=== added file 'src/logic/world/terrain_description.cc'
--- src/logic/world/terrain_description.cc	1970-01-01 00:00:00 +0000
+++ src/logic/world/terrain_description.cc	2014-06-10 18:27:45 +0000
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "logic/world/terrain_description.h"
+
+#include <boost/format.hpp>
+
+#include "constants.h"
+#include "graphic/graphic.h"
+#include "logic/game_data_error.h"
+#include "logic/world/editor_category.h"
+#include "logic/world/world.h"
+#include "profile/profile.h"
+#include "scripting/lua_table.h"
+
+namespace Widelands {
+
+namespace  {
+
+// Parse a terrain type from the giving string.
+TerrainDescription::Type TerrainTypeFromString(const std::string& type) {
+	if (type == "green") {
+		return TerrainDescription::GREEN;
+	}
+	if (type == "dry") {
+		return TerrainDescription::DRY;
+	}
+	if (type == "water") {
+		return static_cast<TerrainDescription::Type>(
+		   TerrainDescription::WATER | TerrainDescription::DRY | TerrainDescription::UNPASSABLE);
+	}
+	if (type == "acid") {
+		return static_cast<TerrainDescription::Type>(
+		   TerrainDescription::ACID | TerrainDescription::DRY | TerrainDescription::UNPASSABLE);
+	}
+	if (type == "mountain") {
+		return static_cast<TerrainDescription::Type>(TerrainDescription::DRY |
+		                                             TerrainDescription::MOUNTAIN);
+	}
+	if (type == "dead") {
+		return static_cast<TerrainDescription::Type>(
+		   TerrainDescription::DRY | TerrainDescription::UNPASSABLE | TerrainDescription::ACID);
+	}
+	if (type == "unpassable") {
+		return static_cast<TerrainDescription::Type>(TerrainDescription::DRY |
+		                                             TerrainDescription::UNPASSABLE);
+	}
+	throw LuaError((boost::format("invalid terrain type '%s'") % type).str());
+}
+
+}  // namespace
+
+TerrainDescription::TerrainDescription(const LuaTable& table, const Widelands::World& world)
+   : name_(table.get_string("name")),
+     descname_(table.get_string("descname")),
+     is_(TerrainTypeFromString(table.get_string("is"))),
+     default_resource_index_(world.get_resource(table.get_string("default_resource").c_str())),
+     default_resource_amount_(table.get_int("default_resource_amount")),
+     dither_layer_(table.get_int("dither_layer")) {
+
+
+	const std::vector<std::string> textures =
+	   table.get_table("textures")->array_entries<std::string>();
+	int frame_length = FRAME_LENGTH;
+	if (textures.empty()) {
+		throw game_data_error("Terrain %s has no images.", name_.c_str());
+	} else if (textures.size() == 1) {
+		if (table.has_key("fps")) {
+			throw game_data_error("Terrain %s with one images must not have fps.", name_.c_str());
+		}
+	} else {
+		frame_length = 1000 / get_positive_int(table, "fps");
+	}
+	texture_ = g_gr->new_maptexture(textures, frame_length);
+
+	for (const std::string& resource :
+	     table.get_table("valid_resources")->array_entries<std::string>()) {
+		valid_resources_.push_back(world.safe_resource_index(resource.c_str()));
+	}
+
+	if (default_resource_amount_ > 0 && !is_resource_valid(default_resource_index_)) {
+		throw game_data_error("Default resource is not in valid resources.\n");
+	}
+
+	int editor_category =
+	   world.editor_terrain_categories().get_index(table.get_string("editor_category"));
+	if (editor_category < 0) {
+		throw game_data_error("Unknown editor_category: %s\n",
+		                      table.get_string("editor_category").c_str());
+	}
+	editor_category_ = world.editor_terrain_categories().get(editor_category);
+}
+
+TerrainDescription::~TerrainDescription() {
+}
+
+uint32_t TerrainDescription::get_texture() const {
+	return texture_;
+}
+
+TerrainDescription::Type TerrainDescription::get_is() const {
+	return is_;
+}
+
+const std::string& TerrainDescription::name() const {
+	return name_;
+}
+
+const std::string& TerrainDescription::descname() const {
+	return descname_;
+}
+
+const EditorCategory& TerrainDescription::editor_category() const {
+	return *editor_category_;
+}
+
+Resource_Index TerrainDescription::get_valid_resource(uint8_t index) const {
+	return valid_resources_[index];
+}
+
+int TerrainDescription::get_num_valid_resources() const {
+	return valid_resources_.size();
+}
+
+bool TerrainDescription::is_resource_valid(const int32_t res) const {
+	for (const uint8_t resource_index : valid_resources_) {
+		if (resource_index == res) {
+			return true;
+		}
+	}
+	return false;
+}
+
+int8_t TerrainDescription::get_default_resource() const {
+	return default_resource_index_;
+}
+
+int32_t TerrainDescription::get_default_resource_amount() const {
+	return default_resource_amount_;
+}
+
+int32_t TerrainDescription::dither_layer() const {
+	return dither_layer_;
+}
+
+}  // namespace Widelands

=== added file 'src/logic/world/terrain_description.h'
--- src/logic/world/terrain_description.h	1970-01-01 00:00:00 +0000
+++ src/logic/world/terrain_description.h	2014-06-10 18:27:45 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef TERRAIN_DESCRIPTION_H
+#define TERRAIN_DESCRIPTION_H
+
+#include <string>
+
+#include <boost/noncopyable.hpp>
+
+#include "logic/widelands.h"
+#include "logic/world/resource_description.h"
+
+class LuaTable;
+
+namespace Widelands {
+
+class EditorCategory;
+class World;
+
+class TerrainDescription : boost::noncopyable {
+public:
+	enum Type {
+		GREEN = 0,
+		DRY = 1,
+		WATER =  2,
+		ACID = 4,
+		MOUNTAIN = 8,
+		UNPASSABLE = 16,
+	};
+
+	TerrainDescription(const LuaTable& table, const World&);
+	~TerrainDescription();
+
+	// The name used internally for this terrain.
+	const std::string& name() const;
+
+	// The name showed to users of Widelands. Usually translated.
+	const std::string& descname() const;
+
+	// Returns the texture index for this terrain.
+	uint32_t get_texture() const;
+
+	// Returns the type of terrain this is (water, walkable, and so on).
+	Type get_is() const;
+
+	// Returns the valid resource with the given index.
+	Resource_Index get_valid_resource(uint8_t index) const;
+
+	// Returns the number of valid resources.
+	int get_num_valid_resources() const;
+
+	// Returns true if this resource can be found in this terrain type.
+	bool is_resource_valid(int32_t res) const;
+
+	// Returns the resource index that can by default always be found in this
+	// terrain.
+	int8_t get_default_resource() const;
+
+	// Returns the default amount of resources you can find in this terrain.
+	int32_t get_default_resource_amount() const;
+
+	// Returns the dither layer, i.e. the information in which zlayer this
+	// texture should be drawn.
+	int32_t dither_layer() const;
+
+	// Returns the editor category.
+	const EditorCategory& editor_category() const;
+
+private:
+	const std::string name_;
+	const std::string descname_;
+	const EditorCategory* editor_category_;  // not owned.
+	Type is_;
+	std::vector<uint8_t> valid_resources_;
+	int8_t default_resource_index_;
+	int32_t default_resource_amount_;
+	const std::vector<std::string> texture_paths_;
+	int32_t dither_layer_;
+	uint32_t texture_;  //  renderer's texture
+};
+
+}  // namespace Widelands
+
+#endif /* end of include guard: TERRAIN_DESCRIPTION_H */

=== renamed file 'src/logic/world.cc' => 'src/logic/world/world.cc'
--- src/logic/world.cc	2014-05-11 07:38:01 +0000
+++ src/logic/world/world.cc	2014-06-10 18:27:45 +0000
@@ -17,918 +17,131 @@
  *
  */
 
-#include "logic/world.h"
+#include "logic/world/world.h"
 
 #include <iostream>
 #include <sstream>
 
 #include "constants.h"
-#include "container_iterate.h"
 #include "graphic/graphic.h"
-#include "helper.h"
-#include "i18n.h"
-#include "io/fileread.h"
-#include "io/filesystem/layered_filesystem.h"
-#include "io/filewrite.h"
-#include "log.h"
 #include "logic/critter_bob.h"
 #include "logic/game_data_error.h"
-#include "logic/worlddata.h"
-#include "parse_map_object_types.h"
-#include "profile/profile.h"
-#include "wexception.h"
-
-using std::cerr;
-using std::endl;
-
+#include "logic/immovable.h"
+#include "logic/widelands.h"
+#include "logic/world/editor_category.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/terrain_description.h"
 
 namespace Widelands {
 
-/*
-==============
-Parse a resource description section.
-==============
-*/
-void Resource_Descr::parse(Section & s, const std::string & basedir)
-{
-	m_name = s.get_name();
-	m_descname = s.get_string("name", s.get_name());
-	m_is_detectable = s.get_bool("detectable", true);
-
-	m_max_amount = s.get_safe_int("max_amount");
-	while (Section::Value const * const v = s.get_next_val("editor_pic")) {
-		Editor_Pic i;
-
-		std::vector<std::string> const args(split_string(v->get_string(), " \t"));
-		if (args.size() != 1 and args.size() != 2) {
-			log
-				("Resource '%s' has bad editor_pic=%s\n",
-				 m_name.c_str(), v->get_string());
-			continue;
-		}
-
-		i.picname = basedir + "/pics/";
-		i.picname += args[0];
-		i.upperlimit = -1;
-
-		if (args.size() >= 2) {
-			char * endp;
-			i.upperlimit = strtol(args[1].c_str(), &endp, 0);
-
-			if (*endp) {
-				log
-					("Resource '%s' has bad editor_pic=%s\n",
-					 m_name.c_str(), v->get_string());
-				continue;
-			}
-		}
-
-		m_editor_pics.push_back(i);
-	}
-	if (m_editor_pics.empty())
-		throw game_data_error("resource '%s' has no editor_pic", m_name.c_str());
-}
-
-
-/*
- * Get the correct editor pic for this amount of this resource
- */
-const std::string & Resource_Descr::get_editor_pic
-	(uint32_t const amount) const
-{
-	uint32_t bestmatch = 0;
-
-	assert(m_editor_pics.size());
-
-	for (uint32_t i = 1; i < m_editor_pics.size(); ++i) {
-		const int32_t diff1 =
-			m_editor_pics[bestmatch].upperlimit - static_cast<int32_t>(amount);
-		const int32_t diff2 =
-			m_editor_pics[i].upperlimit - static_cast<int32_t>(amount);
-
-		// This is a catch-all for high amounts
-		if (m_editor_pics[i].upperlimit < 0)
-		{
-			if (diff1 < 0) {
-				bestmatch = i;
-				continue;
-			}
-
-			continue;
-		}
-
-		// This is lower than the actual amount
-		if (diff2 < 0)
-		{
-			if (m_editor_pics[bestmatch].upperlimit < 0)
-				continue;
-
-			if (diff1 < diff2) {
-				bestmatch = i; // still better than previous best match
-				continue;
-			}
-
-			continue;
-		}
-
-		// This is higher than the actual amount
-		if
-			(m_editor_pics[bestmatch].upperlimit < 0     ||
-			 diff2                               < diff1 ||
-			 diff1                               < 0)
-		{
-			bestmatch = i;
-			continue;
-		}
-	}
-
-	//noLog("Resource(%s): Editor_Pic '%s' for amount = %u\n",
-	//m_name.c_str(), m_editor_pics[bestmatch].picname.c_str(), amount);
-
-	return m_editor_pics[bestmatch].picname;
-}
-
-
-
-/*
-=============================================================================
-
-Map Gen Info
-
-=============================================================================
-*/
-
-void MapGenBobKind::parseSection (Section & s)
-{
-	std::string str;
-
-	str = s.get_safe_string("immovable_bobs");
-	MapGenAreaInfo::split_string(m_ImmovableBobs, str);
-
-	str = s.get_safe_string("moveable_bobs");
-	MapGenAreaInfo::split_string(m_MoveableBobs, str);
-}
-
-const MapGenBobKind * MapGenBobArea::getBobKind
-	(MapGenAreaInfo::MapGenTerrainType terrType) const
-{
-	switch (terrType)
-	{
-		case MapGenAreaInfo::ttLandCoast:
-			return m_LandCoastBobKind;
-		case MapGenAreaInfo::ttLandLand:
-			return m_LandInnerBobKind;
-		case MapGenAreaInfo::ttLandUpper:
-			return m_LandUpperBobKind;
-		case MapGenAreaInfo::ttWastelandInner:
-			return m_WastelandInnerBobKind;
-		case MapGenAreaInfo::ttWastelandOuter:
-			return m_WastelandOuterBobKind;
-		default:
-			return nullptr;
-	};
-	return nullptr;
-}
-
-void MapGenBobArea::parseSection (Section & s, MapGenInfo & mapGenInfo)
-{
-	m_Weight = s.get_int("weight", 1);
-	m_Immovable_Density =
-		static_cast<uint8_t>
-			(s.get_safe_int("immovable_density"));
-	m_Moveable_Density =
-		static_cast<uint8_t>
-			(s.get_safe_int("moveable_density"));
-
-	std::string str;
-
-	str = s.get_safe_string("land_coast_bobs");
-	m_LandCoastBobKind      = str.size() ? mapGenInfo.getBobKind(str) : nullptr;
-
-	str = s.get_safe_string("land_inner_bobs");
-	m_LandInnerBobKind      = str.size() ? mapGenInfo.getBobKind(str) : nullptr;
-
-	str = s.get_safe_string("land_upper_bobs");
-	m_LandUpperBobKind      = str.size() ? mapGenInfo.getBobKind(str) : nullptr;
-
-	str = s.get_safe_string("wasteland_inner_bobs");
-	m_WastelandInnerBobKind = str.size() ? mapGenInfo.getBobKind(str) : nullptr;
-
-	str = s.get_safe_string("wasteland_outer_bobs");
-	m_WastelandOuterBobKind = str.size() ? mapGenInfo.getBobKind(str) : nullptr;
-}
-
-int MapGenAreaInfo::split_string
-	(std::vector<std::string> & strs, std::string & str)
-{
-	strs = ::split_string(str, ",");
-	return strs.size();
-}
-
-void MapGenAreaInfo::readTerrains
-	(std::vector<Terrain_Index> &       list,
-	 Section                    &       s,
-	 char const                 * const value_name)
-{
-	std::string str = s.get_string(value_name, "");
-	if (str.empty())
-		throw game_data_error
-			("terrain info \"%s\" missing in section \"%s\" mapgenconf for world "
-			 "\"%s\"",
-			 value_name, s.get_name(), m_world->get_name());
-	std::vector<std::string> strs;
-
-	split_string(strs, str);
-
-	for (uint32_t ix = 0; ix < strs.size(); ++ix) {
-		Terrain_Index const tix = m_world->index_of_terrain(strs[ix].c_str());
-		if (tix > 128)
-			throw game_data_error
-				("unknown terrain \"%s\" in section \"%s\" in mapgenconf for "
-				 "world \"%s\"",
-				 value_name, s.get_name(), m_world->get_name());
-		list.push_back(tix);
-	}
-}
-
-
-void MapGenAreaInfo::parseSection
-	(World * const world, Section & s, MapGenAreaType const areaType)
-{
-	m_weight = s.get_positive("weight", 1);
-	m_world = world;
-	switch (areaType) {
-		case atWater:
-			readTerrains(m_Terrains1, s, "ocean_terrains");
-			readTerrains(m_Terrains2, s, "shelf_terrains");
-			readTerrains(m_Terrains3, s, "shallow_terrains");
-			break;
-		case atLand:
-			readTerrains(m_Terrains1, s, "coast_terrains");
-			readTerrains(m_Terrains2, s, "land_terrains");
-			readTerrains(m_Terrains3, s, "upper_terrains");
-			break;
-		case atMountains:
-			readTerrains(m_Terrains1, s, "mountainfoot_terrains");
-			readTerrains(m_Terrains2, s, "mountain_terrains");
-			readTerrains(m_Terrains3, s, "snow_terrains");
-			break;
-		case atWasteland:
-			readTerrains(m_Terrains1, s, "inner_terrains");
-			readTerrains(m_Terrains2, s, "outer_terrains");
-			break;
-		default:
-			throw wexception("MapGenAreaInfo::parseSection: bad areaType");
-	}
-}
-
-size_t MapGenAreaInfo::getNumTerrains(MapGenTerrainType const terrType) const
-{
-	switch (terrType) {
-		case ttWaterOcean:        return m_Terrains1.size();
-		case ttWaterShelf:        return m_Terrains2.size();
-		case ttWaterShallow:      return m_Terrains3.size();
-
-		case ttLandCoast:         return m_Terrains1.size();
-		case ttLandLand:          return m_Terrains2.size();
-		case ttLandUpper:         return m_Terrains3.size();
-
-		case ttWastelandInner:    return m_Terrains1.size();
-		case ttWastelandOuter:    return m_Terrains2.size();
-
-		case ttMountainsFoot:     return m_Terrains1.size();
-		case ttMountainsMountain: return m_Terrains2.size();
-		case ttMountainsSnow:     return m_Terrains3.size();
-
-		default:                  return 0;
-	}
-}
-
-Terrain_Index MapGenAreaInfo::getTerrain
-	(MapGenTerrainType const terrType, uint32_t const index) const
-{
-	switch (terrType) {
-		case ttWaterOcean:        return m_Terrains1[index];
-		case ttWaterShelf:        return m_Terrains2[index];
-		case ttWaterShallow:      return m_Terrains3[index];
-
-		case ttLandCoast:         return m_Terrains1[index];
-		case ttLandLand:          return m_Terrains2[index];
-		case ttLandUpper:         return m_Terrains3[index];
-
-		case ttWastelandInner:    return m_Terrains1[index];
-		case ttWastelandOuter:    return m_Terrains2[index];
-
-		case ttMountainsFoot:     return m_Terrains1[index];
-		case ttMountainsMountain: return m_Terrains2[index];
-		case ttMountainsSnow:     return m_Terrains3[index];
-
-		default:                  return 0;
-	}
-}
-
-
-uint32_t MapGenInfo::getSumLandWeight() const
-{
-	if (m_land_weight_valid)
-		return m_land_weight;
-
-	uint32_t sum = 0;
-	for (uint32_t ix = 0; ix < getNumAreas(MapGenAreaInfo::atLand); ++ix)
-		sum += getArea(MapGenAreaInfo::atLand, ix).getWeight();
-	m_land_weight = sum;
-	m_land_weight_valid = true;
-
-	return m_land_weight;
-}
-
-const MapGenBobArea & MapGenInfo::getBobArea(size_t index) const
-{
-	return m_BobAreas[index];
-}
-
-size_t MapGenInfo::getNumBobAreas() const
-{
-	return m_BobAreas.size();
-}
-
-uint32_t MapGenInfo::getSumBobAreaWeight() const
-{
-	if (m_sum_bob_area_weights_valid)
-		return m_sum_bob_area_weights;
-
-	uint32_t sum = 0;
-	for (uint32_t ix = 0; ix < m_BobAreas.size(); ++ix)
-		sum += m_BobAreas[ix].getWeight();
-	m_sum_bob_area_weights = sum;
-	m_sum_bob_area_weights_valid = true;
-
-	return m_sum_bob_area_weights;
-}
-
-size_t MapGenInfo::getNumAreas
-	(MapGenAreaInfo::MapGenAreaType const areaType) const
-{
-	switch (areaType) {
-	case MapGenAreaInfo::atWater:     return m_WaterAreas    .size();
-	case MapGenAreaInfo::atLand:      return m_LandAreas     .size();
-	case MapGenAreaInfo::atMountains: return m_MountainAreas .size();
-	case MapGenAreaInfo::atWasteland: return m_WasteLandAreas.size();
-	default:
-		throw wexception("invalid MapGenAreaType %u", areaType);
-	}
-}
-
-const MapGenAreaInfo & MapGenInfo::getArea
-	(MapGenAreaInfo::MapGenAreaType const areaType,
-	 uint32_t const index)
-	const
-{
-	switch (areaType) {
-	case MapGenAreaInfo::atWater:     return m_WaterAreas    .at(index);
-	case MapGenAreaInfo::atLand:      return m_LandAreas     .at(index);
-	case MapGenAreaInfo::atMountains: return m_MountainAreas .at(index);
-	case MapGenAreaInfo::atWasteland: return m_WasteLandAreas.at(index);
-	default:
-		throw wexception("invalid MapGenAreaType %u", areaType);
-	}
-}
-
-const MapGenBobKind * MapGenInfo::getBobKind
-	(const std::string & bobKindName) const
-{
-	if (m_BobKinds.find(bobKindName) == m_BobKinds.end())
-		throw wexception("invalid MapGenBobKind %s", bobKindName.c_str());
-	// Ugly workaround because at is not defined for some systems
-	// and operator[] does not fare well with constants
-	return & m_BobKinds.find(bobKindName)->second;
-}
-
-void MapGenInfo::parseProfile(World * const world, Profile & profile)
-{
-	m_world = world;
-	m_land_weight_valid = false;
-	m_sum_bob_area_weights_valid = false;
-
-	{ //  find out about the general heights
-		Section & s = profile.get_safe_section("heights");
-		m_ocean_height        = s.get_positive("ocean",        10);
-		m_shelf_height        = s.get_positive("shelf",        10);
-		m_shallow_height      = s.get_positive("shallow",      10);
-		m_coast_height        = s.get_positive("coast",        12);
-		m_upperland_height    = s.get_positive("upperland",    16);
-		m_mountainfoot_height = s.get_positive("mountainfoot", 18);
-		m_mountain_height     = s.get_positive("mountain",     20);
-		m_snow_height         = s.get_positive("snow",         33);
-		m_summit_height       = s.get_positive("summit",       40);
-	}
-
-
-	//  read the area names
-	Section & areas_s = profile.get_safe_section("areas");
-	std::string              str;
-	std::vector<std::string> water_strs;
-	std::vector<std::string> land_strs;
-	std::vector<std::string> wasteland_strs;
-	std::vector<std::string> mountain_strs;
-
-	str = areas_s.get_string("water", "water_area");
-	MapGenAreaInfo::split_string(water_strs, str);
-
-	str = areas_s.get_string("land", "land_area");
-	MapGenAreaInfo::split_string(land_strs, str);
-
-	str = areas_s.get_string("wasteland", "wasteland_area");
-	MapGenAreaInfo::split_string(wasteland_strs, str);
-
-	str = areas_s.get_string("mountains", "mountains_area");
-	MapGenAreaInfo::split_string(mountain_strs, str);
-
-	for (uint32_t ix = 0; ix < water_strs.size(); ++ix) {
-		Section & s = profile.get_safe_section(water_strs[ix].c_str());
-		MapGenAreaInfo info;
-		info.parseSection(m_world, s, MapGenAreaInfo::atWater);
-		m_WaterAreas.push_back(info);
-	}
-
-	for (uint32_t ix = 0; ix < land_strs.size(); ++ix) {
-		Section & s = profile.get_safe_section(land_strs[ix].c_str());
-		MapGenAreaInfo info;
-		info.parseSection(m_world, s, MapGenAreaInfo::atLand);
-		m_LandAreas.push_back(info);
-	}
-
-	for (uint32_t ix = 0; ix < wasteland_strs.size(); ++ix) {
-		Section & s = profile.get_safe_section(wasteland_strs[ix].c_str());
-		MapGenAreaInfo info;
-		info.parseSection(m_world, s, MapGenAreaInfo::atWasteland);
-		m_WasteLandAreas.push_back(info);
-	}
-
-	for (uint32_t ix = 0; ix < mountain_strs.size(); ++ix) {
-		Section & s = profile.get_safe_section(mountain_strs[ix].c_str());
-		MapGenAreaInfo info;
-		info.parseSection(m_world, s, MapGenAreaInfo::atMountains);
-		m_MountainAreas.push_back(info);
-	}
-
-	Section & bobs_s = profile.get_safe_section("bobs");
-	std::vector<std::string> bob_area_strs;
-	std::vector<std::string> bob_kind_strs;
-
-	str = bobs_s.get_string("areas");
-	MapGenAreaInfo::split_string(bob_area_strs, str);
-
-	str = bobs_s.get_string("bob_kinds");
-	MapGenAreaInfo::split_string(bob_kind_strs, str);
-
-	for (uint32_t ix = 0; ix < bob_kind_strs.size(); ++ix) {
-		Section & s = profile.get_safe_section(bob_kind_strs[ix].c_str());
-		MapGenBobKind kind;
-		kind.parseSection(s);
-		m_BobKinds[bob_kind_strs[ix]] = kind;
-
-		for (size_t jx = 0; jx < kind.getNumImmovableBobs(); jx++)
-			if
-				(m_world->get_immovable_index(kind.getImmovableBob(jx).c_str())
-				 <
-				 0)
-				throw wexception
-					("unknown immovable %s", kind.getImmovableBob(jx).c_str());
-
-		for (size_t jx = 0; jx < kind.getNumMoveableBobs(); jx++)
-			if
-				(m_world->get_bob(kind.getMoveableBob(jx).c_str()) < 0)
-				throw wexception
-					("unknown moveable %s", kind.getMoveableBob(jx).c_str());
-	}
-
-	for (uint32_t ix = 0; ix < bob_area_strs.size(); ++ix) {
-		Section & s = profile.get_safe_section(bob_area_strs[ix].c_str());
-		MapGenBobArea area;
-		area.parseSection(s, *this);
-		m_BobAreas.push_back(area);
-	}
-}
-
-/*
-=============================================================================
-
-World
-
-=============================================================================
-*/
-
-World::World(const std::string & name) : m_basedir("worlds/" + name + '/') {
-	try {
-		i18n::Textdomain textdomain("world_" + name);
-
-		std::unique_ptr<FileSystem> fs(g_fs->MakeSubFileSystem(m_basedir));
-		FileSystemLayer filesystemlayer(*fs);
-
-		{
-			Profile root_conf((m_basedir + "conf").c_str());
-			parse_root_conf(name, root_conf);
-			parse_resources();
-			parse_terrains();
-			log("Parsing world bobs...\n");
-			parse_bobs(m_basedir, root_conf);
-			root_conf.check_used();
-		}
-
-		{ //  General bobs mainly for scenarios
-			Profile global_root_conf("global/conf");
-			std::string global_dir = "global/bobs/";
-			log("Parsing global bobs in world...\n");
-			parse_bobs(global_dir, global_root_conf);
-			global_root_conf.check_used();
-		}
-
-		{
-			log("Parsing map gen info...\n");
-			parse_mapgen();
-		}
-	} catch (const std::exception & e) {
-		throw game_data_error("world %s: %s", name.c_str(), e.what());
-	}
-}
-
-
-/*
-===============
-Load graphics data here
-===============
-*/
-void World::load_graphics()
-{
-	g_gr->flush_maptextures();
-
-	// Load terrain graphics
-	for (size_t i = 0; i < ters.get_nitems(); ++i)
-		ters.get(i)->load_graphics();
-
-	// TODO: load more graphics
-}
-
-
-//
-// down here: Private functions for loading
-//
-
-/**
- * Read the <world-directory>/conf
- */
-void World::parse_root_conf(const std::string & name, Profile & root_conf)
-{
-	Section & s = root_conf.get_safe_section("world");
-	snprintf
-		(hd.name,   sizeof(hd.name),   "%s", s.get_string("name", name.c_str()));
-	snprintf
-		(hd.author, sizeof(hd.author), "%s", s.get_safe_string("author"));
-	snprintf
-		(hd.descr,  sizeof(hd.descr),  "%s", s.get_safe_string("descr"));
-}
-
-void World::parse_resources()
-{
-	char fname[256];
-
-	snprintf(fname, sizeof(fname), "%s/resconf", m_basedir.c_str());
-
-	try {
-		Profile prof(fname);
-		while (Section * const section = prof.get_next_section(nullptr)) {
-			Resource_Descr & descr = *new Resource_Descr();
-			descr.parse(*section, m_basedir);
-			m_resources.add(&descr);
-		}
-	} catch (const std::exception & e) {
-		throw game_data_error("%s: %s", fname, e.what());
-	}
-}
-
-void World::parse_terrains()
-{
-	char fname[256];
-
-	snprintf(fname, sizeof(fname), "%s/terrainconf", m_basedir.c_str());
-
-	try {
-		Profile prof(fname);
-
-		for (Terrain_Index i = 0;; ++i) {
-			Section * const s = prof.get_next_section(nullptr);
-			if (not s)
-				break;
-			if (i == 0x10)
-				throw game_data_error
-					("%s: too many terrain types, cannot be more than 16",
-					 fname);
-			ters.add(new Terrain_Descr(m_basedir.c_str(), s, &m_resources));
-		}
-
-		prof.check_used();
-	} catch (const game_data_error & e) {
-		throw game_data_error("%s: %s", fname, e.what());
-	}
-}
-
-void World::parse_bobs(std::string & path, Profile & root_conf) {
-	std::string::size_type const base_path_size = path.size();
-	std::set<std::string> names; //  To enforce name uniqueness.
-
-	PARSE_MAP_OBJECT_TYPES_BEGIN("immovable")
-		immovables.add
-			(new Immovable_Descr
-			 	(_name, _descname, path, prof, global_s, *this, nullptr));
-	PARSE_MAP_OBJECT_TYPES_END;
-
-	PARSE_MAP_OBJECT_TYPES_BEGIN("critter bob")
-		bobs      .add
-			(new Critter_Bob_Descr
-			 	(_name, _descname, path, prof, global_s, nullptr));
-	PARSE_MAP_OBJECT_TYPES_END;
-}
-
-void World::parse_mapgen   ()
-{
-	char fname[256];
-
-	snprintf(fname, sizeof(fname), "%s/mapgenconf", m_basedir.c_str());
-
-	try {
-		Profile prof(fname);
-
-		m_mapGenInfo.parseProfile(this, prof);
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atWater) < 1)
-			throw game_data_error("missing a water area");
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atWater) < 1)
-			throw game_data_error("too many water areas (>3)");
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atLand) < 1)
-			throw game_data_error("missing a land area");
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atLand) > 3)
-			throw game_data_error("too many land areas (>3)");
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atWasteland) < 1)
-			throw game_data_error("missing a wasteland area");
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atWasteland) > 2)
-			throw game_data_error("too many wasteland areas (>2)");
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atMountains) < 1)
-			throw game_data_error("missing a mountain area");
-
-		if (m_mapGenInfo.getNumAreas(MapGenAreaInfo::atMountains) < 1)
-			throw game_data_error("too many mountain areas (>1)");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atWater, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttWaterOcean) < 1)
-			throw game_data_error("missing a water/ocean terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atWater, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttWaterShelf)
-			 <
-			 1)
-			throw game_data_error("missing a water/shelf terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atWater, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttWaterShallow)
-			 <
-			 1)
-			throw game_data_error("is missing a water/shallow terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atLand, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttLandCoast)
-			 <
-			 1)
-			throw game_data_error("missing a land/coast terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atLand, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttLandLand)
-			 <
-			 1)
-			throw game_data_error("missing a land/land terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atMountains, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttMountainsFoot)
-			 <
-			 1)
-			throw game_data_error("missing a mountain/foot terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atMountains, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttMountainsMountain)
-			 <
-			 1)
-			throw game_data_error("missing a monutain/mountain terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atMountains, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttMountainsSnow)
-			 <
-			 1)
-			throw game_data_error("missing a mountain/snow terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atWasteland, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttWastelandInner)
-			 <
-			 1)
-			throw game_data_error("missing a land/coast terrain type");
-
-		if
-			(m_mapGenInfo.getArea(MapGenAreaInfo::atWasteland, 0).getNumTerrains
-			 	(MapGenAreaInfo::ttWastelandOuter)
-			 <
-			 1)
-			throw game_data_error("missing a land/land terrain type");
-
-		prof.check_used();
-	} catch (const _wexception & e) {
-		throw game_data_error("%s: %s", fname, e.what());
-	}
-}
-
-/**
- * Check if the world data can actually be read
- */
-bool World::exists_world(std::string worldname)
-{
-	FileRead f;
-	return
-		f.TryOpen
-			(*
-			 std::unique_ptr<FileSystem>
-				(g_fs->MakeSubFileSystem("worlds/" + worldname)),
-			 "conf");
-}
-
-void World::get_all_worlds(std::vector<std::string> & result) {
-	result.clear();
-
-	//  get all worlds
-	filenameset_t m_worlds = g_fs->ListDirectory("worlds");
-	for
-		(filenameset_t::iterator pname = m_worlds.begin();
-		 pname != m_worlds.end();
-		 ++pname)
-	{
-		std::string world = *pname;
-		world.erase(0, 7); //  remove worlds/
-		if (World::exists_world(world.c_str()))
-			result.push_back(world);
-	}
-}
-
-int32_t World::safe_resource_index(const char * const resourcename) const {
+World::World()
+   : bobs_(new DescriptionMaintainer<BobDescr>()),
+     immovables_(new DescriptionMaintainer<Immovable_Descr>()),
+     terrains_(new DescriptionMaintainer<TerrainDescription>()),
+     resources_(new DescriptionMaintainer<ResourceDescription>()),
+     editor_terrain_categories_(new DescriptionMaintainer<EditorCategory>()),
+     editor_immovable_categories_(new DescriptionMaintainer<EditorCategory>()) {
+}
+
+World::~World() {
+}
+
+const DescriptionMaintainer<TerrainDescription>& World::terrains() const {
+	return *terrains_;
+}
+
+void World::add_resource_type(const LuaTable& table) {
+	resources_->add(new ResourceDescription(table));
+}
+
+void World::add_terrain_type(const LuaTable& table) {
+	terrains_->add(new TerrainDescription(table, *this));
+}
+
+void World::add_critter_type(const LuaTable& table) {
+	bobs_->add(new Critter_Bob_Descr(table));
+}
+
+const DescriptionMaintainer<Immovable_Descr>& World::immovables() const {
+	return *immovables_;
+}
+
+void World::add_immovable_type(const LuaTable& table) {
+	immovables_->add(new Immovable_Descr(table, *this));
+}
+
+void World::add_editor_terrain_category(const LuaTable& table) {
+	editor_terrain_categories_->add(new EditorCategory(table));
+}
+
+const DescriptionMaintainer<EditorCategory>& World::editor_terrain_categories() const {
+	return *editor_terrain_categories_;
+}
+
+void World::add_editor_immovable_category(const LuaTable& table) {
+	editor_immovable_categories_->add(new EditorCategory(table));
+}
+
+const DescriptionMaintainer<EditorCategory>& World::editor_immovable_categories() const {
+	return *editor_immovable_categories_;
+}
+
+int32_t World::safe_resource_index(const char* const resourcename) const {
 	int32_t const result = get_resource(resourcename);
 
-	if (result == -1)
-		throw game_data_error
-			("world %s does not define resource type \"%s\"",
-			 get_name(), resourcename);
+	if (result == INVALID_INDEX)
+		throw game_data_error("world does not define resource type \"%s\"", resourcename);
 	return result;
 }
 
-
-MapGenInfo & World::getMapGenInfo()
-{
-	return m_mapGenInfo;
-}
-
-
-/*
-==============================================================================
-
-Terrain_Descr
-
-==============================================================================
-*/
-Terrain_Descr::Terrain_Descr
-	(char                       const * const directory,
-	 Section                          * const s,
-	 DescriptionMaintainer<Resource_Descr> * const resources)
-:
-m_name              (s->get_name()),
-m_descname          (s->get_string("name", s->get_name())),
-m_frametime         (FRAME_LENGTH),
-m_dither_layer   (0),
-m_valid_resources   (nullptr),
-m_nr_valid_resources(0),
-m_default_resources (-1),
-m_default_amount    (0),
-m_texture           (0)
-{
-
-	// Parse the default resource
-	if (const char * str = s->get_string("def_resources", nullptr)) {
-		std::istringstream str1(str);
-		std::string resource;
-		int32_t amount;
-		str1 >> resource >> amount;
-		int32_t const res = resources->get_index(resource.c_str());;
-		if (res == -1)
-			throw game_data_error
-				("terrain type %s has valid resource type %s, which does not "
-				 "exist in world",
-				 s->get_name(), resource.c_str());
-		m_default_resources = res;
-		m_default_amount    = amount;
-	}
-
-	//  parse valid resources
-	std::string str1 = s->get_string("resources", "");
-	if (str1 != "") {
-		int32_t nres = 1;
-		container_iterate_const(std::string, str1, i)
-			if (*i.current == ',')
-				++nres;
-
-		m_nr_valid_resources = nres;
-		m_valid_resources    = new uint8_t[nres];
-		std::string curres;
-		int32_t cur_res = 0;
-		for (uint32_t i = 0; i <= str1.size(); ++i) {
-			if (i == str1.size() || str1[i] == ',') {
-				const int32_t res = resources->get_index(curres.c_str());
-				if (res == -1)
-					throw game_data_error
-						("terrain type %s has valid resource type %s which does not "
-						 "exist in world",
-						 s->get_name(), curres.c_str());
-				m_valid_resources[cur_res++] = res;
-				curres = "";
-			} else if (str1[i] != ' ' && str1[i] != '\t') {
-				curres.append(1, str1[i]);
-			}
-		}
-	}
-
-	int32_t fps = s->get_int("fps");
-	if (fps > 0)
-		m_frametime = 1000 / fps;
-
-	{
-		const char * const is = s->get_safe_string("is");
-		if      (not strcmp(is, "dry"))
-			m_is = TERRAIN_DRY;
-		else if (not strcmp(is, "green"))
-			m_is = 0;
-		else if (not strcmp(is, "water"))
-			m_is = TERRAIN_WATER|TERRAIN_DRY|TERRAIN_UNPASSABLE;
-		else if (not strcmp(is, "acid"))
-			m_is = TERRAIN_ACID|TERRAIN_DRY|TERRAIN_UNPASSABLE;
-		else if (not strcmp(is, "mountain"))
-			m_is = TERRAIN_DRY|TERRAIN_MOUNTAIN;
-		else if (not strcmp(is, "dead"))
-			m_is = TERRAIN_DRY|TERRAIN_UNPASSABLE|TERRAIN_ACID;
-		else if (not strcmp(is, "unpassable"))
-			m_is = TERRAIN_DRY|TERRAIN_UNPASSABLE;
-		else
-			throw game_data_error("%s: invalid type '%s'", m_name.c_str(), is);
-	}
-
-	m_dither_layer = s->get_int("dither_layer", 0);
-
-	// Determine template of the texture animation pictures
-	char fnametmpl[256];
-
-	if (const char * const texture = s->get_string("texture", nullptr))
-		snprintf(fnametmpl, sizeof(fnametmpl), "%s/%s", directory, texture);
-	else
-		snprintf
-			(fnametmpl, sizeof(fnametmpl),
-			 "%s/pics/%s_??.png", directory, m_name.c_str());
-
-	m_picnametempl = fnametmpl;
-}
-
-Terrain_Descr::~Terrain_Descr()
-{
-	delete[] m_valid_resources;
-	m_nr_valid_resources = 0;
-	m_valid_resources    = nullptr;
-}
-
-
-/*
-===============
-Trigger load of the actual animation frames.
-===============
-*/
-void Terrain_Descr::load_graphics() {
-	if (!m_picnametempl.empty())
-		m_texture = g_gr->get_maptexture(m_picnametempl, m_frametime);
-}
-
-}
+TerrainDescription& World::terrain_descr(Terrain_Index const i) const {
+	return *terrains_->get(i);
+}
+
+TerrainDescription const* World::get_ter(char const* const name) const {
+	int32_t const i = terrains_->get_index(name);
+	return i != INVALID_INDEX ? terrains_->get(i) : nullptr;
+}
+
+int32_t World::get_bob(char const* const l) const {
+	return bobs_->get_index(l);
+}
+
+BobDescr const* World::get_bob_descr(uint16_t const index) const {
+	return bobs_->get(index);
+}
+
+BobDescr const* World::get_bob_descr(const std::string& name) const {
+	return bobs_->exists(name.c_str());
+}
+
+int32_t World::get_nr_bobs() const {
+	return bobs_->get_nitems();
+}
+
+int32_t World::get_immovable_index(char const* const l) const {
+	return immovables_->get_index(l);
+}
+
+int32_t World::get_nr_immovables() const {
+	return immovables_->get_nitems();
+}
+
+Immovable_Descr const* World::get_immovable_descr(int32_t const index) const {
+	return immovables_->get(index);
+}
+
+int32_t World::get_resource(const char* const name) const {
+	return resources_->get_index(name);
+}
+
+ResourceDescription const* World::get_resource(Resource_Index const res) const {
+	assert(res < resources_->get_nitems());
+	return resources_->get(res);
+}
+
+int32_t World::get_nr_resources() const {
+	return resources_->get_nitems();
+}
+
+}  // namespace Widelands

=== renamed file 'src/logic/world.h' => 'src/logic/world/world.h'
--- src/logic/world.h	2014-05-10 16:47:03 +0000
+++ src/logic/world/world.h	2014-06-10 18:27:45 +0000
@@ -20,358 +20,77 @@
 #ifndef WORLD_H
 #define WORLD_H
 
+#include <memory>
+
+#include "description_maintainer.h"
 #include "logic/bob.h"
-#include "description_maintainer.h"
-#include "logic/immovable.h"
-#include "logic/widelands.h"
-#include "logic/worlddata.h"
-
-struct Section;
 
 namespace Widelands {
 
+class EditorCategory;
 class Editor_Game_Base;
-struct World;
-
-#define WORLD_NAME_LEN 128
-#define WORLD_AUTHOR_LEN 128
-#define WORLD_DESCR_LEN 1024
-
-struct World_Descr_Header {
-	char name  [WORLD_NAME_LEN];
-	char author[WORLD_AUTHOR_LEN];
-	char descr [WORLD_DESCR_LEN];
-};
-
-struct Resource_Descr : boost::noncopyable {
-	Resource_Descr() : m_is_detectable(true), m_max_amount(0) {}
-	~Resource_Descr() {}
-
-	void parse(Section &, const std::string &);
-
-	const std::string & name     () const {return m_name;}
-	const std::string & descname() const {return m_descname;}
-
-	bool is_detectable() const {return m_is_detectable;}
-	int32_t get_max_amount() const {return m_max_amount;}
-
-	const std::string & get_editor_pic(uint32_t amount) const;
-
-private:
-	struct Indicator {
-		std::string bobname;
-		int32_t         upperlimit;
-	};
-	struct Editor_Pic {
-		std::string picname;
-		int32_t     upperlimit;
-	};
-
-	bool                    m_is_detectable;
-	int32_t                 m_max_amount;
-	std::string             m_name;
-	std::string             m_descname;
-	std::vector<Editor_Pic> m_editor_pics;
-};
-
-struct Terrain_Descr : boost::noncopyable {
-	friend struct World;
-
-	Terrain_Descr
-		(char const * directory, Section *, DescriptionMaintainer<Resource_Descr> *);
-	~Terrain_Descr();
-
-	void load_graphics();
-
-	uint32_t         get_texture() const {return m_texture;}
-	uint8_t        get_is     () const {return m_is;}
-	const std::string & name() const {return m_name;}
-	const std::string & descname() const {return m_descname;}
-	int32_t resource_value(const Resource_Index resource) const {
-		return
-			resource == get_default_resources() or is_resource_valid(resource) ?
-			(get_is() & TERRAIN_UNPASSABLE ? 8 : 1) : -1;
-	}
-
-	uint8_t get_num_valid_resources() const {
-		return m_nr_valid_resources;
-	}
-
-	Resource_Index get_valid_resource(uint8_t index) const {
-		return m_valid_resources[index];
-	}
-
-	bool is_resource_valid(const int32_t res) const {
-		for (int32_t i = 0; i < m_nr_valid_resources; ++i)
-			if (m_valid_resources[i] == res)
-				return true;
-		return false;
-	}
-	int8_t get_default_resources() const {return m_default_resources;}
-	int32_t get_default_resources_amount() const {
-		return m_default_amount;
-	}
-	int32_t dither_layer() const {return m_dither_layer;}
-
-private:
-	const std::string m_name;
-	const std::string m_descname;
-	std::string m_picnametempl;
-	uint32_t    m_frametime;
-	uint8_t   m_is;
-
-	int32_t m_dither_layer;
-
-	uint8_t         * m_valid_resources;
-	uint8_t           m_nr_valid_resources;
-	int8_t            m_default_resources;
-	int32_t           m_default_amount;
-	uint32_t          m_texture; //  renderer's texture
-};
-
-struct MapGenInfo;
-
-/// Holds world and area specific information for the map generator.
-/// Areas are: Water, Land, Wasteland and Mountains.
-struct MapGenAreaInfo {
-	static int split_string(std::vector<std::string> & strs, std::string & str);
-
-	enum MapGenAreaType {
-		atWater,
-		atLand,
-		atWasteland,
-		atMountains
-	};
-
-	enum MapGenTerrainType {
-		ttWaterOcean,
-		ttWaterShelf,
-		ttWaterShallow,
-
-		ttLandCoast,
-		ttLandLand,
-		ttLandUpper,
-
-		ttWastelandInner,
-		ttWastelandOuter,
-
-		ttMountainsFoot,
-		ttMountainsMountain,
-		ttMountainsSnow
-	};
-
-	void parseSection (World *, Section &, MapGenAreaType areaType);
-	size_t getNumTerrains(MapGenTerrainType) const;
-	Terrain_Index getTerrain(MapGenTerrainType terrType, uint32_t index) const;
-	uint32_t getWeight() const {return m_weight;}
-
-private:
-
-	void readTerrains
-		(std::vector<Terrain_Index> & list, Section &, char const * value_name);
-
-	std::vector<Terrain_Index>  m_Terrains1; //  ocean, coast, inner or foot
-	std::vector<Terrain_Index>  m_Terrains2; //  shelf, land, outer or mountain
-	std::vector<Terrain_Index>  m_Terrains3; //  shallow, upper, snow
-
-	uint32_t m_weight;
-
-	MapGenAreaType m_areaType;
-
-	World * m_world;
-
-};
-
-struct MapGenBobKind {
-
-	void parseSection (Section &);
-
-	size_t getNumImmovableBobs() const {return m_ImmovableBobs.size();}
-	size_t getNumMoveableBobs() const {return m_MoveableBobs.size();}
-
-	const std::string & getImmovableBob(size_t index) const {
-		return m_ImmovableBobs[index];
-	};
-	const std::string & getMoveableBob(size_t index) const {
-		return m_MoveableBobs[index];
-	};
-
-private:
-	std::vector<std::string> m_ImmovableBobs;
-	std::vector<std::string> m_MoveableBobs;
-
-};
-
-struct MapGenBobArea {
-
-	void parseSection (Section &, MapGenInfo & mapGenInfo);
-
-	uint32_t getWeight() const {return m_Weight;};
-	const MapGenBobKind * getBobKind
-		(MapGenAreaInfo::MapGenTerrainType terrType) const;
-
-	uint8_t getImmovableDensity() const {return m_Immovable_Density;};
-	uint8_t getMoveableDensity() const {return m_Moveable_Density;};
-
-private:
-	uint32_t        m_Weight;
-	uint8_t         m_Immovable_Density; // In percent
-	uint8_t         m_Moveable_Density;  // In percent
-	const MapGenBobKind * m_LandCoastBobKind;
-	const MapGenBobKind * m_LandInnerBobKind;
-	const MapGenBobKind * m_LandUpperBobKind;
-	const MapGenBobKind * m_WastelandInnerBobKind;
-	const MapGenBobKind * m_WastelandOuterBobKind;
-};
-
-/** struct MapGenInfo
-  *
-  * This class holds world specific information for the map generator.
-  * This info is usually read from the file "mapgeninfo" of a world.
-  */
-struct MapGenInfo {
-
-	void parseProfile(World * world, Profile & profile);
-
-	size_t getNumAreas(MapGenAreaInfo::MapGenAreaType areaType) const;
-	const MapGenAreaInfo & getArea
-		(MapGenAreaInfo::MapGenAreaType const areaType, uint32_t const index)
-		const;
-	const MapGenBobKind * getBobKind(const std::string & bobKindName) const;
-
-	uint8_t getWaterOceanHeight  () const {return m_ocean_height;}
-	uint8_t getWaterShelfHeight  () const {return m_shelf_height;}
-	uint8_t getWaterShallowHeight() const {return m_shallow_height;}
-	uint8_t getLandCoastHeight   () const {return m_coast_height;}
-	uint8_t getLandUpperHeight   () const {return m_upperland_height;}
-	uint8_t getMountainFootHeight() const {return m_mountainfoot_height;}
-	uint8_t getMountainHeight    () const {return m_mountain_height;}
-	uint8_t getSnowHeight        () const {return m_snow_height;}
-	uint8_t getSummitHeight      () const {return m_summit_height;}
-
-	uint32_t getSumLandWeight() const;
-
-	size_t getNumBobAreas() const;
-	const MapGenBobArea & getBobArea(size_t index) const;
-	uint32_t getSumBobAreaWeight() const;
-
-private:
-
-	World * m_world;
-
-	std::vector<MapGenAreaInfo> m_WaterAreas;
-	std::vector<MapGenAreaInfo> m_LandAreas;
-	std::vector<MapGenAreaInfo> m_WasteLandAreas;
-	std::vector<MapGenAreaInfo> m_MountainAreas;
-
-	std::vector<MapGenBobArea>           m_BobAreas;
-	std::map<std::string, MapGenBobKind> m_BobKinds;
-
-	uint8_t m_ocean_height;
-	uint8_t m_shelf_height;
-	uint8_t m_shallow_height;
-	uint8_t m_coast_height;
-	uint8_t m_upperland_height;
-	uint8_t m_mountainfoot_height;
-	uint8_t m_snow_height;
-	uint8_t m_mountain_height;
-	uint8_t m_summit_height;
-
-	mutable int32_t  m_land_weight;
-	mutable bool m_land_weight_valid;
-
-	mutable int32_t m_sum_bob_area_weights;
-	mutable bool m_sum_bob_area_weights_valid;
-
-};
-
-/** struct World
-  *
-  * This class provides information on a worldtype usable to create a map;
-  * it can read a world file.
-  */
-struct World : boost::noncopyable {
-	friend class Game;
-
-	enum {
-		OK = 0,
-		ERR_WRONGVERSION
-	};
-
-	World(const std::string & name);
-
-	static bool exists_world(std::string); ///  check if a world really exists
-	static void get_all_worlds(std::vector<std::string> &);
-
-	void load_graphics();
-
-	const char * get_name  () const {return hd.name;}
-	const char * get_author() const {return hd.author;}
-	const char * get_descr () const {return hd.descr;}
-
-	Terrain_Index index_of_terrain(char const * const name) const {
-		return ters.get_index(name);
-	}
-	Terrain_Descr & terrain_descr(Terrain_Index const i) const {
-		return *ters.get(i);
-	}
-	const Terrain_Descr & get_ter(Terrain_Index const i) const {
-		assert(i < ters.get_nitems());
-		return *ters.get(i);
-	}
-	Terrain_Descr const * get_ter(char const * const name) const {
-		int32_t const i = ters.get_index(name);
-		return i != -1 ? ters.get(i) : nullptr;
-	}
-	int32_t get_nr_terrains() const {return ters.get_nitems();}
-	int32_t get_bob(char const * const l) const {return bobs.get_index(l);}
-	BobDescr const * get_bob_descr(uint16_t const index) const {
-		return bobs.get(index);
-	}
-	BobDescr const * get_bob_descr(const std::string & name) const {
-		return bobs.exists(name.c_str());
-	}
-	int32_t get_nr_bobs() const {return bobs.get_nitems();}
-	int32_t get_immovable_index(char const * const l)const {
-		return immovables.get_index(l);
-	}
-	int32_t get_nr_immovables() const {return immovables.get_nitems();}
-	Immovable_Descr const * get_immovable_descr(int32_t const index) const {
-		return immovables.get(index);
-	}
-
-	int32_t get_resource(const char * const name) const {
-		return m_resources.get_index(name);
-	}
-	Resource_Descr const * get_resource(Resource_Index const res) const {
-		assert(res < m_resources.get_nitems());
-		return m_resources.get(res);
-	}
-	int32_t get_nr_resources() const {return m_resources.get_nitems();}
-	int32_t safe_resource_index(const char * const warename) const;
-	const std::string & basedir() const {return m_basedir;}
-
-	MapGenInfo & getMapGenInfo();
-
-private:
-	std::string m_basedir; //  base directory, where the main conf file resides
-	World_Descr_Header                hd;
-
-	DescriptionMaintainer<BobDescr>      bobs;
-	DescriptionMaintainer<Immovable_Descr> immovables;
-	DescriptionMaintainer<Terrain_Descr>   ters;
-	DescriptionMaintainer<Resource_Descr>  m_resources;
-
-	//  TODO: Should this be a description-maintainer?
-	MapGenInfo m_mapGenInfo;
-
-	void parse_root_conf(const std::string & name, Profile & root_conf);
-	void parse_resources();
-	void parse_terrains ();
-	void parse_bobs     (std::string & directory, Profile & root_conf);
-	void parse_mapgen   ();
-};
-
-}
+class ResourceDescription;
+class TerrainDescription;
+struct Critter_Bob_Descr;
+struct Immovable_Descr;
+
+// This is the in memory descriptions of the world and provides access to
+// terrains, immovables and resources.
+class World : boost::noncopyable {
+public:
+	World();
+	~World();  // Defined in .cc because all forward declarations are known then.
+
+	// TODO(sirver): Refactor these to only return the description_maintainer so that world
+	// becomes a pure container.
+	const DescriptionMaintainer<TerrainDescription>& terrains() const;
+	TerrainDescription& terrain_descr(Terrain_Index i) const;
+	TerrainDescription const* get_ter(char const* const name) const;
+
+	int32_t get_bob(char const* const l) const;
+	BobDescr const* get_bob_descr(uint16_t index) const;
+	BobDescr const* get_bob_descr(const std::string& name) const;
+	int32_t get_nr_bobs() const;
+
+	const DescriptionMaintainer<Immovable_Descr>& immovables() const;
+	int32_t get_immovable_index(char const* const l) const;
+	int32_t get_nr_immovables() const;
+	Immovable_Descr const* get_immovable_descr(int32_t index) const;
+
+	int32_t get_resource(const char* const name) const;
+	ResourceDescription const* get_resource(Resource_Index res) const;
+	int32_t get_nr_resources() const;
+	int32_t safe_resource_index(const char* const warename) const;
+
+	// Add this new resource to the world description.
+	void add_resource_type(const LuaTable& table);
+
+	// Add this new terrain to the world description.
+	void add_terrain_type(const LuaTable& table);
+
+	// Add a new critter to the world description.
+	void add_critter_type(const LuaTable& table);
+
+	// Add a new immovable to the world description.
+	void add_immovable_type(const LuaTable& table);
+
+	// Add an editor categories for grouping items in the editor.
+	void add_editor_terrain_category(const LuaTable& table);
+	void add_editor_immovable_category(const LuaTable& table);
+
+	// Access to the editor categories.
+	const DescriptionMaintainer<EditorCategory>& editor_terrain_categories() const;
+	const DescriptionMaintainer<EditorCategory>& editor_immovable_categories() const;
+
+private:
+	std::unique_ptr<DescriptionMaintainer<BobDescr>> bobs_;
+	std::unique_ptr<DescriptionMaintainer<Immovable_Descr>> immovables_;
+	std::unique_ptr<DescriptionMaintainer<TerrainDescription>> terrains_;
+	std::unique_ptr<DescriptionMaintainer<ResourceDescription>> resources_;
+	std::unique_ptr<DescriptionMaintainer<EditorCategory>> editor_terrain_categories_;
+	std::unique_ptr<DescriptionMaintainer<EditorCategory>> editor_immovable_categories_;
+};
+
+}  // namespace Widelands
 
 #endif

=== removed file 'src/logic/worlddata.h'
--- src/logic/worlddata.h	2012-02-15 21:25:34 +0000
+++ src/logic/worlddata.h	1970-01-01 00:00:00 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2002, 2008 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- */
-
-#ifndef WORLDDATA_H
-#define WORLDDATA_H
-
-#include <stdint.h>
-
-#ifndef PACK_VERSION
-#define PACK_VERSION(major, minor)                                            \
-   (static_cast<uint16_t>((static_cast<uint8_t>(major)) << 8) |               \
-    ((static_cast<uint8_t>(minor))))
-#endif
-
-#ifndef VERSION_MAJOR
-#define VERSION_MAJOR(vers) \
-   (static_cast<uint16_t>((static_cast<uint16_t>(vers) >> 8) & 0xff))
-#endif
-
-#ifndef VERSION_MINOR
-#define VERSION_MINOR(vers) \
-   (static_cast<uint16_t>((static_cast<uint16_t>(vers)) & 0xff))
-#endif
-
-#define WLWF_VERSION PACK_VERSION(1, 0)
-
-
-#define TERRAIN_DRY        1
-// #define TERRAIN_GREEN      1
-#define TERRAIN_WATER      2
-#define TERRAIN_ACID       4
-#define TERRAIN_MOUNTAIN   8
-// fine TERRAIN_DEAD       5
-#define TERRAIN_UNPASSABLE 16
-
-
-#endif

=== modified file 'src/map_generator.cc'
--- src/map_generator.cc	2014-03-09 18:32:29 +0000
+++ src/map_generator.cc	2014-06-10 18:27:45 +0000
@@ -19,27 +19,36 @@
 
 #include "map_generator.h"
 
+#include <stdint.h>
+
 #include "editor/tools/editor_increase_resources_tool.h"
 #include "log.h"
 #include "logic/editor_game_base.h"
 #include "logic/findnode.h"
 #include "logic/map.h"
-
-#define AVG_ELEVATION   (0x80000000)
-#define MAX_ELEVATION   (0xffffffff)
-#define MAP_ID_DIGITS   24
-#define ISLAND_BORDER   10
-#define MAX_ELEVATION_HALF (0x80000000)
-
-namespace Widelands
-{
-
-MapGenerator::MapGenerator
-	(Map & map, const UniqueRandomMapInfo & mapInfo,
-	 Editor_Game_Base & egbase)
-	: m_map(map), m_mapInfo(mapInfo), m_egbase(egbase)
-{
-
+#include "logic/world/map_gen.h"
+#include "logic/world/world.h"
+#include "scripting/lua_table.h"
+#include "scripting/scripting.h"
+
+constexpr uint32_t kAverageElevation = 0x80000000;
+constexpr uint32_t kMaxElevation = 0xffffffff;
+constexpr int kMapIdDigits = 24;
+constexpr int kIslandBorder = 10;
+constexpr uint32_t kMaxElevationHalf = 0x80000000;
+
+namespace Widelands {
+
+MapGenerator::MapGenerator(Map& map, const UniqueRandomMapInfo& mapInfo, Editor_Game_Base& egbase) :
+	map_(map),
+	map_info_(mapInfo),
+	egbase_(egbase)
+{
+	std::unique_ptr<LuaTable> map_gen_config(egbase.lua().run_script("world/map_generation.lua"));
+	map_gen_config->do_not_warn_about_unaccessed_keys();
+
+	map_gen_info_.reset(
+	   new MapGenInfo(*map_gen_config->get_table(mapInfo.world_name), egbase.world()));
 }
 
 void MapGenerator::generate_bobs
@@ -49,16 +58,13 @@
 	 MapGenAreaInfo::MapGenTerrainType const terrType)
 {
 	//  Figure out which bob area is due here...
-
-	MapGenInfo & mapGenInfo = m_map.world().getMapGenInfo();
-
-	size_t num = mapGenInfo.getNumBobAreas();
+	size_t num = map_gen_info_->getNumLandResources();
 	size_t found = num;
-	uint32_t sum_weight = mapGenInfo.getSumBobAreaWeight();
+	uint32_t sum_weight = map_gen_info_->getSumLandResourceWeight();
 	uint32_t max_val = 0;
 	for (size_t ix = 0; ix < num; ++ix) {
-		uint32_t val = random_bobs[ix][fc.x + m_mapInfo.w * fc.y];
-		val = (val / sum_weight) * mapGenInfo.getBobArea(ix).getWeight();
+		uint32_t val = random_bobs[ix][fc.x + map_info_.w * fc.y];
+		val = (val / sum_weight) * map_gen_info_->getLandResource(ix).getWeight();
 		if (val >= max_val) {
 			found = ix;
 			max_val = val;
@@ -69,21 +75,21 @@
 
 	// Figure out if we really need to set a bob here...
 
-	const MapGenBobArea & bobArea = mapGenInfo.getBobArea(found);
-
-	const MapGenBobKind * bobKind = bobArea.getBobKind(terrType);
-
-	if (not bobKind) //  no bobs defined here...
+	const MapGenLandResource & landResource = map_gen_info_->getLandResource(found);
+
+	const MapGenBobCategory * bobCategory = landResource.getBobCategory(terrType);
+
+	if (not bobCategory) //  no bobs defined here...
 		return;
 
-	uint32_t immovDens = bobArea.getImmovableDensity();
-	uint32_t movDens   = bobArea.getMoveableDensity();
+	uint32_t immovDens = landResource.getImmovableDensity();
+	uint32_t movDens   = landResource.getMoveableDensity();
 
 	immovDens *= max_val / 100;
 	movDens   *= max_val / 100;
 
-	immovDens = immovDens >= MAX_ELEVATION_HALF ? MAX_ELEVATION : immovDens * 2;
-	movDens   = movDens   >= MAX_ELEVATION_HALF ? MAX_ELEVATION : movDens   * 2;
+	immovDens = immovDens >= kMaxElevationHalf ? kMaxElevation : immovDens * 2;
+	movDens   = movDens   >= kMaxElevationHalf ? kMaxElevation : movDens   * 2;
 
 	uint32_t val = rng.rand();
 	bool set_immovable = (val <= immovDens);
@@ -93,68 +99,68 @@
 
 	// Set bob according to bob area
 
-	if (set_immovable and (num = bobKind->getNumImmovableBobs()))
-		m_egbase.create_immovable
+	if (set_immovable and (num = bobCategory->num_immovables()))
+		egbase_.create_immovable
 			(fc,
-			 bobKind->getImmovableBob
-			 	(static_cast<size_t>(rng.rand() / (MAX_ELEVATION / num))),
+			 bobCategory->get_immovable
+			 	(static_cast<size_t>(rng.rand() / (kMaxElevation / num))),
 			 nullptr);
 
-	if (set_moveable and (num = bobKind->getNumMoveableBobs()))
-		m_egbase.create_bob
+	if (set_moveable and (num = bobCategory->num_critters()))
+		egbase_.create_bob
 			(fc,
-			 m_map.world().get_bob
-			 	(bobKind->getMoveableBob
-			 	 	(static_cast<size_t>(rng.rand() / (MAX_ELEVATION / num)))
+			 egbase_.world().get_bob
+			 	(bobCategory->get_critter
+			 	 	(static_cast<size_t>(rng.rand() / (kMaxElevation / num)))
 			 	 .c_str()),
 			 nullptr);
 }
 
-#define set_resource_helper(rnd1, res)                                                             \
-	{                                                                                               \
-		Resource_Index const res_idx = terr.get_valid_resource(res);                                 \
-		uint32_t const max_amount = m_map.world().get_resource(res_idx)->get_max_amount();           \
-		uint8_t res_val = static_cast<uint8_t>(rnd1 / (MAX_ELEVATION / max_amount));                 \
-		res_val *= static_cast<uint8_t>(m_mapInfo.resource_amount) + 1;                              \
-		res_val /= 3;                                                                                \
-		if (Editor_Change_Resource_Tool_Callback(fc, m_map, res_idx)) {                              \
-			fc.field->set_resources(res_idx, res_val);                                                \
-			fc.field->set_starting_res_amount(res_val);                                               \
-		}                                                                                            \
-	}
-
-void MapGenerator::generate_resources
-	(uint32_t            const * const random1,
-	 uint32_t            const * const random2,
-	 uint32_t            const * const random3,
-	 uint32_t            const * const random4,
-	 FCoords                     const fc)
-{
+void MapGenerator::generate_resources(uint32_t const* const random1,
+                                      uint32_t const* const random2,
+                                      uint32_t const* const random3,
+                                      uint32_t const* const random4,
+                                      FCoords const fc) {
 	// We'll take the "D" terrain at first...
 	// TODO: Check how the editor handles this...
 
+	const World& world = egbase_.world();
 	Terrain_Index const tix = fc.field->get_terrains().d;
-	const Terrain_Descr & terr = m_map.world().get_ter(tix);
-	switch (terr.get_num_valid_resources()) {
+	const TerrainDescription& terrain_description = egbase_.world().terrain_descr(tix);
+
+	const auto set_resource_helper = [this, &world, &terrain_description, &fc] (
+	   const uint32_t random_value, const int valid_resource_index) {
+		const Resource_Index  res_idx = terrain_description.get_valid_resource(valid_resource_index);
+		const uint32_t max_amount = world.get_resource(res_idx)->max_amount();
+		uint8_t res_val = static_cast<uint8_t>(random_value / (kMaxElevation / max_amount));
+		res_val *= static_cast<uint8_t>(map_info_.resource_amount) + 1;
+		res_val /= 3;
+		if (Editor_Change_Resource_Tool_Callback(fc, map_, world, res_idx)) {
+			fc.field->set_resources(res_idx, res_val);
+			fc.field->set_starting_res_amount(res_val);
+		}
+	};
+
+	switch (terrain_description.get_num_valid_resources()) {
 	case 1: {
-		uint32_t const rnd1 = random1[fc.x + m_mapInfo.w * fc.y];
+		uint32_t const rnd1 = random1[fc.x + map_info_.w * fc.y];
 		set_resource_helper(rnd1, 0);
 		break;
 	}
 	case 2: {
-		uint32_t const rnd1 = random1[fc.x + m_mapInfo.w * fc.y];
-		uint32_t const rnd2 = random2[fc.x + m_mapInfo.w * fc.y];
+		uint32_t const rnd1 = random1[fc.x + map_info_.w * fc.y];
+		uint32_t const rnd2 = random2[fc.x + map_info_.w * fc.y];
 		if (rnd1 > rnd2) {
-			set_resource_helper(rnd1, 0)
+			set_resource_helper(rnd1, 0);
 		} else
 			set_resource_helper(rnd2, 1);
 		break;
 	}
 	case 3: {
-		uint32_t const rnd1 = random1[fc.x + m_mapInfo.w * fc.y];
-		uint32_t const rnd2 = random2[fc.x + m_mapInfo.w * fc.y];
-		uint32_t const rnd3 = random3[fc.x + m_mapInfo.w * fc.y];
-		if        (rnd1 > rnd2 && rnd1 > rnd3) {
+		uint32_t const rnd1 = random1[fc.x + map_info_.w * fc.y];
+		uint32_t const rnd2 = random2[fc.x + map_info_.w * fc.y];
+		uint32_t const rnd3 = random3[fc.x + map_info_.w * fc.y];
+		if (rnd1 > rnd2 && rnd1 > rnd3) {
 			set_resource_helper(rnd1, 0);
 		} else if (rnd2 > rnd1 && rnd2 > rnd3) {
 			set_resource_helper(rnd2, 1);
@@ -163,11 +169,11 @@
 		break;
 	}
 	case 4: {
-		uint32_t const rnd1 = random1[fc.x + m_mapInfo.w * fc.y];
-		uint32_t const rnd2 = random2[fc.x + m_mapInfo.w * fc.y];
-		uint32_t const rnd3 = random3[fc.x + m_mapInfo.w * fc.y];
-		uint32_t const rnd4 = random4[fc.x + m_mapInfo.w * fc.y];
-		if        (rnd1 > rnd2 && rnd1 > rnd3 && rnd1 > rnd4) {
+		uint32_t const rnd1 = random1[fc.x + map_info_.w * fc.y];
+		uint32_t const rnd2 = random2[fc.x + map_info_.w * fc.y];
+		uint32_t const rnd3 = random3[fc.x + map_info_.w * fc.y];
+		uint32_t const rnd4 = random4[fc.x + map_info_.w * fc.y];
+		if (rnd1 > rnd2 && rnd1 > rnd3 && rnd1 > rnd4) {
 			set_resource_helper(rnd1, 0);
 		} else if (rnd2 > rnd1 && rnd2 > rnd3 && rnd2 > rnd4) {
 			set_resource_helper(rnd2, 1);
@@ -178,7 +184,8 @@
 		break;
 	}
 	default:
-		break; // currently mountains have the maximum of allowed resources, which is 4
+		break;
+		// currently mountains have the maximum of allowed resources, which is 4
 	}
 }
 
@@ -186,7 +193,7 @@
 /// within the random map generation methods.
 ///
 /// \param elevation Random value.
-/// \param mapGenInfo Map generator information used to translate random values
+/// \param map_gen_info_ Map generator information used to translate random values
 /// to height information (world specific info).
 /// \param c position within map
 /// \param mapInfo Information about the random map currently begin created
@@ -197,14 +204,12 @@
 	(double                      const elevation,
 	 Coords                      const c)
 {
-	MapGenInfo & mapGenInfo = m_map.world().getMapGenInfo();
-
-	int32_t const water_h  = mapGenInfo.getWaterShallowHeight();
-	int32_t const mount_h  = mapGenInfo.getMountainFootHeight();
-	int32_t const summit_h = mapGenInfo.getSummitHeight      ();
-
-	double const water_fac = m_mapInfo.waterRatio;
-	double const land_fac  = m_mapInfo.landRatio;
+	int32_t const water_h  = map_gen_info_->getWaterShallowHeight();
+	int32_t const mount_h  = map_gen_info_->getMountainFootHeight();
+	int32_t const summit_h = map_gen_info_->getSummitHeight      ();
+
+	double const water_fac = map_info_.waterRatio;
+	double const land_fac  = map_info_.landRatio;
 
 	uint8_t res_h =
 		elevation < water_fac            ? water_h :
@@ -218,16 +223,16 @@
 			(summit_h - mount_h);
 
 	//  Handle Map Border in island mode
-	if (m_mapInfo.islandMode) {
+	if (map_info_.islandMode) {
 		int32_t const border_dist =
 			std::min
-				(std::min<X_Coordinate>(c.x, m_mapInfo.w - c.x),
-				 std::min<Y_Coordinate>(c.y, m_mapInfo.h - c.y));
-		if (border_dist <= ISLAND_BORDER) {
+				(std::min<X_Coordinate>(c.x, map_info_.w - c.x),
+				 std::min<Y_Coordinate>(c.y, map_info_.h - c.y));
+		if (border_dist <= kIslandBorder) {
 			res_h =
 				static_cast<uint8_t>
 					(static_cast<double>(res_h) * border_dist /
-					 static_cast<double>(ISLAND_BORDER));
+					 static_cast<double>(kIslandBorder));
 			if (res_h < water_h)
 				res_h = water_h;
 		}
@@ -250,8 +255,8 @@
 repeating set of random values.
 What is more, the different heights are weighed so that the
 random distribution of all random values in the array is linear.
-The minimum valu will be 0, the maximum value will be MAX_ELEVATION,
-the average will be AVG_ELEVATION.
+The minimum valu will be 0, the maximum value will be kMaxElevation,
+the average will be kAverageElevation.
 
 w, h: are width and height of the two-dimensional array
       produced. Thus, the array has w * h entries. To access a certain
@@ -273,7 +278,7 @@
 		//  We will do some initing here...
 
 		for (uint32_t ix = 0; ix < numFields; ++ix)
-			values[ix] = AVG_ELEVATION;
+			values[ix] = kAverageElevation;
 
 		//  This will be the first starting random values...
 
@@ -281,7 +286,7 @@
 			for (uint32_t y = 0; y < h; y += 16) {
 				values[x + y * w] = rng.rand();
 				if (x % 32 or y % 32) {
-					values[x + y * w] += AVG_ELEVATION;
+					values[x + y * w] += kAverageElevation;
 					values[x + y * w] /= 2;
 				}
 			}
@@ -289,7 +294,7 @@
 		//  randomize the values
 
 		uint32_t step_x  = std::min(16U, w), step_y  = std::min(16U, h);
-		uint32_t max = AVG_ELEVATION, min = AVG_ELEVATION;
+		uint32_t max = kAverageElevation, min = kAverageElevation;
 		double    ele_fac  = 0.15;
 
 		bool end = false;
@@ -319,17 +324,17 @@
 					uint32_t x_new       =
 						x_0_y_0 / 2 + x_1_y_0 / 2 +
 						static_cast<uint32_t>
-							(ele_fac * rng.rand() - ele_fac * AVG_ELEVATION);
+							(ele_fac * rng.rand() - ele_fac * kAverageElevation);
 
 					uint32_t y_new       =
 						x_0_y_0 / 2 + x_0_y_1 / 2 +
 						static_cast<uint32_t>
-							(ele_fac * rng.rand() - ele_fac * AVG_ELEVATION);
+							(ele_fac * rng.rand() - ele_fac * kAverageElevation);
 
 					uint32_t xy_new      =
 						x_0_y_0 / 4 + x_1_y_1 / 4 + x_1_y_0 / 4 + x_0_y_1 / 4 +
 						static_cast<uint32_t>
-							(ele_fac * rng.rand() - ele_fac * AVG_ELEVATION);
+							(ele_fac * rng.rand() - ele_fac * kAverageElevation);
 
 					values[x + step_x / 2 + w * (y)]              =  x_new;
 					values[x + step_x / 2 + w * (y + step_y / 2)] = xy_new;
@@ -379,7 +384,7 @@
 					 /
 					 static_cast<double>(max - min))
 					*
-					MAX_ELEVATION;
+					kMaxElevation;
 				++histo[values[x + y * w] >> 22];
 			}
 
@@ -402,7 +407,7 @@
 				values[x + y * w] =
 					minVals[values[x + y * w] >> 22]
 					*
-					static_cast<double>(MAX_ELEVATION);
+					static_cast<double>(kMaxElevation);
 		return values;
 	} catch (...) {
 		delete[] values;
@@ -417,7 +422,7 @@
 ===============
 Figures out terrain info for a field in a random map.
 
-mapGenInfo:  Map generator information used to translate
+map_gen_info_:  Map generator information used to translate
              Random values to height information (world-
              specific info)
 x, y:        first coordinate of the current triangle
@@ -446,60 +451,58 @@
 	 RNG                       &       rng,
 	 MapGenAreaInfo::MapGenTerrainType & terrType)
 {
-	MapGenInfo & mapGenInfo = m_map.world().getMapGenInfo();
-
 	uint32_t       numLandAreas      =
-		mapGenInfo.getNumAreas(MapGenAreaInfo::atLand);
+		map_gen_info_->getNumAreas(MapGenAreaInfo::atLand);
 	uint32_t const numWasteLandAreas =
-		mapGenInfo.getNumAreas(MapGenAreaInfo::atWasteland);
+		map_gen_info_->getNumAreas(MapGenAreaInfo::atWasteland);
 
 	bool isDesert  = false;
 	bool isDesertOuter = false;
 	uint32_t landAreaIndex = 0;
 
 	uint32_t rand2 =
-		random2[c0.x + m_mapInfo.w * c0.y] / 3 +
-		random2[c1.x + m_mapInfo.w * c1.y] / 3 +
-		random2[c2.x + m_mapInfo.w * c2.y] / 3;
+		random2[c0.x + map_info_.w * c0.y] / 3 +
+		random2[c1.x + map_info_.w * c1.y] / 3 +
+		random2[c2.x + map_info_.w * c2.y] / 3;
 	uint32_t rand3 =
-		random3[c0.x + m_mapInfo.w * c0.y] / 3 +
-		random3[c1.x + m_mapInfo.w * c1.y] / 3 +
-		random3[c2.x + m_mapInfo.w * c2.y] / 3;
+		random3[c0.x + map_info_.w * c0.y] / 3 +
+		random3[c1.x + map_info_.w * c1.y] / 3 +
+		random3[c2.x + map_info_.w * c2.y] / 3;
 	uint32_t rand4 =
-		random4[c0.x + m_mapInfo.w * c0.y] / 3 +
-		random4[c1.x + m_mapInfo.w * c1.y] / 3 +
-		random4[c2.x + m_mapInfo.w * c2.y] / 3;
+		random4[c0.x + map_info_.w * c0.y] / 3 +
+		random4[c1.x + map_info_.w * c1.y] / 3 +
+		random4[c2.x + map_info_.w * c2.y] / 3;
 
 	//  At first we figure out if it is wasteland or not.
 
 	if        (numWasteLandAreas == 0) {
 	} else if (numWasteLandAreas == 1) {
-		if (rand4 < (AVG_ELEVATION * m_mapInfo.wastelandRatio)) {
+		if (rand4 < (kAverageElevation * map_info_.wastelandRatio)) {
 			numLandAreas = numWasteLandAreas;
 			isDesert = true;
 			isDesertOuter =
-				rand4 > (AVG_ELEVATION * m_mapInfo.wastelandRatio / 4) * 3;
+				rand4 > (kAverageElevation * map_info_.wastelandRatio / 4) * 3;
 			landAreaIndex = 0;
 		}
 	} else {
-		if (rand4<(AVG_ELEVATION * m_mapInfo.wastelandRatio * 0.5)) {
+		if (rand4<(kAverageElevation * map_info_.wastelandRatio * 0.5)) {
 			numLandAreas = numWasteLandAreas;
 			isDesert = true;
 			isDesertOuter =
-				rand4 > (AVG_ELEVATION * m_mapInfo.wastelandRatio * 0.5 / 4) * 3;
+				rand4 > (kAverageElevation * map_info_.wastelandRatio * 0.5 / 4) * 3;
 			landAreaIndex = 0;
 		}
 		else if
 			(rand4
 			 >
-			 (MAX_ELEVATION - AVG_ELEVATION * m_mapInfo.wastelandRatio * 0.5))
+			 (kMaxElevation - kAverageElevation * map_info_.wastelandRatio * 0.5))
 		{
 			numLandAreas = numWasteLandAreas;
 			isDesert = true;
 			isDesertOuter =
 				rand4
 				<
-				1 - AVG_ELEVATION * m_mapInfo.wastelandRatio * 0.5 / 4 * 3;
+				1 - kAverageElevation * map_info_.wastelandRatio * 0.5 / 4 * 3;
 			landAreaIndex = 1;
 		}
 	}
@@ -513,25 +516,25 @@
 			landAreaIndex = 0;
 		else if (numLandAreas == 2) {
 			uint32_t const weight1 =
-				mapGenInfo.getArea(MapGenAreaInfo::atLand, 0).getWeight();
+				map_gen_info_->getArea(MapGenAreaInfo::atLand, 0).getWeight();
 			uint32_t const weight2 =
-				mapGenInfo.getArea(MapGenAreaInfo::atLand, 1).getWeight();
-			uint32_t const sum     = mapGenInfo.getSumLandWeight();
+				map_gen_info_->getArea(MapGenAreaInfo::atLand, 1).getWeight();
+			uint32_t const sum     = map_gen_info_->getSumLandWeight();
 			if
-				(weight1 * (random2[c0.x + m_mapInfo.w * c0.y] / sum)
+				(weight1 * (random2[c0.x + map_info_.w * c0.y] / sum)
 				 >=
-				 weight2 * (AVG_ELEVATION / sum))
+				 weight2 * (kAverageElevation / sum))
 				landAreaIndex = 0;
 			else
 				landAreaIndex = 1;
 		} else {
 			uint32_t const weight1 =
-				mapGenInfo.getArea(MapGenAreaInfo::atLand, 0).getWeight();
+				map_gen_info_->getArea(MapGenAreaInfo::atLand, 0).getWeight();
 			uint32_t const weight2 =
-				mapGenInfo.getArea(MapGenAreaInfo::atLand, 1).getWeight();
+				map_gen_info_->getArea(MapGenAreaInfo::atLand, 1).getWeight();
 			uint32_t const weight3 =
-				mapGenInfo.getArea(MapGenAreaInfo::atLand, 2).getWeight();
-			uint32_t const sum     = mapGenInfo.getSumLandWeight();
+				map_gen_info_->getArea(MapGenAreaInfo::atLand, 2).getWeight();
+			uint32_t const sum     = map_gen_info_->getSumLandWeight();
 			uint32_t const randomX = (rand2 + rand3) / 2;
 			if
 				(weight1 * (rand2 / sum) > weight2 * (rand3   / sum) &&
@@ -554,14 +557,14 @@
 
 	//  see whether it is water
 
-	uint32_t const coast_h   = mapGenInfo.getLandCoastHeight();
+	uint32_t const coast_h   = map_gen_info_->getLandCoastHeight();
 	if (h1 <= coast_h && h2 <= coast_h && h3 <= coast_h) { //  water or coast...
 		atp = MapGenAreaInfo::atLand;
 		ttp = MapGenAreaInfo::ttLandCoast;
 
-		uint32_t const ocean_h   = mapGenInfo.getWaterOceanHeight();
-		uint32_t const shelf_h   = mapGenInfo.getWaterShelfHeight();
-		uint32_t const shallow_h = mapGenInfo.getWaterShallowHeight();
+		uint32_t const ocean_h   = map_gen_info_->getWaterOceanHeight();
+		uint32_t const shelf_h   = map_gen_info_->getWaterShelfHeight();
+		uint32_t const shallow_h = map_gen_info_->getWaterShallowHeight();
 
 		//  TODO: The heights can not be lower than water-Shallow --
 		//  TODO: there will never be an ocean yet
@@ -577,10 +580,10 @@
 			ttp = MapGenAreaInfo::ttWaterShallow;
 		}
 	} else { //  it is not water
-		uint32_t const upper_h = mapGenInfo.getLandUpperHeight   ();
-		uint32_t const foot_h  = mapGenInfo.getMountainFootHeight();
-		uint32_t const mount_h = mapGenInfo.getMountainHeight    ();
-		uint32_t const snow_h  = mapGenInfo.getSnowHeight        ();
+		uint32_t const upper_h = map_gen_info_->getLandUpperHeight   ();
+		uint32_t const foot_h  = map_gen_info_->getMountainFootHeight();
+		uint32_t const mount_h = map_gen_info_->getMountainHeight    ();
+		uint32_t const snow_h  = map_gen_info_->getSnowHeight        ();
 		if        (h1 >= snow_h  && h2 >= snow_h  && h3 >= snow_h)  {
 			atp = MapGenAreaInfo::atMountains;
 			ttp = MapGenAreaInfo::ttMountainsSnow;
@@ -613,11 +616,11 @@
 
 	//  Figure out which terrain to use at this point in the map...
 	return
-		mapGenInfo.getArea(atp, usedLandIndex).getTerrain
+		map_gen_info_->getArea(atp, usedLandIndex).getTerrain
 			(ttp,
 			 rng.rand()
 			 %
-			 mapGenInfo.getArea(atp, usedLandIndex).getNumTerrains(ttp));
+			 map_gen_info_->getArea(atp, usedLandIndex).getNumTerrains(ttp));
 
 }
 
@@ -630,58 +633,55 @@
 	//  someone else...
 	RNG rng;
 
-	rng.seed(m_mapInfo.mapNumber);
-
-	//  get world generator info
-	MapGenInfo & mapGenInfo = m_map.world().getMapGenInfo();
+	rng.seed(map_info_.mapNumber);
 
 	//  Create a "raw" random elevation matrix.
 	//  We will transform this into reasonable elevations and terrains later on.
 
 	std::unique_ptr<uint32_t[]> elevations
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 
 	//  for land stuff
 	std::unique_ptr<uint32_t[]> random2
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 	std::unique_ptr<uint32_t[]> random3
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 
 	//  for desert/land
 	std::unique_ptr<uint32_t[]> random4
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 
 	// for resources
 	std::unique_ptr<uint32_t[]> random_rsrc_1
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 	std::unique_ptr<uint32_t[]> random_rsrc_2
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 	std::unique_ptr<uint32_t[]> random_rsrc_3
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 	std::unique_ptr<uint32_t[]> random_rsrc_4
-		(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+		(generate_random_value_map(map_info_.w, map_info_.h, rng));
 
 	// for bobs
 	std::unique_ptr<std::unique_ptr<uint32_t[]> []> random_bobs
-		(new std::unique_ptr<uint32_t[]> [mapGenInfo.getNumBobAreas()]);
+		(new std::unique_ptr<uint32_t[]> [map_gen_info_->getNumLandResources()]);
 
-	for (size_t ix = 0; ix < mapGenInfo.getNumBobAreas(); ++ix)
+	for (size_t ix = 0; ix < map_gen_info_->getNumLandResources(); ++ix)
 		random_bobs[ix].reset
-			(generate_random_value_map(m_mapInfo.w, m_mapInfo.h, rng));
+			(generate_random_value_map(map_info_.w, map_info_.h, rng));
 
 	//  Now we have generated a lot of random data!!
 	//  Lets use it !!!
-	iterate_Map_FCoords(m_map, m_mapInfo, fc)
+	iterate_Map_FCoords(map_, map_info_, fc)
 		fc.field->set_height
 			(make_node_elevation
-				(static_cast<double>(elevations[fc.x + m_mapInfo.w * fc.y])
+				(static_cast<double>(elevations[fc.x + map_info_.w * fc.y])
 				 /
-				 static_cast<double>(MAX_ELEVATION),
+				 static_cast<double>(kMaxElevation),
 				 fc));
 
 	//  Now lets set the terrain right according to the heights.
 
-	iterate_Map_FCoords(m_map, m_mapInfo, fc) {
+	iterate_Map_FCoords(map_, map_info_, fc) {
 		//  Calculate coordinates of left and bottom left neighbours of the
 		//  current node.
 
@@ -693,22 +693,22 @@
 		uint32_t lower_x       = fc.x - x_dec;
 		uint32_t lower_right_x = fc.x - x_dec + 1;
 
-		if       (lower_x >  m_mapInfo.w)       lower_x += m_mapInfo.w;
-		if       (right_x >= m_mapInfo.w)       right_x -= m_mapInfo.w;
-		if       (lower_x >= m_mapInfo.w)       lower_x -= m_mapInfo.w;
-		if (lower_right_x >= m_mapInfo.w) lower_right_x -= m_mapInfo.w;
-		if       (lower_y >= m_mapInfo.h)       lower_y -= m_mapInfo.h;
+		if       (lower_x >  map_info_.w)       lower_x += map_info_.w;
+		if       (right_x >= map_info_.w)       right_x -= map_info_.w;
+		if       (lower_x >= map_info_.w)       lower_x -= map_info_.w;
+		if (lower_right_x >= map_info_.w) lower_right_x -= map_info_.w;
+		if       (lower_y >= map_info_.h)       lower_y -= map_info_.h;
 
 		//  get the heights of my neighbour nodes and of my current node
 
 		uint8_t height_x0_y0 =
 			fc.field                            ->get_height();
 		uint8_t height_x1_y0 =
-			m_map[Coords(right_x,          fc.y)].get_height();
+			map_[Coords(right_x,          fc.y)].get_height();
 		uint8_t height_x0_y1 =
-			m_map[Coords(lower_x,       lower_y)].get_height();
+			map_[Coords(lower_x,       lower_y)].get_height();
 		uint8_t height_x1_y1 =
-			m_map[Coords(lower_right_x, lower_y)].get_height();
+			map_[Coords(lower_right_x, lower_y)].get_height();
 
 		MapGenAreaInfo::MapGenTerrainType terrType;
 
@@ -737,52 +737,52 @@
 	}
 
 	//  Aftermaths...
-	m_map.recalc_whole_map();
+	map_.recalc_whole_map(egbase_.world());
 
 	// Care about players and place their start positions
-	const std::string tribe = m_map.get_scenario_player_tribe(1);
-	const std::string ai    = m_map.get_scenario_player_ai(1);
-	m_map.set_nrplayers(m_mapInfo.numPlayers);
+	const std::string tribe = map_.get_scenario_player_tribe(1);
+	const std::string ai    = map_.get_scenario_player_ai(1);
+	map_.set_nrplayers(map_info_.numPlayers);
 	FindNodeSize functor(FindNodeSize::sizeBig);
 	Coords playerstart;
 
 	// Build a basic structure how player start positions are placed
 	uint8_t line[3];
 	uint8_t rows = 1, lines = 1;
-	if (m_mapInfo.numPlayers > 1) {
+	if (map_info_.numPlayers > 1) {
 		++lines;
-		if (m_mapInfo.numPlayers > 2) {
+		if (map_info_.numPlayers > 2) {
 			++rows;
-			if (m_mapInfo.numPlayers > 4) {
+			if (map_info_.numPlayers > 4) {
 				++lines;
-				if (m_mapInfo.numPlayers > 6) {
+				if (map_info_.numPlayers > 6) {
 					++rows;
 				}
 			}
 		}
 	}
 	line[0] = line[1] = line[2] = rows;
-	if (rows * lines > m_mapInfo.numPlayers) {
+	if (rows * lines > map_info_.numPlayers) {
 		--line[1];
-		if (rows * lines - 1 > m_mapInfo.numPlayers)
+		if (rows * lines - 1 > map_info_.numPlayers)
 			--line[2];
 	}
 
 	// Random placement of starting positions
-	assert(m_mapInfo.numPlayers);
-	std::vector<Player_Number> pn(m_mapInfo.numPlayers);
-	for (Player_Number n = 1; n <= m_mapInfo.numPlayers; ++n) {
+	assert(map_info_.numPlayers);
+	std::vector<Player_Number> pn(map_info_.numPlayers);
+	for (Player_Number n = 1; n <= map_info_.numPlayers; ++n) {
 		bool okay = false;
 		// This is a kinda dump algorithm -> we generate a random number and increase it until it fits.
 		// However it's working and simple ;) - if you've got a better idea, feel free to fix it.
-		Player_Number x = rng.rand() % m_mapInfo.numPlayers;
+		Player_Number x = rng.rand() % map_info_.numPlayers;
 		while (!okay) {
 			okay = true;
 			++x; // Player_Number begins at 1 not at 0
 			for (Player_Number p = 1; p < n; ++p) {
 				if (pn[p - 1] == x) {
 					okay = false;
-					x = x % m_mapInfo.numPlayers;
+					x = x % map_info_.numPlayers;
 					break;
 				}
 			}
@@ -790,56 +790,56 @@
 		pn[n - 1] = x;
 	}
 
-	for (Player_Number n = 1; n <= m_mapInfo.numPlayers; ++n) {
+	for (Player_Number n = 1; n <= map_info_.numPlayers; ++n) {
 		// Set scenario information - needed even if it's not a scenario
-		m_map.set_scenario_player_name(n, "Random Player");
-		m_map.set_scenario_player_tribe(n, tribe);
-		m_map.set_scenario_player_ai(n, ai);
-		m_map.set_scenario_player_closeable(n, false);
+		map_.set_scenario_player_name(n, "Random Player");
+		map_.set_scenario_player_tribe(n, tribe);
+		map_.set_scenario_player_ai(n, ai);
+		map_.set_scenario_player_closeable(n, false);
 
 		// Calculate wished coords for player starting position
 		if (line[0] + 1 > pn[n - 1]) {
 			// X-Coordinates
-			playerstart.x  = m_mapInfo.w * (line[0] * line[0] + 1 - pn[n - 1] * pn[n - 1]);
+			playerstart.x  = map_info_.w * (line[0] * line[0] + 1 - pn[n - 1] * pn[n - 1]);
 			playerstart.x /= line[0] * line[0] + 1;
 			// Y-Coordinates
 			if (lines == 1)
-				playerstart.y = m_mapInfo.h / 2;
+				playerstart.y = map_info_.h / 2;
 			else
-				playerstart.y = m_mapInfo.h / 7 + ISLAND_BORDER;
+				playerstart.y = map_info_.h / 7 + kIslandBorder;
 		} else if (line[0] + line[1] + 1 > pn[n - 1]) {
 			// X-Coordinates
 			uint8_t pos = pn[n - 1] - line[0];
-			playerstart.x  = m_mapInfo.w;
+			playerstart.x  = map_info_.w;
 			playerstart.x *= line[1] * line[1] + 1 - pos * pos;
 			playerstart.x /= line[1] * line[1] + 1;
 			// Y-Coordinates
 			if (lines == 3)
-				playerstart.y = m_mapInfo.h / 2;
+				playerstart.y = map_info_.h / 2;
 			else
-				playerstart.y = m_mapInfo.h - m_mapInfo.h / 7 - ISLAND_BORDER;
+				playerstart.y = map_info_.h - map_info_.h / 7 - kIslandBorder;
 		} else {
 			// X-Coordinates
 			uint8_t pos = pn[n - 1] - line[0] - line[1];
-			playerstart.x  = m_mapInfo.w;
+			playerstart.x  = map_info_.w;
 			playerstart.x *= line[2] * line[2] + 1 - pos * pos;
 			playerstart.x /= line[2] * line[2] + 1;
 			// Y-Coordinates
-			playerstart.y = m_mapInfo.h - m_mapInfo.h / 7 - ISLAND_BORDER;
+			playerstart.y = map_info_.h - map_info_.h / 7 - kIslandBorder;
 		}
 
 		// Now try to find a place as near as possible to the wished
 		// starting position
 		std::vector<Coords> coords;
-		m_map.find_fields
-			(Area<FCoords>(m_map.get_fcoords(playerstart), 20),
+		map_.find_fields
+			(Area<FCoords>(map_.get_fcoords(playerstart), 20),
 			 &coords, functor);
 
 		// Take the nearest ones
 		uint32_t min_distance = -1;
 		Coords coords2;
 		for (uint16_t i = 0; i < coords.size(); ++i) {
-			uint32_t test = m_map.calc_distance(coords[i], playerstart);
+			uint32_t test = map_.calc_distance(coords[i], playerstart);
 			if (test < min_distance) {
 				min_distance = test;
 				coords2 = coords[i];
@@ -854,7 +854,7 @@
 		}
 
 		// Finally set the found starting position
-		m_map.set_starting_pos(n, coords2);
+		map_.set_starting_pos(n, coords2);
 	}
 }
 
@@ -951,23 +951,22 @@
 */
 
 bool UniqueRandomMapInfo::setFromIdString
-	(UniqueRandomMapInfo & mapInfo_out, const std::string & mapIdString,
-	 const std::vector<std::string> & worlds)
+	(UniqueRandomMapInfo & mapInfo_out, const std::string & mapIdString)
 {
 	//  check string
 
-	if (mapIdString.length() != MAP_ID_DIGITS + MAP_ID_DIGITS / 4 - 1)
+	if (mapIdString.length() != kMapIdDigits + kMapIdDigits / 4 - 1)
 		return false;
 
-	for (uint32_t ix = 4; ix < MAP_ID_DIGITS; ix += 5)
+	for (uint32_t ix = 4; ix < kMapIdDigits; ix += 5)
 		if (mapIdString[ix] != '-')
 			return false;
 
 	//  convert digits to values
 
-	int32_t nums[MAP_ID_DIGITS];
+	int32_t nums[kMapIdDigits];
 
-	for (uint32_t ix = 0; ix < MAP_ID_DIGITS; ++ix) {
+	for (uint32_t ix = 0; ix < kMapIdDigits; ++ix) {
 		int const num = mapIdCharToNumber(mapIdString[ix + (ix / 4)]);
 		if (num < 0)
 			return false;
@@ -976,9 +975,9 @@
 
 	//  get xxor start value
 
-	int32_t xorr = nums[MAP_ID_DIGITS - 1];
+	int32_t xorr = nums[kMapIdDigits - 1];
 
-	for (int32_t ix = MAP_ID_DIGITS - 1; ix >= 0; --ix) {
+	for (int32_t ix = kMapIdDigits - 1; ix >= 0; --ix) {
 		nums[ix] = nums[ix] ^ xorr;
 		xorr -= 7;
 		xorr -= ix;
@@ -987,15 +986,15 @@
 	}
 
 	//  check if xxor was right
-	if (nums[MAP_ID_DIGITS - 1])
+	if (nums[kMapIdDigits - 1])
 		return false;
 
 	//  check if version number is 1
-	if (nums[MAP_ID_DIGITS - 2] != 1)
+	if (nums[kMapIdDigits - 2] != 1)
 		return false;
 
 	//  check if csm is right
-	if (nums[MAP_ID_DIGITS - 3] != 0x15)
+	if (nums[kMapIdDigits - 3] != 0x15)
 		return false;
 
 
@@ -1040,12 +1039,6 @@
 	nameHash |= nums[16] << 10;
 	nameHash |= nums[17] << 15;
 
-	for (size_t idx = 0; idx<worlds.size(); idx++)
-		if (generateWorldNameHash(worlds[idx]) == nameHash) {
-			mapInfo_out.worldName = worlds[idx];
-			return true;
-		}
-
 	return false; // No valid world name found
 }
 
@@ -1078,12 +1071,12 @@
 	assert(mapInfo.resource_amount <= Widelands::UniqueRandomMapInfo::raHigh);
 
 	mapIdsString_out = "";
-	int32_t nums[MAP_ID_DIGITS];
-	for (uint32_t ix = 0; ix < MAP_ID_DIGITS; ++ix)
+	int32_t nums[kMapIdDigits];
+	for (uint32_t ix = 0; ix < kMapIdDigits; ++ix)
 		nums[ix] = 0;
 
 	// Generate world name hash
-	uint16_t nameHash = generateWorldNameHash(mapInfo.worldName);
+	uint16_t nameHash = generateWorldNameHash(mapInfo.world_name);
 
 	//  Convert map random number
 	nums [0] =  mapInfo.mapNumber        & 31;
@@ -1122,11 +1115,11 @@
 	nums[17] = (nameHash >> 15) & 1;
 
 	//  Set id csm
-	nums[MAP_ID_DIGITS - 3] = 0x15;
+	nums[kMapIdDigits - 3] = 0x15;
 	//  Set id version number
-	nums[MAP_ID_DIGITS - 2] = 0x01;
+	nums[kMapIdDigits - 2] = 0x01;
 	//  Last number intentionally left blank
-	nums[MAP_ID_DIGITS - 1] = 0x00;
+	nums[kMapIdDigits - 1] = 0x00;
 
 
 	//  Nox xor everything
@@ -1134,10 +1127,10 @@
 	//  Every change in a digit will result in a complete id change
 
 	int32_t xorr = 0x0a;
-	for (uint32_t ix = 0; ix < MAP_ID_DIGITS; ++ix)
+	for (uint32_t ix = 0; ix < kMapIdDigits; ++ix)
 		xorr = xorr ^ nums[ix];
 
-	for (int32_t ix = MAP_ID_DIGITS - 1; ix >= 0; --ix) {
+	for (int32_t ix = kMapIdDigits - 1; ix >= 0; --ix) {
 		nums[ix] = nums[ix] ^ xorr;
 		xorr -= 7;
 		xorr -= ix;
@@ -1146,9 +1139,9 @@
 	}
 
 	//  translate it to ASCII
-	for (uint32_t ix = 0; ix < MAP_ID_DIGITS; ++ix) {
+	for (uint32_t ix = 0; ix < kMapIdDigits; ++ix) {
 		mapIdsString_out += mapIdNumberToChar(nums[ix]);
-		if (ix % 4 == 3 && ix != MAP_ID_DIGITS - 1)
+		if (ix % 4 == 3 && ix != kMapIdDigits - 1)
 			mapIdsString_out += "-";
 	}
 }
@@ -1175,7 +1168,7 @@
 // TODO: Also take mountain and water areas into bob generation
 // (we have ducks and chamois)
 // TODO: Move other map generation functions from Map to MapGenerator
-// TODO: Define the "none"-bob to weigh other bobs lower within BobKinds...
+// TODO: Define the "none"-bob to weigh other bobs lower within BobCategory...
 // TODO: Clean up code
 // TODO: Improve mapgenconf files for nicer generated worlds
 // TODO: MapGen: Bob generation, configurable in mapgenconf

=== modified file 'src/map_generator.h'
--- src/map_generator.h	2013-09-22 18:01:36 +0000
+++ src/map_generator.h	2014-06-10 18:27:45 +0000
@@ -20,7 +20,10 @@
 #ifndef MAP_GENERATOR_H
 #define MAP_GENERATOR_H
 
-#include "logic/world.h"
+#include <memory>
+
+#include "logic/widelands_geometry.h"
+#include "logic/world/map_gen.h"
 
 // This is the first step of separating map generation from
 // map.
@@ -55,7 +58,7 @@
 	uint32_t w;
 	uint32_t h;
 	Resource_Amount resource_amount;
-	std::string worldName;
+	std::string world_name;
 
 	double        waterRatio;     //  How much of the map is water?
 	double        landRatio;      //  How much of the map is land?
@@ -65,8 +68,7 @@
 
 	//  other stuff
 	static bool setFromIdString
-		(UniqueRandomMapInfo & mapInfo_out, const std::string & mapIdString,
-		 const std::vector<std::string> & worlds);
+		(UniqueRandomMapInfo & mapInfo_out, const std::string & mapIdString);
 	static void generateIdString
 		(std::string & mapIdsString_out, const UniqueRandomMapInfo & mapInfo);
 
@@ -115,9 +117,10 @@
 		 RNG                       &       rng,
 		 MapGenAreaInfo::MapGenTerrainType & terrType);
 
-	Map &                        m_map;
-	const UniqueRandomMapInfo & m_mapInfo;
-	Editor_Game_Base &           m_egbase;
+	std::unique_ptr<const MapGenInfo> map_gen_info_;
+	Map& map_;
+	const UniqueRandomMapInfo& map_info_;
+	Editor_Game_Base& egbase_;
 };
 
 }

=== modified file 'src/map_io/map_loader.h'
--- src/map_io/map_loader.h	2013-09-22 18:01:36 +0000
+++ src/map_io/map_loader.h	2014-06-10 18:27:45 +0000
@@ -22,6 +22,8 @@
 
 #include "logic/map.h"
 
+class LuaInterface;
+
 namespace Widelands {
 
 class Editor_Game_Base;
@@ -39,7 +41,6 @@
 	virtual ~Map_Loader() {};
 
 	virtual int32_t preload_map(bool as_scenario) = 0;
-	virtual void load_world() = 0;
 	virtual int32_t load_map_complete(Editor_Game_Base &, bool as_scenario) = 0;
 
 	Map & map() {return m_map;}
@@ -48,7 +49,6 @@
 	enum State {
 		STATE_INIT,
 		STATE_PRELOADED,
-		STATE_WORLD_LOADED,
 		STATE_LOADED
 	};
 	void set_state(State const s) {m_s = s;}

=== added file 'src/map_io/one_world_legacy_lookup_table.cc'
--- src/map_io/one_world_legacy_lookup_table.cc	1970-01-01 00:00:00 +0000
+++ src/map_io/one_world_legacy_lookup_table.cc	2014-06-10 18:27:45 +0000
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "map_io/one_world_legacy_lookup_table.h"
+
+#include "log.h"
+
+namespace  {
+
+// If the map is newish and there is no old world to convert names from, we use
+// this one that simply returns the looked up values.
+class PassthroughOneWorldLegacyLookupTable : public OneWorldLegacyLookupTable {
+public:
+	// Implements OneWorldLegacyLookupTable.
+	std::string lookup_resource(const std::string& resource) const override;
+	std::string lookup_terrain(const std::string& terrain) const override;
+	std::string lookup_critter(const std::string& critter) const override;
+	std::string lookup_immovable(const std::string& immovable) const override;
+};
+
+std::string
+PassthroughOneWorldLegacyLookupTable::lookup_resource(const std::string& resource) const {
+	return resource;
+}
+
+std::string PassthroughOneWorldLegacyLookupTable::lookup_terrain(const std::string& terrain) const {
+	return terrain;
+}
+
+std::string PassthroughOneWorldLegacyLookupTable::lookup_critter(const std::string& critter) const {
+	return critter;
+}
+
+std::string
+PassthroughOneWorldLegacyLookupTable::lookup_immovable(const std::string& immovable) const {
+	return immovable;
+}
+
+class RealOneWorldLegacyLookupTable : public OneWorldLegacyLookupTable {
+public:
+	RealOneWorldLegacyLookupTable(const std::string& old_world_name);
+
+	// Implements OneWorldLegacyLookupTable.
+	std::string lookup_resource(const std::string& resource) const override;
+	std::string lookup_terrain(const std::string& terrain) const override;
+	std::string lookup_critter(const std::string& critter) const override;
+	std::string lookup_immovable(const std::string& immovable) const override;
+
+private:
+	const std::string old_world_name_;
+	const std::map<std::string, std::string> resources_;
+	const std::map<std::string, std::map<std::string, std::string>> terrains_;
+	const std::map<std::string, std::map<std::string, std::string>> critters_;
+	const std::map<std::string, std::map<std::string, std::string>> immovables_;
+};
+
+
+RealOneWorldLegacyLookupTable::RealOneWorldLegacyLookupTable(const std::string& old_world_name) :
+old_world_name_(old_world_name),
+// RESOURCES - They were all the same for all worlds.
+resources_
+{
+	{"granit", "granite"},
+},
+
+// TERRAINS
+terrains_
+{std::make_pair(
+	"greenland", std::map<std::string, std::string>
+	{
+		// No changes for greenland.
+	}),
+std::make_pair(
+	"blackland", std::map<std::string, std::string>
+	{
+		{"mountain1", "wasteland_mountain1"},
+		{"mountain2", "wasteland_mountain2"},
+		{"mountain3", "wasteland_mountain3"},
+		{"mountain4", "wasteland_mountain4"},
+		{"strand", "wasteland_beach"},
+		{"water", "wasteland_water"},
+	}),
+std::make_pair(
+	"winterland", std::map<std::string, std::string>
+	{
+		{"ice_flows", "ice_floes"},
+		{"ice_flows2", "ice_floes2"},
+		{"mountain1", "winter_mountain1"},
+		{"mountain2", "winter_mountain2"},
+		{"mountain3", "winter_mountain3"},
+		{"mountain4", "winter_mountain4"},
+		{"strand", "winter_beach"},
+		{"water", "winter_water"},
+	}),
+std::make_pair(
+	"desert", std::map<std::string, std::string>
+	{
+		{"beach", "desert_beach"},
+		{"steppe", "desert_steppe"},
+		{"wasser", "desert_water"},
+	}),
+},
+
+// CRITTERS
+critters_
+{std::make_pair(
+	"greenland", std::map<std::string, std::string>
+	{
+		{"deer", "stag"},
+	}),
+std::make_pair(
+	"blackland", std::map<std::string, std::string>
+	{
+		// No changes.
+	}),
+std::make_pair(
+	"winterland", std::map<std::string, std::string>
+	{
+		{"deer", "stag"},
+	}),
+std::make_pair(
+	"desert", std::map<std::string, std::string>
+	{
+		// No changes.
+	}),
+},
+
+// IMMOVABLES
+immovables_
+{std::make_pair(
+	"blackland", std::map<std::string, std::string>
+	{
+		{"stones1", "blackland_stones1"},
+		{"stones2", "blackland_stones2"},
+		{"stones3", "blackland_stones3"},
+		{"stones4", "blackland_stones4"},
+		{"stones5", "blackland_stones5"},
+		{"stones6", "blackland_stones6"},
+		{"sstones1", "standing_stone1_wasteland"},
+		{"sstones2", "standing_stone2_wasteland"},
+		{"sstones3", "standing_stone3_wasteland"},
+		{"sstones4", "standing_stone4_wasteland"},
+		{"sstones5", "standing_stone5_wasteland"},
+		{"sstones6", "standing_stone6"},
+		{"sstones7", "standing_stone7"},
+		{"tree1", "umbrella_red_wasteland_old"},
+		{"tree1_m", "umbrella_red_wasteland_mature"},
+		{"tree1_s", "umbrella_red_wasteland_pole"},
+		{"tree1_t", "umbrella_red_wasteland_sapling"},
+		{"tree2", "mushroom_dark_wasteland_old"},
+		{"tree2_m", "mushroom_dark_wasteland_mature"},
+		{"tree2_s", "mushroom_dark_wasteland_pole"},
+		{"tree2_t", "mushroom_dark_wasteland_sapling"},
+		{"tree3", "twine_wasteland_old"},
+		{"tree3_m", "twine_wasteland_mature"},
+		{"tree3_s", "twine_wasteland_pole"},
+		{"tree3_t", "twine_wasteland_sapling"},
+		{"tree4", "umbrella_green_wasteland_old"},
+		{"tree4_m", "umbrella_green_wasteland_mature"},
+		{"tree4_s", "umbrella_green_wasteland_pole"},
+		{"tree4_t", "umbrella_green_wasteland_sapling"},
+		{"tree5", "mushroom_red_wasteland_old"},
+		{"tree5_m", "mushroom_red_wasteland_mature"},
+		{"tree5_s", "mushroom_red_wasteland_pole"},
+		{"tree5_t", "mushroom_red_wasteland_sapling"},
+		{"tree6", "mushroom_green_wasteland_old"},
+		{"tree6_m", "mushroom_green_wasteland_mature"},
+		{"tree6_s", "mushroom_green_wasteland_pole"},
+		{"tree6_t", "mushroom_green_wasteland_sapling"},
+		{"tree7", "cirrus_wasteland_old"},
+		{"tree7_m", "cirrus_wasteland_mature"},
+		{"tree7_s", "cirrus_wasteland_pole"},
+		{"tree7_t", "cirrus_wasteland_sapling"},
+		{"tree8", "liana_wasteland_old"},
+		{"tree8_m", "liana_wasteland_mature"},
+		{"tree8_s", "liana_wasteland_pole"},
+		{"tree8_t", "liana_wasteland_sapling"},
+	}),
+std::make_pair(
+	"desert", std::map<std::string, std::string>
+	{
+		{"deadtree2", "deadtree5"},
+		{"deadtree3", "deadtree6"},
+		{"sstones1", "standing_stone1_desert"},
+		{"sstones2", "standing_stone2_desert"},
+		{"sstones3", "standing_stone3_desert"},
+		{"sstones4", "standing_stone4_desert"},
+		{"sstones5", "standing_stone5_desert"},
+		{"sstones6", "standing_stone6"},
+		{"sstones7", "standing_stone7"},
+		{"stones1", "desert_stones1"},
+		{"stones2", "desert_stones2"},
+		{"stones3", "desert_stones3"},
+		{"stones4", "desert_stones4"},
+		{"stones5", "desert_stones5"},
+		{"stones6", "desert_stones6"},
+		{"tree1", "palm_date_desert_old"},
+		{"tree1_m", "palm_date_desert_mature"},
+		{"tree1_s", "palm_date_desert_pole"},
+		{"tree1_t", "palm_date_desert_sapling"},
+		{"tree2", "palm_borassus_desert_old"},
+		{"tree2_m", "palm_borassus_desert_mature"},
+		{"tree2_s", "palm_borassus_desert_pole"},
+		{"tree2_t", "palm_borassus_desert_sapling"},
+		{"tree3", "palm_coconut_desert_old"},
+		{"tree3_m", "palm_coconut_desert_mature"},
+		{"tree3_s", "palm_coconut_desert_pole"},
+		{"tree3_t", "palm_coconut_desert_sapling"},
+		{"tree4", "palm_roystonea_desert_old"},
+		{"tree4_m", "palm_roystonea_desert_mature"},
+		{"tree4_s", "palm_roystonea_desert_pole"},
+		{"tree4_t", "palm_roystonea_desert_sapling"},
+		{"tree5", "palm_oil_desert_old"},
+		{"tree5_m", "palm_oil_desert_mature"},
+		{"tree5_s", "palm_oil_desert_pole"},
+		{"tree5_t", "palm_oil_desert_sapling"},
+		{"tree6", "beech_summer_old"},
+		{"tree6_m", "beech_summer_mature"},
+		{"tree6_s", "beech_summer_pole"},
+		{"tree6_t", "beech_summer_sapling"},
+		{"tree7", "larch_summer_old"},
+		{"tree7_m", "larch_summer_mature"},
+		{"tree7_s", "larch_summer_pole"},
+		{"tree7_t", "larch_summer_sapling"},
+		{"tree8", "rowan_summer_old"},
+		{"tree8_m", "rowan_summer_mature"},
+		{"tree8_s", "rowan_summer_pole"},
+		{"tree8_t", "rowan_summer_sapling"},
+	}),
+std::make_pair(
+	"greenland", std::map<std::string, std::string>
+	{
+		{"sstones1", "standing_stone1_summer"},
+		{"sstones2", "standing_stone2_summer"},
+		{"sstones3", "standing_stone3_summer"},
+		{"sstones4", "standing_stone4_summer"},
+		{"sstones5", "standing_stone5_summer"},
+		{"sstones6", "standing_stone6"},
+		{"sstones7", "standing_stone7"},
+		{"stones1", "greenland_stones1"},
+		{"stones2", "greenland_stones2"},
+		{"stones3", "greenland_stones3"},
+		{"stones4", "greenland_stones4"},
+		{"stones5", "greenland_stones5"},
+		{"stones6", "greenland_stones6"},
+		{"tree1", "aspen_summer_old"},
+		{"tree1_m", "aspen_summer_mature"},
+		{"tree1_s", "aspen_summer_pole"},
+		{"tree1_t", "aspen_summer_sapling"},
+		{"tree2", "oak_summer_old"},
+		{"tree2_m", "oak_summer_mature"},
+		{"tree2_s", "oak_summer_pole"},
+		{"tree2_t", "oak_summer_sapling"},
+		{"tree3", "spruce_summer_old"},
+		{"tree3_m", "spruce_summer_mature"},
+		{"tree3_s", "spruce_summer_pole"},
+		{"tree3_t", "spruce_summer_sapling"},
+		{"tree4", "alder_summer_old"},
+		{"tree4_m", "alder_summer_mature"},
+		{"tree4_s", "alder_summer_pole"},
+		{"tree4_t", "alder_summer_sapling"},
+		{"tree5", "birch_summer_old"},
+		{"tree5_m", "birch_summer_mature"},
+		{"tree5_s", "birch_summer_pole"},
+		{"tree5_t", "birch_summer_sapling"},
+		{"tree6", "beech_summer_old"},
+		{"tree6_m", "beech_summer_mature"},
+		{"tree6_s", "beech_summer_pole"},
+		{"tree6_t", "beech_summer_sapling"},
+		{"tree7", "larch_summer_old"},
+		{"tree7_m", "larch_summer_mature"},
+		{"tree7_s", "larch_summer_pole"},
+		{"tree7_t", "larch_summer_sapling"},
+		{"tree8", "rowan_summer_old"},
+		{"tree8_m", "rowan_summer_mature"},
+		{"tree8_s", "rowan_summer_pole"},
+		{"tree8_t", "rowan_summer_sapling"},
+	}),
+std::make_pair(
+	"winterland", std::map<std::string, std::string>
+	{
+		{"sstones1", "standing_stone1_winter"},
+		{"sstones2", "standing_stone2_winter"},
+		{"sstones3", "standing_stone3_winter"},
+		{"sstones4", "standing_stone4_winter"},
+		{"sstones5", "standing_stone5_winter"},
+		{"sstones6", "standing_stone6"},
+		{"sstones7", "standing_stone7"},
+		{"stones1", "winterland_stones1"},
+		{"stones2", "winterland_stones2"},
+		{"stones3", "winterland_stones3"},
+		{"stones4", "winterland_stones4"},
+		{"stones5", "winterland_stones5"},
+		{"stones6", "winterland_stones6"},
+		{"track", "track_winter"},
+		{"tree1", "aspen_summer_old"},
+		{"tree1_m", "aspen_summer_mature"},
+		{"tree1_s", "aspen_summer_pole"},
+		{"tree1_t", "aspen_summer_sapling"},
+		{"tree2", "oak_summer_old"},
+		{"tree2_m", "oak_summer_mature"},
+		{"tree2_s", "oak_summer_pole"},
+		{"tree2_t", "oak_summer_sapling"},
+		{"tree3", "spruce_summer_old"},
+		{"tree3_m", "spruce_summer_mature"},
+		{"tree3_s", "spruce_summer_pole"},
+		{"tree3_t", "spruce_summer_sapling"},
+		{"tree4", "maple_winter_old"},
+		{"tree4_m", "maple_winter_mature"},
+		{"tree4_s", "maple_winter_pole"},
+		{"tree4_t", "maple_winter_sapling"},
+		{"tree5", "birch_summer_old"},
+		{"tree5_m", "birch_summer_mature"},
+		{"tree5_s", "birch_summer_pole"},
+		{"tree5_t", "birch_summer_sapling"},
+		{"tree6", "beech_summer_old"},
+		{"tree6_m", "beech_summer_mature"},
+		{"tree6_s", "beech_summer_pole"},
+		{"tree6_t", "beech_summer_sapling"},
+		{"tree7", "larch_summer_old"},
+		{"tree7_m", "larch_summer_mature"},
+		{"tree7_s", "larch_summer_pole"},
+		{"tree7_t", "larch_summer_sapling"},
+		{"tree8", "rowan_summer_old"},
+		{"tree8_m", "rowan_summer_mature"},
+		{"tree8_s", "rowan_summer_pole"},
+		{"tree8_t", "rowan_summer_sapling"},
+	}),
+}
+
+{}
+
+std::string RealOneWorldLegacyLookupTable::lookup_resource(const std::string& resource) const {
+	const auto& i = resources_.find(resource);
+	if (i == resources_.end()) {
+		return resource;
+	}
+	return i->second;
+};
+
+std::string RealOneWorldLegacyLookupTable::lookup_terrain(const std::string& terrain) const {
+	const std::map<std::string, std::string>& world_terrains = terrains_.at(old_world_name_);
+	const auto& i = world_terrains.find(terrain);
+	if (i != world_terrains.end()) {
+		return i->second;
+	}
+	return terrain;
+}
+
+std::string RealOneWorldLegacyLookupTable::lookup_critter(const std::string& critter) const {
+	const std::map<std::string, std::string>& world_critters = critters_.at(old_world_name_);
+	const auto& i = world_critters.find(critter);
+	if (i != world_critters.end()) {
+		return i->second;
+	}
+	return critter;
+}
+
+std::string RealOneWorldLegacyLookupTable::lookup_immovable(const std::string& immovable) const {
+	const std::map<std::string, std::string>& world_immovables = immovables_.at(old_world_name_);
+	const auto& i = world_immovables.find(immovable);
+	if (i != world_immovables.end()) {
+		return i->second;
+	}
+	return immovable;
+}
+
+}  // namespace
+
+OneWorldLegacyLookupTable::~OneWorldLegacyLookupTable() {
+}
+
+std::unique_ptr<OneWorldLegacyLookupTable>
+create_one_world_legacy_lookup_table(const std::string& old_world_name) {
+	if (old_world_name.empty()) {
+		return std::unique_ptr<OneWorldLegacyLookupTable>(new PassthroughOneWorldLegacyLookupTable());
+	}
+	return std::unique_ptr<OneWorldLegacyLookupTable>(new RealOneWorldLegacyLookupTable(old_world_name));
+}

=== added file 'src/map_io/one_world_legacy_lookup_table.h'
--- src/map_io/one_world_legacy_lookup_table.h	1970-01-01 00:00:00 +0000
+++ src/map_io/one_world_legacy_lookup_table.h	2014-06-10 18:27:45 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef ONE_WORLD_LEGACY_CONVERSION_H
+#define ONE_WORLD_LEGACY_CONVERSION_H
+
+#include <map>
+#include <string>
+
+#include <boost/noncopyable.hpp>
+
+class OneWorldLegacyLookupTable : boost::noncopyable {
+public:
+	virtual ~OneWorldLegacyLookupTable();
+
+	// Looks up the new name for the 'resource'.
+	virtual std::string lookup_resource(const std::string& resource) const = 0;
+
+	// Looks up the new name for the 'terrain'.
+	virtual std::string lookup_terrain(const std::string& terrain) const = 0;
+
+	// Looks up the new name for the 'critter'.
+	virtual std::string lookup_critter(const std::string& critter) const = 0;
+
+	// Looks up the new name for the 'immovable'.
+	virtual std::string lookup_immovable(const std::string& immovable) const = 0;
+};
+
+std::unique_ptr<OneWorldLegacyLookupTable>
+create_one_world_legacy_lookup_table(const std::string& old_world);
+
+#endif /* end of include guard: ONE_WORLD_LEGACY_CONVERSION_H */

=== modified file 'src/map_io/widelands_map_building_data_packet.h'
--- src/map_io/widelands_map_building_data_packet.h	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_building_data_packet.h	2014-06-10 18:27:45 +0000
@@ -33,12 +33,9 @@
  * This packet cares for the existence of buildings
  * on the map, the data is parsed somewhere else
  */
-struct Map_Building_Data_Packet : public Map_Data_Packet {
-	void Read
-		(FileSystem &, Editor_Game_Base &, bool, Map_Map_Object_Loader &) override
-	;
-	void Write(FileSystem &, Editor_Game_Base &, Map_Map_Object_Saver &) override
-	;
+struct Map_Building_Data_Packet {
+	void Read(FileSystem&, Editor_Game_Base&, bool, Map_Map_Object_Loader&);
+	void Write(FileSystem&, Editor_Game_Base&, Map_Map_Object_Saver&);
 
 protected:
 	void read_priorities (Building       &, FileRead  &);

=== modified file 'src/map_io/widelands_map_buildingdata_data_packet.h'
--- src/map_io/widelands_map_buildingdata_data_packet.h	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_buildingdata_data_packet.h	2014-06-10 18:27:45 +0000
@@ -40,12 +40,10 @@
 /*
  * This cares for the data of buildings
  */
-struct Map_Buildingdata_Data_Packet : public Map_Data_Packet {
-	void Read
-		(FileSystem &, Editor_Game_Base &, bool, Map_Map_Object_Loader &) override
-	;
-	void Write(FileSystem &, Editor_Game_Base &, Map_Map_Object_Saver &) override
-	;
+class Map_Buildingdata_Data_Packet {
+public:
+	void Read(FileSystem&, Editor_Game_Base&, bool, Map_Map_Object_Loader&);
+	void Write(FileSystem&, Editor_Game_Base&, Map_Map_Object_Saver&);
 
 private:
 	virtual void read_constructionsite

=== modified file 'src/map_io/widelands_map_data_packet.h'
--- src/map_io/widelands_map_data_packet.h	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_data_packet.h	2014-06-10 18:27:45 +0000
@@ -20,8 +20,6 @@
 #ifndef WIDELANDS_MAP_DATA_PACKET_H
 #define WIDELANDS_MAP_DATA_PACKET_H
 
-#include "wexception.h"
-
 class FileSystem;
 
 namespace Widelands {
@@ -30,32 +28,15 @@
 class Map_Map_Object_Loader;
 struct Map_Map_Object_Saver;
 
-/** This class represents a data packet in a widelands map file. it is an
- * abstract base class
-*/
-struct Map_Data_Packet {
-	virtual ~Map_Data_Packet() {}
-
-	virtual void Read
-		(FileSystem &, Editor_Game_Base &, bool, Map_Map_Object_Loader &)
-
-		= 0;
-	virtual void Write
-		(FileSystem &, Editor_Game_Base &, Map_Map_Object_Saver &)
-
-		= 0;
-};
-
 }
 
-#define MAP_DATA_PACKET(name)                                                 \
-namespace Widelands {                                                         \
-struct name : public Map_Data_Packet {                                        \
-   virtual ~name() {}                                                         \
-   void Read                                                                  \
-      (FileSystem &, Editor_Game_Base &, bool, Map_Map_Object_Loader &);      \
-   void Write(FileSystem &, Editor_Game_Base &, Map_Map_Object_Saver &);      \
-};                                                                            \
-}                                                                             \
+#define MAP_DATA_PACKET(name)                                                                      \
+	namespace Widelands {                                                                           \
+	class name {                                                                                    \
+	public:                                                                                         \
+		void Read(FileSystem&, Editor_Game_Base&, bool, Map_Map_Object_Loader&);                     \
+		void Write(FileSystem&, Editor_Game_Base&, Map_Map_Object_Saver&);                           \
+	};                                                                                              \
+	}
 
 #endif

=== modified file 'src/map_io/widelands_map_elemental_data_packet.cc'
--- src/map_io/widelands_map_elemental_data_packet.cc	2014-03-04 13:24:58 +0000
+++ src/map_io/widelands_map_elemental_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -25,7 +25,6 @@
 #include "logic/editor_game_base.h"
 #include "logic/game_data_error.h"
 #include "logic/map.h"
-#include "logic/world.h"
 #include "profile/profile.h"
 
 namespace Widelands {
@@ -44,12 +43,12 @@
 			map->m_width       = s.get_int   ("map_w");
 			map->m_height      = s.get_int   ("map_h");
 			map->set_nrplayers  (s.get_int   ("nr_players"));
-			map->set_world_name (s.get_string("world"));
 			map->set_name       (s.get_string("name"));
 			map->set_author     (s.get_string("author"));
 			map->set_description(s.get_string("descr"));
 			map->set_hint       (s.get_string("hint", ""));
 			map->set_background (s.get_string("background"));
+			old_world_name_ = s.get_string("world", "");
 
 			std::string t = s.get_string("tags", "");
 			if (t != "") {
@@ -90,7 +89,6 @@
 	s.set_int   ("map_w",          map.get_width      ());
 	s.set_int   ("map_h",          map.get_height     ());
 	s.set_int   ("nr_players",     map.get_nrplayers  ());
-	s.set_string("world",          map.get_world_name ());
 	s.set_string("name",           map.get_name       ());
 	s.set_string("author",         map.get_author     ());
 	s.set_string("descr",          map.get_description());

=== modified file 'src/map_io/widelands_map_elemental_data_packet.h'
--- src/map_io/widelands_map_elemental_data_packet.h	2014-02-22 18:04:02 +0000
+++ src/map_io/widelands_map_elemental_data_packet.h	2014-06-10 18:27:45 +0000
@@ -20,6 +20,10 @@
 #ifndef WIDELANDS_MAP_ELEMENTAL_DATA_PACKET_H
 #define WIDELANDS_MAP_ELEMENTAL_DATA_PACKET_H
 
+#include <string>
+
+#include <stdint.h>
+
 #include "map_io/widelands_map_data_packet.h"
 
 namespace Widelands {
@@ -30,12 +34,9 @@
  * The elemental data packet contains all basic and elemental data
  * like number of players, map size, world name, magic bytes and so on
  */
-struct Map_Elemental_Data_Packet : public Map_Data_Packet {
-	void Read
-		(FileSystem &, Editor_Game_Base &, bool, Map_Map_Object_Loader &) override
-	;
-	void Write(FileSystem &, Editor_Game_Base &, Map_Map_Object_Saver &) override
-	;
+struct Map_Elemental_Data_Packet {
+	void Read(FileSystem&, Editor_Game_Base&, bool, Map_Map_Object_Loader&);
+	void Write(FileSystem&, Editor_Game_Base&, Map_Map_Object_Saver&);
 
 	//  The following function prereads a given map without the need of a
 	//  properly configured Editor_Game_Base object.
@@ -43,7 +44,12 @@
 
 	uint32_t get_version() {return m_version;}
 
+	// If this map was created before the one_world merge was done, this returns
+	// the old world name, otherwise "".
+	const std::string& old_world_name() const { return old_world_name_; }
+
 private:
+	std::string old_world_name_;
 	uint32_t m_version;
 };
 

=== modified file 'src/map_io/widelands_map_extradata_data_packet.cc'
--- src/map_io/widelands_map_extradata_data_packet.cc	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_extradata_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -35,13 +35,7 @@
 
 #define CURRENT_PACKET_VERSION 1
 
-
-void Map_Extradata_Data_Packet::Read
-	(FileSystem            &       fs,
-	 Editor_Game_Base&,
-	 bool                    const skip,
-	 Map_Map_Object_Loader &)
-{
+void Map_Extradata_Data_Packet::Read(FileSystem& fs, bool const skip) {
 	if (skip)
 		return;
 
@@ -90,7 +84,7 @@
 
 
 void Map_Extradata_Data_Packet::Write
-	(FileSystem & fs, Editor_Game_Base & egbase, Map_Map_Object_Saver &)
+	(FileSystem & fs, Editor_Game_Base & egbase)
 {
 	Profile prof;
 	prof.create_section("global").set_int

=== modified file 'src/map_io/widelands_map_extradata_data_packet.h'
--- src/map_io/widelands_map_extradata_data_packet.h	2013-07-26 20:19:36 +0000
+++ src/map_io/widelands_map_extradata_data_packet.h	2014-06-10 18:27:45 +0000
@@ -22,11 +22,19 @@
 
 #include "map_io/widelands_map_data_packet.h"
 
+namespace Widelands {
+
 /*
  * This packet contains all extra data in the map. This can currently be one of
  * the followings
  *   - Images
  */
-MAP_DATA_PACKET(Map_Extradata_Data_Packet);
+class Map_Extradata_Data_Packet {
+public:
+	void Read(FileSystem&, bool);
+	void Write(FileSystem&, Editor_Game_Base&);
+};
+
+}  // namespace Widelands
 
 #endif

=== modified file 'src/map_io/widelands_map_heights_data_packet.cc'
--- src/map_io/widelands_map_heights_data_packet.cc	2014-05-10 16:47:03 +0000
+++ src/map_io/widelands_map_heights_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -24,7 +24,7 @@
 #include "logic/editor_game_base.h"
 #include "logic/game_data_error.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 
 namespace Widelands {
 

=== modified file 'src/map_io/widelands_map_loader.cc'
--- src/map_io/widelands_map_loader.cc	2014-04-01 18:15:56 +0000
+++ src/map_io/widelands_map_loader.cc	2014-06-10 18:27:45 +0000
@@ -24,7 +24,7 @@
 #include "logic/map.h"
 #include "logic/player.h"
 #include "logic/tribe.h"
-#include "logic/world.h"
+#include "map_io/one_world_legacy_lookup_table.h"
 #include "map_io/widelands_map_allowed_building_types_data_packet.h"
 #include "map_io/widelands_map_allowed_worker_types_data_packet.h"
 #include "map_io/widelands_map_building_data_packet.h"
@@ -56,14 +56,13 @@
 namespace Widelands {
 
 WL_Map_Loader::WL_Map_Loader(FileSystem* fs, Map * const m)
-	: Map_Loader("", *m), m_fs(fs), m_mol(nullptr)
+	: Map_Loader("", *m), m_fs(fs)
 {
 	m->filesystem_.reset(fs);
 }
 
 
 WL_Map_Loader::~WL_Map_Loader() {
-	delete m_mol;
 }
 
 /**
@@ -77,14 +76,6 @@
 
 	{Map_Elemental_Data_Packet mp; mp.Pre_Read(*m_fs, &m_map);}
 
-	if (not World::exists_world(m_map.get_world_name()))
-		throw warning
-			(_("Invalid World"),
-			 _
-			 	("The world \"%s\" set by the map does not exist on your "
-			 	 "filesystem."),
-			 m_map.get_world_name());
-
 	{
 		Map_Player_Names_And_Tribes_Data_Packet p;
 		p.Pre_Read(*m_fs, &m_map, !scenario);
@@ -102,14 +93,6 @@
 	return 0;
 }
 
-
-void WL_Map_Loader::load_world() {
-	assert(get_state() == STATE_PRELOADED);
-	m_map.load_world();
-	set_state(STATE_WORLD_LOADED);
-}
-
-
 /*
  * Load the complete map and make sure that it runs without problems
  */
@@ -118,23 +101,16 @@
 {
 	ScopedTimer timer("WL_Map_Loader::load_map_complete() took %ums");
 
-	//  This is needed to ensure that world is loaded for multiplayer clients,
-	//  hosts do world loading while creating the game and the states are not
-	//  available outside this class to make a conditional load. If You know a
-	//  better way to fix this, DO IT! -- Alexia Death
-	if (get_state() == STATE_PRELOADED)
-		load_world();
-	assert(get_state() == STATE_WORLD_LOADED);
-
+	preload_map(scenario);
 	m_map.set_size(m_map.m_width, m_map.m_height);
-
-	delete m_mol;
-	m_mol = new Map_Map_Object_Loader;
+	m_mol.reset(new Map_Map_Object_Loader());
 
 	// MANDATORY PACKETS
 	// PRELOAD DATA BEGIN
 	log("Reading Elemental Data ... ");
-	{Map_Elemental_Data_Packet      p; p.Read(*m_fs, egbase, !scenario, *m_mol);}
+	Map_Elemental_Data_Packet elemental_data_packet;
+	elemental_data_packet.Read(*m_fs, egbase, !scenario, *m_mol);
+	const std::string old_world_name = elemental_data_packet.old_world_name();
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	egbase.allocate_player_maps(); //  Can do this now that map size is known.
@@ -157,19 +133,19 @@
 		log("took %ums\n ", timer.ms_since_last_query());
 	}
 
-
 	log("Reading Heights Data ... ");
 	{Map_Heights_Data_Packet        p; p.Read(*m_fs, egbase, !scenario, *m_mol);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
+	std::unique_ptr<OneWorldLegacyLookupTable> lookup_table(create_one_world_legacy_lookup_table(old_world_name));
 	log("Reading Terrain Data ... ");
-	{Map_Terrain_Data_Packet        p; p.Read(*m_fs, egbase, !scenario, *m_mol);}
+	{Map_Terrain_Data_Packet p; p.Read(*m_fs, egbase, *lookup_table);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	Map_Object_Packet mapobjects;
 
 	log("Reading Map Objects ... ");
-	mapobjects.Read(*m_fs, egbase, *m_mol);
+	mapobjects.Read(*m_fs, egbase, *m_mol, *lookup_table);
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	log("Reading Player Start Position Data ... ");
@@ -180,12 +156,12 @@
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	log("Reading Resources Data ... ");
-	{Map_Resources_Data_Packet      p; p.Read(*m_fs, egbase, !scenario, *m_mol);}
+	{Map_Resources_Data_Packet      p; p.Read(*m_fs, egbase, *lookup_table);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	//  NON MANDATORY PACKETS BELOW THIS POINT
 	log("Reading Map Extra Data ... ");
-	{Map_Extradata_Data_Packet      p; p.Read(*m_fs, egbase, !scenario, *m_mol);}
+	{Map_Extradata_Data_Packet      p; p.Read(*m_fs, !scenario);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	log("Reading Map Version Data ... ");
@@ -240,7 +216,6 @@
 	{Map_Roaddata_Data_Packet       p; p.Read(*m_fs, egbase, !scenario, *m_mol);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
-
 	log("Reading Buildingdata Data ... ");
 	{Map_Buildingdata_Data_Packet   p; p.Read(*m_fs, egbase, !scenario, *m_mol);}
 	log("took %ums\n ", timer.ms_since_last_query());
@@ -291,7 +266,7 @@
 			 "consider committing!\n",
 			 m_mol->get_nr_unloaded_objects());
 
-	m_map.recalc_whole_map();
+	m_map.recalc_whole_map(egbase.world());
 
 	set_state(STATE_LOADED);
 

=== modified file 'src/map_io/widelands_map_loader.h'
--- src/map_io/widelands_map_loader.h	2014-03-24 21:47:08 +0000
+++ src/map_io/widelands_map_loader.h	2014-06-10 18:27:45 +0000
@@ -21,11 +21,13 @@
 #define WIDELANDS_MAP_LOADER_H
 
 #include <cstring>
+#include <memory>
 #include <string>
 
 #include "map_io/map_loader.h"
 
 class FileSystem;
+class LuaInterface;
 
 namespace Widelands {
 
@@ -39,10 +41,9 @@
 	virtual ~WL_Map_Loader();
 
 	virtual int32_t preload_map(bool) override;
-	void load_world() override;
 	virtual int32_t load_map_complete(Editor_Game_Base &, bool) override;
 
-	Map_Map_Object_Loader * get_map_object_loader() {return m_mol;}
+	Map_Map_Object_Loader * get_map_object_loader() {return m_mol.get();}
 
 	static bool is_widelands_map(const std::string & filename) {
 		return !strcasecmp(&filename.c_str()[filename.size() - 4], WLMF_SUFFIX);
@@ -51,7 +52,7 @@
 private:
 	FileSystem* m_fs;  // not owned (owned by Map).
 	std::string m_filename;
-	Map_Map_Object_Loader * m_mol;
+	std::unique_ptr<Map_Map_Object_Loader> m_mol;
 };
 
 }

=== modified file 'src/map_io/widelands_map_node_ownership_data_packet.cc'
--- src/map_io/widelands_map_node_ownership_data_packet.cc	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_node_ownership_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -24,7 +24,7 @@
 #include "logic/editor_game_base.h"
 #include "logic/game_data_error.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 
 namespace Widelands {
 

=== modified file 'src/map_io/widelands_map_object_packet.cc'
--- src/map_io/widelands_map_object_packet.cc	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_object_packet.cc	2014-06-10 18:27:45 +0000
@@ -48,7 +48,7 @@
 
 
 void Map_Object_Packet::Read
-	(FileSystem & fs, Editor_Game_Base & egbase, Map_Map_Object_Loader & mol)
+	(FileSystem & fs, Editor_Game_Base & egbase, Map_Map_Object_Loader & mol, const OneWorldLegacyLookupTable& lookup_table)
 {
 	try {
 		FileRead fr;
@@ -65,7 +65,7 @@
 			case 0:
 				return;
 			case Map_Object::header_Immovable:
-				loaders.insert(Immovable::load(egbase, mol, fr));
+				loaders.insert(Immovable::load(egbase, mol, fr, lookup_table));
 				break;
 
 			case Map_Object::header_Battle:
@@ -73,7 +73,7 @@
 				break;
 
 			case Map_Object::header_Critter:
-				loaders.insert(Critter_Bob::load(egbase, mol, fr));
+				loaders.insert(Critter_Bob::load(egbase, mol, fr, lookup_table));
 				break;
 
 			case Map_Object::header_Worker:

=== modified file 'src/map_io/widelands_map_object_packet.h'
--- src/map_io/widelands_map_object_packet.h	2014-03-24 21:47:08 +0000
+++ src/map_io/widelands_map_object_packet.h	2014-06-10 18:27:45 +0000
@@ -25,6 +25,7 @@
 #include "logic/instances.h"
 
 class FileSystem;
+class OneWorldLegacyLookupTable;
 
 namespace Widelands {
 
@@ -53,7 +54,7 @@
 
 	~Map_Object_Packet();
 
-	void Read (FileSystem &, Editor_Game_Base &, Map_Map_Object_Loader &);
+	void Read (FileSystem &, Editor_Game_Base &, Map_Map_Object_Loader &, const OneWorldLegacyLookupTable& lookup_table);
 
 	void LoadFinish();
 

=== modified file 'src/map_io/widelands_map_player_names_and_tribes_data_packet.cc'
--- src/map_io/widelands_map_player_names_and_tribes_data_packet.cc	2014-03-04 13:24:58 +0000
+++ src/map_io/widelands_map_player_names_and_tribes_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -22,7 +22,7 @@
 #include "logic/editor_game_base.h"
 #include "logic/game_data_error.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "profile/profile.h"
 
 namespace Widelands {

=== modified file 'src/map_io/widelands_map_player_names_and_tribes_data_packet.h'
--- src/map_io/widelands_map_player_names_and_tribes_data_packet.h	2014-02-22 18:04:02 +0000
+++ src/map_io/widelands_map_player_names_and_tribes_data_packet.h	2014-06-10 18:27:45 +0000
@@ -30,14 +30,11 @@
  * This data packet contains player names
  * and tribes (scenario packet)
  */
-struct Map_Player_Names_And_Tribes_Data_Packet : public Map_Data_Packet {
+struct Map_Player_Names_And_Tribes_Data_Packet {
 	virtual ~Map_Player_Names_And_Tribes_Data_Packet();
 
-	virtual void Read
-		(FileSystem &, Editor_Game_Base &, bool, Map_Map_Object_Loader &) override
-	;
-	void Write(FileSystem &, Editor_Game_Base &, Map_Map_Object_Saver &) override
-	;
+	virtual void Read(FileSystem&, Editor_Game_Base&, bool, Map_Map_Object_Loader&);
+	void Write(FileSystem&, Editor_Game_Base&, Map_Map_Object_Saver&);
 
 	void Pre_Read(FileSystem &, Map *, bool skip);
 };

=== modified file 'src/map_io/widelands_map_player_position_data_packet.cc'
--- src/map_io/widelands_map_player_position_data_packet.cc	2014-06-08 21:02:17 +0000
+++ src/map_io/widelands_map_player_position_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -46,7 +46,7 @@
 			Map               & map        = egbase.map();
 			Extent        const extent     = map.extent       ();
 			Player_Number const nr_players = map.get_nrplayers();
-			iterate_player_numbers(p, nr_players)
+			iterate_player_numbers(p, nr_players) {
 				try {
 					char buffer[10];
 					snprintf(buffer, sizeof(buffer), "player_%u", p);
@@ -54,6 +54,7 @@
 				} catch (const _wexception & e) {
 					throw game_data_error("player %u: %s", p, e.what());
 				}
+			}
 		} else
 			throw game_data_error
 				("unknown/unhandled version %u", packet_version);

=== modified file 'src/map_io/widelands_map_players_view_data_packet.cc'
--- src/map_io/widelands_map_players_view_data_packet.cc	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_players_view_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -32,6 +32,7 @@
 #include "logic/instances.h" //for g_flag_descr
 #include "logic/player.h"
 #include "logic/tribe.h"
+#include "logic/world/world.h"
 #include "upcast.h"
 
 
@@ -212,12 +213,11 @@
 	std::string name;
 };
 struct world_immovable_nonexistent : public FileRead::_data_error {
-	world_immovable_nonexistent(char const* const Worldname, char const* const Name)
-	   : _data_error("world %s does not define immovable type \"%s\"", Worldname, Name),
-	     worldname(Worldname),
+	world_immovable_nonexistent(char const* const Name)
+	   : _data_error("world does not define immovable type \"%s\"",  Name),
 	     name(Name) {
 	}
-	char const* const worldname, *const name;
+	char const* const name;
 };
 struct building_nonexistent : public FileRead::_data_error {
 	building_nonexistent(const std::string& Tribename, char const* const Name)
@@ -284,7 +284,7 @@
 	char const* const name = fr->CString();
 	int32_t const index = world.get_immovable_index(name);
 	if (index == -1)
-		throw world_immovable_nonexistent(world.get_name(), name);
+		throw world_immovable_nonexistent(name);
 	return *world.get_immovable_descr(index);
 }
 
@@ -296,7 +296,7 @@
 	if (Tribe_Descr const* const tribe = ReadTribe_allow_null(fr, egbase))
 		return ReadImmovable_Type(fr, *tribe);
 	else
-		return ReadImmovable_Type(fr, egbase.map().world());
+		return ReadImmovable_Type(fr, egbase.world());
 }
 
 // Reads a CString and interprets t as the name of an immovable type.
@@ -472,10 +472,7 @@
 						//  Must be initialized because the rendering code is
 						//  accessing it even for triangles that the player does not
 						//  see (it is the darkening that actually hides the ground
-						//  from the player). This is important for worlds where the
-						//  number of terrain types is not maximal (16), so that an
-						//  uninitialized terrain index could cause a not found error
-						//  in DescriptionMaintainer<Terrain_Descr>::get(Terrain_Index).
+						//  from the player).
 						Field::Terrains terrains; terrains.d = terrains.r = 0;
 
 						if (f_vision | bl_vision | br_vision)

=== modified file 'src/map_io/widelands_map_port_spaces_data_packet.cc'
--- src/map_io/widelands_map_port_spaces_data_packet.cc	2014-06-08 21:02:17 +0000
+++ src/map_io/widelands_map_port_spaces_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -85,7 +85,7 @@
 	for (const Coords& c : map.get_port_spaces()) {
 		FCoords fc = map.get_fcoords(c);
 		if
-			((map.get_max_nodecaps(fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG
+			((map.get_max_nodecaps(egbase.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG
 			 ||
 			 map.find_portdock(fc).empty())
 		{

=== modified file 'src/map_io/widelands_map_port_spaces_data_packet.h'
--- src/map_io/widelands_map_port_spaces_data_packet.h	2014-02-22 18:04:02 +0000
+++ src/map_io/widelands_map_port_spaces_data_packet.h	2014-06-10 18:27:45 +0000
@@ -20,6 +20,8 @@
 #ifndef WIDELANDS_MAP_PORT_SPACES_DATA_PACKET_H
 #define WIDELANDS_MAP_PORT_SPACES_DATA_PACKET_H
 
+#include <stdint.h>
+
 #include "map_io/widelands_map_data_packet.h"
 
 namespace Widelands {
@@ -27,10 +29,9 @@
 class Map;
 
 /// The port data packet contains all port build spaces
-struct Map_Port_Spaces_Data_Packet : public Map_Data_Packet {
-	void Read
-		(FileSystem &, Editor_Game_Base &, bool, Map_Map_Object_Loader &) override;
-	void Write(FileSystem &, Editor_Game_Base &, Map_Map_Object_Saver &) override;
+struct Map_Port_Spaces_Data_Packet {
+	void Read(FileSystem&, Editor_Game_Base&, bool, Map_Map_Object_Loader&);
+	void Write(FileSystem&, Editor_Game_Base&, Map_Map_Object_Saver&);
 
 	//  The following function prereads a given map without the need of a
 	//  properly configured Editor_Game_Base object.

=== modified file 'src/map_io/widelands_map_resources_data_packet.cc'
--- src/map_io/widelands_map_resources_data_packet.cc	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_resources_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -25,7 +25,9 @@
 #include "logic/editor_game_base.h"
 #include "logic/game_data_error.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/world.h"
+#include "map_io/one_world_legacy_lookup_table.h"
 
 namespace Widelands {
 
@@ -33,14 +35,13 @@
 
 
 void Map_Resources_Data_Packet::Read
-	(FileSystem & fs, Editor_Game_Base & egbase, bool, Map_Map_Object_Loader &)
+	(FileSystem & fs, Editor_Game_Base & egbase, const OneWorldLegacyLookupTable& lookup_table)
 {
 	FileRead fr;
-
 	fr.Open(fs, "binary/resource");
 
 	Map   & map   = egbase.map();
-	World & world = map.world();
+	const World & world = egbase.world();
 
 	const uint16_t packet_version = fr.Unsigned16();
 	if (packet_version == CURRENT_PACKET_VERSION) {
@@ -55,11 +56,11 @@
 		std::map<uint8_t, uint8_t> smap;
 		for (uint8_t i = 0; i < nr_res; ++i) {
 			uint8_t const id = fr.Unsigned16();
-			char const * const buffer = fr.CString();
-			int32_t const res = world.get_resource(buffer);
+			const std::string resource_name = lookup_table.lookup_resource(fr.CString());
+			int32_t const res = world.get_resource(resource_name.c_str());
 			if (res == -1)
 				throw game_data_error
-					("resource '%s' exists in map but not in world", buffer);
+					("resource '%s' exists in map but not in world", resource_name.c_str());
 			smap[id] = res;
 		}
 
@@ -102,7 +103,7 @@
  * in nearly all cases.
  */
 void Map_Resources_Data_Packet::Write
-	(FileSystem & fs, Editor_Game_Base & egbase, Map_Map_Object_Saver &)
+	(FileSystem & fs, Editor_Game_Base & egbase)
 {
 	FileWrite fw;
 
@@ -113,13 +114,13 @@
 	// (saved like terrains)
 	// Write the number of resources
 	const Map   & map   = egbase.map  ();
-	const World & world = map   .world();
+	const World& world = egbase.world();
 	uint8_t const nr_res = world.get_nr_resources();
 	fw.Unsigned16(nr_res);
 
 	//  write all resources names and their id's
 	for (int32_t i = 0; i < nr_res; ++i) {
-		const Resource_Descr & res = *world.get_resource(i);
+		const ResourceDescription & res = *world.get_resource(i);
 		fw.Unsigned16(i);
 		fw.CString(res.name().c_str());
 	}

=== modified file 'src/map_io/widelands_map_resources_data_packet.h'
--- src/map_io/widelands_map_resources_data_packet.h	2013-07-26 20:19:36 +0000
+++ src/map_io/widelands_map_resources_data_packet.h	2014-06-10 18:27:45 +0000
@@ -22,6 +22,16 @@
 
 #include "map_io/widelands_map_data_packet.h"
 
-MAP_DATA_PACKET(Map_Resources_Data_Packet);
+class OneWorldLegacyLookupTable;
+
+namespace Widelands {
+
+class Map_Resources_Data_Packet {
+public:
+	void Read(FileSystem&, Editor_Game_Base&, const OneWorldLegacyLookupTable&);
+	void Write(FileSystem&, Editor_Game_Base&);
+};
+
+}
 
 #endif

=== modified file 'src/map_io/widelands_map_saver.cc'
--- src/map_io/widelands_map_saver.cc	2014-04-21 09:19:14 +0000
+++ src/map_io/widelands_map_saver.cc	2014-06-10 18:27:45 +0000
@@ -94,7 +94,7 @@
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	log("Writing Terrain Data ... ");
-	{Map_Terrain_Data_Packet                 p; p.Write(m_fs, m_egbase, *m_mos);}
+	{Map_Terrain_Data_Packet                 p; p.Write(m_fs, m_egbase);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	log("Writing Player Start Position Data ... ");
@@ -109,12 +109,12 @@
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	log("Writing Resources Data ... ");
-	{Map_Resources_Data_Packet               p; p.Write(m_fs, m_egbase, *m_mos);}
+	{Map_Resources_Data_Packet               p; p.Write(m_fs, m_egbase);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	//  NON MANDATORY PACKETS BELOW THIS POINT
 	log("Writing Map Extra Data ... ");
-	{Map_Extradata_Data_Packet               p; p.Write(m_fs, m_egbase, *m_mos);}
+	{Map_Extradata_Data_Packet               p; p.Write(m_fs, m_egbase);}
 	log("took %ums\n ", timer.ms_since_last_query());
 
 	log("Writing Map Version ... ");
@@ -122,7 +122,6 @@
 	log("took %ums\n ", timer.ms_since_last_query());
 
 
-
 	const Map & map = m_egbase.map();
 
 	Player_Number const nr_players = map.get_nrplayers();

=== modified file 'src/map_io/widelands_map_scripting_data_packet.cc'
--- src/map_io/widelands_map_scripting_data_packet.cc	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_scripting_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -30,6 +30,7 @@
 #include "logic/game.h"
 #include "logic/game_data_error.h"
 #include "logic/map.h"
+#include "logic/world/world.h"
 #include "profile/profile.h"
 #include "scripting/scripting.h"
 #include "upcast.h"

=== modified file 'src/map_io/widelands_map_terrain_data_packet.cc'
--- src/map_io/widelands_map_terrain_data_packet.cc	2014-05-11 07:38:01 +0000
+++ src/map_io/widelands_map_terrain_data_packet.cc	2014-06-10 18:27:45 +0000
@@ -27,21 +27,22 @@
 #include "logic/editor_game_base.h"
 #include "logic/game_data_error.h"
 #include "logic/map.h"
-#include "logic/world.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
+#include "map_io/one_world_legacy_lookup_table.h"
 
 namespace Widelands {
 
 #define CURRENT_PACKET_VERSION 1
 
-
-void Map_Terrain_Data_Packet::Read
-	(FileSystem & fs, Editor_Game_Base & egbase, bool, Map_Map_Object_Loader &)
-{
+void Map_Terrain_Data_Packet::Read(FileSystem& fs,
+                                   Editor_Game_Base& egbase,
+                                   const OneWorldLegacyLookupTable& lookup_table) {
 	FileRead fr;
 	fr.Open(fs, "binary/terrain");
 
 	Map & map = egbase.map();
-	World & world = map.world();
+	const World & world = egbase.world();
 
 	try {
 		uint16_t const packet_version = fr.Unsigned16();
@@ -51,19 +52,19 @@
 			typedef std::map<const uint16_t, Terrain_Index> terrain_id_map;
 			terrain_id_map smap;
 			for (uint16_t i = 0; i < nr_terrains; ++i) {
-				uint16_t                       const id   = fr.Unsigned16();
-				char                   const * const name = fr.CString   ();
-				terrain_id_map::const_iterator const it   = smap.find(id);
-				if (it != smap.end())
-					log
-						("Map_Terrain_Data_Packet::Read: WARNING: Found duplicate "
-						 "terrain id %i: Previously defined as \"%s\", now as "
-						 "\"%s\".",
-						 id, world.terrain_descr(it->second).name().c_str(), name);
-				if (not world.get_ter(name))
-					throw game_data_error
-						("Terrain '%s' exists in map, not in world!", name);
-				smap[id] = world.index_of_terrain(name);
+				const uint16_t id = fr.Unsigned16();
+				char const* const old_terrain_name = fr.CString();
+				terrain_id_map::const_iterator const it = smap.find(id);
+				if (it != smap.end()) {
+					throw game_data_error(
+					   "Map_Terrain_Data_Packet::Read: WARNING: Found duplicate terrain id %i.", id);
+				}
+				const std::string new_terrain_name =
+				   lookup_table.lookup_terrain(old_terrain_name);
+				if (!world.get_ter(new_terrain_name.c_str())) {
+					throw game_data_error("Terrain '%s' exists in map, not in world!", new_terrain_name.c_str());
+				}
+				smap[id] = world.terrains().get_index(new_terrain_name.c_str());
 			}
 
 			Map_Index const max_index = map.max_index();
@@ -72,9 +73,9 @@
 				f.set_terrain_r(smap[fr.Unsigned8()]);
 				f.set_terrain_d(smap[fr.Unsigned8()]);
 			}
-		} else
-			throw game_data_error
-				("unknown/unhandled version %u", packet_version);
+		} else {
+			throw game_data_error("unknown/unhandled version %u", packet_version);
+		}
 	} catch (const _wexception & e) {
 		throw game_data_error("terrain: %s", e.what());
 	}
@@ -82,7 +83,7 @@
 
 
 void Map_Terrain_Data_Packet::Write
-	(FileSystem & fs, Editor_Game_Base & egbase, Map_Map_Object_Saver &)
+	(FileSystem & fs, Editor_Game_Base & egbase)
 {
 
 	FileWrite fw;
@@ -92,13 +93,13 @@
 	//  This is a bit more complicated saved so that the order of loading of the
 	//  terrains at run time does not matter. This is slow like hell.
 	const Map & map = egbase.map();
-	const World & world = map.world();
-	Terrain_Index const nr_terrains = world.get_nr_terrains();
+	const World & world = egbase.world();
+	Terrain_Index const nr_terrains = world.terrains().get_nitems();
 	fw.Unsigned16(nr_terrains);
 
 	std::map<const char * const, Terrain_Index> smap;
 	for (Terrain_Index i = 0; i < nr_terrains; ++i) {
-		const char * const name = world.get_ter(i).name().c_str();
+		const char * const name = world.terrain_descr(i).name().c_str();
 		smap[name] = i;
 		fw.Unsigned16(i);
 		fw.CString(name);

=== modified file 'src/map_io/widelands_map_terrain_data_packet.h'
--- src/map_io/widelands_map_terrain_data_packet.h	2013-07-26 20:19:36 +0000
+++ src/map_io/widelands_map_terrain_data_packet.h	2014-06-10 18:27:45 +0000
@@ -20,8 +20,21 @@
 #ifndef WIDELANDS_MAP_TERRAIN_DATA_PACKET_H
 #define WIDELANDS_MAP_TERRAIN_DATA_PACKET_H
 
-#include "map_io/widelands_map_data_packet.h"
-
-MAP_DATA_PACKET(Map_Terrain_Data_Packet);
+#include <string>
+
+class OneWorldLegacyLookupTable;
+class FileSystem;
+
+namespace Widelands {
+
+class Editor_Game_Base;
+
+class Map_Terrain_Data_Packet {
+public:
+	void Read(FileSystem&, Editor_Game_Base&, const OneWorldLegacyLookupTable& lookup_table);
+	void Write(FileSystem&, Editor_Game_Base&);
+};
+
+}
 
 #endif

=== modified file 'src/network/netclient.cc'
--- src/network/netclient.cc	2014-05-10 17:07:11 +0000
+++ src/network/netclient.cc	2014-06-10 18:27:45 +0000
@@ -905,6 +905,7 @@
 			for (uint8_t j = packet.Unsigned8(); j; --j) {
 				std::string const initialization_script = packet.String();
 				std::unique_ptr<LuaTable> t = lua.run_script(initialization_script);
+				t->do_not_warn_about_unaccessed_keys();
 				info.initializations.push_back
 					(TribeBasicInfo::Initialization(initialization_script, t->get_string("name")));
 			}

=== modified file 'src/profile/profile.cc'
--- src/profile/profile.cc	2014-06-08 21:02:17 +0000
+++ src/profile/profile.cc	2014-06-10 18:27:45 +0000
@@ -33,6 +33,7 @@
 #include "log.h"
 #include "logic/player.h"
 #include "logic/tribe.h"
+#include "logic/world/world.h"
 #include "wexception.h"
 
 #define TRUE_WORDS 4
@@ -353,7 +354,6 @@
 	return get_safe_string(name.c_str());
 }
 
-
 /**
  * Returns the integer value of the given key. Falls back to a default value
  * if the key is not found.
@@ -802,11 +802,12 @@
 							throw wexception("key %s outside section", p);
 					}
 
-					if (translate_line && *tail)
+					if (translate_line && *tail) {
 						data += i18n::translate(tail);
-					else
+					 } else {
 						data += tail;
-					if (s && ! reading_multiline) { // error() may or may not throw
+					 }
+					if (s && ! reading_multiline) {
 						s->create_val_duplicate(key, data.c_str());
 						data.clear();
 					}

=== modified file 'src/profile/profile.h'
--- src/profile/profile.h	2014-06-08 21:02:17 +0000
+++ src/profile/profile.h	2014-06-10 18:27:45 +0000
@@ -31,8 +31,7 @@
 #include "point.h"
 #include "port.h"
 
-
-extern struct Profile g_options;
+extern class Profile g_options;
 class FileSystem;
 
 /**
@@ -53,8 +52,9 @@
  * retrieve any unused key. Value::used is used to determine which key is next.
  * The value of the key is stored in the second parameter.
  */
-struct Section {
-	friend struct Profile;
+class Section {
+public:
+	friend class Profile;
 
 	struct Value {
 		bool   m_used;
@@ -189,7 +189,8 @@
  * Returns the next unused section of the given name, or 0 if all sections
  * have been used. name can be 0 to retrieve any remaining sections.
  */
-struct Profile : boost::noncopyable {
+class Profile : boost::noncopyable {
+public:
 	enum {
 		err_ignore = 0,
 		err_log,

=== modified file 'src/s2map.cc'
--- src/s2map.cc	2014-05-11 07:38:01 +0000
+++ src/s2map.cc	2014-06-10 18:27:45 +0000
@@ -34,10 +34,11 @@
 #include "logic/game.h"
 #include "logic/map.h"
 #include "logic/mapregion.h"
-#include "logic/message.h"
-#include "logic/player.h"
-#include "logic/world.h"
+#include "logic/world/world.h"
 #include "map_io/map_loader.h"
+#include "map_io/one_world_legacy_lookup_table.h"
+#include "scoped_timer.h"
+#include "scripting/scripting.h"
 #include "upcast.h"
 #include "wexception.h"
 
@@ -46,18 +47,270 @@
 using std::ios;
 using std::setiosflags;
 
-// this is a detail of S2 maps
-#define CRITTER_PER_DEFINITION   1
+namespace  {
+
+struct S2MapDescrHeader {
+
+	char    magic[10]; // "WORLD_V1.0"
+	char    name [20];
+	int16_t w;
+	int16_t h;
+	int8_t  uses_world; // 0 = green, 1 =black, 2 = winter
+	int8_t  nplayers;
+	char    author[26];
+	char    bulk[2290]; // unknown
+} /* size 2352 */;
+
+// TODO: the following bob types appear in S2 maps but are unknown
+//  Somebody who can run Settlers II please check them out
+//  11 (0x0B)
+//  40 (0x28)
+//  41 (0x29)
+
+const int BOB_NONE = 0x00;
+
+const int BOB_STONE1 = 0x01;
+const int BOB_STONE2 = 0x02;
+const int BOB_STONE3 = 0x03;
+const int BOB_STONE4 = 0x04;
+const int BOB_STONE5 = 0x05;
+const int BOB_STONE6 = 0x06;
+
+const int BOB_SKELETON1 = 0x07;
+const int BOB_SKELETON2 = 0x08;
+const int BOB_SKELETON3 = 0x21;
+
+const int BOB_STANDING_STONES1 = 0x18;
+const int BOB_STANDING_STONES2 = 0x19;
+const int BOB_STANDING_STONES3 = 0x1a;
+const int BOB_STANDING_STONES4 = 0x1b;
+const int BOB_STANDING_STONES5 = 0x1c;
+const int BOB_STANDING_STONES6 = 0x1d;
+const int BOB_STANDING_STONES7 = 0x1e;
+
+const int BOB_MUSHROOM1 = 0x01;
+const int BOB_MUSHROOM2 = 0x22;
+
+const int BOB_PEBBLE1 = 0x02;
+const int BOB_PEBBLE2 = 0x03;
+const int BOB_PEBBLE3 = 0x04;
+const int BOB_PEBBLE4 = 0x25;
+const int BOB_PEBBLE5 = 0x26;
+const int BOB_PEBBLE6 = 0x27;
+
+const int BOB_DEADTREE1 = 0x05;
+const int BOB_DEADTREE2 = 0x06;
+const int BOB_DEADTREE3 = 0x20;
+const int BOB_DEADTREE4 = 0x1f;
+
+const int BOB_CACTUS1 = 0x0c;
+const int BOB_CACTUS2 = 0x0d;
+
+const int BOB_BUSH1 = 0x11;
+const int BOB_BUSH2 = 0x13;
+const int BOB_BUSH3 = 0x10;
+const int BOB_BUSH4 = 0x12;
+const int BOB_BUSH5 = 0x0a;
+
+// Settlers 2 has 8 types of trees.
+// I assume that different animation states are stored in the map file
+// to create the following 32 values. I assume that 4 trees are grouped
+// together.
+// Unfortunately, I can't verify that (can't run the S2 editor).
+// In the end, it doesn't matter much anyway.
+const int BOB_TREE1_T = 0x70;
+const int BOB_TREE1_S = 0x71;
+const int BOB_TREE1_M = 0x72;
+const int BOB_TREE1 = 0x73;
+
+const int BOB_TREE2_T = 0x74;
+const int BOB_TREE2_S = 0x75;
+const int BOB_TREE2_M = 0x76;
+const int BOB_TREE2 = 0x77;
+
+const int BOB_TREE3_T = 0xb0;
+const int BOB_TREE3_S = 0xb1;
+const int BOB_TREE3_M = 0xb2;
+const int BOB_TREE3 = 0xb3;
+
+const int BOB_TREE4_T = 0xb4;
+const int BOB_TREE4_S = 0xb5;
+const int BOB_TREE4_M = 0xb6;
+const int BOB_TREE4 = 0xb7;
+
+const int BOB_TREE5_T = 0xf0;
+const int BOB_TREE5_S = 0xf1;
+const int BOB_TREE5_M = 0xf2;
+const int BOB_TREE5 = 0xf3;
+
+const int BOB_TREE6_T = 0xf4;
+const int BOB_TREE6_S = 0xf5;
+const int BOB_TREE6_M = 0xf6;
+const int BOB_TREE6 = 0xf7;
+
+const int BOB_TREE7_T = 0x30;
+const int BOB_TREE7_S = 0x31;
+const int BOB_TREE7_M = 0x32;
+const int BOB_TREE7 = 0x33;
+
+const int BOB_TREE8_T = 0x34;
+const int BOB_TREE8_S = 0x35;
+const int BOB_TREE8_M = 0x36;
+const int BOB_TREE8 = 0x37;
+
+const int BOB_GRASS1 = 0x0e;
+const int BOB_GRASS2 = 0x14;
+const int BOB_GRASS3 = 0x0f;
+
+/// Some of the original S2 maps have rather odd sizes. In that case, however,
+/// width (and height?) are rounded up to some alignment. The in-file size of a
+/// section is stored in the section header (I think ;)).
+/// This is the work-around.
+///
+/// Returns a pointer to the (packed) contents of the section. nullptr if the
+//read / failed.
+std::unique_ptr<uint8_t[]>
+load_s2mf_section(FileRead& fr, int32_t const width, int32_t const height) {
+	char buffer[256];
+
+	std::unique_ptr<uint8_t[]> section;
+	memcpy(buffer, fr.Data(6), 6);
+	if
+		(buffer[0] != 0x10 or
+		 buffer[1] != 0x27 or
+		 buffer[2] != 0x00 or
+		 buffer[3] != 0x00 or
+		 buffer[4] != 0x00 or
+		 buffer[5] != 0x00)
+	{
+		cerr << "Section marker not found" << endl;
+		return section;
+	}
+
+	uint16_t const dw = fr.Unsigned16();
+	uint16_t const dh = fr.Unsigned16();
+
+	{
+		uint16_t const one = fr.Unsigned16();
+		if (one != 1)
+			throw wexception("expected 1 but found %u", one);
+	}
+	int32_t const size = fr.Signed32();
+	if (size != dw * dh)
+		throw wexception("expected %u but found %u", dw * dh, size);
+
+	if (dw < width || dh < height) {
+		cerr << "Section not big enough" << endl;
+		return nullptr;
+	}
+
+	section.reset(new uint8_t[size]);
+	int32_t y = 0;
+	for (; y < height; ++y) {
+		uint8_t const* const ptr = reinterpret_cast<uint8_t*>(fr.Data(width));
+		memcpy(section.get() + y * width, ptr, width);
+		fr.Data(dw - width);  // skip the alignment junk
+	}
+	while (y < dh) {
+		fr.Data(dw);  // more alignment junk++ y;
+	}
+
+	return section;
+}
+
+std::string get_world_name(S2_Map_Loader::WorldType world) {
+	switch (world) {
+		case S2_Map_Loader::GREENLAND: return "greenland";
+		case S2_Map_Loader::BLACKLAND: return "blackland";
+		case S2_Map_Loader::WINTERLAND: return "winterland";
+		default:
+			throw wexception("Unknown World in map file.");
+	}
+}
+
+// Returns S2 terrain index into (pre one-world) terrain names. Those are then
+// looked up in the legacy conversion code and this gives the Widelands
+// terrain.
+class TerrainConverter : boost::noncopyable {
+public:
+	TerrainConverter(const Widelands::World& world, const OneWorldLegacyLookupTable& lookup_table);
+	Widelands::Terrain_Index lookup(S2_Map_Loader::WorldType world, int8_t c) const;
+
+protected:
+	const OneWorldLegacyLookupTable& one_world_legacy_lookup_table_;
+	const Widelands::World& world_;
+	const std::map<S2_Map_Loader::WorldType, std::vector<std::string>> table_;
+};
+
+TerrainConverter::TerrainConverter(const Widelands::World& world, const OneWorldLegacyLookupTable& lookup_table) :
+	one_world_legacy_lookup_table_(lookup_table),
+	world_(world),
+	table_
+	{
+	std::make_pair(S2_Map_Loader::GREENLAND, std::vector<std::string>
+		{
+			"steppe", "berg1", "schnee", "sumpf", "strand", "wasser", "wiese1",
+			"wiese2", "wiese3", "berg2", "berg3", "berg4", "steppe_kahl",
+			"wiese4", "lava", "bergwiese"
+		}),
+	std::make_pair(S2_Map_Loader::BLACKLAND, std::vector<std::string>
+		{
+			"ashes", "mountain1", "lava-stone1", "lava-stone2", "strand", "water",
+			"hardground1", "hardground2", "hardground3", "mountain2", "mountain3",
+			"mountain4", "ashes2", "hardground4", "lava", "hardlava"
+		}),
+	std::make_pair(S2_Map_Loader::WINTERLAND, std::vector<std::string>
+		{
+			"tundra", "mountain1", "ice_flows", "ice_flows2", "ice", "water",
+			"tundra_taiga", "tundra2", "tundra3", "mountain2", "mountain3",
+			"mountain4", "strand", "taiga", "lava", "snow"
+		})
+	}
+{}
+
+Widelands::Terrain_Index TerrainConverter::lookup(S2_Map_Loader::WorldType world, int8_t c) const {
+	switch (c) {
+	// the following comments are valid for greenland - blackland and winterland have equivalents
+	// source: http://bazaar.launchpad.net/~xaser/s25rttr/s25edit/view/head:/WLD_reference.txt
+	case 0x00: c =  0; break; // steppe meadow1
+	case 0x01: c =  1; break; // mountain 1
+	case 0x02: c =  2; break; // snow
+	case 0x03: c =  3; break; // swamp
+	case 0x04: c =  4; break; // steppe = strand
+	case 0x05: c =  5; break; // water
+	case 0x06: c =  4; break; // strand
+	case 0x07: c = 12; break; // steppe 2 = dry land
+	case 0x08: c =  6; break; // meadow 1
+	case 0x09: c =  7; break; // meadow 2
+	case 0x0a: c =  8; break; // meadow 3
+	case 0x0b: c =  9; break; // mountain 2
+	case 0x0c: c = 10; break; // mountain 3
+	case 0x0d: c = 11; break; // mountain 4
+	case 0x0e: c = 12; break; // steppe meadow 2
+	case 0x0f: c = 13; break; // flower meadow
+	case 0x10: c = 14; break; // lava
+	// case 0x11: // color
+	case 0x12: c = 15; break; // mountain meadow
+	case 0x13: c =  4; break; // unknown texture
+
+	default:
+		log("Unknown texture %x. Defaulting to water.\n", c);
+		c = 7;
+		break;
+	}
+
+	const std::string& old_terrain_name = table_.at(world)[c];
+	return world_.terrains().get_index(
+	   one_world_legacy_lookup_table_.lookup_terrain(old_terrain_name));
+}
+
+}  // namespace
 
 S2_Map_Loader::S2_Map_Loader(const char * filename, Widelands::Map & M)
-: Widelands::Map_Loader(filename, M)
+: Widelands::Map_Loader(filename, M), m_filename(filename)
 {
-	strncpy(m_filename, filename, sizeof(m_filename));
-	if (m_filename[sizeof(m_filename) - 1])
-		throw;
 }
 
-
 /// Load the header. The map will then return valid information when
 /// get_width(), get_nrplayers(), get_author() and so on are called.
 int32_t S2_Map_Loader::preload_map(bool const scenario) {
@@ -65,10 +318,10 @@
 
 	m_map.cleanup();
 
-	load_s2mf_header();
+	FileRead fr;
+	fr.Open(*g_fs, m_filename.c_str());
 
-	if (not Widelands::World::exists_world(m_map.get_world_name()))
-		throw wexception("world %s does not exist", m_map.get_world_name());
+	load_s2mf_header(fr);
 
 	if (scenario) {
 		//  Load this as scenario. There is no such a thing as S2 scenario,
@@ -101,32 +354,17 @@
 }
 
 /**
- * load predefined world of the S2Map
- */
-void S2_Map_Loader::load_world() {
-	assert(get_state() == STATE_PRELOADED);
-	m_map.load_world();
-	set_state(STATE_WORLD_LOADED);
-}
-
-
-/**
- * Completely loads the map, loads the
- * corresponding world, loads the graphics
- * and places all the objects. From now on
- * the Map* can't be set to another one.
+ * Completely loads the map, loads the graphics and places all the objects.
+ * From now on the Map* can't be set to another one.
  */
 int32_t S2_Map_Loader::load_map_complete
 	(Widelands::Editor_Game_Base & egbase, bool)
 {
-	if (get_state() == STATE_PRELOADED)
-		load_world();
-	assert(get_state() == STATE_WORLD_LOADED);
+	ScopedTimer timer("S2_Map_Loader::load_map_complete() took %ums");
 
-	m_map.set_size(m_map.m_width, m_map.m_height);
 	load_s2mf(egbase);
 
-	m_map.recalc_whole_map();
+	m_map.recalc_whole_map(egbase.world());
 
 	postload_fix_conversion(egbase);
 
@@ -136,81 +374,12 @@
 }
 
 
-/// Some of the original S2 maps have rather odd sizes. In that case, however,
-/// width (and height?) are rounded up to some alignment. The in-file size of a
-/// section is stored in the section header (I think ;)).
-/// This is the work-around.
-///
-/// Returns a pointer to the (packed) contents of the section. 0 if the read
-/// failed.
-/// If successful, you must free the returned pointer.
-uint8_t * S2_Map_Loader::load_s2mf_section
-	(FileRead & fr, int32_t const width, int32_t const height)
-{
-	char buffer[256];
-
-	memcpy(buffer, fr.Data(6), 6);
-	if
-		(buffer[0] != 0x10 or
-		 buffer[1] != 0x27 or
-		 buffer[2] != 0x00 or
-		 buffer[3] != 0x00 or
-		 buffer[4] != 0x00 or
-		 buffer[5] != 0x00)
-	{
-		cerr << "Section marker not found" << endl;
-		return nullptr;
-	}
-
-	uint16_t const dw = fr.Unsigned16();
-	uint16_t const dh = fr.Unsigned16();
-
-	{
-		uint16_t const one = fr.Unsigned16();
-		if (one != 1)
-			throw wexception("expected 1 but found %u", one);
-	}
-	int32_t const size = fr.Signed32();
-	if (size != dw * dh)
-		throw wexception("expected %u but found %u", dw * dh, size);
-
-	if (dw < width || dh < height) {
-		cerr << "Section not big enough" << endl;
-		return nullptr;
-	}
-
-	uint8_t * const section = static_cast<uint8_t *>(malloc(size));
-
-	try {
-		int32_t y = 0;
-		for (; y < height; ++y) {
-			uint8_t const * const ptr =
-				reinterpret_cast<uint8_t *>(fr.Data(width));
-			memcpy(section + y * width, ptr, width);
-			fr.Data(dw - width); //  skip the alignment junk
-		}
-		while (y < dh) {
-			fr.Data(dw); //  more alignment junk
-			++y;
-		}
-	} catch (...) {
-		free(section);
-		throw;
-	}
-
-	return section;
-}
-
 
 /**
  * Load informational data of an S2 map
  */
-void S2_Map_Loader::load_s2mf_header()
+void S2_Map_Loader::load_s2mf_header(FileRead& fr)
 {
-	FileRead fr;
-
-	fr.Open(*g_fs, m_filename);
-
 	S2MapDescrHeader header;
 	memcpy(&header, fr.Data(sizeof(header)), sizeof(header));
 
@@ -231,16 +400,7 @@
 	m_map.set_nrplayers(header.nplayers);
 	m_map.set_description(_("Bluebyte Settlers II Map. No comment defined!"));
 
-	//  This is not the name, this is the directory of the world, so please
-	//  do not translate it.
-	switch (header.uses_world) {
-	case 0: m_map.set_world_name("greenland");  break;
-	case 1: m_map.set_world_name("blackland");  break;
-	case 2: m_map.set_world_name("winterland"); break;
-	default:
-		assert(false);
-		break;
-	}
+	m_worldtype = static_cast<WorldType>(header.uses_world);
 }
 
 
@@ -249,578 +409,465 @@
  */
 void S2_Map_Loader::load_s2mf(Widelands::Editor_Game_Base & egbase)
 {
-	uint8_t * section   = nullptr;
-	uint8_t * bobs      = nullptr;
-	uint8_t * buildings = nullptr;
-
 	uint8_t * pc;
 
-	try {
-		FileRead fr;
-		fr.Open(*g_fs, m_filename);
-
-		S2MapDescrHeader header;
-		memcpy(&header, fr.Data(sizeof(header)), sizeof(header));
-
-		//  Header must be swapped for big-endian Systems, works at the moment
-		//  only for PowerPC architecture.
-		//
-		//  \todo Generalize
-#if defined(__ppc__)
-		header.w = Swap16(header.w);
-		header.h = Swap16(header.h);
-#endif
-
-		//  The header must already have been processed.
-		assert(m_map.m_world);
-		assert(m_map.m_fields.get());
-		Widelands::X_Coordinate const mapwidth  = m_map.get_width ();
-		Widelands::Y_Coordinate const mapheight = m_map.get_height();
-		assert(mapwidth  == header.w);
-		assert(mapheight == header.h);
-		egbase.allocate_player_maps(); //  initializes player_fields.vision
-
-
-		//  SWD-SECTION 1: Heights
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 1 (Heights) not found");
-
-		Widelands::Field * f = m_map.m_fields.get();
-		pc = section;
-		for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
-			for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc)
-				f->set_height(*pc);
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 2: Terrain 1
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 2 (Terrain 1) not found");
-
-		f = m_map.m_fields.get();
-		pc = section;
-		for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
-			for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc) {
-				uint8_t c = *pc;
-				// Harbour buildspace & textures - Information taken from:
-				if (c & 0x40)
-					m_map.set_port_space(Widelands::Coords(x, y), true);
-				c &= 0x1f;
-				switch (c) {
-				// the following comments are valid for greenland - blackland and winterland have equivalents
-				// source: http://bazaar.launchpad.net/~xaser/s25rttr/s25edit/view/head:/WLD_reference.txt
-				case 0x00: c =  0; break; // steppe meadow1
-				case 0x01: c =  1; break; // mountain 1
-				case 0x02: c =  2; break; // snow
-				case 0x03: c =  3; break; // swamp
-				case 0x04: c =  4; break; // steppe = strand
-				case 0x05: c =  5; break; // water
-				case 0x06: c =  4; break; // strand
-				case 0x07: c = 12; break; // steppe 2 = dry land
-				case 0x08: c =  6; break; // meadow 1
-				case 0x09: c =  7; break; // meadow 2
-				case 0x0a: c =  8; break; // meadow 3
-				case 0x0b: c =  9; break; // mountain 2
-				case 0x0c: c = 10; break; // mountain 3
-				case 0x0d: c = 11; break; // mountain 4
-				case 0x0e: c = 12; break; // steppe meadow 2
-				case 0x0f: c = 13; break; // flower meadow
-				case 0x10: c = 14; break; // lava
-				// case 0x11: // color
-				case 0x12: c = 15; break; // mountain meadow
-				case 0x13: c =  4; break; // unknown texture
-
-				default:
-					c = 7;
-					cerr
-						<< "ERROR: Unknown texture1: "
-						<< setiosflags(ios::hex) << c
-						<< setiosflags(ios::dec) << " ("
-						<< x << "," << y << ") (defaults to water!)" << endl;
-						break;
-				}
-				f->set_terrain_d(c);
-			}
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 3: Terrain 2
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 3 (Terrain 2) not found");
-
-		f = m_map.m_fields.get();
-		pc = section;
-		for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
-			for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc) {
-				uint8_t c = *pc;
-				// Harbour buildspace & textures - Information taken from:
-				// http://bazaar.launchpad.net/~xaser/s25rttr/s25edit/view/head:/WLD_reference.txt
-				if (c & 0x40)
-					m_map.set_port_space(Widelands::Coords(x, y), true);
-				c &= 0x1f;
-				switch (c) {
-				// the following comments are valid for greenland - blackland and winterland have equivalents
-				// source: http://bazaar.launchpad.net/~xaser/s25rttr/s25edit/view/head:/WLD_reference.txt
-				case 0x00: c =  0; break; // steppe meadow1
-				case 0x01: c =  1; break; // mountain 1
-				case 0x02: c =  2; break; // snow
-				case 0x03: c =  3; break; // swamp
-				case 0x04: c =  4; break; // steppe = strand
-				case 0x05: c =  5; break; // water
-				case 0x06: c =  4; break; // strand
-				case 0x07: c = 12; break; // steppe 2 = dry land
-				case 0x08: c =  6; break; // meadow 1
-				case 0x09: c =  7; break; // meadow 2
-				case 0x0a: c =  8; break; // meadow 3
-				case 0x0b: c =  9; break; // mountain 2
-				case 0x0c: c = 10; break; // mountain 3
-				case 0x0d: c = 11; break; // mountain 4
-				case 0x0e: c = 12; break; // steppe meadow 2
-				case 0x0f: c = 13; break; // flower meadow
-				case 0x10: c = 14; break; // lava
-				// case 0x11: // color
-				case 0x12: c = 15; break; // mountain meadow
-				case 0x13: c =  4; break; // unknown texture
-
-				default:
-					c = 7;
-					cerr
-						<< "ERROR: Unknown texture1: "
-						<< setiosflags(ios::hex) << c
-						<< setiosflags(ios::dec) << " ("
-						<< x << "," << y << ") (defaults to water!)" << endl;
-					break;
-				}
-				f->set_terrain_r(c);
-			}
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 4: Existing Roads
-		//  As loading of Roads at game-start is not supported, yet - we simply
-		//  skip it.
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 4 (Existing Roads) not found");
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 5: Bobs
-		bobs = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!bobs)
-			throw wexception("Section 5 (Bobs) not found");
-
-
-		//  SWD-SECTION 6: Ways
-		//  This describes where you can put ways
-		//  0xc* == it's not possible to build ways here now
-		//  0x80 == Heres a HQ, owner is Player number
-		//   owner == 0 -> blue
-		//   owner == 1 -> yellow
-		//   owner == 2 -> red
-		//   owner == 3 -> pink
-		//   owner == 4 -> grey
-		//   owner == 6 -> green
-		//   owner == 6 -> orange
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 6 (Ways) not found");
-
-		for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y) {
-			uint32_t i = y * mapwidth;
-			for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++i) {
-				// ignore everything but HQs
-				if (section[i] == 0x80) {
-					if (bobs[i] < m_map.get_nrplayers())
-						m_map.set_starting_pos
-							(bobs[i] + 1, Widelands::Coords(x, y));
-				}
-			}
-		}
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 7: Animals
-		//  0x01        == Bunny
-		//  0x02        == fox
-		//  0x03        == reindeer
-		//  0x04 + 0x07 == deer
-		//  0x05 + 0x08 == duck
-		//  0x06        == sheep
-		//  0x09        == donkey
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 7 (Animals) not found");
-
-		for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y) {
-			uint32_t i = y * mapwidth;
-			for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++i) {
-				char const * bobname = nullptr;
-
-				switch (section[i]) {
-				case 0: break;
-				case 0x01: bobname = "bunny";    break;
-				case 0x02: bobname = "fox";      break;
-				case 0x03: bobname = "reindeer"; break;
-				case 0x04: bobname = "deer";     break;
-				case 0x05: bobname = "duck";     break;
-				case 0x06: bobname = "sheep";    break;
-				case 0x07: bobname = "deer";     break;
-				case 0x08: bobname = "duck";     break;
-				case 0x09: bobname = "elk";      break; // original "donkey"
-				default:
-					cerr
-						<< "Unsupported animal: " << static_cast<int32_t>(section[i])
-						<< endl;
-					break;
-				}
-
-				if (bobname) {
-					int32_t const idx = m_map.world().get_bob(bobname);
-					if (idx < 0)
-						throw wexception("Missing bob type %s", bobname);
-					for (uint32_t z = 0; z < CRITTER_PER_DEFINITION; ++z)
-						egbase.create_bob(Widelands::Coords(x, y), idx);
-				}
-			}
-		}
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 8: Unknown
-		//  Skipped
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 8 (Unknown) not found");
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 9: Buildings
-		//  What kind of buildings can be build?
-		//  0x01 == flags (??)
-		//  0x02 == buildings (small) (??)
-		//  0x04 == buildings
-		//  0x09 == flags
-		//  0x0a == buildings (small) (??)
-		//  0x0c == buildings (big) (??)
-		//  0x0d == mining
-		//  0x68 == trees
-		//  0x78 == no buildings
-		buildings = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!buildings)
-			throw wexception("Section 9 (Buildings) not found");
-
-
-		//  SWD-SECTION 10: Unknown
-		//  Skipped
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 10 (Unknown) not found");
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 11: Settlers2 Mapeditor tool position
-		//  In this section the positions of the Mapeditor tools seem to be
-		//  saved. But as this is unusable for playing or the WL-Editor, we just
-		//  skip it!
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 11 (Tool Position) not found");
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 12: Resources
-		//  0x00 == Water
-		//  0x87 == fish
-		//  0x21 == ground water
-		//  0x40 == nothing
-		//  0x51-57 == gold 1-7
-		//  0x49-4f == iron 1-7
-		//  0x41-47 == coal 1-7
-		//  0x59-5f == granite 1-7
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 12 (Resources) not found");
-
-		f = m_map.m_fields.get();
-		pc = section;
-		char const * res;
-		int32_t amount = 0;
-		for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
-			for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc) {
-				uint8_t c = *pc;
-
-				switch (c & 0xF8) {
-				case 0x40: res = "coal";   amount = c & 7; break;
-				case 0x48: res = "iron";   amount = c & 7; break;
-				case 0x50: res = "gold";   amount = c & 7; break;
-				case 0x59: res = "granit"; amount = c & 7; break;
-				default:   res = "";       amount = 0; break;
-				};
-
-				int32_t nres = 0;
-				if (*res) {
-					nres = m_map.world().get_resource(res);
-					if (nres == -1)
-						throw wexception
-							("world does not define resource type %s, you can not "
-							 "play settler maps here",
-							 res);
-				}
-				const int32_t real_amount = static_cast<int32_t>
-					(2.86 * static_cast<float>(amount));
-				f->set_resources(nres, real_amount);
-				f->set_starting_res_amount(real_amount);
-			}
-
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 13: Higlights and Shadows
-		//  It seems as if the Settlers2 Mapeditor saves the highlights and
-		//  shadows from slopes to this section.
-		//  But as this is unusable for the WL engine, we just skip it.
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 13 (Highlights and Shadows) not found");
-		free(section);
-		section = nullptr;
-
-
-		//  SWD-SECTION 14: Fieldcount
-		//  Describes to which island the field sticks
-		//  0 == water
-		//  1 == island 1
-		//  2 == island 2
-		//  ...
-		//  fe == killing field (lava)
-		//
-		//  Unusable (and if it was needed, it would have to be recomputed anyway
-		//  to verify it) so we simply skip it.
-		section = load_s2mf_section(fr, mapwidth, mapheight);
-		if (!section)
-			throw wexception("Section 14 (Island id) not found");
-		free(section);
-		section = nullptr;
-
-		fr.Close();
-
-
-		//  Map is completely read into memory.
-		//  Now try to convert the last stuff to Widelands-format
-		uint8_t c;
-		for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
-			for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x) {
-				char const * bobname = nullptr;
-
-				Widelands::Coords const location(x, y);
-				Widelands::Map_Index const index =
-					Widelands::Map::get_index(location, mapwidth);
-				c = bobs[index];
-				if (buildings[index] == 0x78) {
-					switch (c) {
-					case BOB_STONE1:        bobname = "stones1"; break;
-					case BOB_STONE2:        bobname = "stones2"; break;
-					case BOB_STONE3:        bobname = "stones3"; break;
-					case BOB_STONE4:        bobname = "stones4"; break;
-					case BOB_STONE5:        bobname = "stones5"; break;
-					case BOB_STONE6:        bobname = "stones6"; break;
-					default:
-						break;
-					}
-					if (bobname) {
-						int32_t const idx =
-							m_map.world().get_immovable_index(bobname);
-						if (idx < 0)
-							throw wexception("Missing immovable type %s", bobname);
-						egbase.create_immovable(Widelands::Coords(x, y), idx, nullptr);
-						continue;
-					}
-				}
-
-				switch (c) {
-				case BOB_NONE : break; // DO nothing
-
-				case BOB_PEBBLE1:          bobname = "pebble1";   break;
-				case BOB_PEBBLE2:          bobname = "pebble2";   break;
-				case BOB_PEBBLE3:          bobname = "pebble3";   break;
-				case BOB_PEBBLE4:          bobname = "pebble4";   break;
-				case BOB_PEBBLE5:          bobname = "pebble5";   break;
-				case BOB_PEBBLE6:          bobname = "pebble6";   break;
-
-				case BOB_MUSHROOM1:        bobname = "mushroom1"; break;
-				case BOB_MUSHROOM2:        bobname = "mushroom2"; break;
-
-				case BOB_DEADTREE1:        bobname = "deadtree1"; break;
-				case BOB_DEADTREE2:        bobname = "deadtree2"; break;
-				case BOB_DEADTREE3:        bobname = "deadtree3"; break;
-				case BOB_DEADTREE4:        bobname = "deadtree4"; break;
-
-				case BOB_TREE1_T:          bobname = "tree1_t";   break;
-				case BOB_TREE1_S:          bobname = "tree1_s";   break;
-				case BOB_TREE1_M:          bobname = "tree1_m";   break;
-				case BOB_TREE1:            bobname = "tree1";     break;
-
-				case BOB_TREE2_T:          bobname = "tree2_t";   break;
-				case BOB_TREE2_S:          bobname = "tree2_s";   break;
-				case BOB_TREE2_M:          bobname = "tree2_m";   break;
-				case BOB_TREE2:            bobname = "tree2";     break;
-
-				case BOB_TREE3_T:          bobname = "tree3_t";   break;
-				case BOB_TREE3_S:          bobname = "tree3_s";   break;
-				case BOB_TREE3_M:          bobname = "tree3_m";   break;
-				case BOB_TREE3:            bobname = "tree3";     break;
-
-				case BOB_TREE4_T:          bobname = "tree4_t";   break;
-				case BOB_TREE4_S:          bobname = "tree4_s";   break;
-				case BOB_TREE4_M:          bobname = "tree4_m";   break;
-				case BOB_TREE4:            bobname = "tree4";     break;
-
-				case BOB_TREE5_T:          bobname = "tree5_t";   break;
-				case BOB_TREE5_S:          bobname = "tree5_s";   break;
-				case BOB_TREE5_M:          bobname = "tree5_m";   break;
-				case BOB_TREE5:            bobname = "tree5";     break;
-
-				case BOB_TREE6_T:          bobname = "tree6_t";   break;
-				case BOB_TREE6_S:          bobname = "tree6_s";   break;
-				case BOB_TREE6_M:          bobname = "tree6_m";   break;
-				case BOB_TREE6:            bobname = "tree6";     break;
-
-				case BOB_TREE7_T:          bobname = "tree7_t";   break;
-				case BOB_TREE7_S:          bobname = "tree7_s";   break;
-				case BOB_TREE7_M:          bobname = "tree7_m";   break;
-				case BOB_TREE7:            bobname = "tree7";     break;
-
-				case BOB_TREE8_T:          bobname = "tree8_t";   break;
-				case BOB_TREE8_S:          bobname = "tree8_s";   break;
-				case BOB_TREE8_M:          bobname = "tree8_m";   break;
-				case BOB_TREE8:            bobname = "tree8";     break;
-
-
-				case BOB_GRASS1:           bobname = "grass1";    break;
-				case BOB_GRASS2:           bobname = "grass2";    break;
-				case BOB_GRASS3:           bobname = "grass3";    break;
-
-				case BOB_STANDING_STONES1: bobname = "sstones1";  break;
-				case BOB_STANDING_STONES2: bobname = "sstones2";  break;
-				case BOB_STANDING_STONES3: bobname = "sstones3";  break;
-				case BOB_STANDING_STONES4: bobname = "sstones4";  break;
-				case BOB_STANDING_STONES5: bobname = "sstones5";  break;
-				case BOB_STANDING_STONES6: bobname = "sstones6";  break;
-				case BOB_STANDING_STONES7: bobname = "sstones7";  break;
-
-				case BOB_SKELETON1:        bobname = "skeleton1"; break;
-				case BOB_SKELETON2:        bobname = "skeleton2"; break;
-				case BOB_SKELETON3:        bobname = "skeleton3"; break;
-
-				case BOB_CACTUS1:
-					bobname =
-						strcmp(m_map.get_world_name(), "winterland") ?
-						"cactus1" : "snowman";
-					break;
-				case BOB_CACTUS2:
-					bobname =
-						strcmp(m_map.get_world_name(), "winterland") ?
-						"cactus2" : "track";
-					break;
-
-				case BOB_BUSH1:            bobname = "bush1";     break;
-				case BOB_BUSH2:            bobname = "bush2";     break;
-				case BOB_BUSH3:            bobname = "bush3";     break;
-				case BOB_BUSH4:            bobname = "bush4";     break;
-				case BOB_BUSH5:            bobname = "bush5";     break;
-
-				default:
-					cerr << "Unknown bob " << static_cast<uint32_t>(c) << endl;
-					break;
-				}
-
-				if (bobname) {
-					int32_t idx = m_map.world().get_immovable_index(bobname);
-					if (idx < 0)
-						throw wexception("Missing immovable type %s", bobname);
-					egbase.create_immovable(Widelands::Coords(x, y), idx, nullptr);
-				}
-			}
-
-		//  WORKAROUND:
-		//  Unfortunately the Widelands engine is not completely compatible with
-		//  the Settlers 2; space for buildings is defined differently. To allow
-		//  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.
-		m_map.recalc_whole_map(); //  to initialize buildcaps
-
-		const Widelands::Player_Number nr_players = m_map.get_nrplayers();
-		log("Checking starting position for all %u players:\n", nr_players);
-		iterate_player_numbers(p, nr_players) {
-			log("-> Player %u: ", p);
-
-			Widelands::Coords starting_pos = m_map.get_starting_pos(p);
-			if (!starting_pos) {
-				//  Do not throw exception, else map will not be loadable in the
-				//  editor. Player initialization will keep track of wrong starting
-				//  positions.
-				log("Has no starting position.\n");
-				continue;
-			}
-			Widelands::FCoords fpos = m_map.get_fcoords(starting_pos);
-
-			if (!(m_map.get_max_nodecaps(fpos) & Widelands::BUILDCAPS_BIG)) {
-				log("wrong size - trying to fix it: ");
-				bool fixed = false;
-
-				Widelands::MapRegion<Widelands::Area<Widelands::FCoords> >
-					mr(m_map, Widelands::Area<Widelands::FCoords>(fpos, 3));
-				do {
-					if
-						(m_map.get_max_nodecaps(const_cast<Widelands::FCoords &>(mr.location()))
-						 &
-						 Widelands::BUILDCAPS_BIG)
-					{
-						m_map.set_starting_pos(p, mr.location());
-						fixed = true;
-						break;
-					}
-				} while (mr.advance(m_map));
-
-
-				// check whether starting position was fixed.
-				if (fixed)
-					log("Fixed!\n");
-				else {
-					//  Do not throw exception, else map will not be loadable in
-					//  the editor. Player initialization will keep track of
-					//  wrong starting positions.
-					log("FAILED!\n");
-					log("   Invalid starting position, that could not be fixed.\n");
-					log("   Please try to fix it manually in the editor.\n");
-				}
-			} else
-				log("OK\n");
-		}
-	} catch (...) {
-		free(section);
-		free(bobs);
-		free(buildings);
-		throw;
-	}
-
-	free(bobs);
-	free(buildings);
+	FileRead fr;
+	fr.Open(*g_fs, m_filename.c_str());
+
+	load_s2mf_header(fr);
+	m_map.set_size(m_map.m_width, m_map.m_height);
+
+	//  The header must already have been processed.
+	assert(m_map.m_fields.get());
+	Widelands::X_Coordinate const mapwidth  = m_map.get_width ();
+	Widelands::Y_Coordinate const mapheight = m_map.get_height();
+	assert(mapwidth > 0 && mapheight > 0);
+	egbase.allocate_player_maps(); //  initializes player_fields.vision
+
+	//  SWD-SECTION 1: Heights
+	std::unique_ptr<uint8_t[]> section(load_s2mf_section(fr, mapwidth, mapheight));
+	if (!section)
+		throw wexception("Section 1 (Heights) not found");
+
+	Widelands::Field * f = m_map.m_fields.get();
+	pc = section.get();
+	for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
+		for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc)
+			f->set_height(*pc);
+
+	//  SWD-SECTION 2: Terrain 1
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 2 (Terrain 1) not found");
+
+	std::unique_ptr<OneWorldLegacyLookupTable> lookup_table(
+	   create_one_world_legacy_lookup_table(get_world_name(m_worldtype)));
+
+	const Widelands::World& world = egbase.world();
+	TerrainConverter terrain_converter(world, *lookup_table);
+
+	f = m_map.m_fields.get();
+	pc = section.get();
+	for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
+		for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc) {
+			uint8_t c = *pc;
+			// Harbour buildspace & textures - Information taken from:
+			if (c & 0x40)
+				m_map.set_port_space(Widelands::Coords(x, y), true);
+			f->set_terrain_d(terrain_converter.lookup(m_worldtype, c & 0x1f));
+		}
+
+	//  SWD-SECTION 3: Terrain 2
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 3 (Terrain 2) not found");
+
+	f = m_map.m_fields.get();
+	pc = section.get();
+	for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
+		for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc) {
+			uint8_t c = *pc;
+			// Harbour buildspace & textures - Information taken from:
+			// http://bazaar.launchpad.net/~xaser/s25rttr/s25edit/view/head:/WLD_reference.txt
+			if (c & 0x40)
+				m_map.set_port_space(Widelands::Coords(x, y), true);
+			f->set_terrain_r(terrain_converter.lookup(m_worldtype, c & 0x1f));
+		}
+
+
+	//  SWD-SECTION 4: Existing Roads
+	//  As loading of Roads at game-start is not supported, yet - we simply
+	//  skip it.
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 4 (Existing Roads) not found");
+
+
+	//  SWD-SECTION 5: Bobs
+	std::unique_ptr<uint8_t[]> bobs(load_s2mf_section(fr, mapwidth, mapheight));
+	if (!bobs)
+		throw wexception("Section 5 (Bobs) not found");
+
+
+	//  SWD-SECTION 6: Ways
+	//  This describes where you can put ways
+	//  0xc* == it's not possible to build ways here now
+	//  0x80 == Heres a HQ, owner is Player number
+	//   owner == 0 -> blue
+	//   owner == 1 -> yellow
+	//   owner == 2 -> red
+	//   owner == 3 -> pink
+	//   owner == 4 -> grey
+	//   owner == 6 -> green
+	//   owner == 6 -> orange
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 6 (Ways) not found");
+
+	for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y) {
+		uint32_t i = y * mapwidth;
+		for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++i) {
+			// ignore everything but HQs
+			if (section[i] == 0x80) {
+				if (bobs[i] < m_map.get_nrplayers())
+					m_map.set_starting_pos
+						(bobs[i] + 1, Widelands::Coords(x, y));
+			}
+		}
+	}
+
+
+	//  SWD-SECTION 7: Animals
+	//  0x01        == Bunny
+	//  0x02        == fox
+	//  0x03        == reindeer
+	//  0x04 + 0x07 == deer
+	//  0x05 + 0x08 == duck
+	//  0x06        == sheep
+	//  0x09        == donkey
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 7 (Animals) not found");
+
+	for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y) {
+		uint32_t i = y * mapwidth;
+		for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++i) {
+			std::string bobname;
+
+			switch (section[i]) {
+			case 0: break;
+			case 0x01: bobname = "bunny";    break;
+			case 0x02: bobname = "fox";      break;
+			case 0x03: bobname = "reindeer"; break;
+			case 0x04: bobname = "deer";     break;
+			case 0x05: bobname = "duck";     break;
+			case 0x06: bobname = "sheep";    break;
+			case 0x07: bobname = "deer";     break;
+			case 0x08: bobname = "duck";     break;
+			case 0x09: bobname = "elk";      break; // original "donkey"
+			default:
+				cerr
+					<< "Unsupported animal: " << static_cast<int32_t>(section[i])
+					<< endl;
+				break;
+			}
+
+			if (!bobname.empty()) {
+				int32_t const idx = world.get_bob(bobname.c_str());
+				if (idx < 0) {
+					throw wexception("Missing bob type %s", bobname.c_str());
+				}
+				egbase.create_bob(Widelands::Coords(x, y), idx);
+			}
+		}
+	}
+
+
+	//  SWD-SECTION 8: Unknown
+	//  Skipped
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 8 (Unknown) not found");
+
+
+	//  SWD-SECTION 9: Buildings
+	//  What kind of buildings can be build?
+	//  0x01 == flags (??)
+	//  0x02 == buildings (small) (??)
+	//  0x04 == buildings
+	//  0x09 == flags
+	//  0x0a == buildings (small) (??)
+	//  0x0c == buildings (big) (??)
+	//  0x0d == mining
+	//  0x68 == trees
+	//  0x78 == no buildings
+	std::unique_ptr<uint8_t[]> buildings(load_s2mf_section(fr, mapwidth, mapheight));
+	if (!buildings)
+		throw wexception("Section 9 (Buildings) not found");
+
+
+	//  SWD-SECTION 10: Unknown
+	//  Skipped
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 10 (Unknown) not found");
+
+
+	//  SWD-SECTION 11: Settlers2 Mapeditor tool position
+	//  In this section the positions of the Mapeditor tools seem to be
+	//  saved. But as this is unusable for playing or the WL-Editor, we just
+	//  skip it!
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 11 (Tool Position) not found");
+
+
+	//  SWD-SECTION 12: Resources
+	//  0x00 == Water
+	//  0x87 == fish
+	//  0x21 == ground water
+	//  0x40 == nothing
+	//  0x51-57 == gold 1-7
+	//  0x49-4f == iron 1-7
+	//  0x41-47 == coal 1-7
+	//  0x59-5f == granite 1-7
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 12 (Resources) not found");
+
+	f = m_map.m_fields.get();
+	pc = section.get();
+	char const * res;
+	int32_t amount = 0;
+	for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
+		for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x, ++f, ++pc) {
+			uint8_t c = *pc;
+
+			switch (c & 0xF8) {
+			case 0x40: res = "coal";   amount = c & 7; break;
+			case 0x48: res = "iron";   amount = c & 7; break;
+			case 0x50: res = "gold";   amount = c & 7; break;
+			case 0x59: res = "granite"; amount = c & 7; break;
+			default:   res = "";       amount = 0; break;
+			};
+
+			int32_t nres = 0;
+			if (*res) {
+				nres = world.get_resource(res);
+				if (nres == -1)
+					throw wexception
+						("world does not define resource type %s, you can not "
+						 "play settler maps here",
+						 res);
+			}
+			const int32_t real_amount = static_cast<int32_t>
+				(2.86 * static_cast<float>(amount));
+			f->set_resources(nres, real_amount);
+			f->set_starting_res_amount(real_amount);
+		}
+
+
+
+	//  SWD-SECTION 13: Higlights and Shadows
+	//  It seems as if the Settlers2 Mapeditor saves the highlights and
+	//  shadows from slopes to this section.
+	//  But as this is unusable for the WL engine, we just skip it.
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 13 (Highlights and Shadows) not found");
+
+
+	//  SWD-SECTION 14: Fieldcount
+	//  Describes to which island the field sticks
+	//  0 == water
+	//  1 == island 1
+	//  2 == island 2
+	//  ...
+	//  fe == killing field (lava)
+	//
+	//  Unusable (and if it was needed, it would have to be recomputed anyway
+	//  to verify it) so we simply skip it.
+	section = load_s2mf_section(fr, mapwidth, mapheight);
+	if (!section)
+		throw wexception("Section 14 (Island id) not found");
+
+	fr.Close();
+
+	//  Map is completely read into memory.
+	//  Now try to convert the remaining stuff to Widelands-format. This will
+	//  read and construct the name of the old immovables before the one world
+	//  conversion. We will then convert them using the
+	//  OneWorldLegacyLookupTable.
+	// Puts an immovable with the 'old_immovable_name' onto the field 'locations'.
+	auto place_immovable = [&egbase, &lookup_table, &world](
+	   const Widelands::Coords& location, const std::string& old_immovable_name) {
+		const std::string new_immovable_name = lookup_table->lookup_immovable(old_immovable_name);
+		int32_t const idx = world.get_immovable_index(new_immovable_name.c_str());
+		if (idx < 0) {
+			throw wexception("Missing immovable type %s", new_immovable_name.c_str());
+		}
+		egbase.create_immovable(location, idx, nullptr);
+	};
+
+	uint8_t c;
+	for (Widelands::Y_Coordinate y = 0; y < mapheight; ++y)
+		for (Widelands::X_Coordinate x = 0; x < mapwidth; ++x) {
+			const Widelands::Coords location(x, y);
+			Widelands::Map_Index const index =
+				Widelands::Map::get_index(location, mapwidth);
+			c = bobs[index];
+			std::string bobname;
+			if (buildings[index] == 0x78) {
+				switch (c) {
+				case BOB_STONE1:        bobname = "stones1"; break;
+				case BOB_STONE2:        bobname = "stones2"; break;
+				case BOB_STONE3:        bobname = "stones3"; break;
+				case BOB_STONE4:        bobname = "stones4"; break;
+				case BOB_STONE5:        bobname = "stones5"; break;
+				case BOB_STONE6:        bobname = "stones6"; break;
+				default:
+					break;
+				}
+				if (!bobname.empty()) {
+					place_immovable(location, bobname);
+					continue;
+				}
+			}
+
+			switch (c) {
+			case BOB_NONE : break; // DO nothing
+
+			case BOB_PEBBLE1:          bobname = "pebble1";   break;
+			case BOB_PEBBLE2:          bobname = "pebble2";   break;
+			case BOB_PEBBLE3:          bobname = "pebble3";   break;
+			case BOB_PEBBLE4:          bobname = "pebble4";   break;
+			case BOB_PEBBLE5:          bobname = "pebble5";   break;
+			case BOB_PEBBLE6:          bobname = "pebble6";   break;
+
+			case BOB_MUSHROOM1:        bobname = "mushroom1"; break;
+			case BOB_MUSHROOM2:        bobname = "mushroom2"; break;
+
+			case BOB_DEADTREE1:        bobname = "deadtree1"; break;
+			case BOB_DEADTREE2:        bobname = "deadtree2"; break;
+			case BOB_DEADTREE3:        bobname = "deadtree3"; break;
+			case BOB_DEADTREE4:        bobname = "deadtree4"; break;
+
+			case BOB_TREE1_T:          bobname = "tree1_t";   break;
+			case BOB_TREE1_S:          bobname = "tree1_s";   break;
+			case BOB_TREE1_M:          bobname = "tree1_m";   break;
+			case BOB_TREE1:            bobname = "tree1";     break;
+
+			case BOB_TREE2_T:          bobname = "tree2_t";   break;
+			case BOB_TREE2_S:          bobname = "tree2_s";   break;
+			case BOB_TREE2_M:          bobname = "tree2_m";   break;
+			case BOB_TREE2:            bobname = "tree2";     break;
+
+			case BOB_TREE3_T:          bobname = "tree3_t";   break;
+			case BOB_TREE3_S:          bobname = "tree3_s";   break;
+			case BOB_TREE3_M:          bobname = "tree3_m";   break;
+			case BOB_TREE3:            bobname = "tree3";     break;
+
+			case BOB_TREE4_T:          bobname = "tree4_t";   break;
+			case BOB_TREE4_S:          bobname = "tree4_s";   break;
+			case BOB_TREE4_M:          bobname = "tree4_m";   break;
+			case BOB_TREE4:            bobname = "tree4";     break;
+
+			case BOB_TREE5_T:          bobname = "tree5_t";   break;
+			case BOB_TREE5_S:          bobname = "tree5_s";   break;
+			case BOB_TREE5_M:          bobname = "tree5_m";   break;
+			case BOB_TREE5:            bobname = "tree5";     break;
+
+			case BOB_TREE6_T:          bobname = "tree6_t";   break;
+			case BOB_TREE6_S:          bobname = "tree6_s";   break;
+			case BOB_TREE6_M:          bobname = "tree6_m";   break;
+			case BOB_TREE6:            bobname = "tree6";     break;
+
+			case BOB_TREE7_T:          bobname = "tree7_t";   break;
+			case BOB_TREE7_S:          bobname = "tree7_s";   break;
+			case BOB_TREE7_M:          bobname = "tree7_m";   break;
+			case BOB_TREE7:            bobname = "tree7";     break;
+
+			case BOB_TREE8_T:          bobname = "tree8_t";   break;
+			case BOB_TREE8_S:          bobname = "tree8_s";   break;
+			case BOB_TREE8_M:          bobname = "tree8_m";   break;
+			case BOB_TREE8:            bobname = "tree8";     break;
+
+
+			case BOB_GRASS1:           bobname = "grass1";    break;
+			case BOB_GRASS2:           bobname = "grass2";    break;
+			case BOB_GRASS3:           bobname = "grass3";    break;
+
+			case BOB_STANDING_STONES1: bobname = "sstones1";  break;
+			case BOB_STANDING_STONES2: bobname = "sstones2";  break;
+			case BOB_STANDING_STONES3: bobname = "sstones3";  break;
+			case BOB_STANDING_STONES4: bobname = "sstones4";  break;
+			case BOB_STANDING_STONES5: bobname = "sstones5";  break;
+			case BOB_STANDING_STONES6: bobname = "sstones6";  break;
+			case BOB_STANDING_STONES7: bobname = "sstones7";  break;
+
+			case BOB_SKELETON1:        bobname = "skeleton1"; break;
+			case BOB_SKELETON2:        bobname = "skeleton2"; break;
+			case BOB_SKELETON3:        bobname = "skeleton3"; break;
+
+			case BOB_CACTUS1:
+				bobname = m_worldtype != S2_Map_Loader::WINTERLAND ? "cactus1" : "snowman";
+				break;
+			case BOB_CACTUS2:
+				bobname = m_worldtype != S2_Map_Loader::WINTERLAND ? "cactus2" : "track";
+				break;
+
+			case BOB_BUSH1:            bobname = "bush1";     break;
+			case BOB_BUSH2:            bobname = "bush2";     break;
+			case BOB_BUSH3:            bobname = "bush3";     break;
+			case BOB_BUSH4:            bobname = "bush4";     break;
+			case BOB_BUSH5:            bobname = "bush5";     break;
+
+			default:
+				cerr << "Unknown bob " << static_cast<uint32_t>(c) << endl;
+				break;
+			}
+
+			if (!bobname.empty()) {
+				place_immovable(location, bobname);
+			}
+		}
+
+	//  WORKAROUND:
+	//  Unfortunately the Widelands engine is not completely compatible with
+	//  the Settlers 2; space for buildings is defined differently. To allow
+	//  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.
+	m_map.recalc_whole_map(world); //  to initialize buildcaps
+
+	const Widelands::Player_Number nr_players = m_map.get_nrplayers();
+	log("Checking starting position for all %u players:\n", nr_players);
+	iterate_player_numbers(p, nr_players) {
+		log("-> Player %u: ", p);
+
+		Widelands::Coords starting_pos = m_map.get_starting_pos(p);
+		if (!starting_pos) {
+			//  Do not throw exception, else map will not be loadable in the
+			//  editor. Player initialization will keep track of wrong starting
+			//  positions.
+			log("Has no starting position.\n");
+			continue;
+		}
+		Widelands::FCoords fpos = m_map.get_fcoords(starting_pos);
+
+		if (!(m_map.get_max_nodecaps(world, fpos) & Widelands::BUILDCAPS_BIG)) {
+			log("wrong size - trying to fix it: ");
+			bool fixed = false;
+
+			Widelands::MapRegion<Widelands::Area<Widelands::FCoords> >
+				mr(m_map, Widelands::Area<Widelands::FCoords>(fpos, 3));
+			do {
+				if
+					(m_map.get_max_nodecaps(world, const_cast<Widelands::FCoords &>(mr.location()))
+					 &
+					 Widelands::BUILDCAPS_BIG)
+				{
+					m_map.set_starting_pos(p, mr.location());
+					fixed = true;
+					break;
+				}
+			} while (mr.advance(m_map));
+
+
+			// check whether starting position was fixed.
+			if (fixed)
+				log("Fixed!\n");
+			else {
+				//  Do not throw exception, else map will not be loadable in
+				//  the editor. Player initialization will keep track of
+				//  wrong starting positions.
+				log("FAILED!\n");
+				log("   Invalid starting position, that could not be fixed.\n");
+				log("   Please try to fix it manually in the editor.\n");
+			}
+		} else
+			log("OK\n");
+	}
 }
 
 
@@ -832,12 +879,13 @@
  */
 	const Widelands::Map::PortSpacesSet ports(m_map.get_port_spaces());
 	uint16_t num_failed = 0;
-	char buf[256];
+
+	const Widelands::World& world = egbase.world();
 
 	// Check if port spaces are valid
 	for (const Widelands::Coords& c : ports) {
 		Widelands::FCoords fc = m_map.get_fcoords(c);
-		Widelands::NodeCaps nc = m_map.get_max_nodecaps(fc);
+		Widelands::NodeCaps nc = m_map.get_max_nodecaps(world, fc);
 		if
 			((nc & Widelands::BUILDCAPS_SIZEMASK) != Widelands::BUILDCAPS_BIG
 			 ||
@@ -851,7 +899,8 @@
 				mr(m_map, Widelands::Area<Widelands::FCoords>(fc, 3));
 			do {
 				// Check whether the maximum theoretical possible NodeCap of the field is big + port
-				Widelands::NodeCaps nc2 = m_map.get_max_nodecaps(const_cast<Widelands::FCoords &>(mr.location()));
+				Widelands::NodeCaps nc2 =
+				   m_map.get_max_nodecaps(world, const_cast<Widelands::FCoords&>(mr.location()));
 				if
 					((nc2 & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_BIG
 					 &&
@@ -869,29 +918,4 @@
 				log("Fixed!\n");
 		}
 	}
-
-	sprintf(buf, "%i %s %s", num_failed,
-		ngettext("WARNING: %i invalid port building space could not be fixed and has been removed! "
-				"Some islands might be unreachable now. Please consider fixing the map in the map editor.",
-				"WARNING: %i invalid port building spaces could not be fixed and have been removed! "
-				"Some islands might be unreachable now. Please consider fixing the map in the map editor.",
-				num_failed),
-		"\n\n");
-	fputs(buf, stdout);
-
-	// If fixing failed and this is a game, inform the players about the problem
-	if (num_failed > 0)
-		if (upcast(Widelands::Game, game, &egbase)) {
-			std::string rt_description = "<rt image=pics/port.png><p font-size=14 font-face=DejaVuSerif>";
-			rt_description += buf;
-			rt_description += "</p></rt>";
-
-			Widelands::Message m = Widelands::Message("S2_Map_Loader", 0, 3600000, _("WARNING"), rt_description);
-
-			for (uint8_t i = 0; i < MAX_PLAYERS; ++i) {
-				Widelands::Player * p = game->get_player(i + 1);
-				if (p)
-					p->add_message(*game, *(new Widelands::Message(m)));
-			}
-		}
 }

=== modified file 'src/s2map.h'
--- src/s2map.h	2014-05-11 07:38:01 +0000
+++ src/s2map.h	2014-06-10 18:27:45 +0000
@@ -20,137 +20,30 @@
 #ifndef S2MAP_H
 #define S2MAP_H
 
+#include <string>
+
 #include "map_io/map_loader.h"
 
-struct S2MapDescrHeader {
-	char    magic[10]; // "WORLD_V1.0"
-	char    name [20];
-	int16_t w;
-	int16_t h;
-	int8_t  uses_world; // 0 = green, 1 =black, 2 = winter
-	int8_t  nplayers;
-	char    author[26];
-	char    bulk[2290]; // unknown
-} /* size 2352 */;
-
-// MILLIONS of Definitions
-// Bobs
-
-// TODO: the following bob types appear in S2 maps but are unknown
-//  Somebody who can run Settlers II please check them out
-//  11 (0x0B)
-//  40 (0x28)
-//  41 (0x29)
-
-#define BOB_NONE             0x00
-
-#define BOB_STONE1           0x01
-#define BOB_STONE2           0x02
-#define BOB_STONE3           0x03
-#define BOB_STONE4           0x04
-#define BOB_STONE5           0x05
-#define BOB_STONE6           0x06
-
-#define BOB_SKELETON1        0x07
-#define BOB_SKELETON2        0x08
-#define BOB_SKELETON3        0x21
-
-#define BOB_STANDING_STONES1 0x18
-#define BOB_STANDING_STONES2 0x19
-#define BOB_STANDING_STONES3 0x1a
-#define BOB_STANDING_STONES4 0x1b
-#define BOB_STANDING_STONES5 0x1c
-#define BOB_STANDING_STONES6 0x1d
-#define BOB_STANDING_STONES7 0x1e
-
-#define BOB_MUSHROOM1        0x01
-#define BOB_MUSHROOM2        0x22
-
-#define BOB_PEBBLE1          0x02
-#define BOB_PEBBLE2          0x03
-#define BOB_PEBBLE3          0x04
-#define BOB_PEBBLE4          0x25
-#define BOB_PEBBLE5          0x26
-#define BOB_PEBBLE6          0x27
-
-#define BOB_DEADTREE1        0x05
-#define BOB_DEADTREE2        0x06
-#define BOB_DEADTREE3        0x20
-#define BOB_DEADTREE4        0x1f
-
-#define BOB_CACTUS1          0x0c
-#define BOB_CACTUS2          0x0d
-
-#define BOB_BUSH1            0x11
-#define BOB_BUSH2            0x13
-#define BOB_BUSH3            0x10
-#define BOB_BUSH4            0x12
-#define BOB_BUSH5            0x0a
-
-// Settlers 2 has 8 types of trees.
-// I assume that different animation states are stored in the map file
-// to create the following 32 values. I assume that 4 trees are grouped
-// together.
-// Unfortunately, I can't verify that (can't run the S2 editor).
-// In the end, it doesn't matter much anyway.
-#define BOB_TREE1_T          0x70
-#define BOB_TREE1_S          0x71
-#define BOB_TREE1_M          0x72
-#define BOB_TREE1            0x73
-
-#define BOB_TREE2_T          0x74
-#define BOB_TREE2_S          0x75
-#define BOB_TREE2_M          0x76
-#define BOB_TREE2            0x77
-
-#define BOB_TREE3_T          0xb0
-#define BOB_TREE3_S          0xb1
-#define BOB_TREE3_M          0xb2
-#define BOB_TREE3            0xb3
-
-#define BOB_TREE4_T          0xb4
-#define BOB_TREE4_S          0xb5
-#define BOB_TREE4_M          0xb6
-#define BOB_TREE4            0xb7
-
-#define BOB_TREE5_T          0xf0
-#define BOB_TREE5_S          0xf1
-#define BOB_TREE5_M          0xf2
-#define BOB_TREE5            0xf3
-
-#define BOB_TREE6_T          0xf4
-#define BOB_TREE6_S          0xf5
-#define BOB_TREE6_M          0xf6
-#define BOB_TREE6            0xf7
-
-#define BOB_TREE7_T          0x30
-#define BOB_TREE7_S          0x31
-#define BOB_TREE7_M          0x32
-#define BOB_TREE7            0x33
-
-#define BOB_TREE8_T          0x34
-#define BOB_TREE8_S          0x35
-#define BOB_TREE8_M          0x36
-#define BOB_TREE8            0x37
-
-#define BOB_GRASS1           0x0e
-#define BOB_GRASS2           0x14
-#define BOB_GRASS3           0x0f
-
+class FileRead;
 
 struct S2_Map_Loader : public Widelands::Map_Loader {
+	enum WorldType {
+		GREENLAND = 0,
+		BLACKLAND = 1,
+		WINTERLAND = 2,
+	};
+
 	S2_Map_Loader(const char *, Widelands::Map &);
 
 	virtual int32_t preload_map(bool) override;
-	void load_world() override;
 	virtual int32_t load_map_complete
 		(Widelands::Editor_Game_Base &, bool scenario) override;
 
 private:
-	char  m_filename[256];
+	const std::string m_filename;
+	WorldType m_worldtype;
 
-	uint8_t * load_s2mf_section(FileRead &, int32_t width, int32_t height);
-	void load_s2mf_header();
+	void load_s2mf_header(FileRead&);
 	void load_s2mf(Widelands::Editor_Game_Base &);
 	void postload_fix_conversion(Widelands::Editor_Game_Base &);
 };

=== modified file 'src/scripting/c_utils.cc'
--- src/scripting/c_utils.cc	2014-05-27 11:01:15 +0000
+++ src/scripting/c_utils.cc	2014-06-10 18:27:45 +0000
@@ -116,6 +116,6 @@
 	lua_pushinteger(L, 2);  /* skip this function and traceback */
 	lua_call(L, 2, 1);  /* call debug.traceback */
 
-	lua_error(L);
+	lua_error(L); // lua_error never returns.
 	throw LuaError("Never here."); // Shutup compiler warnings.
 }

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2014-04-21 10:47:03 +0000
+++ src/scripting/lua_map.cc	2014-06-10 18:27:45 +0000
@@ -32,6 +32,9 @@
 #include "logic/soldier.h"
 #include "logic/warelist.h"
 #include "logic/widelands_geometry.h"
+#include "logic/world/resource_description.h"
+#include "logic/world/terrain_description.h"
+#include "logic/world/world.h"
 #include "scripting/c_utils.h"
 #include "scripting/lua_game.h"
 #include "wui/mapviewpixelfunctions.h"
@@ -908,7 +911,7 @@
 			report_error(L, "Problem loading tribe <%s>. Maybe not existent?", from_where.c_str());
 		}
 	} else {
-		int32_t const imm_idx = egbase.map().world().get_immovable_index(objname);
+		int32_t const imm_idx = egbase.world().get_immovable_index(objname);
 		if (imm_idx < 0)
 			report_error(L, "Unknown immovable <%s>", objname);
 
@@ -946,7 +949,8 @@
 */
 // TODO: do we really want this function?
 int L_Map::recalculate(lua_State * L) {
-	get_egbase(L).map().recalc_whole_map();
+	Editor_Game_Base & egbase = get_egbase(L);
+	egbase.map().recalc_whole_map(egbase.world());
 	return 0;
 }
 
@@ -2531,7 +2535,8 @@
 	if (height > MAX_FIELD_HEIGHT)
 		report_error(L, "height must be <= %i", MAX_FIELD_HEIGHT);
 
-	get_egbase(L).map().set_height(f, height);
+	Editor_Game_Base & egbase = get_egbase(L);
+	egbase.map().set_height(egbase.world(), f, height);
 
 	return 0;
 }
@@ -2594,14 +2599,14 @@
 */
 int L_Field::get_resource(lua_State * L) {
 	lua_pushstring
-		(L, get_egbase(L).map().world().get_resource
+		(L, get_egbase(L).world().get_resource
 			 (fcoords(L).field->get_resources())->name().c_str());
 
 	return 1;
 }
 int L_Field::set_resource(lua_State * L) {
 	Field * field = fcoords(L).field;
-	int32_t res = get_egbase(L).map().world().get_resource
+	int32_t res = get_egbase(L).world().get_resource
 		(luaL_checkstring(L, -1));
 
 	if (res == -1)
@@ -2627,8 +2632,7 @@
 	Field * field = fcoords(L).field;
 	int32_t res = field->get_resources();
 	int32_t amount = luaL_checkint32(L, -1);
-	int32_t max_amount = get_egbase(L).map().world().get_resource
-		(res)->get_max_amount();
+	int32_t max_amount = get_egbase(L).world().get_resource(res)->max_amount();
 
 	if (amount < 0 or amount > max_amount)
 		report_error(L, "Illegal amount: %i, must be >= 0 and <= %i", amount, max_amount);
@@ -2684,44 +2688,44 @@
 		valid name to these variables.
 */
 int L_Field::get_terr(lua_State * L) {
-	Terrain_Descr & td =
-		get_egbase(L).map().world().terrain_descr
+	TerrainDescription & td =
+		get_egbase(L).world().terrain_descr
 			(fcoords(L).field->terrain_r());
 	lua_pushstring(L, td.name().c_str());
 	return 1;
 }
-int L_Field::set_terr(lua_State * L) {
-	const char * name = luaL_checkstring(L, -1);
-	Map & map = get_egbase(L).map();
-	Terrain_Index td =
-		map.world().index_of_terrain(name);
+int L_Field::set_terr(lua_State* L) {
+	const char* name = luaL_checkstring(L, -1);
+	Editor_Game_Base& egbase = get_egbase(L);
+	const World& world = egbase.world();
+	const Terrain_Index td = world.terrains().get_index(name);
 	if (td == static_cast<Terrain_Index>(-1))
 		report_error(L, "Unknown terrain '%s'", name);
 
-	map.change_terrain(TCoords<FCoords>(fcoords(L), TCoords<FCoords>::R), td);
-
+	egbase.map().change_terrain(world, TCoords<FCoords>(fcoords(L), TCoords<FCoords>::R), td);
 
 	lua_pushstring(L, name);
 	return 1;
 }
 
 int L_Field::get_terd(lua_State * L) {
-	Terrain_Descr & td =
-		get_egbase(L).map().world().terrain_descr
+	TerrainDescription & td =
+		get_egbase(L).world().terrain_descr
 			(fcoords(L).field->terrain_d());
 	lua_pushstring(L, td.name().c_str());
 	return 1;
 }
 int L_Field::set_terd(lua_State * L) {
 	const char * name = luaL_checkstring(L, -1);
-	Map & map = get_egbase(L).map();
-	Terrain_Index td =
-		map.world().index_of_terrain(name);
+	Editor_Game_Base& egbase = get_egbase(L);
+	const World& world = egbase.world();
+	const Terrain_Index td =
+		world.terrains().get_index(name);
 	if (td == static_cast<Terrain_Index>(-1))
 		report_error(L, "Unknown terrain '%s'", name);
 
-	map.change_terrain
-		(TCoords<FCoords> (fcoords(L), TCoords<FCoords>::D), td);
+	egbase.map().change_terrain
+		(world, TCoords<FCoords> (fcoords(L), TCoords<FCoords>::D), td);
 
 	lua_pushstring(L, name);
 	return 1;

=== added file 'src/scripting/lua_path.cc'
--- src/scripting/lua_path.cc	1970-01-01 00:00:00 +0000
+++ src/scripting/lua_path.cc	2014-06-10 18:27:45 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "scripting/lua_path.h"
+
+#include <boost/regex.hpp>
+
+#include "helper.h"
+#include "io/filesystem/layered_filesystem.h"
+
+namespace LuaPath {
+
+/* RST
+:mod:`path`
+=============
+
+.. module:: path
+   :synopsis: Provides access to path modifications, globbing and so on.
+
+.. moduleauthor:: The Widelands development team
+
+.. currentmodule:: path
+
+*/
+
+/* RST
+Module Functions
+^^^^^^^^^^^^^^^^
+
+*/
+
+/* RST
+.. function:: basename(filename)
+
+   Returns everything behind the last /.
+
+	:type filename: class:`string`
+	:arg filename: filename to return basename for.
+
+   :returns: The basename.
+*/
+static int L_basename(lua_State * L) {
+	lua_pushstring(L, FileSystem::FS_Filename(luaL_checkstring(L, -1)));
+	return 1;
+}
+
+/* RST
+.. function:: dirname(filename)
+
+	Everything before the final / in filename. The returned value is either the empty string or
+	ends with a '/'.
+
+	:type filename: class:`string`
+	:arg filename: filename to return dirname for.
+
+   :returns: The dirname.
+*/
+static int L_dirname(lua_State * L) {
+	lua_pushstring(L, FileSystem::FS_Dirname(luaL_checkstring(L, -1)));
+	return 1;
+}
+
+
+/* RST
+.. function:: list_directory(directory[, regexp])
+
+	Lists all files and directories in the given directory. If regexp is not
+	:const:`nil` only the files whose basename matches the regular expression
+	will be returned. The method never returns "." or ".." in its results.
+
+	:type directory: class:`string`
+	:arg directory: The directory to list files for.
+	:type regexp: class:`string`
+	:arg regexp: The regular expression each files must match.
+
+   :returns: An :class:`array` of filenames in lexicographical order.
+*/
+static int L_list_directory(lua_State * L) {
+	const std::string dir = luaL_checkstring(L, 1);
+	std::set<std::string> files = g_fs->ListDirectory(dir);
+
+	if (lua_gettop(L) > 1) {
+		boost::regex re(luaL_checkstring(L, 2));
+		files = filter(files, [&re](const std::string& filename) {
+			return boost::regex_match(FileSystem::FS_Filename(filename.c_str()), re);
+		});
+	}
+
+	lua_newtable(L);
+	int idx = 1;
+
+	for (const std::string& filename : files) {
+		lua_pushint32(L, idx++);
+		lua_pushstring(L, filename);
+		lua_settable(L, -3);
+	}
+	return 1;
+}
+
+const static struct luaL_Reg path [] = {
+	{"basename", &L_basename},
+	{"dirname", &L_dirname},
+	{"list_directory", &L_list_directory},
+	{nullptr, nullptr}
+};
+
+void luaopen_path(lua_State * L) {
+	luaL_newlib(L, path);
+	lua_setglobal(L, "path");
+}
+
+} // namespace LuaPath

=== added file 'src/scripting/lua_path.h'
--- src/scripting/lua_path.h	1970-01-01 00:00:00 +0000
+++ src/scripting/lua_path.h	2014-06-10 18:27:45 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006-2014 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef LUA_PATH_H
+#define LUA_PATH_H
+
+#include "scripting/eris/lua.hpp"
+#include "scripting/luna.h"
+
+namespace LuaPath {
+
+/*
+ * Base class for all classes in path.
+ */
+class L_PathModuleClass : public LunaClass {
+	public:
+		const char * get_modulename() override {return "path";}
+};
+
+void luaopen_path(lua_State *);
+
+};
+
+#endif /* end of include guard: LUA_PATH_H */

=== modified file 'src/scripting/lua_root.cc'
--- src/scripting/lua_root.cc	2014-03-24 21:47:08 +0000
+++ src/scripting/lua_root.cc	2014-06-10 18:27:45 +0000
@@ -19,17 +19,22 @@
 
 #include "scripting/lua_root.h"
 
+#include <boost/format.hpp>
+
 #include "gamecontroller.h"
 #include "log.h"
 #include "logic/cmd_luacoroutine.h"
+#include "logic/critter_bob.h"
 #include "logic/findimmovable.h"
 #include "logic/game.h"
 #include "logic/immovable.h"
 #include "logic/tribe.h"
+#include "logic/world/world.h"
 #include "scripting/lua_coroutine.h"
 #include "scripting/lua_editor.h"
 #include "scripting/lua_game.h"
 #include "scripting/lua_map.h"
+#include "scripting/lua_table.h"
 
 using namespace Widelands;
 
@@ -277,6 +282,199 @@
  ==========================================================
  */
 
+
+/* RST
+World
+-----
+
+.. class:: World
+
+	This offers access to the objects in a the widelands world and allows to add
+	new objects.
+*/
+
+const char L_World::className[] = "World";
+const MethodType<L_World> L_World::Methods[] = {
+	METHOD(L_World, new_critter_type),
+	METHOD(L_World, new_editor_immovable_category),
+	METHOD(L_World, new_editor_terrain_category),
+	METHOD(L_World, new_immovable_type),
+	METHOD(L_World, new_resource_type),
+	METHOD(L_World, new_terrain_type),
+	{0, 0},
+};
+const PropertyType<L_World> L_World::Properties[] = {
+	{0, 0, 0},
+};
+
+L_World::L_World(lua_State * /* L */) {
+	// Nothing to do.
+}
+
+void L_World::__persist(lua_State*) {
+	// Nothing to be done.
+}
+void L_World::__unpersist(lua_State*) {
+	// Nothing to be done.
+}
+
+/*
+ ==========================================================
+ PROPERTIES
+ ==========================================================
+ */
+
+/*
+ ==========================================================
+ LUA METHODS
+ ==========================================================
+ */
+
+/* RST
+	.. method:: new_resource_type(table)
+
+		Adds a new resource type that can be in the different maps. Takes a
+		single argument, a table with the descriptions for the resource type. See the
+		files in world/ for usage examples.
+
+		:returns: :const:`nil`
+*/
+int L_World::new_resource_type(lua_State* L) {
+	if (lua_gettop(L) != 2) {
+		report_error(L, "Takes only one argument.");
+	}
+
+	try {
+		LuaTable table(L);  // Will pop the table eventually.
+		get_egbase(L).mutable_world()->add_resource_type(table);
+	} catch (std::exception& e) {
+		report_error(L, "%s", e.what());
+	}
+
+	return 0;
+}
+
+/* RST
+	.. method:: new_terrain_type(table)
+
+		Adds a new terrain type that can be used in maps. Takes a single
+		argument, a table with the descriptions for the terrain type. See the files in world/
+		for usage examples.
+
+		:returns: :const:`nil`
+*/
+int L_World::new_terrain_type(lua_State * L) {
+	if (lua_gettop(L) != 2) {
+		report_error(L, "Takes only one argument.");
+	}
+	try {
+		LuaTable table(L);  // Will pop the table eventually.
+		get_egbase(L).mutable_world()->add_terrain_type(table);
+	}
+	catch (std::exception& e) {
+	

Follow ups