← Back to team overview

widelands-dev team mailing list archive

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

 

I am currently reviewing your code. I already added some small things for the first 5000 lines as inline comments. I am not yet sure how to add comments for the rest.

Diff comments:

> === modified file 'CMakeLists.txt'
> --- CMakeLists.txt	2014-05-27 19:10:20 +0000
> +++ CMakeLists.txt	2014-06-14 14:34:06 +0000
> @@ -453,7 +453,7 @@
>      global
>      tribes
>      txts
> -    worlds
> +    world
>      pics
>      scripting
>    DESTINATION ${WL_INSTALL_DATADIR}
> 
> === 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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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

Why did you hardcode the compiler path?

>      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-14 14:34:06 +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-14 14:34:06 +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	2014-06-06 20:27:28 +0000
> +++ src/ai/ai_help_structs.h	2014-06-14 14:34:06 +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 {
>  
> @@ -102,10 +104,15 @@
>  };
>  
>  struct FindNodeWater {

Should maybe also be a class because it is not a POD object.

> -	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& /* 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_;
>  };
>  
>  struct FindNodeWithFlagOrRoad {
> @@ -125,7 +132,7 @@
>  		return cost_ > f.cost_;
>  	}
>  
> -	bool operator==(Flag const* const f) const {
> +	bool operator == (Flag const* const f) const {
>  		return flag == f;
>  	}
>  };
> 
> === modified file 'src/ai/ai_hints.h'
> --- src/ai/ai_hints.h	2014-06-06 20:27:28 +0000
> +++ src/ai/ai_hints.h	2014-06-14 14:34:06 +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-06-14 13:53:57 +0000
> +++ src/ai/defaultai.cc	2014-06-14 14:34:06 +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"
>  
> @@ -260,7 +260,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);
> @@ -530,7 +530,7 @@
>  		std::vector<Coords> water_list;
>  
>  		if (field.water_nearby_ == -1) {  //-1 means "value has never been calculated"
> -			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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/editor/editorinteractive.cc	2014-06-14 14:34:06 +0000
> @@ -38,6 +38,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"
> @@ -110,8 +112,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);
> @@ -155,17 +159,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);
>  		}
>  	}
>  
> @@ -183,36 +184,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);
> @@ -279,7 +274,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);
> @@ -469,14 +464,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:
> @@ -512,8 +507,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;
> @@ -579,17 +573,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
> @@ -604,10 +588,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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 */) {

Formatting not as perfect as the rest ;)

>  	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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/editor/ui_menus/editor_main_menu_save_map.cc	2014-06-14 14:34:06 +0000
> @@ -100,13 +100,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
> @@ -237,7 +230,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());
> @@ -248,7 +240,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/game_io/game_map_data_packet.cc	2014-06-14 14:34:06 +0000
> @@ -46,7 +46,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-14 14:34:06 +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-06-14 13:53:57 +0000
> +++ src/graphic/animation.cc	2014-06-14 14:34:06 +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,112 +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()){
> -				log("ANIMATION ERROR: playercolor mask has wrong size: (%s: %u, %u), should "
> -					 "be (%u, %u) like the animation frame\n",
> -					 pc_filename.c_str(),pc_image->width(), pc_image->height(), frames_[0]->width(), frames_[0]->height());
> -					 hasplrclrs_ = false;
> -					 break;
> -				}
> -				//throw wexception
> -					//("playercolor mask has wrong size: (%s: %u, %u), should "
> -					 //"be (%u, %u) like the animation frame",
> -					 //pc_filename.c_str(),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 {
> @@ -266,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
> @@ -409,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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/graphic/graphic.cc	2014-06-14 14:34:06 +0000
> @@ -314,6 +314,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()
> @@ -322,7 +325,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)
> @@ -526,34 +529,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]
>  }
>  
> @@ -568,16 +546,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
> @@ -618,24 +586,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:42:45 +0000
> +++ src/graphic/texture.h	2014-06-14 14:34:06 +0000
> @@ -40,8 +40,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;}
> @@ -53,8 +54,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();}
>  
> @@ -67,7 +66,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-06-14 13:53:57 +0000
> +++ src/io/filesystem/disk_filesystem.cc	2014-06-14 14:34:06 +0000
> @@ -383,8 +383,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:42:45 +0000
> +++ src/logic/editor_game_base.h	2014-06-14 14:34:06 +0000
> @@ -70,11 +70,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();
> @@ -118,8 +118,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
> @@ -133,11 +133,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 *);
> @@ -158,33 +155,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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/logic/game.cc	2014-06-14 14:34:06 +0000
> @@ -229,10 +229,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();
> @@ -293,8 +289,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;
> @@ -335,6 +329,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()));
> @@ -501,7 +496,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
> @@ -647,9 +642,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
> @@ -1033,8 +1028,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-06-10 20:38:57 +0000
> +++ src/logic/immovable.cc	2014-06-14 14:34:06 +0000
> @@ -22,6 +22,7 @@
>  #include <cstdio>
>  #include <memory>
>  
> +#include <boost/algorithm/string.hpp>
>  #include <boost/format.hpp>
>  #include <config.h>
>  
> @@ -43,7 +44,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"
> @@ -52,6 +56,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)
>  {}
> @@ -81,7 +102,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));
>  }
>  
>  /**
> @@ -100,7 +121,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));
>  }
>  
>  
> @@ -112,40 +133,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");
> +}
>  
>  /*
>  ==============================================================================
> @@ -157,28 +216,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"))
> @@ -195,17 +242,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();
> @@ -215,7 +260,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
> @@ -223,63 +268,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
> @@ -450,26 +495,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.
>  */
> @@ -611,8 +640,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) {
> @@ -729,39 +758,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));
>  			}
> @@ -780,22 +810,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-05-30 16:21:05 +0000
> +++ src/logic/productionsite.cc	2014-06-14 14:34:06 +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-05-30 16:21:05 +0000
> +++ src/logic/productionsite.h	2014-06-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/logic/ship.cc	2014-06-14 14:34:06 +0000
> @@ -52,8 +52,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");
> @@ -356,7 +360,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/logic/worker.cc	2014-06-14 14:34:06 +0000
> @@ -50,6 +50,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"
> @@ -108,7 +111,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
>  			(_
> @@ -213,7 +216,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
>  			(_
> @@ -346,7 +349,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());
>  
> @@ -542,7 +545,7 @@
>  {
>  	std::vector<Coords> list;
>  	Map & map = game.map();
> -	World * const w = &map.world();
> +	const World& world = game.world();
>  
>  	CheckStepDefault cstep(descr().movecaps());
>  
> @@ -554,10 +557,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)
> @@ -599,11 +602,11 @@
>  	if (building.name() == "fish_breeders_house")
>  		return;
>  
> -	// TODO "stone" is defined as "granit" in the worlds
> +	// TODO "stone" is defined as "granit" in the world
>  	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();
> @@ -809,10 +812,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) {
> @@ -941,23 +944,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.
> @@ -979,7 +984,7 @@
>  			(position,
>  			 t.get_resource_indicator
>  			 	(rdescr,
> -			 	 rdescr->is_detectable() ?
> +			 	 rdescr->detectable() ?
>  			 	 position.field->get_resources_amount() : 0),
>  			 &t);
>  	}
> @@ -2666,7 +2671,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()),
> @@ -2703,11 +2708,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;
> @@ -2720,11 +2725,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/logic/world/world.cc	2014-06-14 14:34:06 +0000
> @@ -17,919 +17,132 @@
>   *
>   */
>  
> -#include "logic/world.h"
> +#include "logic/world/world.h"
>  
>  #include <iostream>
>  #include <memory>
>  #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-14 14:34:06 +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-06-10 20:38:57 +0000
> +++ src/map_generator.cc	2014-06-14 14:34:06 +0000
> @@ -21,27 +21,36 @@
>  
>  #include <memory>
>  
> +#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
> @@ -51,16 +60,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;
> @@ -71,21 +77,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);
> @@ -95,68 +101,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);
> @@ -165,11 +171,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);
> @@ -180,7 +186,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
>  	}
>  }
>  
> @@ -188,7 +195,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
> @@ -199,14 +206,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 :
> @@ -220,16 +225,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;
>  		}
> @@ -252,8 +257,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
> @@ -275,7 +280,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...
>  
> @@ -283,7 +288,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;
>  				}
>  			}
> @@ -291,7 +296,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;
> @@ -321,17 +326,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;
> @@ -381,7 +386,7 @@
>  					 /
>  					 static_cast<double>(max - min))
>  					*
> -					MAX_ELEVATION;
> +					kMaxElevation;
>  				++histo[values[x + y * w] >> 22];
>  			}
>  
> @@ -404,7 +409,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;
> @@ -419,7 +424,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
> @@ -448,60 +453,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;
>  		}
>  	}
> @@ -515,25 +518,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) &&
> @@ -556,14 +559,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
> @@ -579,10 +582,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;
> @@ -615,11 +618,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));
>  
>  }
>  
> @@ -632,58 +635,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.
>  
> @@ -695,22 +695,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;
>  
> @@ -739,52 +739,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;
>  				}
>  			}
> @@ -792,56 +792,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];
> @@ -856,7 +856,7 @@
>  		}
>  
>  		// Finally set the found starting position
> -		m_map.set_starting_pos(n, coords2);
> +		map_.set_starting_pos(n, coords2);
>  	}
>  }
>  
> @@ -953,23 +953,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;
> @@ -978,9 +977,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;
> @@ -989,15 +988,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;
>  
>  
> @@ -1042,12 +1041,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
>  }
>  
> @@ -1080,12 +1073,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;
> @@ -1124,11 +1117,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
> @@ -1136,10 +1129,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;
> @@ -1148,9 +1141,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 += "-";
>  	}
>  }
> @@ -1176,18 +1169,10 @@
>  
>  // 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: Clean up code
> -// TODO: Improve mapgenconf files for nicer generated worlds
> +// TODO: Define the "none"-bob to weigh other bobs lower within BobCategory...
>  // TODO: MapGen: Bob generation, configurable in mapgenconf
> -// TODO: MapGen: How to handle "Bob layers" ???
>  // TODO: MapGen: Resource generation, configurable in mapgenconf
>  // TODO: MapGen: Check out sample map
> -// TODO: MapGen: Generate Start positions
>  // TODO: MapGen: How to handle height profile in make_blah...
> -// TODO: MapGen: Display something else than
> -// TODO:         "Preparing..." when generating map...
> -// TODO: MapGen: Allow up to 3 different water areas
>  
>  };
> 
> === modified file 'src/map_generator.h'
> --- src/map_generator.h	2014-06-10 20:42:45 +0000
> +++ src/map_generator.h	2014-06-14 14:34:06 +0000
> @@ -22,11 +22,8 @@
>  
>  #include <memory>
>  
> -#include "logic/world.h"
> -
> -// This is the first step of separating map generation from
> -// map.
> -// TODO: Put other generation stuff here too...
> +#include "logic/widelands_geometry.h"
> +#include "logic/world/map_gen.h"
>  
>  struct RNG;
>  
> @@ -57,7 +54,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?
> @@ -67,8 +64,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);
>  
> @@ -117,9 +113,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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +0000
> @@ -0,0 +1,49 @@
> +/*
> + * 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 <memory>
> +#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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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-14 14:34:06 +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
> + ==========================================================
> + */
> +
> +/*
> + =================


-- 
https://code.launchpad.net/~widelands-dev/widelands/one_world/+merge/222708
Your team Widelands Developers is subscribed to branch lp:~widelands-dev/widelands/one_world.


References