← Back to team overview

widelands-dev team mailing list archive

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

 

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

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #536493 in widelands: "Get rid of line numbers in programs"
  https://bugs.launchpad.net/widelands/+bug/536493
  Bug #1341080 in widelands: "Building help: remove logic from wrappers"
  https://bugs.launchpad.net/widelands/+bug/1341080
  Bug #1345663 in widelands: "format_help.lua has no Textdomain"
  https://bugs.launchpad.net/widelands/+bug/1345663
  Bug #1368133 in widelands: "One Tribe"
  https://bugs.launchpad.net/widelands/+bug/1368133

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

Tada-ching!

Related forum post: https://wl.widelands.org/forum/topic/1827/

Once this branch has been tested, reviewed etc, I will need to merge it personally, because there is some fixing up to do for the translations, which will be semi-automated only. I have left some NOCOM comments in utils for that.
-- 
The attached diff has been truncated due to its size.
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/one_tribe into lp:widelands.
=== modified file '.tx/config'
--- .tx/config	2015-07-25 10:28:16 +0000
+++ .tx/config	2015-10-18 20:57:50 +0000
@@ -79,21 +79,9 @@
 source_lang = en
 type = PO
 
-[widelands.tribe_atlanteans]
-file_filter = po/tribe_atlanteans/<lang>.po
-source_file = po/tribe_atlanteans/tribe_atlanteans.pot
-source_lang = en
-type = PO
-
-[widelands.tribe_barbarians]
-file_filter = po/tribe_barbarians/<lang>.po
-source_file = po/tribe_barbarians/tribe_barbarians.pot
-source_lang = en
-type = PO
-
-[widelands.tribe_empire]
-file_filter = po/tribe_empire/<lang>.po
-source_file = po/tribe_empire/tribe_empire.pot
+[widelands.tribes_encyclopedia]
+file_filter = po/tribes_encyclopedia/<lang>.po
+source_file = po/tribes_encyclopedia/tribes_encyclopedia.pot
 source_lang = en
 type = PO
 

=== removed file 'campaigns/atl01.wmf/allowed_worker_types'
--- campaigns/atl01.wmf/allowed_worker_types	2014-08-26 17:25:00 +0000
+++ campaigns/atl01.wmf/allowed_worker_types	1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
-# Automatically created by Widelands bzr5319[campaigns] (Debug)
-
-[global]
-packet_version="1"
-
-[player_1]
-carrier="true"
-soldier="true"
-baker="true"
-blacksmith="true"
-brewer="true"
-builder="true"
-charcoal_burner="true"
-farmer="true"
-gardener="true"
-fisher="true"
-gamekeeper="true"
-geologist="true"
-helmsmith="true"
-hunter="true"
-innkeeper="true"
-lime-burner="true"
-lumberjack="true"
-miner="true"
-ranger="true"
-smelter="true"
-stonemason="true"
-trainer="true"
-weaver="true"
-scout="true"
-cattlebreeder="true"

=== modified file 'campaigns/atl01.wmf/scripting/init.lua'
--- campaigns/atl01.wmf/scripting/init.lua	2014-10-03 08:58:44 +0000
+++ campaigns/atl01.wmf/scripting/init.lua	2015-10-18 20:57:50 +0000
@@ -57,8 +57,8 @@
 -- ware.
 function count_in_warehouses(ware)
    local whs = array_combine(
-      p1:get_buildings("headquarters"),
-      p1:get_buildings("warehouse")
+      p1:get_buildings("atlanteans_headquarters"),
+      p1:get_buildings("atlanteans_warehouse")
    )
    local rv = 0
    for idx,wh in ipairs(whs) do

=== modified file 'campaigns/atl01.wmf/scripting/mission_thread.lua'
--- campaigns/atl01.wmf/scripting/mission_thread.lua	2014-10-31 11:36:29 +0000
+++ campaigns/atl01.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -46,7 +46,8 @@
 
    local o = add_campaign_objective(obj_horsefarm_and_warehouse)
    while not check_for_buildings(p1, {
-      horsefarm = 1, warehouse = 1,
+      atlanteans_horsefarm = 1,
+      atlanteans_warehouse = 1,
    }) do sleep(2384) end
    o.done = true
 end
@@ -56,7 +57,8 @@
 
    local o = add_campaign_objective(obj_make_training_buildings)
    while not check_for_buildings(p1, {
-      dungeon = 1, labyrinth = 1
+      atlanteans_dungeon = 1,
+      atlanteans_labyrinth = 1
    }) do sleep(3874) end
    o.done = true
 
@@ -68,9 +70,14 @@
 
    local o = add_campaign_objective(obj_make_heavy_industry_and_mining)
    while not check_for_buildings(p1, {
-      coalmine = 1, ironmine = 1, goldmine = 1, crystalmine = 1,
-      smelting_works = 1, weaponsmithy = 1, armorsmithy = 1,
-      toolsmithy = 1,
+      atlanteans_coalmine = 1,
+      atlanteans_ironmine = 1,
+      atlanteans_goldmine = 1,
+      atlanteans_crystalmine = 1,
+      atlanteans_smelting_works = 1,
+      atlanteans_weaponsmithy = 1,
+      atlanteans_armorsmithy = 1,
+      atlanteans_toolsmithy = 1,
    }) do sleep(3478) end
    o.done = true
 
@@ -88,10 +95,15 @@
 
    local o = add_campaign_objective(obj_make_food_infrastructure)
    while not check_for_buildings(p1, {
-      farm = 1, blackroot_farm = 1,
-      sawmill = 1, well = 1, bakery = 1,
-      hunters_house = 1, fishers_house = 1,
-      fish_breeders_house = 1, smokery = 2,
+      atlanteans_farm = 1,
+      atlanteans_blackroot_farm = 1,
+      atlanteans_sawmill = 1,
+      atlanteans_well = 1,
+      atlanteans_bakery = 1,
+      hunters_house = 1,
+      atlanteans_fishers_house = 1,
+      atlanteans_fishbreeders_house = 1,
+      atlanteans_smokery = 2,
    }) do sleep(2789) end
    o.done = true
 
@@ -106,7 +118,9 @@
    local o = add_campaign_objective(obj_spidercloth_production)
 
    while not check_for_buildings(p1, {
-      spiderfarm = 1, ["gold-spinning-mill"] = 1, ["weaving-mill"] = 1
+      atlanteans_spiderfarm = 1,
+      atlanteans_gold_spinning_mill = 1,
+      atlanteans_weaving_mill = 1
    }) do sleep(6273) end
    o.done = true
 
@@ -121,10 +135,10 @@
    expand_objective = add_campaign_objective(obj_expand)
 
    while not check_for_buildings(p1, {
-      woodcutters_house = 2,
-      foresters_house = 2,
-      quarry = 1,
-      sawmill = 1,
+      atlanteans_woodcutters_house = 2,
+      atlanteans_foresters_house = 2,
+      atlanteans_quarry = 1,
+      atlanteans_sawmill = 1,
    }) do sleep(3731) end
    o.done = true
 
@@ -183,7 +197,7 @@
          local bobs = f.bobs
          if #bobs then
             for idx, b in ipairs(bobs) do
-               if b.descr.type_name == "ship" then
+               if b.descr.type_name == "atlanteans_ship" then
                   nships = nships + 1
                end
             end
@@ -215,7 +229,7 @@
             wait_for_roadbuilding_and_scroll(f)
             msg_boxes(field_flooded_msg)
             add_campaign_objective(obj_build_ships)
-            p1:allow_buildings{"shipyard"}
+            p1:allow_buildings{"atlanteans_shipyard"}
             run(check_for_ships)
          end)
       end

=== modified file 'campaigns/atl01.wmf/scripting/starting_conditions.lua'
--- campaigns/atl01.wmf/scripting/starting_conditions.lua	2014-10-03 08:58:44 +0000
+++ campaigns/atl01.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -7,21 +7,21 @@
 -- ===============
 
 p1:allow_buildings("all")
-p1:forbid_buildings{"shipyard"}
+p1:forbid_buildings{"atlanteans_shipyard"}
 
 -- A default headquarters
-include "tribes/atlanteans/scripting/sc00_headquarters.lua"
-init.func(p1) -- defined in sc00_headquarters
+include "tribes/scripting/starting_conditions/atlanteans/headquarters.lua"
+init.func(p1) -- defined in headquarters
 
 local hq = wl.Game().map.player_slots[1].starting_field.immovable
-hq:set_workers{shipwright=1}
+hq:set_workers{atlanteans_shipwright=1}
 
 -- Place some buildings
 prefilled_buildings(p1,
-	{"high_tower", first_tower_field.x, first_tower_field.y,
+	{"atlanteans_tower_high", first_tower_field.x, first_tower_field.y,
 		soldiers = { [{0,0,0,0}] = 1 }
 	},
-	{"high_tower", second_tower_field.x, second_tower_field.y,
+	{"atlanteans_tower_high", second_tower_field.x, second_tower_field.y,
 		soldiers = { [{0,0,0,0}] = 1 }
 	}
 )

=== modified file 'campaigns/atl01.wmf/scripting/texts.lua'
--- campaigns/atl01.wmf/scripting/texts.lua	2015-09-11 17:38:01 +0000
+++ campaigns/atl01.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -58,9 +58,9 @@
 		_[[Food is very important for mines and military training areas. Establish a well working food environment by building at least one farm, one blackroot farm and a mill. The two kinds of flour together with water from a well will be baked into bread in a bakery, so build a bakery and a well, too.]] .. paragraphdivider() ..
       _[[The other two important food wares are smoked fish and smoked meat. Raw meat is delivered from a hunter. A fisher gets the fish out of the sea while a fish breeder makes sure that a school of fish does not go extinct by breeding more. Make sure that there are always fish left, otherwise the fish breeder won’t be able to breed new ones. The smoking happens in a smokery, you will need at least two of those.]] .. paragraphdivider() ..
       listitem_bullet(_[[Build a farm and a blackroot farm]]) ..
-      listitem_bullet(_[[Build a mill to make cornflour and blackroot flour]]) ..
+      listitem_bullet(_[[Build a mill to make cornmeal and blackroot flour]]) ..
       listitem_bullet(_[[Build a well]]) ..
-      listitem_bullet(_[[Build a bakery to bake bread from cornflour, blackroot flour and water]]) ..
+      listitem_bullet(_[[Build a bakery to bake bread from cornmeal, blackroot flour and water]]) ..
       listitem_bullet(_[[Build a hunter’s house to get raw meat]]) ..
       listitem_bullet(_[[Build a fisher’s house close to water to get raw fish]]) ..
       listitem_bullet(_[[Build a fish breeder’s house close to the fisher to make sure the fish do not die out]]) ..
@@ -73,7 +73,7 @@
    title = _"Build a spider farm and a weaving mill",
    number = 3,
    body = objective_text(_"Spidercloth Production",
-		_[[The weavers produce spidercloth and tabards in the weaving mill. Spidercloth is needed for the construction of some buildings and clothing, while tabards are the uniforms of soldiers. The weaving mill needs gold yarn and spideryarn as raw material. Spideryarn is produced by the spider farm, while gold yarn is produced by the gold spinning mill out of gold.]] .. paragraphdivider() ..
+		_[[The weavers produce spidercloth and tabards in the weaving mill. Spidercloth is needed for the construction of some buildings and clothing, while tabards are the uniforms of soldiers. The weaving mill needs gold thread and spider silk as raw material. Spider silk is produced by the spider farm, while gold thread is produced by the gold spinning mill out of gold.]] .. paragraphdivider() ..
       listitem_bullet(_[[Build a weaving mill]]) ..
       listitem_bullet(_[[Build a spider farm]]) ..
       listitem_bullet(_[[Build a gold spinning mill]])

=== modified file 'campaigns/bar01.wmf/scripting/mission_thread.lua'
--- campaigns/bar01.wmf/scripting/mission_thread.lua	2014-10-30 11:37:38 +0000
+++ campaigns/bar01.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -19,8 +19,8 @@
 
    message_box_objective(plr, briefing_msg_01)
    -- these buildings are still burning, but only for a while
-   map:place_immovable("destroyed_building",map:get_field(7,41),"barbarians")
-   map:place_immovable("destroyed_building",map:get_field(5,52),"barbarians")
+   map:place_immovable("destroyed_building",map:get_field(7,41),"tribes")
+   map:place_immovable("destroyed_building",map:get_field(5,52),"tribes")
    plr:reveal_fields(al_thunran:region(8))
    message_box_objective(plr, briefing_msg_02) -- Al'thunran
    plr:reveal_fields(grave:region(4))
@@ -37,10 +37,10 @@
    message_box_objective(plr, order_msg_ranger)
    local obj = add_campaign_objective(obj_build_rangers)
 
-   while not check_for_buildings(plr, {rangers_hut = 2}) do sleep(500) end
+   while not check_for_buildings(plr, {barbarians_rangers_hut = 2}) do sleep(500) end
    obj.done = true
 
-   plr:allow_buildings{"sentry","barrier"}
+   plr:allow_buildings{"barbarians_sentry", "barbarians_barrier"}
 
    message_box_objective(plr, order_msg_1)
    message_box_objective(plr, order_msg_2)
@@ -59,7 +59,7 @@
 
    -- Now, wait till the quarry comes up
    local f = wl.Game().map:get_field(27,48):region(6)
-   while not check_for_buildings(plr, { quarry = 1 }, f) do
+   while not check_for_buildings(plr, { barbarians_quarry = 1 }, f) do
       sleep(5000)
    end
    obj.done = true
@@ -85,17 +85,17 @@
    message_box_objective(plr, order_msg_6_geologist)
    o = add_campaign_objective(obj_build_mines)
    plr:allow_buildings{
-      "coalmine",
-      "oremine",
-      "goldmine",
-      "granitemine"
+      "barbarians_coalmine",
+      "barbarians_ironmine",
+      "barbarians_goldmine",
+      "barbarians_granitemine"
    }
 
    sleep(10000)
    message_box_objective(plr, story_msg2)
 
    -- Wait for completion
-   while not check_for_buildings(plr, {coalmine = 1, oremine = 1}) do
+   while not check_for_buildings(plr, {barbarians_coalmine = 1, barbarians_ironmine = 1}) do
       sleep(5000)
    end
    o.done = true
@@ -111,7 +111,9 @@
       local hunter_msg_done = nil
       while true do
          local rv = plr:get_buildings{
-            "hunters_hut", "gamekeepers_hut", "tavern"
+            "barbarians_hunters_hut",
+            "barbarians_gamekeepers_hut",
+            "barbarians_tavern"
          }
          if #rv.hunters_hut >= 1 and not hunter_msg_done then
             message_box_objective(plr, order_msg_11_basic_food_began)
@@ -137,7 +139,7 @@
 
    run(function()
       while 1 do
-         local rv = plr:get_buildings{"well", "bakery", "farm"}
+         local rv = plr:get_buildings{"barbarians_well", "barbarians_bakery", "barbarians_farm"}
          if #rv.well >= 1 and #rv.bakery >= 1 and #rv.farm >= 1 then
             break
          end
@@ -149,13 +151,13 @@
 
    -- Enable food production
    plr:allow_buildings{
-      "hunters_hut",
-      "fishers_hut",
-      "gamekeepers_hut",
-      "tavern",
-      "farm",
-      "well",
-      "bakery",
+      "barbarians_hunters_hut",
+      "barbarians_fishers_hut",
+      "barbarians_gamekeepers_hut",
+      "barbarians_tavern",
+      "barbarians_farm",
+      "barbarians_well",
+      "barbarians_bakery",
    }
 
    while not (obj_bf.done and obj_farming.done) do
@@ -164,9 +166,9 @@
 
    -- Ready to build refiner stuff
    message_box_objective(plr, order_msg_14_refine_ore)
-   plr:allow_buildings{"smelting_works"}
+   plr:allow_buildings{"barbarians_smelting_works"}
    o = add_campaign_objective(obj_refine_ores)
-   while #plr:get_buildings("smelting_works") < 1 do
+   while #plr:get_buildings("barbarians_smelting_works") < 1 do
       sleep(6223)
    end
    o.done = true
@@ -175,15 +177,15 @@
    -- Wait until the player has an experienced worker.
    local chiefminer_found = false
    while not chiefminer_found do
-      local mines = plr:get_buildings{"coalmine","oremine"}
+      local mines = plr:get_buildings{"barbarians_coalmine","barbarians_ironmine"}
       for k,v in ipairs(mines.coalmine) do
-         if v:get_workers("chief-miner") > 0 then
+         if v:get_workers("barbarians_miner_chief") > 0 then
             chiefminer_found = true
             break
          end
       end
-      for k,v in ipairs(mines.oremine) do
-         if v:get_workers("chief-miner") > 0 then
+      for k,v in ipairs(mines.barbarians_ironmine) do
+         if v:get_workers("barbarians_miner_chief") > 0 then
             chiefminer_found = true
             break
          end
@@ -196,14 +198,22 @@
       sleep(5000)
    end
    message_box_objective(plr, order_msg_15_mines_exhausted)
-   plr:allow_buildings{"deep_coalmine", "deep_oremine", "inn", "micro-brewery"}
+   plr:allow_buildings{
+		"barbarians_coalmine_deep",
+		"barbarians_ironmine_deep",
+		"barbarians_inn",
+		"barbarians_micro_brewery"}
    local obj = add_campaign_objective(obj_enhance_buildings)
 
    run(function()
       while true do
-         local rv = plr:get_buildings{"deep_coalmine", "deep_oremine", "inn", "micro-brewery"}
-         if (#rv.inn > 0 and #rv["micro-brewery"] > 0) and
-            (#rv.deep_coalmine + #rv.deep_oremine > 0) then
+         local rv = plr:get_buildings{
+				"barbarians_coalmine_deep",
+				"barbarians_ironmine_deep",
+				"barbarians_inn",
+				"barbarians_micro_brewery"}
+         if (#rv.barbarians_inn > 0 and #rv["barbarians_micro_brewery"] > 0) and
+            (#rv.barbarians_coalmine_deep + #rv.barbarians_ironmine_deep > 0) then
             break
          end
          sleep(5421)
@@ -222,33 +232,37 @@
 
    -- Wait for a barrier or sentry to be built
    while true do
-      local rv = plr:get_buildings{"sentry", "barrier"}
-      if #rv.sentry + #rv.barrier > 0 then
+      local rv = plr:get_buildings{"barbarians_sentry", "barbarians_barrier"}
+      if #rv.barbarians_sentry + #rv.barbarians_barrier > 0 then
          break
       end
       sleep(5421)
    end
 
    message_box_objective(plr, order_msg_16_blackwood)
-   plr:allow_buildings{"hardener"}
+   plr:allow_buildings{"barbarians_wood_hardener"}
    sf.immovable:set_wares("blackwood",5)
    -- So that player has really little, but still enough to expand a bit
    local o = add_campaign_objective(obj_better_material_1)
 
    sleep(30*1000)
    message_box_objective(plr, story_msg1)
-   while #plr:get_buildings("hardener") < 1 do sleep(5421) end
+   while #plr:get_buildings("barbarians_wood_hardener") < 1 do sleep(5421) end
    o.done = true
 
    message_box_objective(plr, order_msg_17_grout)
-   plr:allow_buildings{"lime_kiln", "well", "charcoal_kiln"}
+   plr:allow_buildings{"barbarians_lime_kiln", "barbarians_well", "barbarians_charcoal_kiln"}
    o = add_campaign_objective(obj_better_material_2)
    -- Wait for the buildings to be built
    while true do
-      local rv = plr:get_buildings{"lime_kiln", "well",
-         "coalmine", "deep_coalmine", "charcoal_kiln"}
-      if (#rv.lime_kiln > 0 and #rv.well > 0) and
-         (#rv.coalmine + #rv.deep_coalmine + #rv.charcoal_kiln > 0) then
+      local rv = plr:get_buildings{
+			"barbarians_lime_kiln",
+			"barbarians_well",
+         "barbarians_coalmine",
+         "barbarians_coalmine_deep",
+         "barbarians_charcoal_kiln"}
+      if (#rv.barbarians_lime_kiln > 0 and #rv.barbarians_well > 0) and
+         (#rv.barbarians_coalmine + #rv.barbarians_coalmine_deep + #rv.barbarians_charcoal_kiln > 0) then
          break
       end
       sleep(5421)
@@ -256,9 +270,9 @@
    o.done = true
 
    message_box_objective(plr, order_msg_18_reed)
-   plr:allow_buildings{"reed_yard"}
+   plr:allow_buildings{"barbarians_reed_yard"}
    o = add_campaign_objective(obj_better_material_3)
-   while #plr:get_buildings("reed_yard") < 1 do sleep(5421) end
+   while #plr:get_buildings("barbarians_reed_yard") < 1 do sleep(5421) end
 
    message_box_objective(plr, order_msg_19_all_material)
    o.done = true
@@ -270,19 +284,19 @@
 -- Cattlefarm thread
 -- ==================
 function cattle_farm()
-   while not check_for_buildings(plr, { farm = 1, well = 1 }) do
+   while not check_for_buildings(plr, { barbarians_farm = 1, barbarians_well = 1 }) do
       sleep(7834)
    end
 
    message_box_objective(plr, msg_cattlefarm_00)
 
    local o = add_campaign_objective(obj_build_cattlefarm)
-   plr:allow_buildings{"cattlefarm"}
+   plr:allow_buildings{"barbarians_cattlefarm"}
 
    sleep(10000)
    message_box_objective(plr, story_msg3)
 
-   while not check_for_buildings(plr, { cattlefarm = 1 }) do
+   while not check_for_buildings(plr, { barbarians_cattlefarm = 1 }) do
       sleep(2323)
    end
    o.done = true

=== modified file 'campaigns/bar01.wmf/scripting/secret_village.lua'
--- campaigns/bar01.wmf/scripting/secret_village.lua	2014-10-28 19:23:06 +0000
+++ campaigns/bar01.wmf/scripting/secret_village.lua	2015-10-18 20:57:50 +0000
@@ -48,7 +48,7 @@
          if f.immovable then
             pcall(f.immovable.remove, f.immovable)
          end
-         map:place_immovable(id[1], f, id[4])
+         map:place_immovable(id[1], f, id[4], "world")
       end
    end
 
@@ -95,33 +95,33 @@
 
    local plr = wl.Game().players[1]
    prefilled_buildings(plr,
-      {"sentry", 57, 9},
-      {"sentry", 52, 39},
-      {"hunters_hut", 56, 10},
-      {"gamekeepers_hut", 56, 12},
-      {"farm", 56, 16},
-      {"well", 54, 18},
-      {"bakery", 55, 20, wares = {wheat=6, water=6}},
-      {"lumberjacks_hut", 56, 21},
-      {"lumberjacks_hut", 55, 22},
-      {"lumberjacks_hut", 54, 24},
-      {"rangers_hut", 57, 24},
-      {"rangers_hut", 55, 25},
-      {"hardener", 54, 26, wares = {log = 8}},
+      {"barbarians_sentry", 57, 9},
+      {"barbarians_sentry", 52, 39},
+      {"barbarians_hunters_hut", 56, 10},
+      {"barbarians_gamekeepers_hut", 56, 12},
+      {"barbarians_farm", 56, 16},
+      {"barbarians_well", 54, 18},
+      {"barbarians_bakery", 55, 20, wares = {wheat = 6, water = 6}},
+      {"barbarians_lumberjacks_hut", 56, 21},
+      {"barbarians_lumberjacks_hut", 55, 22},
+      {"barbarians_lumberjacks_hut", 54, 24},
+      {"barbarians_rangers_hut", 57, 24},
+      {"barbarians_rangers_hut", 55, 25},
+      {"barbarians_wood_hardener", 54, 26, wares = {log = 8}},
       -- to make it more realistic
-      {"warehouse", 53, 28,
+      {"barbarians_warehouse", 53, 28,
          wares = {
             wheat = 20,
             log = 40,
             meat = 30
          }
       },
-      {"inn", 55, 28, wares = {pittabread = 4, meat = 4}},
-      {"tavern", 57, 28, wares = {pittabread=4, meat = 4}},
-      {"well", 52, 30},
-      {"farm", 54, 33},
-      {"bakery", 51, 35, wares = {wheat = 6, water = 6}},
-      {"well", 52, 37}
+      {"barbarians_inn", 55, 28, wares = {barbarians_bread = 4, meat = 4}},
+      {"barbarians_tavern", 57, 28, wares = {barbarians_bread = 4, meat = 4}},
+      {"barbarians_well", 52, 30},
+      {"barbarians_farm", 54, 33},
+      {"barbarians_bakery", 51, 35, wares = {wheat = 6, water = 6}},
+      {"barbarians_well", 52, 37}
    )
 
    -- Adjust the borders so that the village owns everything green

=== modified file 'campaigns/bar01.wmf/scripting/starting_conditions.lua'
--- campaigns/bar01.wmf/scripting/starting_conditions.lua	2014-10-18 12:34:17 +0000
+++ campaigns/bar01.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -5,65 +5,64 @@
 -- Allow some buildings
 plr:forbid_buildings("all")
 plr:allow_buildings{
-   "lumberjacks_hut",
-   "quarry",
-   "rangers_hut"
+   "barbarians_lumberjacks_hut",
+   "barbarians_quarry",
+   "barbarians_rangers_hut"
 }
 
 -- Place headquarters and fill it with wares
-hq = plr:place_building("headquarters_interim", sf, false, true)
+hq = plr:place_building("barbarians_headquarters_interim", sf, false, true)
 hq:set_wares{
-   ax=6,
-   bread_paddle=2,
-   blackwood=32,
-   coal=5,
-   fire_tongs=2,
-   fish=6,
-   grout=4,
-   hammer=12,
-   hunting_spear=2,
-   ironore=5,
-   kitchen_tools=4,
-   meal=4,
-   meat=6,
-   pick=14,
-   pittabread=8,
-   ration=12,
-   raw_stone=40,
-   scythe=6,
-   shovel=4,
-   snack=3,
-   thatchreed=24,
-   log=80,
+   ax = 6,
+   blackwood = 32,
+   barbarians_bread = 8,
+   bread_paddle = 2,
+   coal = 5,
+   fire_tongs = 2,
+   fish = 6,
+   granite = 40,
+   grout = 4,
+   hammer = 12,
+   hunting_spear = 2,
+   iron_ore = 5,
+   kitchen_tools = 4,
+   log = 80,
+   meal = 4,
+   meat = 6,
+   pick = 14,
+   ration = 12,
+   scythe = 6,
+   shovel = 4,
+   snack = 3,
+   thatch_reed = 24,
 }
 hq:set_workers{
-   blacksmith=2,
-   brewer=1,
-   builder=10,
-   carrier=40,
-   charcoal_burner=1,
-   gardener=1,
-   fisher=1,
-   geologist=4,
-   ["lime-burner"]=1,
-   lumberjack=3,
-   miner=4,
-   ranger=2,
-   stonemason=2
+   barbarians_blacksmith = 2,
+   barbarians_brewer = 1,
+   barbarians_builder = 10,
+   barbarians_carrier = 40,
+   barbarians_charcoal_burner = 1,
+   barbarians_fisher = 1,
+   barbarians_gardener = 1,
+   barbarians_geologist = 4,
+   barbarians_lime_burner = 1,
+   barbarians_lumberjack = 3,
+   barbarians_miner = 4,
+   barbarians_ranger = 2,
+   barbarians_stonemason = 2
 }
 hq:set_soldiers({0,0,0,0}, 45)
 
 -- ============
 -- Build roads
 -- ============
---connected_road(plr,sf.brn.immovable, "r,r|br,r")
 connected_road(plr, sf.brn.immovable, "r,r|br,r|r,r")
 connected_road(plr, sf.brn.immovable, "l,l|l,bl,bl|br,r|br,r|r,tr|tr,tr,tr")
 connected_road(plr, map:get_field(13,14).immovable, "r,br|br,r")
 
 -- Place some initial buildings
 prefilled_buildings(plr,
-   {"lumberjacks_hut", 15, 11},
-   {"lumberjacks_hut", 9, 13},
-   {"quarry", 8, 12}
+   {"barbarians_lumberjacks_hut", 15, 11},
+   {"barbarians_lumberjacks_hut", 9, 13},
+   {"barbarians_quarry", 8, 12}
 )

=== modified file 'campaigns/bar01.wmf/scripting/texts.lua'
--- campaigns/bar01.wmf/scripting/texts.lua	2015-09-11 17:38:01 +0000
+++ campaigns/bar01.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -103,7 +103,7 @@
    title = _"Build a wood hardener",
    number = 1,
    body = objective_text(_"Build a wood hardener",
-      _([[Bigger and better buildings – including all military ones – require better building materials. They cannot be built out of simple logs – the wood has to be refined to blackwood by a wood hardener first. Always remember to build a wood hardener before you run out of blackwood, as without it you cannot expand.]])
+      _([[Bigger and better buildings – including all military ones – require better building materials. They cannot be built out of simple logs – the logs have to be refined to blackwood by a wood hardener first. Always remember to build a wood hardener before you run out of blackwood, as without it you cannot expand.]])
       .. paragraphdivider() ..
       listitem_bullet(_"Build a wood hardener"))
 }

=== modified file 'campaigns/bar02.wmf/scripting/mission_thread.lua'
--- campaigns/bar02.wmf/scripting/mission_thread.lua	2014-10-02 18:51:30 +0000
+++ campaigns/bar02.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -26,9 +26,9 @@
 
    campaign_message_box(cattlefarm_01)
 
-   p1:allow_buildings{"cattlefarm"}
+   p1:allow_buildings{"barbarians_cattlefarm"}
    local o = add_campaign_objective(obj_build_cattlefarm)
-   while not check_for_buildings(p1, {cattlefarm = 1}) do
+   while not check_for_buildings(p1, {barbarians_cattlefarm = 1}) do
       sleep(1223) end
    o.done = true
 
@@ -42,23 +42,24 @@
    campaign_message_box(briefing_msg_1)
    campaign_message_box(order_msg_1_small_food_economy)
 
-   p1:allow_buildings{"fishers_hut",
-      "hunters_hut",
-      "gamekeepers_hut",
-      "tavern",
-      "farm",
-      "well",
-      "bakery",
-      "sentry",
+   p1:allow_buildings{
+		"barbarians_fishers_hut",
+      "barbarians_hunters_hut",
+      "barbarians_gamekeepers_hut",
+      "barbarians_tavern",
+      "barbarians_farm",
+      "barbarians_well",
+      "barbarians_bakery",
+      "barbarians_sentry",
    }
 
    local o = add_campaign_objective(obj_build_small_food_economy)
    while not check_for_buildings(p1, {
-         fishers_hut = 1,
-         hunters_hut = 1,
-         well = 1,
-         farm = 1,
-         bakery = 1,
+         barbarians_fishers_hut = 1,
+         barbarians_hunters_hut = 1,
+         barbarians_well = 1,
+         barbarians_farm = 1,
+         barbarians_bakery = 1,
       }) do sleep(3413) end
    o.done = true
    campaign_message_box(story_note_1)
@@ -70,7 +71,7 @@
 function foottracks()
    -- Hunter build and some time passed or expanded east
    while true do
-      if game.time > 900000 and #p1:get_buildings("hunters_hut") > 0
+      if game.time > 900000 and #p1:get_buildings("barbarians_hunters_hut") > 0
       then break end
       if check_conquered_footprints()
       then break end
@@ -86,10 +87,10 @@
 
    local pts = scroll_smoothly_to(game.map:get_field(67,19))
 
-   campaign_message_box(order_msg_2_build_a_donjon)
-   local o = add_campaign_objective(obj_build_a_donjon)
-   p1:forbid_buildings{"sentry"}
-   p1:allow_buildings{"donjon"}
+   campaign_message_box(order_msg_2_build_a_tower)
+   local o = add_campaign_objective(obj_build_a_tower)
+   p1:forbid_buildings{"barbarians_sentry"}
+   p1:allow_buildings{"barbarians_tower"}
 
    timed_scroll(array_reverse(pts), 10)
 
@@ -97,13 +98,13 @@
    sleep(5003)
    p1:hide_fields(fields)
 
-   while not check_for_buildings(p1, {donjon=1}) do sleep(2341) end
+   while not check_for_buildings(p1, {barbarians_tower=1}) do sleep(2341) end
    o.done = true
    campaign_message_box(order_msg_3_explore_further)
    -- "explore further" is active untill "Boldreth shout out", so the player always has one open objectve.
    exploration_objective = add_campaign_objective(obj_explore_further)
 
-   p1:allow_buildings{"sentry", "barrier"}
+   p1:allow_buildings{"barbarians_sentry", "barbarians_barrier"}
 
    -- Wait till we see the mountain and at least one frontier
    while true do
@@ -133,26 +134,33 @@
    local o = add_campaign_objective(obj_build_mining_economy)
 
    p1:allow_buildings{
-      "coalmine",
-      "oremine",
-      "goldmine",
-      "granitemine",
-      "smelting_works",
-      "metalworks",
-      "charcoal_kiln",
-      "micro-brewery",
+      "barbarians_coalmine",
+      "barbarians_ironmine",
+      "barbarians_goldmine",
+      "barbarians_granitemine",
+      "barbarians_smelting_works",
+      "barbarians_metal_workshop",
+      "barbarians_charcoal_kiln",
+      "barbarians_micro_brewery",
    }
 
    timed_scroll(array_reverse(pts), 10)
    sleep(500)
 
    while true do
-      local h = p1:get_buildings{"coalmine","charcoal_kiln", "oremine",
-         "tavern", "smelting_works", "metalworks"}
+      local h = p1:get_buildings{
+			"barbarians_coalmine",
+			"barbarians_charcoal_kiln",
+			"barbarians_ironmine",
+         "barbarians_tavern",
+         "barbarians_smelting_works",
+         "barbarians_metal_workshop"}
 
-      if (#h.coalmine + #h.charcoal_kiln > 0) and
-         #h.oremine > 0 and #h.tavern > 0 and #h.smelting_works > 0 and
-         #h.metalworks > 0
+      if (#h.barbarians_coalmine + #h.barbarians_charcoal_kiln > 0) and
+          #h.barbarians_ironmine > 0 and
+          #h.barbarians_tavern > 0 and
+          #h.barbarians_smelting_works > 0 and
+          #h.barbarians_metal_workshop > 0
       then
          break
       end
@@ -165,21 +173,21 @@
 
    campaign_message_box(order_msg_6_build_enhanced_economy_and_training)
    p1:allow_buildings{
-      "axfactory",
-      "warmill",
-      "helmsmithy",
-      "battlearena",
-      "trainingcamp",
-      "inn",
-      "big_inn",
-      "deep_coalmine",
-      "deep_goldmine",
-      "deep_oremine",
-      "deeper_coalmine",
-      "deeper_goldmine",
-      "deeper_oremine",
-      "warehouse",
-      "brewery",
+      "barbarians_axfactory",
+      "barbarians_warmill",
+      "barbarians_helmsmithy",
+      "barbarians_battlearena",
+      "barbarians_trainingcamp",
+      "barbarians_inn",
+      "barbarians_big_inn",
+      "barbarians_coalmine_deep",
+      "barbarians_goldmine_deep",
+      "barbarians_ironmine_deep",
+      "barbarians_coalmine_deeper",
+      "barbarians_goldmine_deeper",
+      "barbarians_ironmine_deeper",
+      "barbarians_warehouse",
+      "barbarians_brewery",
    }
    run(check_warehouse_obj, add_campaign_objective(obj_build_a_warehouse))
    run(check_trainingssite_obj, add_campaign_objective(obj_build_trainingssites))
@@ -195,8 +203,12 @@
 end
 function check_weapon_productions_obj(o)
    while true do
-      local rv = p1:get_buildings{"metalworks", "axfactory", "warmill"}
-      if #rv.metalworks > 0 and (#rv.axfactory + #rv.warmill > 0) then
+      local rv = p1:get_buildings{
+			"barbarians_metal_workshop",
+			"barbarians_axfactory",
+			"barbarians_warmill"}
+      if #rv.barbarians_metal_workshop > 0 and
+			(#rv.barbarians_axfactory + #rv.barbarians_warmill > 0) then
          break
       end
       sleep(6523)
@@ -219,9 +231,9 @@
 
    campaign_message_box(order_msg_5_build_a_fortress)
    local o = add_campaign_objective(obj_build_a_fortress)
-   p1:allow_buildings{"fortress"}
+   p1:allow_buildings{"barbarians_fortress"}
 
-   while #p1:get_buildings("fortress") == 0 do sleep(6523) end
+   while #p1:get_buildings("barbarians_fortress") == 0 do sleep(6523) end
 
    o.done = true
    campaign_message_box(story_note_3)
@@ -248,12 +260,12 @@
 
 -- checks if all military buildings are drestroyed (the build-in function "defeated" only checks if all warehouses are destroyed)
 function check_player_completely_defeated(dp)
-    if #dp:get_buildings("fortress")  > 0 then return false end
-    if #dp:get_buildings("citadel")   > 0 then return false end
-    if #dp:get_buildings("donjon")    > 0 then return false end
-    if #dp:get_buildings("barrier")   > 0 then return false end
-    if #dp:get_buildings("sentry")    > 0 then return false end
-    if #dp:get_buildings("warehouse") > 0 then return false end
+    if #dp:get_buildings("barbarians_fortress")  > 0 then return false end
+    if #dp:get_buildings("barbarians_citadel")   > 0 then return false end
+    if #dp:get_buildings("barbarians_tower")    > 0 then return false end
+    if #dp:get_buildings("barbarians_barrier")   > 0 then return false end
+    if #dp:get_buildings("barbarians_sentry")    > 0 then return false end
+    if #dp:get_buildings("barbarians_warehouse") > 0 then return false end
     return true
 end
 
@@ -295,14 +307,14 @@
    do sleep(6833) end
 
    prefilled_buildings(p1,
-      {"barrier", 118, 100, soldiers =
+      {"barbarians_barrier", 118, 100, soldiers =
          {[{0,0,0,0}]= 1, [{1,1,0,1}] = 1, [{0,1,0,0}] = 1}
       },
-      {"citadel", 117, 97, soldiers = {
+      {"barbarians_citadel", 117, 97, soldiers = {
          [{0,0,0,0}]=3, [{1,1,0,0}]=1, [{0,0,0,1}]=2,
          [{0,1,0,1}]=1, [{1,1,0,1}]=1, [{2,1,0,2}]=1,
       }},
-      {"sentry", 116, 98 }
+      {"barbarians_sentry", 116, 98 }
    )
 
    -- Some something of the enemy land

=== modified file 'campaigns/bar02.wmf/scripting/starting_conditions.lua'
--- campaigns/bar02.wmf/scripting/starting_conditions.lua	2014-08-26 17:25:00 +0000
+++ campaigns/bar02.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -3,57 +3,57 @@
 -- =======================================================================
 p1:forbid_buildings("all")
 p1:allow_buildings{
-   "lumberjacks_hut",
-   "quarry",
-   "rangers_hut",
-   "hardener",
-   "lime_kiln",
-   "reed_yard",
-   "sentry",
+   "barbarians_lumberjacks_hut",
+   "barbarians_quarry",
+   "barbarians_rangers_hut",
+   "barbarians_wood_hardener",
+   "barbarians_lime_kiln",
+   "barbarians_reed_yard",
+   "barbarians_sentry",
 }
 
-hq = p1:place_building("headquarters", wl.Game().map:get_field(52, 33), false, true)
+hq = p1:place_building("barbarians_headquarters", wl.Game().map:get_field(52, 33), false, true)
 hq:set_wares{
-   ax=1,
-   bread_paddle=2,
-   blackwood=32,
-   coal=12,
-   felling_ax=5,
-   fire_tongs=2,
-   fish=6,
-   grout=12,
-   hammer=12,
-   hunting_spear=2,
-   iron=12,
-   ironore=25,
-   kitchen_tools=4,
-   meal=4,
-   meat=6,
-   pick=14,
-   pittabread=8,
-   ration=12,
-   raw_stone=40,
-   scythe=6,
-   shovel=4,
-   snack=3,
-   thatchreed=24,
-   log=80,
+   ax = 1,
+   blackwood = 32,
+   barbarians_bread = 8,
+   bread_paddle = 2,
+   coal = 12,
+   felling_ax = 5,
+   fire_tongs = 2,
+   fish = 6,
+   granite = 40,
+   grout = 12,
+   hammer = 12,
+   hunting_spear = 2,
+   iron = 12,
+   iron_ore = 25,
+   kitchen_tools = 4,
+   log = 80,
+   meal = 4,
+   meat = 6,
+   pick = 14,
+   ration = 12,
+   scythe = 6,
+   shovel = 4,
+   snack = 3,
+   thatch_reed = 24,
 }
 hq:set_workers{
-   carrier=40,
-   blacksmith=2,
-   brewer=1,
-   builder=10,
-   charcoal_burner=1,
-   gardener=1,
-   fisher=2,
-   geologist=4,
-   ["lime-burner"]=1,
-   lumberjack=3,
-   miner=4,
-   ranger=1,
-   stonemason=2,
-   ox = 40,
+   barbarians_blacksmith = 2,
+   barbarians_brewer = 1,
+   barbarians_builder = 10,
+   barbarians_carrier = 40,
+   barbarians_charcoal_burner = 1,
+   barbarians_fisher = 2,
+   barbarians_gardener = 1,
+   barbarians_geologist = 4,
+   barbarians_lime_burner = 1,
+   barbarians_lumberjack = 3,
+   barbarians_miner = 4,
+   barbarians_ox = 40,
+   barbarians_ranger = 1,
+   barbarians_stonemason = 2,
 }
 hq:set_soldiers({0,0,0,0}, 45)
 
@@ -61,33 +61,33 @@
 --                                 Player 2
 -- =======================================================================
 p2:forbid_buildings("all")
-p2:allow_buildings{"lumberjacks_hut"}
+p2:allow_buildings{"barbarians_lumberjacks_hut"}
 
-wh = p2:place_building("warehouse", wl.Game().map:get_field(100,25), false, true)
-wh:set_wares{log=200}
-wh:set_workers{ carrier=40, builder=1, lumberjack=4 }
+wh = p2:place_building("barbarians_warehouse", wl.Game().map:get_field(100,25), false, true)
+wh:set_wares{log = 200}
+wh:set_workers{ barbarians_carrier=40, barbarians_builder=1, barbarians_lumberjack=4 }
 
 prefilled_buildings(p2,
-   {"donjon", 102, 71, soldiers={[{0,0,0,0}] = 4}},
-   {"donjon", 104, 18, soldiers={
+   {"barbarians_tower", 102, 71, soldiers={[{0,0,0,0}] = 4}},
+   {"barbarians_tower", 104, 18, soldiers={
       [{0,0,0,0}] = 1, [{2,0,0,0}] = 1, [{0,1,0,0}] = 1
    }},
-   {"donjon", 104, 25, soldiers = {[{0,0,0,0}]=2, [{1,0,0,0}]=1, }},
-   {"donjon", 102, 83, soldiers = {[{0,0,0,0}]=2 }},
-   {"barrier", 103, 11, soldiers = {[{0,0,0,0}]=2, [{0,0,0,1}]=1 }},
-   {"barrier", 104, 4, soldiers = {[{0,0,0,0}]=4}},
-   {"barrier", 102, 103, soldiers = {[{0,0,0,0}]=2, [{0,1,0,1}]=1}},
-   {"barrier", 103, 96, soldiers = {[{0,0,0,0}]=3}},
-   {"barrier", 104, 110, soldiers = {[{0,0,0,0}]=2}},
-   {"barrier", 104, 30, soldiers = {
+   {"barbarians_tower", 104, 25, soldiers = {[{0,0,0,0}]=2, [{1,0,0,0}]=1, }},
+   {"barbarians_tower", 102, 83, soldiers = {[{0,0,0,0}]=2 }},
+   {"barbarians_barrier", 103, 11, soldiers = {[{0,0,0,0}]=2, [{0,0,0,1}]=1 }},
+   {"barbarians_barrier", 104, 4, soldiers = {[{0,0,0,0}]=4}},
+   {"barbarians_barrier", 102, 103, soldiers = {[{0,0,0,0}]=2, [{0,1,0,1}]=1}},
+   {"barbarians_barrier", 103, 96, soldiers = {[{0,0,0,0}]=3}},
+   {"barbarians_barrier", 104, 110, soldiers = {[{0,0,0,0}]=2}},
+   {"barbarians_barrier", 104, 30, soldiers = {
       [{0,1,0,1}]=1, [{1,0,0,0}]=1, [{0,0,0,0}]=1
    }},
-   {"barrier", 102, 90, soldiers = {[{0,0,0,0}]=1}},
-   {"sentry", 108, 3, soldiers = {[{0,0,0,0}]=2}},
-   {"sentry", 107, 104, soldiers = {[{0,0,0,0}]=1}},
-   {"sentry", 110, 19, soldiers = {[{0,0,0,0}]=2}},
-   {"sentry", 106, 91, soldiers = {[{0,0,0,0}]=2}},
-   {"sentry", 108, 84, soldiers = {[{0,0,0,0}]=2}}
+   {"barbarians_barrier", 102, 90, soldiers = {[{0,0,0,0}]=1}},
+   {"barbarians_sentry", 108, 3, soldiers = {[{0,0,0,0}]=2}},
+   {"barbarians_sentry", 107, 104, soldiers = {[{0,0,0,0}]=1}},
+   {"barbarians_sentry", 110, 19, soldiers = {[{0,0,0,0}]=2}},
+   {"barbarians_sentry", 106, 91, soldiers = {[{0,0,0,0}]=2}},
+   {"barbarians_sentry", 108, 84, soldiers = {[{0,0,0,0}]=2}}
 )
 
 -- =======================================================================
@@ -95,13 +95,13 @@
 -- =======================================================================
 p3:forbid_buildings("all")
 prefilled_buildings(p3,
-   {"sentry", 137, 87, soldiers = {[{0,0,0,0}]=2}},
-   {"barrier", 130, 86, soldiers = {[{0,0,0,0}]=4}},
-   {"barrier", 132, 82, soldiers = {[{0,0,0,0}]=4}},
-   {"fortress", 135, 85, soldiers = {
+   {"barbarians_sentry", 137, 87, soldiers = {[{0,0,0,0}]=2}},
+   {"barbarians_barrier", 130, 86, soldiers = {[{0,0,0,0}]=4}},
+   {"barbarians_barrier", 132, 82, soldiers = {[{0,0,0,0}]=4}},
+   {"barbarians_fortress", 135, 85, soldiers = {
       [{0,0,0,0}]=4, [{1,0,0,0}]=2, [{1,1,0,0}]=2,
    }},
-   {"barrier", 132, 78, soldiers = {
+   {"barbarians_barrier", 132, 78, soldiers = {
       [{0,0,0,0}]=1, [{1,1,0,1}]=1, [{0,1,0,0}]=1,
    }}
 )
@@ -110,24 +110,29 @@
 --                                 Player 4
 -- =======================================================================
 p4:forbid_buildings("all")
-wh = p4:place_building("warehouse", wl.Game().map:get_field(132,110), false, true)
-wh:set_wares{log=10}
-wh:set_workers{carrier=40, builder=1, blacksmith=1, ["master-blacksmith"]=1}
+wh = p4:place_building("barbarians_warehouse", wl.Game().map:get_field(132,110), false, true)
+wh:set_wares {log = 10}
+wh:set_workers {
+	barbarians_carrier = 40,
+	barbarians_builder = 1,
+	barbarians_blacksmith = 1,
+	barbarians_blacksmith_master = 1
+}
 
 prefilled_buildings(p4,
-   {"citadel", 135, 3, soldiers = {
+   {"barbarians_citadel", 135, 3, soldiers = {
       [{0,0,0,0}]=2, [{1,1,0,0}]=1, [{0,0,0,1}]=2, [{0,1,0,1}]=1,
    }},
-   {"sentry", 137, 5, soldiers = {[{0,0,0,0}]=2}},
-   {"sentry", 133, 1, soldiers = {[{0,1,0,0}]=2}},
-   {"sentry", 130, 6, soldiers = {[{0,0,0,0}]=2}},
-   {"barrier", 133, 106, soldiers = {[{0,0,0,0}]=2, [{1,0,0,0}]=2}},
-   {"donjon", 132, 7, soldiers = {
+   {"barbarians_sentry", 137, 5, soldiers = {[{0,0,0,0}]=2}},
+   {"barbarians_sentry", 133, 1, soldiers = {[{0,1,0,0}]=2}},
+   {"barbarians_sentry", 130, 6, soldiers = {[{0,0,0,0}]=2}},
+   {"barbarians_barrier", 133, 106, soldiers = {[{0,0,0,0}]=2, [{1,0,0,0}]=2}},
+   {"barbarians_tower", 132, 7, soldiers = {
       [{0,0,0,0}]=2, [{1,1,0,0}]=1, [{1,0,0,1}]=1,
    }},
-   {"barrier", 132, 3, soldiers = {
+   {"barbarians_barrier", 132, 3, soldiers = {
       [{0,0,0,0}]=1, [{1,0,0,1}]=1, [{0,1,0,1}]=1,
    }},
-   {"warmill", 135, 7}
+   {"barbarians_warmill", 135, 7}
 )
 

=== modified file 'campaigns/bar02.wmf/scripting/texts.lua'
--- campaigns/bar02.wmf/scripting/texts.lua	2015-09-11 17:38:01 +0000
+++ campaigns/bar02.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -41,12 +41,12 @@
    ),
 }
 
-obj_build_a_donjon = {
-   name = "build_a_donjon",
-   title = _"Build a donjon",
+obj_build_a_tower = {
+   name = "build_a_tower",
+   title = _"Build a tower",
    number = 1,
-   body = objective_text(_"Build a donjon",
-      listitem_bullet(_"Build a donjon at the north-east border of your territory to get greater visual range and to protect your people from sudden attacks by enemies."))
+   body = objective_text(_"Build a tower",
+      listitem_bullet(_"Build a tower at the north-east border of your territory to get greater visual range and to protect your people from sudden attacks by enemies."))
 }
 
 obj_explore_further = {
@@ -240,13 +240,13 @@
 		_([[Khantrukh has just informed me that our basic food economy was built up successfully. Finally, none of us has to fear starvation anymore.]]))
 }
 
-order_msg_2_build_a_donjon = {
+order_msg_2_build_a_tower = {
    posy = 1,
    title = _"Tracks",
    body = boldreth(_"Boldreth says:",
       -- TRANSLATORS: Boldreth
-		_([[Thron told me that he discovered tracks in the snow to the northeast of our settlement. He has instructed us to build a donjon, to have a greater visual range over the area around our hall to protect our people from sudden attacks.]]))
-		.. new_objectives(obj_build_a_donjon)
+		_([[Thron told me that he discovered tracks in the snow to the northeast of our settlement. He has instructed us to build a tower,  to have a greater visual range over the area around our hall to protect our people from sudden attacks.]]))
+		.. new_objectives(obj_build_a_tower)
 }
 
 order_msg_3_explore_further = {
@@ -292,7 +292,7 @@
    title = _"Fortress Completed",
    body = thron(_"Thron says:",
       -- TRANSLATORS: Thron
-		_([[Finally! The fortress has just been completed, so the entrance to our settlement should be safe for now. For the future, we might think on building some more fortifications like barriers and donjons at the passages, but for now we can take a deep breath.]]))
+		_([[Finally! The fortress has just been completed, so the entrance to our settlement should be safe for now. For the future, we might think on building some more fortifications like barriers and towers at the passages, but for now we can take a deep breath.]]))
 }
 
 order_msg_6_build_enhanced_economy_and_training = {

=== modified file 'campaigns/emp01.wmf/scripting/mission_thread.lua'
--- campaigns/emp01.wmf/scripting/mission_thread.lua	2015-05-31 13:45:13 +0000
+++ campaigns/emp01.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -12,7 +12,7 @@
 
    -- Show the sea
    p1:reveal_fields(sea:region(6))
-   local ship = p1:place_bob("ship",sea)
+   local ship = p1:place_ship(sea)
    sleep(200)
    campaign_message_box(diary_page_2)
    -- Hide the sea after 5 seconds
@@ -27,40 +27,40 @@
    sleep(400)
 
    campaign_message_box(saledus_1)
-   p1:allow_buildings{"barracks"}
-   local o = add_campaign_objective(obj_build_barracks)
-   while #p1:get_buildings("barracks") < 1 do sleep(3249) end
+   p1:allow_buildings{"empire_blockhouse"}
+   local o = add_campaign_objective(obj_build_blockhouse)
+   while #p1:get_buildings("empire_blockhouse") < 1 do sleep(3249) end
    o.done = true
 
-   -- Barracks are completed now
+   -- Blockhouse is completed now
    campaign_message_box(saledus_2)
-   p1:allow_buildings{"lumberjacks_house"}
+   p1:allow_buildings{"empire_lumberjacks_house"}
    o = add_campaign_objective(obj_build_lumberjack)
    campaign_message_box(amalea_1)
-   while #p1:get_buildings("lumberjacks_house") < 1 do sleep(3249) end
+   while #p1:get_buildings("empire_lumberjacks_house") < 1 do sleep(3249) end
    o.done = true
 
    -- Lumberjack is now build
    campaign_message_box(amalea_2)
-   p1:allow_buildings{"sawmill"}
+   p1:allow_buildings{"empire_sawmill"}
    o = add_campaign_objective(obj_build_sawmill_and_lumberjacks)
-   while not check_for_buildings(p1, { lumberjacks_house = 3, sawmill = 1})
+   while not check_for_buildings(p1, { lempire_umberjacks_house = 3, empire_sawmill = 1})
       do sleep(2343) end
    o.done = true
 
    -- Now the lady demands a forester after having us cut down the whole forest.
    campaign_message_box(amalea_3)
    o = add_campaign_objective(obj_build_forester)
-   p1:allow_buildings{"foresters_house"}
-   while not check_for_buildings(p1, { foresters_house = 1 }) do sleep(2434) end
+   p1:allow_buildings{"empire_foresters_house"}
+   while not check_for_buildings(p1, { empire_foresters_house = 1 }) do sleep(2434) end
    o.done = true
 
 
    -- Now a quarry
    campaign_message_box(saledus_3)
    o = add_campaign_objective(obj_build_quarry)
-   p1:allow_buildings{"quarry"}
-   while not check_for_buildings(p1, { quarry = 1 }) do sleep(2434) end
+   p1:allow_buildings{"empire_quarry"}
+   while not check_for_buildings(p1, { empire_quarry = 1 }) do sleep(2434) end
    o.done = true
 
    -- All buildings done. Got home
@@ -72,9 +72,9 @@
    p1:reveal_scenario("empiretut01")
 end
 
--- Show a funny message when the player has build 10 barracks
+-- Show a funny message when the player has build 10 blockhouses
 function easter_egg()
-   while not check_for_buildings(p1, {barracks = 10}) do sleep(4253) end
+   while not check_for_buildings(p1, {empire_blockhouse = 10}) do sleep(4253) end
 
    campaign_message_box(safe_peninsula)
 end

=== modified file 'campaigns/emp01.wmf/scripting/starting_conditions.lua'
--- campaigns/emp01.wmf/scripting/starting_conditions.lua	2014-10-17 08:38:24 +0000
+++ campaigns/emp01.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -3,57 +3,56 @@
 -- =======================================================================
 p1:forbid_buildings("all")
 
-hq = p1:place_building("headquarters_shipwreck",
+hq = p1:place_building("empire_headquarters_shipwreck",
    wl.Game().map:get_field(6, 62), false, true)
-hq:set_wares{
-   helm = 4,
-   wood_lance = 5,
-   ax = 6,
+hq:set_wares {
+   basket = 1,
+   empire_bread = 8,
    bread_paddle = 2,
-   basket = 1,
-   bread = 8,
    cloth = 5,
    coal = 12,
+   felling_ax = 6,
    fire_tongs = 2,
    fish = 6,
    fishing_rod = 2,
    flour = 4,
    gold = 4,
+   granite = 40,
    grape = 4,
    hammer = 12,
+   armor_helmet = 4,
    hunting_spear = 2,
    iron = 12,
-   ironore = 5,
+   iron_ore = 5,
    kitchen_tools = 4,
+   log = 30,
    marble = 25,
-   marblecolumn = 6,
+   marble_column = 6,
    meal = 4,
    meat = 6,
    pick = 14,
+   planks = 45,
    ration = 12,
    saw = 3,
    scythe = 5,
    shovel = 6,
-   stone = 40,
-   log = 30,
+   spear_wooden = 5,
    water = 12,
    wheat = 4,
    wine = 8,
-   wood = 45,
    wool = 2,
 }
-hq:set_workers{
-   armorsmith = 1,
-   brewer = 1,
-   builder = 10,
-   carrier = 40,
-   charcoal_burner = 1,
-   geologist = 4,
-   lumberjack = 3,
-   miner = 4,
-   stonemason = 2,
-   toolsmith = 2,
-   weaponsmith = 1,
+hq:set_workers {
+   empire_armorsmith = 1,
+   empire_brewer = 1,
+   empire_builder = 10,
+   empire_carrier = 40,
+   empire_charcoal_burner = 1,
+   empire_geologist = 4,
+   empire_lumberjack = 3,
+   empire_miner = 4,
+   empire_stonemason = 2,
+   empire_toolsmith = 2,
+   empire_weaponsmith = 1,
 }
 hq:set_soldiers({0,0,0,0}, 45)
-

=== modified file 'campaigns/emp01.wmf/scripting/texts.lua'
--- campaigns/emp01.wmf/scripting/texts.lua	2015-09-11 17:38:01 +0000
+++ campaigns/emp01.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -23,12 +23,12 @@
 -- ===========
 -- objectives
 -- ===========
-obj_build_barracks = {
-   name = "build_barracks",
-   title=_"Build a barracks",
+obj_build_blockhouse = {
+   name = "build_blockhouse",
+   title=_"Build a blockhouse",
    number = 1,
-   body = objective_text(_"Barracks",
-      listitem_bullet(_[[Build a barracks at the red house symbol on the east side of the forests, to the right of your provisional headquarters.]])
+   body = objective_text(_"Blockhouse",
+      listitem_bullet(_[[Build a blockhouse at the red house symbol on the east side of the forests, to the right of your provisional headquarters.]])
    ),
 }
 
@@ -132,8 +132,8 @@
 		_([[Well, perhaps my fear is misguided, but it can’t be wrong to keep watch in the forests – so that we can be sure to see any potential enemies before they can see us.]])
 		.. paragraphdivider() ..
       -- TRANSLATORS: Saledus
-		_([[You really should build a barracks in the eastern portion of the forest. Then one of my men can keep watch in the darkness and keep us safe from these creatures.]]))
-		.. new_objectives(obj_build_barracks),
+		_([[You really should build a blockhouse in the eastern portion of the forest. Then one of my men can keep watch in the darkness and keep us safe from these creatures.]]))
+		.. new_objectives(obj_build_blockhouse),
    w=400,
 }
 
@@ -142,7 +142,7 @@
    title=_"Safe For Now",
    body= saledus(_"Saledus speaks with a sigh of relief…",
       -- TRANSLATORS: Saledus
-		_([[Sire, I saw that the construction of the barracks was completed, so I have assigned one of my best soldiers to it to keep watch on the desert.]])
+		_([[Sire, I saw that the construction of the blockhouse was completed, so I have assigned one of my best soldiers to it to keep watch on the desert.]])
 		.. paragraphdivider() ..
       -- TRANSLATORS: Saledus
 		_([[This is a good step forward. Now we can feel a bit safer and can look forward to repairing our ship.]])),
@@ -156,7 +156,7 @@
 		_([[Greetings, Lutius! I just met Saledus outside.]])
 		.. paragraphdivider() ..
       -- TRANSLATORS: Amalea
-		_([[He told me about the barracks. Well, I don’t think we need more barracks – instead, we might concentrate on other things now.]])
+		_([[He told me about the blockhouse. Well, I don’t think we need more blockhouses – instead, we might concentrate on other things now.]])
 		.. paragraphdivider() ..
       -- TRANSLATORS: Amalea
 		_([[It is absolutely clear that we need wood to repair our ship. So, I walked through the forest yesterday to look for a nice place for a lumberjack’s house and found one right south of our provisional headquarters.]]))
@@ -171,7 +171,7 @@
 		_([[I got the message that our first lumberjack has started his work today. Perhaps it would be a good idea to wait until he cleans enough space for constructing two more lumberjack’s houses, so that we can harvest the logs faster.]])
 		.. paragraphdivider() ..
       -- TRANSLATORS: Amalea
-		_([[But unfortunately the logs are useless for repairing our ship – we need refined lumber, like every ship and every bigger building needs, too. So we should build a sawmill – as soon as we have enough space for this.]]))
+		_([[But unfortunately the logs are useless for repairing our ship – we need to turn them into planks, which are needed by every ship and every bigger building too. So we should build a sawmill – as soon as we have enough space for this.]]))
 		.. new_objectives(obj_build_sawmill_and_lumberjacks),
    w=400,
 }

=== modified file 'campaigns/emp02.wmf/scripting/mission_thread.lua'
--- campaigns/emp02.wmf/scripting/mission_thread.lua	2015-05-31 13:45:13 +0000
+++ campaigns/emp02.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -22,9 +22,9 @@
    -- Check for completing of the woodeconomy
    run(function()
       while not check_for_buildings(p1, {
-         lumberjacks_house = 3,
-         foresters_house = 1,
-         sawmill = 1,
+         empire_lumberjacks_house = 3,
+         empire_foresters_house = 1,
+         empire_sawmill = 1,
       }) do sleep(2342) end
 
       campaign_message_box(diary_page_6)
@@ -38,7 +38,7 @@
    local o_quarry = add_campaign_objective(obj_build_quarry)
    -- Check for completeness of the quarry
    run(function()
-      while not check_for_buildings(p1, {quarry=1}) do sleep(3423) end
+      while not check_for_buildings(p1, {empire_quarry=1}) do sleep(3423) end
       o_quarry.done = true
 
       campaign_message_box(diary_page_7)
@@ -49,11 +49,11 @@
    -- Wait till one mine goes up
    while true do
       local rv = p1:get_buildings{
-         "coalmine",
-         "deep_coalmine",
-         "oremine",
-         "deep_oremine",
-         "marblemine",
+         "empire_coalmine",
+         "empire_coalmine_deep",
+         "empire_ironmine",
+         "empire_ironmine_deep",
+         "empire_marblemine",
       }
       local s = 0
       for idx,a in pairs(rv) do s = s + #a end
@@ -63,41 +63,41 @@
 
    campaign_message_box(amalea_1)
    p1:allow_buildings{
-      "well",
-      "farm",
-      "brewery",
-      "vineyard",
-      "winery",
-      "mill",
-      "bakery",
-      "hunters_house",
-      "piggery",
-      "tavern",
-      "inn",
-      "fishers_house",
+      "empire_well",
+      "empire_farm",
+      "empire_brewery",
+      "empire_vineyard",
+      "empire_winery",
+      "empire_mill",
+      "empire_bakery",
+      "empire_hunters_house",
+      "empire_piggery",
+      "empire_tavern",
+      "empire_inn",
+      "empire_fishers_house",
    }
    local o = add_campaign_objective(obj_build_food_infrastructure)
 
    -- Run easter egg: Amalea says something when Tavern is done
    run(function()
-      while #p1:get_buildings("tavern") < 1 do sleep(2349) end
+      while #p1:get_buildings("empire_tavern") < 1 do sleep(2349) end
       campaign_message_box(amalea_2)
    end)
 
    while true do
       local rv = p1:get_buildings{
-         "brewery",
-         "fishers_house",
-         "bakery",
-         "hunters_house",
-         "piggery",
-         "tavern",
-         "inn",
+         "empire_brewery",
+         "empire_fishers_house",
+         "empire_bakery",
+         "empire_hunters_house",
+         "empire_piggery",
+         "empire_tavern",
+         "empire_inn",
       }
-      if #rv.brewery > 0 and
-         (#rv.tavern + #rv.inn) > 0 and
-         (#rv.fishers_house + #rv.hunters_house +
-          #rv.piggery + #rv.bakery) > 0 then break end
+      if #rv.empire_brewery > 0 and
+         (#rv.empire_tavern + #rv.empire_inn) > 0 and
+         (#rv.empire_fishers_house + #rv.empire_hunters_house +
+          #rv.empire_piggery + #rv.empire_bakery) > 0 then break end
       sleep(4857)
    end
    o.done = true
@@ -123,40 +123,40 @@
 
    campaign_message_box(saledus_3)
    p1:allow_buildings{
-      "coalmine",
-      "deep_coalmine",
-      "oremine",
-      "deep_oremine",
-      "stonemasons_house",
-      "toolsmithy",
-      "armorsmithy",
-      "weaponsmithy",
-      "smelting_works",
-      "charcoal_kiln",
+      "empire_coalmine",
+      "empire_coalmine_deep",
+      "empire_ironmine",
+      "empire_ironmine_deep",
+      "empire_stonemasons_house",
+      "empire_toolsmithy",
+      "empire_armorsmithy",
+      "empire_weaponsmithy",
+      "empire_smelting_works",
+      "empire_charcoal_kiln",
    }
 
    local o = add_campaign_objective(obj_build_mining_infrastructure)
    -- Wait for the infrastructure to come up
    while true do
       local rv = p1:get_buildings{
-         "coalmine",
-         "deep_coalmine",
-         "oremine",
-         "deep_oremine",
-         "stonemasons_house",
-         "toolsmithy",
-         "armorsmithy",
-         "weaponsmithy",
-         "smelting_works",
-         "charcoal_kiln",
+         "empire_coalmine",
+         "empire_coalmine_deep",
+         "empire_ironmine",
+         "empire_ironmine_deep",
+         "empire_stonemasons_house",
+         "empire_toolsmithy",
+         "empire_armorsmithy",
+         "empire_weaponsmithy",
+         "empire_smelting_works",
+         "empire_charcoal_kiln",
       }
-      if #rv.stonemasons_house > 0 and
-         #rv.toolsmithy > 0 and
-         #rv.armorsmithy > 0 and
-         #rv.smelting_works > 0 and
-         (#rv.oremine + #rv.deep_oremine > 0) and
-         (#rv.coalmine + #rv.deep_coalmine + #rv.charcoal_kiln > 0) and
-         #rv.weaponsmithy > 0 then break end
+      if #rv.empire_stonemasons_house > 0 and
+         #rv.empire_toolsmithy > 0 and
+         #rv.empire_armorsmithy > 0 and
+         #rv.empire_smelting_works > 0 and
+         (#rv.empire_ironmine + #rv.empire_ironmine_deep > 0) and
+         (#rv.empire_coalmine + #rv.empire_coalmine_deep + #rv.empire_charcoal_kiln > 0) and
+         #rv.empire_weaponsmithy > 0 then break end
       sleep(4948)
    end
    o.done = true
@@ -175,7 +175,7 @@
 
    campaign_message_box(saledus_1)
    local o = add_campaign_objective(obj_build_military_buildings)
-   p1:allow_buildings{"barracks", "sentry"}
+   p1:allow_buildings{"empire_blockhouse", "empire_sentry"}
 
    -- Go back to where we were
    timed_scroll(array_reverse(pts))
@@ -192,9 +192,9 @@
    pts = wait_for_roadbuilding_and_scroll(marblemountains)
 
    campaign_message_box(saledus_2)
-   p1:allow_buildings{"marblemine", "deep_marblemine"}
+   p1:allow_buildings{"empire_marblemine", "empire_marblemine_deep"}
    o = add_campaign_objective(obj_build_marblemine)
-   run(function() while not check_for_buildings(p1, {marblemine = 1})
+   run(function() while not check_for_buildings(p1, {empire_marblemine = 1})
       do sleep(2133) end  o.done = true end)
 
    -- Go back to where we were
@@ -205,12 +205,13 @@
    -- Wait for various buildings to go up
    while true do
       local rv = p1:get_buildings{
-         "marblemine", "deep_marblemine", "oremine", "deep_oremine",
-         "coalmine", "deep_coalmine", "charcoal_kiln"
+         "empire_marblemine", "empire_marblemine_deep",
+         "empire_ironmine", "empire_ironmine_deep",
+         "empire_coalmine", "empire_coalmine_deep", "empire_charcoal_kiln"
       }
-      local mm = #rv.marblemine + #rv.deep_marblemine
-      local ore = #rv.oremine + #rv.deep_oremine
-      local coal = #rv.coalmine + #rv.deep_coalmine + #rv.charcoal_kiln
+      local mm = #rv.empire_marblemine + #rv.empire_marblemine_deep
+      local ore = #rv.empire_ironmine + #rv.empire_ironmine_deep
+      local coal = #rv.empire_coalmine + #rv.empire_coalmine_deep + #rv.empire_charcoal_kiln
 
       if mm > 0 and ore > 0 and coal > 0 then break end
       sleep(6674)
@@ -227,13 +228,13 @@
 
    campaign_message_box(diary_page_8)
    local o = add_campaign_objective(obj_build_bigger_military_buildings)
-   p1:allow_buildings{"outpost", "barrier", "tower"}
-   p2:allow_buildings{"quarry"}
+   p1:allow_buildings{"empire_outpost", "empire_barrier", "empire_tower"}
+   p2:allow_buildings{"barbarians_quarry"}
 
    -- Wait for one of the buildings to go up
    while true do
-      local rv = p1:get_buildings{"outpost", "barrier", "tower"}
-      if (#rv.tower + #rv.outpost + #rv.barrier) > 0 then
+      local rv = p1:get_buildings{"empire_outpost", "empire_barrier", "empire_tower"}
+      if (#rv.empire_tower + #rv.empire_outpost + #rv.empire_barrier) > 0 then
          break
       end
       sleep(2342)
@@ -245,11 +246,11 @@
       sleep(2343)
    end
    campaign_message_box(diary_page_9)
-   p1:allow_buildings{"fortress"}
+   p1:allow_buildings{"empire_fortress"}
 
    o = add_campaign_objective(obj_remove_the_barbarians)
    -- Wait for the fortress to come up
-   while not check_for_buildings(p1, {fortress=1},
+   while not check_for_buildings(p1, {empire_fortress = 1},
       wl.Game().map:get_field(60,65):region(6))
    do sleep(2435) end
 

=== modified file 'campaigns/emp02.wmf/scripting/starting_conditions.lua'
--- campaigns/emp02.wmf/scripting/starting_conditions.lua	2014-10-17 08:38:24 +0000
+++ campaigns/emp02.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -3,63 +3,63 @@
 -- =======================================================================
 p1:forbid_buildings("all")
 p1:allow_buildings{
-   "foresters_house",
-   "lumberjacks_house",
-   "quarry",
-   "sawmill",
+   "empire_foresters_house",
+   "empire_lumberjacks_house",
+   "empire_quarry",
+   "empire_sawmill",
 }
 prefilled_buildings(p1,
-   {"headquarters", 16, 21,
+   {"empire_headquarters", 16, 21,
       wares = {
-         helm = 4,
-         wood_lance = 5,
-         ax = 6,
+         basket = 1,
+         empire_bread = 8,
          bread_paddle = 2,
-         basket = 1,
-         bread = 8,
          cloth = 5,
          coal = 12,
+         felling_ax = 6,
          fire_tongs = 2,
          fish = 6,
          fishing_rod = 2,
          flour = 4,
          gold = 4,
+         granite = 40,
          grape = 4,
          hammer = 12,
+         armor_helmet = 4,
          hunting_spear = 2,
          iron = 12,
-         ironore = 5,
+         iron_ore = 5,
          kitchen_tools = 4,
+         log = 30,
          marble = 25,
-         marblecolumn = 6,
+         marble_column = 6,
          meal = 4,
          meat = 6,
          pick = 14,
+         planks = 45,
          ration = 12,
          saw = 3,
          scythe = 5,
          shovel = 6,
-         stone = 40,
-         log = 30,
+         spear_wooden = 5,
          water = 12,
          wheat = 4,
          wine = 8,
-         wood = 45,
          wool = 2,
       },
       workers = {
-         armorsmith = 1,
-         brewer = 1,
-         builder = 10,
-         carrier = 40,
-         charcoal_burner = 1,
-         geologist = 4,
-         lumberjack = 3,
-         miner = 4,
-         stonemason = 2,
-         toolsmith = 2,
-         weaponsmith = 1,
-         donkey = 20,
+         empire_armorsmith = 1,
+         empire_brewer = 1,
+         empire_builder = 10,
+         empire_carrier = 40,
+         empire_charcoal_burner = 1,
+         empire_donkey = 20,
+         empire_geologist = 4,
+         empire_lumberjack = 3,
+         empire_miner = 4,
+         empire_stonemason = 2,
+         empire_toolsmith = 2,
+         empire_weaponsmith = 1,
       },
       soldiers = {
          [{0,0,0,0}] = 45,
@@ -72,65 +72,65 @@
 -- =======================================================================
 p2:forbid_buildings("all")
 p2:allow_buildings{
-   "bakery",
-   "barrier",
-   "farm",
-   "reed_yard",
-   "fishers_hut",
-   "hardener",
-   "hunters_hut",
-   "lumberjacks_hut",
-   "micro-brewery",
-   "rangers_hut",
-   "sentry",
-   "lime_kiln",
-   "tavern",
-   "well",
+   "barbarians_bakery",
+   "barbarians_barrier",
+   "barbarians_farm",
+   "barbarians_fishers_hut",
+   "barbarians_hunters_hut",
+   "barbarians_lime_kiln",
+   "barbarians_lumberjacks_hut",
+   "barbarians_micro_brewery",
+   "barbarians_rangers_hut",
+   "barbarians_reed_yard",
+   "barbarians_sentry",
+   "barbarians_tavern",
+   "barbarians_well",
+   "barbarians_wood_hardener",
 }
 
 prefilled_buildings(p2,
-   {"headquarters", 60, 65,
+   {"barbarians_headquarters", 60, 65,
    wares = {
       ax = 6,
+      blackwood = 32,
+      barbarians_bread = 8,
       bread_paddle = 2,
-      blackwood = 32,
       cloth = 5,
       coal = 12,
       fire_tongs = 2,
       fish = 6,
       fishing_rod = 2,
       gold = 4,
+      granite = 40,
       grout = 12,
       hammer = 12,
       hunting_spear = 2,
       iron = 12,
-      ironore = 5,
+      iron_ore = 5,
       kitchen_tools = 4,
+      log = 80,
       meal = 4,
       meat = 6,
       pick = 14,
-      pittabread = 8,
       ration = 12,
-      raw_stone = 40,
       scythe = 6,
       shovel = 4,
       snack = 3,
-      thatchreed = 24,
-      log = 80,
+      thatch_reed = 24,
    },
    workers = {
-      blacksmith = 2,
-      brewer = 1,
-      builder = 10,
-      carrier = 40,
-      charcoal_burner = 1,
-      gardener = 1,
-      geologist = 4,
-      ["lime-burner"] = 1,
-      lumberjack = 3,
-      miner = 4,
-      ranger = 1,
-      stonemason = 2,
+      barbarians_blacksmith = 2,
+      barbarians_brewer = 1,
+      barbarians_builder = 10,
+      barbarians_carrier = 40,
+      barbarians_charcoal_burner = 1,
+      barbarians_gardener = 1,
+      barbarians_geologist = 4,
+      barbarians_lime_burner = 1,
+      barbarians_lumberjack = 3,
+      barbarians_miner = 4,
+      barbarians_ranger = 1,
+      barbarians_stonemason = 2,
    },
    soldiers = {
       [{0,0,0,0}] = 45,

=== modified file 'campaigns/emp02.wmf/scripting/texts.lua'
--- campaigns/emp02.wmf/scripting/texts.lua	2015-09-11 17:38:01 +0000
+++ campaigns/emp02.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -46,7 +46,7 @@
    title =_"Protect your colony",
    number = 1,
    body = objective_text(_"Protect Your Colony",
-      listitem_bullet(_[[Build some barracks and sentries around the colony.]])
+      listitem_bullet(_[[Build some blockhouses and sentries around the colony.]])
    ),
 }
 
@@ -134,7 +134,7 @@
    posy = 1,
    body= lutius(_"Diary of Lutius",
       -- TRANSLATORS: Lutius - Diary
-		_([[Later, I walked down to the rocks in the south and looked for a place where we could build a quarry to get some hard stone for our larger buildings.]])
+		_([[Later, I walked down to the rocks in the south and looked for a place where we could build a quarry to get some hard stones for our larger buildings.]])
 		.. paragraphdivider() ..
       -- TRANSLATORS: Lutius - Diary
 		_([[Again, I felt like I was in paradise when I noticed that some marble-like stones were among the rocks. It seems that we will soon be able to build strong, luxurious buildings, like those we were accustomed to in Fremil.]]))
@@ -150,11 +150,11 @@
 }
 
 diary_page_7 = {
-   title =_ "Stone for the Colony",
+   title =_ "Stones for the Colony",
    posy=1,
    body= lutius(_"Diary of Lutius",
       -- TRANSLATORS: Lutius - Diary
-		_[[Great! Today the building of the quarry was completed. Now we will get enough stone to construct larger buildings.]]),
+		_[[Great! Today the building of the quarry was completed. Now we will get enough stones to construct larger buildings.]]),
 }
 
 saledus_1 = {
@@ -168,7 +168,7 @@
 		_([[Perhaps the people aboard that ship were caught in the same storm which brought us to Malac’ Mor – and were brought to this island.]])
 		.. paragraphdivider() ..
       -- TRANSLATORS: Saledus
-		_([[I beg you to be cautious and to build some barracks or sentries around our colony.]]))
+		_([[I beg you to be cautious and to build some blockhouses or sentries around our colony.]]))
 		.. new_objectives(obj_build_military_buildings)
 }
 

=== modified file 'campaigns/tutorial01_basic_control.wmf/scripting/helper_functions.lua'
--- campaigns/tutorial01_basic_control.wmf/scripting/helper_functions.lua	2014-10-17 08:38:24 +0000
+++ campaigns/tutorial01_basic_control.wmf/scripting/helper_functions.lua	2015-10-18 20:57:50 +0000
@@ -18,7 +18,7 @@
             f.immovable:remove()
             if n > 1 then
                remove_field = false
-               map:place_immovable("greenland_stones" .. n-1, f)
+               map:place_immovable("greenland_stones" .. n-1, f, "world")
             end
             sleep(sleeptime)
          end

=== modified file 'campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua'
--- campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua	2015-06-01 20:08:40 +0000
+++ campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -3,7 +3,7 @@
 -- ================
 
 function starting_infos()
-   map:place_immovable("debris00",second_quarry_field)
+   map:place_immovable("debris00",second_quarry_field, "world")
    -- so that the player cannot build anything here
 
    sleep(1000)
@@ -44,7 +44,7 @@
 
    click_on_field(first_lumberjack_field)
    click_on_panel(wl.ui.MapView().windows.field_action.tabs.small)
-   click_on_panel(wl.ui.MapView().windows.field_action.buttons.lumberjacks_hut)
+   click_on_panel(wl.ui.MapView().windows.field_action.buttons.barbarians_lumberjacks_hut)
 
    sleep(500)
 
@@ -99,7 +99,7 @@
    sleep(30*1000) -- let the player experiment a bit with the speed
    message_box_objective(plr, construction_site_window)
 
-   while #plr:get_buildings("lumberjacks_hut") < 1 do sleep(300) end
+   while #plr:get_buildings("barbarians_lumberjacks_hut") < 1 do sleep(300) end
 
    message_box_objective(plr, lumberjack_message_07)
 
@@ -153,7 +153,7 @@
    immovable_is_legal = function(i)
       -- only allow quarry and flag at this position because the road building below relies on this
       if (i.fields[1] == first_quarry_field) or (i.fields[1] == first_quarry_field.brn) then
-         cs = allow_constructionsite(i, {"quarry"})
+         cs = allow_constructionsite(i, {"barbarians_quarry"})
          return cs
       else return false end
    end
@@ -237,7 +237,7 @@
    -- Interludium: talk about census and statistics
    census_and_statistics()
 
-   while #plr:get_buildings("quarry") < 2 do sleep(1400) end
+   while #plr:get_buildings("barbarians_quarry") < 2 do sleep(1400) end
    o.done = true
 
    messages()
@@ -253,7 +253,7 @@
    local cs = nil
    immovable_is_legal = function(i)
       if (i.fields[1] == second_quarry_field) or (i.fields[1] == second_quarry_field.brn) then
-         cs = allow_constructionsite(i, {"quarry"})
+         cs = allow_constructionsite(i, {"barbarians_quarry"})
          return cs
       elseif(i.descr.type_name == "flag") or (i.descr.type_name == "road") then
          register_immovable_as_allowed(i)
@@ -340,7 +340,7 @@
    -- From now on, the player can build whatever he wants
    terminate_bad_boy_sentinel = true
 
-   while #plr:get_buildings("quarry") > 0 do sleep(200) end
+   while #plr:get_buildings("barbarians_quarry") > 0 do sleep(200) end
    o.done = true
 
    sleep(3000)
@@ -357,7 +357,12 @@
    -- wait until there are soldiers inside so that the player sees the expansion
    local soldier_inside = false
    while not soldier_inside do
-      local military_buildings = array_combine(plr:get_buildings("sentry"), plr:get_buildings("donjon"), plr:get_buildings("barrier"), plr:get_buildings("fortress"), plr:get_buildings("citadel"))
+      local military_buildings = array_combine(
+			plr:get_buildings("barbarians_sentry"),
+			plr:get_buildings("barbarians_tower"),
+			plr:get_buildings("barbarians_barrier"),
+			plr:get_buildings("barbarians_fortress"),
+			plr:get_buildings("barbarians_citadel"))
       for i = 1,#military_buildings do
          for k,v in pairs(military_buildings[i]:get_soldiers("all")) do
             soldier_inside = true

=== modified file 'campaigns/tutorial01_basic_control.wmf/scripting/starting_conditions.lua'
--- campaigns/tutorial01_basic_control.wmf/scripting/starting_conditions.lua	2014-10-17 08:38:24 +0000
+++ campaigns/tutorial01_basic_control.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -5,6 +5,6 @@
 plr:allow_buildings("all")
 
 -- A default headquarters
-include "tribes/barbarians/scripting/sc00_headquarters.lua"
-init.func(plr) -- defined in sc00_headquarters
+include "tribes/scripting/starting_conditions/barbarians/headquarters.lua"
+init.func(plr) -- defined in headquarters
 

=== modified file 'campaigns/tutorial01_basic_control.wmf/scripting/texts.lua'
--- campaigns/tutorial01_basic_control.wmf/scripting/texts.lua	2015-07-30 07:16:09 +0000
+++ campaigns/tutorial01_basic_control.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -40,7 +40,7 @@
    body = rt(
       h1(_"Let’s dive right in!") ..
       p(_[[There are three different tribes in Widelands: the Barbarians, the Empire and the Atlanteans. All tribes have a different economy, strength and weaknesses, but the general gameplay is the same for all. We will play the Barbarians for now.]]) ..
-      p(_[[You will usually start the game with one headquarters. This is the big building with the blue flag in front of it. The headquarters is a warehouse that stores wares, workers and soldiers. Some wares are needed for building houses, others for making other wares. Obviously, the wares in the headquarters will not last forever, so you must make sure to replace them. The most important wares in the early game are the basic construction wares: logs and raw stone. Let’s make sure that we do not run out of logs. For this, we need a lumberjack and a hut for him to stay in.]]) ..
+      p(_[[You will usually start the game with one headquarters. This is the big building with the blue flag in front of it. The headquarters is a warehouse that stores wares, workers and soldiers. Some wares are needed for building houses, others for making other wares. Obviously, the wares in the headquarters will not last forever, so you must make sure to replace them. The most important wares in the early game are the basic construction wares: logs and granite. Let’s make sure that we do not run out of logs. For this, we need a lumberjack and a hut for him to stay in.]]) ..
       p(_[[We need to find a nice place for the lumberjack’s hut. To make this easier, we can activate ‘Show Building Spaces’. There are two ways you can do this, either by clicking on the ‘Show Building Spaces’ button at the bottom of the screen, which is the fourth one from the left. Or you can use the SPACE key to toggle it.]]) ..
       paragraphdivider() ..
       listitem_bullet(_[[Left-click the ‘OK’ button to close this box and then try it.]])
@@ -169,7 +169,7 @@
    title = _"Lumberjack is Done",
    position = "topright",
    body = rt(
-      p(_[[Excellent. The lumberjack’s hut is done. A lumberjack will now move in and start chopping down trees, so our log income is secured for now. Now on to the raw stone.]])
+      p(_[[Excellent. The lumberjack’s hut is done. A lumberjack will now move in and start chopping down trees, so our log income is secured for now. Now on to the granite.]])
    ),
    h = 300,
    w = 350
@@ -179,7 +179,7 @@
    title = _"Some Rocks Were Found",
    body = rt(h1(_"Getting a Quarry Up")) ..
    rt(
-      p(_[[Stones can be mined in granite mines, but the easier way is to build a quarry next to some rocks lying around. As it happens, there is a pile of them just to the west (left) of your headquarters. I will teach you now how to move your view over there.]]) ..
+      p(_[[Granite can be mined in granite mines, but the easier way is to build a quarry next to some rocks lying around. As it happens, there is a pile of them just to the west (left) of your headquarters. I will teach you now how to move your view over there.]]) ..
       paragraphdivider() ..
       listitem_arrow(_[[There are three ways to move your view. The first one is using the cursor keys on your keyboard. Go ahead and try this out.]]) ..
       listitem_bullet(_[[Click the ‘OK’ button and then move the view using the cursor keys]])
@@ -360,7 +360,7 @@
    position = "topright",
    title = _"Build a second quarry",
    body = rt(
-      p(_[[When there are many rocks, you can consider building another quarry. This will make the stone production faster.]]) ..
+      p(_[[When there are many rocks, you can consider building another quarry. This will make the granite production faster.]]) ..
       paragraphdivider() ..
       listitem_bullet(_[[Build a second quarry near the rocks and connect it to your road network.]])
    ),
@@ -474,7 +474,7 @@
    title = _"Expanding Your Territory!",
    body = rt(
       p(_[[There is one more thing I’d like to teach you now: Expanding your territory. The place that we started with around our headquarters is barely enough for a basic building infrastructure, and we do not have access to mountains, which we need to mine minerals and coal. So, we have to expand our territory.]]) ..
-      p(_[[Expanding is as simple as building a military building at the edge of your territory. The Barbarians have a selection of different military buildings: sentries, barriers, donjons, fortresses and citadels. The bigger the building, the more expensive it is to build, but the more land it will conquer around itself and the more soldiers can be stationed there. The buildings also vary in their vision range: buildings with a tower see farther than others.]]) ..
+      p(_[[Expanding is as simple as building a military building at the edge of your territory. The Barbarians have a selection of different military buildings: sentries, barriers, towers, fortresses and citadels. The bigger the building, the more expensive it is to build, but the more land it will conquer around itself and the more soldiers can be stationed there. The buildings also vary in their vision range: buildings with a tower see farther than others.]]) ..
       p(_[[As soon as a military building is manned, it will extend your land. I will tell your more about military buildings in another tutorial.]]) ..
       paragraphdivider() ..
       listitem_bullet(_[[Let’s try it out now: build a military building on your border.]]) ..
@@ -486,7 +486,7 @@
       h1(_"Make your territory grow") ..
       p(_[[In Widelands, it is necessary to build many buildings, which take up a lot of space. To expand your territory, you have to build military buildings next to your border. Every tribe has several military buildings.]]) ..
       paragraphdivider() ..
-      listitem_bullet(_[[The Barbarians have four different military buildings you can build: the sentry (small), the barrier and the donjon (both medium) and the fortress (big). Just choose the one you like most.]]) ..
+      listitem_bullet(_[[The Barbarians have four different military buildings you can build: the sentry (small), the barrier and the tower (both medium) and the fortress (big). Just choose the one you like most.]]) ..
       listitem_arrow(_[[Remember that big buildings (green icon) cannot be built on small (red) or medium (yellow) building plots, but buildings can be built on a building plot that provides more space than they need. You should always keep that in mind when you search for a suitable place.]])
    )
 }

=== modified file 'campaigns/tutorial02_warfare.wmf/scripting/mission_thread.lua'
--- campaigns/tutorial02_warfare.wmf/scripting/mission_thread.lua	2015-05-31 13:45:13 +0000
+++ campaigns/tutorial02_warfare.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -15,12 +15,12 @@
 
    message_box_objective(plr, abilities)
    local o = message_box_objective(plr, battlearena1)
-   while #plr:get_buildings("battlearena") == 0 do sleep(500) end
+   while #plr:get_buildings("barbarians_battlearena") == 0 do sleep(500) end
    o.done = true
    message_box_objective(plr, battlearena2)
 
    o = message_box_objective(plr, trainingcamp1)
-   while #plr:get_buildings("trainingcamp") == 0 do sleep(500) end
+   while #plr:get_buildings("barbarians_trainingcamp") == 0 do sleep(500) end
    o.done = true
    message_box_objective(plr, trainingcamp2)
 
@@ -34,7 +34,7 @@
    message_box_objective(plr, soldier_capacity)
    local o = message_box_objective(plr, dismantle)
 
-   while #plr:get_buildings("sentry") > 1 do sleep(200) end
+   while #plr:get_buildings("barbarians_sentry") > 1 do sleep(200) end
    o.done = true
 
    sleep(2000)
@@ -48,7 +48,7 @@
    local citadel_field = wl.Game().map:get_field(32, 62)
    local o = message_box_objective(plr, fortress_enhancement)
    while not (citadel_field.immovable and
-      citadel_field.immovable.descr.name == "citadel") do sleep(800) end
+      citadel_field.immovable.descr.name == "barbarians_citadel") do sleep(800) end
    o.done = true
 
    create_enemy()
@@ -72,10 +72,10 @@
 
 function create_enemy()
    prefilled_buildings(wl.Game().players[2],
-      {"barrier", 24, 7},
-      {"sentry", 29, 16},
-      {"tower", 30, 21},
-      {"headquarters", 30, 27,
+      {"empire_barrier", 24, 7},
+      {"empire_sentry", 29, 16},
+      {"empire_tower", 30, 21},
+      {"empire_headquarters", 30, 27,
          soldiers = {
             [{0,0,0,0}] = 15,
          }
@@ -88,7 +88,7 @@
    local o = message_box_objective(plr, attack_enemy)
 
    local plr2 = wl.Game().players[2]
-   while #plr2:get_buildings("headquarters") > 0 do
+   while #plr2:get_buildings("empire_headquarters") > 0 do
       sleep(3000)
    end
    o.done = true

=== modified file 'campaigns/tutorial02_warfare.wmf/scripting/starting_conditions.lua'
--- campaigns/tutorial02_warfare.wmf/scripting/starting_conditions.lua	2014-10-17 08:38:24 +0000
+++ campaigns/tutorial02_warfare.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -7,8 +7,8 @@
    plr:allow_buildings("all")
 
    prefilled_buildings(plr,
-      {"fortress", 32, 62, soldiers = {[{3,5,0,2}] = 8 }},
-      {"warehouse", 33, 57,
+      {"barbarians_fortress", 32, 62, soldiers = {[{3,5,0,2}] = 8 }},
+      {"barbarians_warehouse", 33, 57,
          soldiers = {
             [{0,0,0,0}] = 20, -- needed for training
             [{1,0,0,0}] = 1,
@@ -24,9 +24,9 @@
             [{3,5,0,2}] = 30,
          },
          workers = {
-            builder = 3,
-            ox = 15,
-            trainer = 2
+            barbarians_builder = 3,
+            barbarians_ox = 15,
+            barbarians_trainer = 2
          },
          wares = {
             log = 40,
@@ -34,27 +34,27 @@
             cloth = 10,
             gold = 10,
             grout = 30,
-            raw_stone = 30,
-            thatchreed = 40,
+            granite = 30,
+            thatch_reed = 40,
 
             -- wares for training
-            sharpax = 20,
-            broadax = 20,
-            bronzeax = 20,
-            battleax = 20,
-            warriorsax = 20,
-            helm = 20,
-            mask = 20,
-            warhelm = 20,
-            strongbeer = 50,
-            pittabread = 200,
+            ax_sharp = 20,
+            ax_broad = 20,
+            ax_bronze = 20,
+            ax_battle = 20,
+            ax_warriors = 20,
+            helmet = 20,
+            helmet_mask = 20,
+            helmet_warhelm = 20,
+            stout = 50,
+            barbarians_bread = 200,
             meat = 200
          }
       },
-      {"sentry", 28, 57, soldiers = {[{3,5,0,2}] = 2 }},
-      {"sentry", 37, 61, soldiers = {[{3,5,0,2}] = 2 }},
-      {"barrier", 30, 58, soldiers = {[{0,0,0,0}] = 1 }}, -- to make sure some soldiers walk out
-      {"lumberjacks_hut", 24, 1}
+      {"barbarians_sentry", 28, 57, soldiers = {[{3,5,0,2}] = 2 }},
+      {"barbarians_sentry", 37, 61, soldiers = {[{3,5,0,2}] = 2 }},
+      {"barbarians_barrier", 30, 58, soldiers = {[{0,0,0,0}] = 1 }}, -- to make sure some soldiers walk out
+      {"barbarians_lumberjacks_hut", 24, 1}
    )
 
    -- Build the roads

=== modified file 'campaigns/tutorial02_warfare.wmf/scripting/texts.lua'
--- campaigns/tutorial02_warfare.wmf/scripting/texts.lua	2015-09-05 16:42:45 +0000
+++ campaigns/tutorial02_warfare.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -31,14 +31,14 @@
       p(_[[Take a look at the soldiers that are on their way to our military buildings. They look different from normal workers: they have a health bar over their head that displays their remaining health, and they have four symbols, which symbolize the individual soldier’s current levels in the four different categories: health, attack, defense and evade.]]) ..
       p(_[[If a Barbarian soldier is fully trained, he has level 3 health, level 5 attack, level 0 defense and level 2 evade. This is one fearsome warrior then! The individual abilities have the following meaning:]])
    ) ..
-   rt("image=tribes/barbarians/soldier/hp_level0.png", h2(_"Health:"))..
+   rt("image=tribes/workers/barbarians/soldier/hp_level0.png", h2(_"Health:"))..
    rt(p(_[[The total life of a soldier. A Barbarian soldier starts with 130 health, and he will gain 28 health with each health level.]])) ..
-   rt("image=tribes/barbarians/soldier/attack_level0.png", h2(_"Attack:")) ..
+   rt("image=tribes/workers/barbarians/soldier/attack_level0.png", h2(_"Attack:")) ..
    rt(p(_[[The amount of damage a soldier will inflict on the enemy when an attack is successful. A Barbarian soldier with attack level 0 inflicts ~14 points of health damage when he succeeds in hitting an enemy. For each attack level, he gains 7 damage points.]])) ..
    -- The Atlanteans' image, because the Barbarian one has a white background
-   rt("image=tribes/atlanteans/soldier/defense_level0.png", h2(_"Defense:")) ..
+   rt("image=tribes/workers/atlanteans/soldier/defense_level0.png", h2(_"Defense:")) ..
    rt(p(_[[The defense is the percentage that is subtracted from the attack value. The Barbarians cannot train in this skill and therefore have always defense level 0, which means that the damage is always reduced by 3%. If an attacker with an attack value of 35 points hits a Barbarian soldier, the Barbarian will lose 35·0.97 = 34 health.]])) ..
-   rt("image=tribes/barbarians/soldier/evade_level0.png", h2(_"Evade:")) ..
+   rt("image=tribes/workers/barbarians/soldier/evade_level0.png", h2(_"Evade:")) ..
    rt(p(_[[Evade is the chance that the soldier is able to dodge an attack. A level 0 Barbarian has a 25% chance to evade an attack, and this increases in steps of 15% for each level.]]))
 }
 
@@ -48,7 +48,7 @@
    body = rt(
       p(_[[Now I have talked about training and levels. Let me elaborate on that.]]) ..
       p(_[[A newly created soldier has no experience and is not very good at fighting. To make him stronger, you can build training sites.]]) ..
-      p(_[[One of these training sites is the battle arena. It is a big and expensive building, and it trains soldiers in evade. Since soldiers get very hungry during their workout, this building needs a lot of food and strongbeer. In a real game, you should have a good infrastructure before you build it.]]) ..
+      p(_[[One of these training sites is the battle arena. It is a big and expensive building, and it trains soldiers in evade. Since soldiers get very hungry during their workout, this building needs a lot of food and stout. In a real game, you should have a good infrastructure before you build it.]]) ..
       paragraphdivider() ..
       listitem_bullet(_[[To see evade training in action, build a battle arena.]]) ..
       "</p><p font-size=8><br></p>" ..
@@ -71,13 +71,13 @@
       h1(_"The Battle Arena Has Been Constructed") ..
       p(_[[Very good. Our battle arena has been finished, and the soldiers are already walking towards it.]]) ..
       -- Not perfectly correct (some training steps need either bread or meat), but we do not want to confuse new players
-      p(_[[The needed wares are also delivered there. For successful training, you need pitta bread and strongbeer, as well as either fish or meat.]] .. " " ..
+      p(_[[The needed wares are also delivered there. For successful training, you need pitta bread and stout, as well as either fish or meat.]] .. " " ..
       _[[For more information, you can have a look at the building’s help window, accessible via the question mark in every building’s window.]]) ..
       p(_[[To learn how far your soldiers have progressed in their training, you can have a look at their icons. They are modified by red dots:]])
    ) ..
-   rt("image=tribes/barbarians/soldier/evade_level0.png", p(_[[No red dots means that the soldier is not trained, so he has level 0. All your new recruits have this.]])) ..
-   rt("image=tribes/barbarians/soldier/evade_level1.png", p(_[[With every successful training step, your soldier becomes stronger. This is indicated by a red dot. This soldier is on level 1 in evade training.]])) ..
-   rt("image=tribes/barbarians/soldier/evade_level2.png", p(_[[When your soldier has reached the highest possible level (in this case level 2), this is indicated by a white background color.]])),
+   rt("image=tribes/workers/barbarians/soldier/evade_level0.png", p(_[[No red dots means that the soldier is not trained, so he has level 0. All your new recruits have this.]])) ..
+   rt("image=tribes/workers/barbarians/soldier/evade_level1.png", p(_[[With every successful training step, your soldier becomes stronger. This is indicated by a red dot. This soldier is on level 1 in evade training.]])) ..
+   rt("image=tribes/workers/barbarians/soldier/evade_level2.png", p(_[[When your soldier has reached the highest possible level (in this case level 2), this is indicated by a white background color.]])),
    h = 450
 }
 
@@ -105,7 +105,7 @@
    title = _"The Training Camp",
    body = rt(
       p(_[[Great, our training camp has now been finished, too. Now nothing will hinder us from getting the strongest warriors the world has ever seen.]]) ..
-      p(_[[To train in the training camp, our soldiers need food like in the battle arena, but no strongbeer. Instead, they need different axes for attack training and helmets for health training.]]) ..
+      p(_[[To train in the training camp, our soldiers need food like in the battle arena, but no stout. Instead, they need different axes for attack training and helmets for health training.]]) ..
       p(_[[This equipment is produced in smithies out of coal, iron, and sometimes gold. You will learn more about this in the second scenario of the Barbarian campaign.]]) ..
       p(_[[You should also keep in mind that each of the three tribes in Widelands has its own way of training, so the buildings and wares are different. Also, the ability levels cannot be compared: an Imperial soldier with evade level 0 has a 30% chance of evading, while a Barbarian soldier at the same level only has a 25% chance.]])
    )

=== modified file 'campaigns/tutorial03_seafaring.wmf/scripting/mission_thread.lua'
--- campaigns/tutorial03_seafaring.wmf/scripting/mission_thread.lua	2015-06-01 20:08:40 +0000
+++ campaigns/tutorial03_seafaring.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -20,7 +20,7 @@
    wl.ui.MapView().buildhelp = true -- so that the player sees the port building icon
    local o = message_box_objective(plr, tell_about_port_building)
 
-   while #plr:get_buildings("port") < 2 do sleep(200) end
+   while #plr:get_buildings("atlanteans_port") < 2 do sleep(200) end
    o.done = true
 
    build_ships()
@@ -29,9 +29,9 @@
 function build_ships()
    sleep(200)
    local o = message_box_objective(plr, tell_about_shipyard)
-   plr:allow_buildings{"shipyard"}
+   plr:allow_buildings{"atlanteans_shipyard"}
 
-   while #plr:get_buildings("shipyard") < 1 do sleep(200) end
+   while #plr:get_buildings("atlanteans_shipyard") < 1 do sleep(200) end
    o.done = true
 
    local o = message_box_objective(plr, tell_about_ships)
@@ -62,7 +62,7 @@
 
    local o2 = message_box_objective(plr, expedition3)
 
-   while #plr:get_buildings("port") < 3 do sleep(200) end
+   while #plr:get_buildings("atlanteans_port") < 3 do sleep(200) end
    o.done = true
 
    -- places 5 signs with iron to show the player he really found some iron ore
@@ -73,7 +73,7 @@
          local idx = math.random(#fields)
          f = fields[idx]
          if ((f.resource == "iron") and not f.immovable) then
-            map:place_immovable("resi_iron2",f,"atlanteans")
+            map:place_immovable("resi_iron2",f,"tribes")
             successful = true
          end
          table.remove(fields,idx)

=== modified file 'campaigns/tutorial03_seafaring.wmf/scripting/starting_conditions.lua'
--- campaigns/tutorial03_seafaring.wmf/scripting/starting_conditions.lua	2014-10-18 09:02:51 +0000
+++ campaigns/tutorial03_seafaring.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -5,144 +5,144 @@
 plr:allow_buildings("all")
 
 function init_player()
-   filled_buildings(plr, {"port", sf.x, sf.y,
+   filled_buildings(plr, {"atlanteans_port", sf.x, sf.y,
       wares = {
-         diamond = 7,
-         ironore = 20,
-         quartz = 9,
-         stone = 50,
-         spideryarn = 9,
-         log = 80,
+         blackroot = 5,
+         blackroot_flour = 12,
+         atlanteans_bread = 28,
+         bread_paddle = 2,
+         buckets = 2,
          coal = 12,
-         goldyarn = 6,
-         iron = 12,
-         planks = 65,
-         spidercloth = 35,
-         blackroot = 5,
-         blackrootflour = 12,
-         bread = 28,
          corn = 15,
-         cornflour = 12,
+         cornmeal = 12,
+         diamond = 7,
+         fire_tongs = 2,
          fish = 13,
-         meat = 13,
-         smoked_fish = 26,
-         smoked_meat = 26,
-         water = 12,
-         bread_paddle = 2,
-         bucket = 2,
-         fire_tongs = 2,
          fishing_net = 4,
+         gold_thread = 6,
+         granite = 50,
          hammer = 11,
+         hook_pole = 2,
          hunting_bow = 1,
+         iron = 12,
+         iron_ore = 20,
+         log = 80,
+         meat = 13,
          milking_tongs = 2,
-         hook_pole = 2,
          pick = 8,
+         planks = 65,
+         quartz = 9,
          saw = 9,
          scythe = 4,
          shovel = 9,
+         smoked_fish = 26,
+         smoked_meat = 26,
+         spider_silk = 9,
+         spidercloth = 35,
          tabard = 15,
-         light_trident = 15,
+         trident_light = 15,
+         water = 12,
       },
       workers = {
-         armorsmith = 1,
-         blackroot_farmer = 1,
-         builder = 10,
-         charcoal_burner = 1,
-         carrier = 40,
-         fish_breeder = 2,
-         geologist = 4,
-         miner = 3,
-         sawyer = 1,
-         stonecutter = 2,
-         toolsmith = 2,
-         weaponsmith = 1,
-         woodcutter = 3,
-         horse = 15,
+         atlanteans_armorsmith = 1,
+         atlanteans_blackroot_farmer = 1,
+         atlanteans_builder = 10,
+         atlanteans_charcoal_burner = 1,
+         atlanteans_carrier = 40,
+         atlanteans_fishbreeder = 2,
+         atlanteans_geologist = 4,
+         atlanteans_miner = 3,
+         atlanteans_sawyer = 1,
+         atlanteans_stonecutter = 2,
+         atlanteans_toolsmith = 2,
+         atlanteans_weaponsmith = 1,
+         atlanteans_woodcutter = 3,
+         atlanteans_horse = 15,
       },
       soldiers = {
          [{0,0,0,0}] = 35,
       }
    },
-   {"woodcutters_house", 32, 48},
-   {"woodcutters_house", 33, 47},
-   {"woodcutters_house", 29, 56},
-   {"woodcutters_house", 30, 57},
-   {"foresters_house", 31, 53},
-   {"foresters_house", 32, 46},
-   {"foresters_house", 32, 50},
-   {"foresters_house", 34, 50},
-   {"sawmill", 41, 46},
-   {"quarry",  45, 54},
-   {"tower", 43, 52},
-   {"tower", 35, 46},
-   {"guardhouse", 49, 60},
-   {"crystalmine", 51, 61},
-   {"guardhall", 43, 64},
-   {"fish_breeders_house", 40, 66},
-   {"fishers_house", 42, 66},
-   {"fish_breeders_house", 44, 66},
-   {"fishers_house", 46, 66},
-   {"fish_breeders_house", 48, 66},
-   {"castle", 22, 55},
-   {"coalmine", 22, 48},
-   {"coalmine", 16, 49},
-   {"farm", 20, 59},
-   {"farm", 23, 59},
-   {"farm", 19, 64},
-   {"farm", 21, 65},
-   {"farm", 26, 64},
-   {"blackroot_farm", 53, 53},
-   {"blackroot_farm", 56, 50},
-   {"mill", 34, 58},
-   {"mill", 32, 64},
-   {"bakery", 38, 49},
-   {"bakery", 40, 48},
-   {"smokery", 46, 57},
-   {"smokery", 44, 57},
-   {"horsefarm", 40, 55},
-   {"spiderfarm", 37, 45},
-   {"weaving-mill", 45, 45},
-   {"smelting_works", 35, 56, wares = {coal = 8, ironore = 8}}, -- no gold
-   {"smelting_works", 35, 59, wares = {coal = 8, ironore = 8}},
-   {"toolsmithy", 41, 52},
-   {"weaponsmithy", 37, 54},
-   {"small_tower", 34, 63},
-   {"tower", 52, 46},
-   {"well", 39, 43},
-   {"well", 39, 45},
-   {"well", 38, 55},
-   {"well", 35, 61},
-   {"well", 32, 59},
-   {"warehouse", 36, 57},
+   {"atlanteans_woodcutters_house", 32, 48},
+   {"atlanteans_woodcutters_house", 33, 47},
+   {"atlanteans_woodcutters_house", 29, 56},
+   {"atlanteans_woodcutters_house", 30, 57},
+   {"atlanteans_foresters_house", 31, 53},
+   {"atlanteans_foresters_house", 32, 46},
+   {"atlanteans_foresters_house", 32, 50},
+   {"atlanteans_foresters_house", 34, 50},
+   {"atlanteans_sawmill", 41, 46},
+   {"atlanteans_quarry",  45, 54},
+   {"atlanteans_tower", 43, 52},
+   {"atlanteans_tower", 35, 46},
+   {"atlanteans_guardhouse", 49, 60},
+   {"atlanteans_crystalmine", 51, 61},
+   {"atlanteans_guardhall", 43, 64},
+   {"atlanteans_fishbreeders_house", 40, 66},
+   {"atlanteans_fishers_house", 42, 66},
+   {"atlanteans_fishbreeders_house", 44, 66},
+   {"atlanteans_fishers_house", 46, 66},
+   {"atlanteans_fishbreeders_house", 48, 66},
+   {"atlanteans_castle", 22, 55},
+   {"atlanteans_coalmine", 22, 48},
+   {"atlanteans_coalmine", 16, 49},
+   {"atlanteans_farm", 20, 59},
+   {"atlanteans_farm", 23, 59},
+   {"atlanteans_farm", 19, 64},
+   {"atlanteans_farm", 21, 65},
+   {"atlanteans_farm", 26, 64},
+   {"atlanteans_blackroot_farm", 53, 53},
+   {"atlanteans_blackroot_farm", 56, 50},
+   {"atlanteans_mill", 34, 58},
+   {"atlanteans_mill", 32, 64},
+   {"atlanteans_bakery", 38, 49},
+   {"atlanteans_bakery", 40, 48},
+   {"atlanteans_smokery", 46, 57},
+   {"atlanteans_smokery", 44, 57},
+   {"atlanteans_horsefarm", 40, 55},
+   {"atlanteans_spiderfarm", 37, 45},
+   {"atlanteans_weaving_mill", 45, 45},
+   {"atlanteans_smelting_works", 35, 56, wares = {coal = 8, iron_ore = 8}}, -- no gold
+   {"atlanteans_smelting_works", 35, 59, wares = {coal = 8, iron_ore = 8}},
+   {"atlanteans_toolsmithy", 41, 52},
+   {"atlanteans_weaponsmithy", 37, 54},
+   {"atlanteans_tower_small", 34, 63},
+   {"atlanteans_tower", 52, 46},
+   {"atlanteans_well", 39, 43},
+   {"atlanteans_well", 39, 45},
+   {"atlanteans_well", 38, 55},
+   {"atlanteans_well", 35, 61},
+   {"atlanteans_well", 32, 59},
+   {"atlanteans_warehouse", 36, 57},
 
    -- everthing below is in the north
-   {"castle", castle_field.x, castle_field.y},
-   {"warehouse", 37, 16,
+   {"atlanteans_castle", castle_field.x, castle_field.y},
+   {"atlanteans_warehouse", 37, 16,
       wares = {
-         smoked_meat = 50,
-         smoked_fish = 150,
-         bread = 200,
+         atlanteans_bread = 200,
+         diamond = 3,
+         gold = 2,
+         granite = 10,
+         hammer = 1,
          log = 30,
          planks = 30,
-         stone = 10,
-         diamond = 3,
          quartz = 4,
+         smoked_fish = 150,
+         smoked_meat = 50,
          spidercloth = 14,
-         gold = 2,
-         hammer = 1
       },
       workers = {
-         builder = 3,
-         miner = 3
+         atlanteans_builder = 3,
+         atlanteans_miner = 3
       },
       soldiers = {
          [{0,0,0,0}] = 10,
       }
    }, -- end of warehouse on northern peninsula
-   {"goldmine", 32, 25}
+   {"atlanteans_goldmine", 32, 25}
    )
 
-   plr:forbid_buildings{"shipyard"}
+   plr:forbid_buildings{"atlanteans_shipyard"}
 
    connected_road(plr,map:get_field(42,44).immovable,"bl,br,bl|bl,bl|bl,l|l,bl|l,l,l|l,l|tr,tl|r,tr")
    connected_road(plr,map:get_field(42,44).immovable,"br,r|br,r,r|r,r,tr|r,r|r,r|br,bl|br,br|br,br|r,r")

=== modified file 'campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua'
--- campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua	2015-07-31 13:33:50 +0000
+++ campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua	2015-10-18 20:57:50 +0000
@@ -69,7 +69,7 @@
    sleep(100*1000)
    message_box_objective(plr, ware_encyclopedia) -- a small insert
 
-   while #plr:get_buildings("tavern") < 2 do sleep(500) end
+   while #plr:get_buildings("empire_tavern") < 2 do sleep(500) end
    o.done = true
 
    plan_the_future()
@@ -124,7 +124,7 @@
    message_box_objective(plr, economy_settings2)
    o = message_box_objective(plr, economy_settings3)
 
-   while sf.immovable:get_wares("marblecolumn") < 12 do sleep(500) end
+   while sf.immovable:get_wares("marble_column") < 12 do sleep(500) end
    -- wait that the player has really changed the target quantity
 
    o.visible = false
@@ -133,8 +133,9 @@
 
    local enough_wares = false
    while not enough_wares do
-      if (warehouse_field.immovable and (warehouse_field.immovable.descr.name == "warehouse")) then
-         if warehouse_field.immovable:get_wares("marblecolumn") >= 20 then
+      if (warehouse_field.immovable and
+          (warehouse_field.immovable.descr.name == "empire_warehouse")) then
+         if warehouse_field.immovable:get_wares("marble_column") >= 20 then
             enough_wares = true
          end
       end

=== modified file 'campaigns/tutorial04_economy.wmf/scripting/starting_conditions.lua'
--- campaigns/tutorial04_economy.wmf/scripting/starting_conditions.lua	2015-06-10 13:01:28 +0000
+++ campaigns/tutorial04_economy.wmf/scripting/starting_conditions.lua	2015-10-18 20:57:50 +0000
@@ -2,16 +2,16 @@
 -- Initialization
 -- ===============
 
-plr:forbid_buildings{"scouts_house"} -- otherwise, player could scout the wasteland
+plr:forbid_buildings{"empire_scouts_house"} -- otherwise, player could scout the wasteland
 
 function init_player()
-   -- a headquarters without helms, lances, ores and coal
-   prefilled_buildings(plr, { "headquarters", sf.x, sf.y,
+   -- a headquarters without helms, spears, ores and coal
+   prefilled_buildings(plr, { "empire_headquarters", sf.x, sf.y,
       wares = {
-         ax = 6,
+         felling_ax = 6,
          bread_paddle = 2,
          basket = 2,
-         bread = 28,
+         empire_bread = 28,
          cloth = 5,
          fire_tongs = 2,
          fish = 6,
@@ -22,7 +22,7 @@
          hunting_spear = 2,
          kitchen_tools = 4,
          marble = 25,
-         marblecolumn = 6,
+         marble_column = 6,
          meal = 4,
          meat = 6,
          pick = 8,
@@ -30,113 +30,113 @@
          saw = 2,
          scythe = 5,
          shovel = 6,
-         stone = 40,
+         granite = 40,
          log = 60,
          water = 12,
          wheat = 24,
          wine = 8,
-         wood = 45,
+         planks = 45,
          wool = 2,
       },
       workers = {
-         armorsmith = 1,
-         brewer = 1,
-         builder = 10,
-         carrier = 40,
-         charcoal_burner = 1,
-         geologist = 4,
-         lumberjack = 3,
-         miner = 4,
-         stonemason = 2,
-         toolsmith = 2,
-         weaponsmith = 1,
-         donkey = 5,
+         empire_armorsmith = 1,
+         empire_brewer = 1,
+         empire_builder = 10,
+         empire_carrier = 40,
+         empire_charcoal_burner = 1,
+         empire_geologist = 4,
+         empire_lumberjack = 3,
+         empire_miner = 4,
+         empire_stonemason = 2,
+         empire_toolsmith = 2,
+         empire_weaponsmith = 1,
+         empire_donkey = 5,
       }
    })
 
    filled_buildings_one_soldier(plr,
-      {"lumberjacks_house",92,65},
-      {"lumberjacks_house",89,52},
-      {"foresters_house",90,54},
-      {"foresters_house",91,56},
-      {"lumberjacks_house",92,57},
-      {"foresters_house",93,59},
-      {"lumberjacks_house",93,61},
-      {"quarry",99,57},
-      {"quarry",89,38},
-      {"sawmill",91,53},
-      {"stonemasons_house",92,50},
-      {"donkeyfarm",96,58},
-      {"farm",88,48},
-      {"farm",91,38},
-      {"farm",94,39},
-      {"farm",88,34},
-      {"vineyard",97,49},
-      {"vineyard",100,50},
-      {"vineyard",103,50},
-      {"vineyard",103,56},
-      {"winery",101,52},
-      {"winery",101,57},
-      {"brewery",106,49},
-      {"brewery",104,49},
-      {"piggery",110,23},
-      {"piggery",113,21},
-      {"warehouse",110,29,
+      {"empire_lumberjacks_house",92,65},
+      {"empire_lumberjacks_house",89,52},
+      {"empire_foresters_house",90,54},
+      {"empire_foresters_house",91,56},
+      {"empire_lumberjacks_house",92,57},
+      {"empire_foresters_house",93,59},
+      {"empire_lumberjacks_house",93,61},
+      {"empire_quarry",99,57},
+      {"empire_quarry",89,38},
+      {"empire_sawmill",91,53},
+      {"empire_stonemasons_house",92,50},
+      {"empire_donkeyfarm",96,58},
+      {"empire_farm",88,48},
+      {"empire_farm",91,38},
+      {"empire_farm",94,39},
+      {"empire_farm",88,34},
+      {"empire_vineyard",97,49},
+      {"empire_vineyard",100,50},
+      {"empire_vineyard",103,50},
+      {"empire_vineyard",103,56},
+      {"empire_winery",101,52},
+      {"empire_winery",101,57},
+      {"empire_brewery",106,49},
+      {"empire_brewery",104,49},
+      {"empire_piggery",110,23},
+      {"empire_piggery",113,21},
+      {"empire_warehouse",110,29,
          wares = {
             wheat = 20,
             flour = 20
          }
       },
-      {"mill",105,46},
-      {"mill",107,44},
-      {"mill",108,39},
-      {"bakery",114,26},
-      {"bakery",116,28},
-      {"bakery",115,32},
-      {"tavern",tavern_field.x,tavern_field.y}, -- (105,44), will be destroyed
-      {"coalmine",118,45, wares = {beer = 6}},
-      {"coalmine",119,39, wares = {beer = 6}},
-      {"oremine",107,59, wares = {beer = 6}},
-      {"marblemine",98,38, wares = {wine = 6}},
-      {"marblemine",102,38, wares = {wine = 6}},
-      {"smelting_works",110,38, wares = {}},
-      {"smelting_works",111,43, wares = {}},
-      {"toolsmithy",104,64, wares = {log = 8}},
-      {"weaponsmithy",113,40, wares = {wood = 8}},
-      {"armorsmithy",112,37, wares = {cloth = 8}},
-      {"farm",105,70},
-      {"farm",101,71},
-      {"farm",99,77},
-      {"fishers_house",106,77},
-      {"fishers_house",104,77},
-      {"fishers_house",103,79},
-      {"warehouse",100,74},
-      {"hunters_house",95,60},
-      {"well",92,48},
-      {"well",103,45},
-      {"well",107,40},
-      {"well",103,47},
-      {"well",104,51},
-      {"well",106,51},
-      {"well",113,23},
-      {"well",113,32},
-      {"well",112,34},
-      {"well",111,31},
-      {"well",115,24},
-      {"warehouse",warehouse_field.x,warehouse_field.y}, -- (78,67)
+      {"empire_mill",105,46},
+      {"empire_mill",107,44},
+      {"empire_mill",108,39},
+      {"empire_bakery",114,26},
+      {"empire_bakery",116,28},
+      {"empire_bakery",115,32},
+      {"empire_tavern",tavern_field.x,tavern_field.y}, -- (105,44), will be destroyed
+      {"empire_coalmine",118,45, wares = {beer = 6}},
+      {"empire_coalmine",119,39, wares = {beer = 6}},
+      {"empire_ironmine",107,59, wares = {beer = 6}},
+      {"empire_marblemine",98,38, wares = {wine = 6}},
+      {"empire_marblemine",102,38, wares = {wine = 6}},
+      {"empire_smelting_works",110,38, wares = {}},
+      {"empire_smelting_works",111,43, wares = {}},
+      {"empire_toolsmithy",104,64, wares = {log = 8}},
+      {"empire_weaponsmithy",113,40, wares = {planks = 8}},
+      {"empire_armorsmithy",112,37, wares = {cloth = 8}},
+      {"empire_farm",105,70},
+      {"empire_farm",101,71},
+      {"empire_farm",99,77},
+      {"empire_fishers_house",106,77},
+      {"empire_fishers_house",104,77},
+      {"empire_fishers_house",103,79},
+      {"empire_warehouse",100,74},
+      {"empire_hunters_house",95,60},
+      {"empire_well",92,48},
+      {"empire_well",103,45},
+      {"empire_well",107,40},
+      {"empire_well",103,47},
+      {"empire_well",104,51},
+      {"empire_well",106,51},
+      {"empire_well",113,23},
+      {"empire_well",113,32},
+      {"empire_well",112,34},
+      {"empire_well",111,31},
+      {"empire_well",115,24},
+      {"empire_warehouse",warehouse_field.x,warehouse_field.y}, -- (78,67)
 
-      {"barracks",89,31},
-      {"barrier",91,45},
-      {"tower",103,42},
-      {"barrier",112,25},
-      {"sentry",116,41},
-      {"barracks",102,66},
-      {"outpost",103,76},
-      {"tower",90,67},
-      {"sentry",105,56},
-      {"fortress",66,63},
-      {"fortress",71,66},
-      {"fortress",75,72}
+      {"empire_blockhouse",89,31},
+      {"empire_barrier",91,45},
+      {"empire_tower",103,42},
+      {"empire_barrier",112,25},
+      {"empire_sentry",116,41},
+      {"empire_blockhouse",102,66},
+      {"empire_outpost",103,76},
+      {"empire_tower",90,67},
+      {"empire_sentry",105,56},
+      {"empire_fortress",66,63},
+      {"empire_fortress",71,66},
+      {"empire_fortress",75,72}
    )
    plr:place_building("quarry", map:get_field(87,36), true, true) -- a construction site
 

=== modified file 'campaigns/tutorial04_economy.wmf/scripting/texts.lua'
--- campaigns/tutorial04_economy.wmf/scripting/texts.lua	2015-09-03 12:56:54 +0000
+++ campaigns/tutorial04_economy.wmf/scripting/texts.lua	2015-10-18 20:57:50 +0000
@@ -227,7 +227,7 @@
       p(_[[This encyclopedia can be accessed via]])
    ) ..
    rt("image=pics/menu_help.png",p(_[[the help button at the bottom. For all your tribe’s wares, it shows a short help text, a list of buildings that produces the ware and the needed wares.]]) ..
-      p(_[[If you want, you can try it out. A soldier needs a wood lance and a helm – from there on out, you can search backwards.]])
+      p(_[[If you want, you can try it out. A soldier needs a wooden spear and a helm – from there on out, you can search backwards.]])
    ),
    h = 350
 }

=== modified file 'doc/sphinx/source/introduction.rst'
--- doc/sphinx/source/introduction.rst	2014-03-15 11:29:32 +0000
+++ doc/sphinx/source/introduction.rst	2015-10-18 20:57:50 +0000
@@ -12,21 +12,21 @@
 ^^^^^^^^^
 
 The most prominent usage of Lua is in scenarios: All scenario logic is
-scripted using Lua. How this works is described in the :ref:`scenario_tutorial`. 
+scripted using Lua. How this works is described in the :ref:`scenario_tutorial`.
 
 Initializations of Tribes in non-scenario games
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 At the beginning of non scenario games, the player has a choice to use
 different starting conditions. There is the very essential one that just sets
-a hq and some starting wares and there are more sophisticated ones. 
+a hq and some starting wares and there are more sophisticated ones.
 
-Adding new ones is simple. All you have to do is to create a new script in 
+Adding new ones is simple. All you have to do is to create a new script in
 the ``scripting`` directory of a tribe. The script should return a :class:`table`
 with two keys: ``name`` is the name for this start condition shown to the user
 and ``func`` is the function that will be called. This function takes on
 argument, a :class:`~wl.game.Player` for which to create the initial
-infrastructure. 
+infrastructure.
 
 A small example. Let's assume we want to add an initialization to the
 barbarians that gives the player 80 logs, but not at once but one by one
@@ -39,8 +39,8 @@
    use("aux", "coroutine")  -- For convenience function sleep()
 
    -- Set the textdomain, so that all strings given to the _() function are
-   -- properly translated. 
-   set_textdomain("tribe_barbarians")
+   -- properly translated.
+   set_textdomain("tribes")
 
    -- Now for the array we must return
    return {
@@ -50,10 +50,10 @@
          player:allow_workers("all")
 
          -- Place the hq
-         local hq = player:place_building("headquarters", player.starting_field)
+         local hq = player:place_building("barbarians_headquarters", player.starting_field)
 
          -- Now add one log to the hq every 250 ms
-         for i=1,80 do 
+         for i=1,80 do
             hq:set_wares("log", hq:get_wares("log") + 1)
             sleep(250)
          end
@@ -83,7 +83,7 @@
    return {
       name = _ "Harvest logs",
       description = _ "The first player with 200 logs wins!",
-      func = function() 
+      func = function()
          -- Find all valid players.
          local plrs = wl.Game().players
 
@@ -102,7 +102,7 @@
                end
             end
          end
-               
+
          -- Send the winner a hurray message, the losers a boo
          for idx,p in ipairs(losers) do
             p:send_message(_"You lost!", _"You lost this game!")
@@ -116,7 +116,7 @@
 
 Hooks are called by widelands when a certain event happened.  They are a
 rather recent implementation and therefore still limited. More hooks might be
-implemented in the future. 
+implemented in the future.
 
 You set a hook by setting a field in the global variable ``hooks`` which must
 be a dictionary. The only valid hook currently is the ``custom_statistic``
@@ -126,7 +126,7 @@
 something like this:
 
 .. code-block:: lua
-   
+
    hooks = {}
    hooks.custom_statistic = {
       name = _ "Unchanging statistic",
@@ -154,13 +154,13 @@
    print("Hello World!")
    map = wl.Game().map
    hq = map.player_slots[1].starting_field.immovable -- If this is a normal map
-   hq:set_workers("builder", 100)
+   hq:set_workers("barbarians_builder", 100)
 
 This makes for excellent cheating in debug builds, but note that this is for
 debug purposes only -- in network games running Lua commands this way will
 desync and therefore crash the game and also replays where you changed the
 game state via the debug console will not work. It is very useful
-for debugging scenarios though. 
+for debugging scenarios though.
 
 Regression testing infrastructure
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

=== removed directory 'global'
=== removed directory 'global/militarysites'
=== removed directory 'global/militarysites/barracks.empire'
=== removed file 'global/militarysites/barracks.empire/conf'
--- global/militarysites/barracks.empire/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/barracks.empire/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=small
-heal_per_second=60 # very low -> smallest building
-conquers=6
-max_soldiers=1
-buildable=no
-prefer_heroes=false
-occupied_string=
-aggressor_string=_Your barracks discovered an aggressor.
-attack_string=_Your barracks is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the barracks.
-defeated_you_string=_Your soldiers defeated the enemy at the barracks.
-
-
-[idle]
-pics=../../../tribes/empire/barracks/barracks_i_??.png
-hotspot=38 60

=== removed file 'global/militarysites/barracks.empire/menu.png'
Binary files global/militarysites/barracks.empire/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/barracks.empire/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/barrier.barbarians'
=== removed file 'global/militarysites/barrier.barbarians/conf'
--- global/militarysites/barrier.barbarians/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/barrier.barbarians/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=medium
-max_soldiers=5
-heal_per_second=130
-conquers=8
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your barrier discovered an aggressor.
-attack_string=_Your barrier is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the barrier.
-defeated_you_string=_Your soldiers defeated the enemy at the barrier.
-
-
-[idle]
-pics=../../../tribes/barbarians/barrier/barrier_i_??.png
-hotspot=45 66
-fps=10

=== removed file 'global/militarysites/barrier.barbarians/menu.png'
Binary files global/militarysites/barrier.barbarians/menu.png	2010-12-04 13:52:49 +0000 and global/militarysites/barrier.barbarians/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/barrier.empire'
=== removed file 'global/militarysites/barrier.empire/conf'
--- global/militarysites/barrier.empire/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/barrier.empire/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=medium
-max_soldiers=5
-heal_per_second=130
-conquers=8
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your barrier discovered an aggressor.
-attack_string=_Your barrier is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the barrier.
-defeated_you_string=_Your soldiers defeated the enemy at the barrier.
-
-
-[idle]
-pics=../../../tribes/empire/barrier/barrier_i_??.png
-hotspot=55 80

=== removed file 'global/militarysites/barrier.empire/menu.png'
Binary files global/militarysites/barrier.empire/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/barrier.empire/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/castle.atlanteans'
=== removed file 'global/militarysites/castle.atlanteans/conf'
--- global/militarysites/castle.atlanteans/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/castle.atlanteans/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=big
-max_soldiers=12
-heal_per_second=200
-conquers=12
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your castle discovered an aggressor.
-attack_string=_Your castle is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the castle.
-defeated_you_string=_Your soldiers defeated the enemy at the castle.
-
-
-[idle]
-pics=../../../tribes/atlanteans/castle/castle_i_??.png
-hotspot=92 90

=== removed file 'global/militarysites/castle.atlanteans/menu.png'
Binary files global/militarysites/castle.atlanteans/menu.png	2010-04-03 13:26:11 +0000 and global/militarysites/castle.atlanteans/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/castle.empire'
=== removed file 'global/militarysites/castle.empire/conf'
--- global/militarysites/castle.empire/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/castle.empire/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=big
-max_soldiers=12
-heal_per_second=220
-conquers=12
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your castle discovered an aggressor.
-attack_string=_Your castle is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the castle.
-defeated_you_string=_Your soldiers defeated the enemy at the castle.
-
-
-[idle]
-pics=../../../tribes/empire/castle/castle_i_??.png
-hotspot=90 106

=== removed file 'global/militarysites/castle.empire/menu.png'
Binary files global/militarysites/castle.empire/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/castle.empire/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/citadel.barbarians'
=== removed file 'global/militarysites/citadel.barbarians/conf'
--- global/militarysites/citadel.barbarians/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/citadel.barbarians/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=big
-max_soldiers=12
-heal_per_second=220
-conquers=12
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your citadel discovered an aggressor.
-attack_string=_Your citadel is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the citadel.
-defeated_you_string=_Your soldiers defeated the enemy at the citadel.
-
-
-[idle]
-pics=../../../tribes/barbarians/citadel/citadel_i_??.png
-hotspot=102 102
-fps=10

=== removed file 'global/militarysites/citadel.barbarians/menu.png'
Binary files global/militarysites/citadel.barbarians/menu.png	2012-04-12 13:06:20 +0000 and global/militarysites/citadel.barbarians/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/donjon.barbarians'
=== removed file 'global/militarysites/donjon.barbarians/conf'
--- global/militarysites/donjon.barbarians/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/donjon.barbarians/conf	1970-01-01 00:00:00 +0000
@@ -1,18 +0,0 @@
-size=medium
-max_soldiers=5
-heal_per_second=150
-conquers=8
-vision_range=17
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your donjon discovered an aggressor.
-attack_string=_Your donjon is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the donjon.
-defeated_you_string=_Your soldiers defeated the enemy at the donjon.
-
-
-[idle]
-pics=../../../tribes/barbarians/donjon/donjon_i_??.png
-hotspot=55 84
-fps=10

=== removed file 'global/militarysites/donjon.barbarians/menu.png'
Binary files global/militarysites/donjon.barbarians/menu.png	2010-12-04 13:52:49 +0000 and global/militarysites/donjon.barbarians/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/fortress.barbarians'
=== removed file 'global/militarysites/fortress.barbarians/conf'
--- global/militarysites/fortress.barbarians/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/fortress.barbarians/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=big
-max_soldiers=8
-heal_per_second=170
-conquers=11
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your fortress discovered an aggressor.
-attack_string=_Your fortress is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the fortress.
-defeated_you_string=_Your soldiers defeated the enemy at the fortress.
-
-
-[idle]
-pics=../../../tribes/barbarians/fortress/fortress_i_??.png
-hotspot=103 80
-fps=10

=== removed file 'global/militarysites/fortress.barbarians/menu.png'
Binary files global/militarysites/fortress.barbarians/menu.png	2012-04-12 13:06:20 +0000 and global/militarysites/fortress.barbarians/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/fortress.empire'
=== removed file 'global/militarysites/fortress.empire/conf'
--- global/militarysites/fortress.empire/conf	2014-03-14 13:33:31 +0000
+++ global/militarysites/fortress.empire/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=big
-max_soldiers=8
-heal_per_second=170
-conquers=11
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your fortress discovered an aggressor.
-attack_string=_Your fortress is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the fortress.
-defeated_you_string=_Your soldiers defeated the enemy at the fortress.
-
-
-[idle]
-pics=../../../tribes/empire/fortress/fortress_i_??.png
-hotspot=90 106

=== removed file 'global/militarysites/fortress.empire/menu.png'
Binary files global/militarysites/fortress.empire/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/fortress.empire/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/guardhall.atlanteans'
=== removed file 'global/militarysites/guardhall.atlanteans/conf'
--- global/militarysites/guardhall.atlanteans/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/guardhall.atlanteans/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=medium
-max_soldiers=7
-heal_per_second=140
-conquers=7
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your guardhall discovered an aggressor.
-attack_string=_Your guardhall is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the guardhall.
-defeated_you_string=_Your soldiers defeated the enemy at the guardhall.
-
-
-[idle]
-pics=../../../tribes/atlanteans/guardhall/guardhall_i_??.png
-hotspot=58 65

=== removed file 'global/militarysites/guardhall.atlanteans/menu.png'
Binary files global/militarysites/guardhall.atlanteans/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/guardhall.atlanteans/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/guardhouse.atlanteans'
=== removed file 'global/militarysites/guardhouse.atlanteans/conf'
--- global/militarysites/guardhouse.atlanteans/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/guardhouse.atlanteans/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=small
-heal_per_second=75
-conquers=6
-max_soldiers=2
-buildable=no
-prefer_heroes=false
-occupied_string=
-aggressor_string=_Your guardhouse discovered an aggressor.
-attack_string=_Your guardhouse is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the guardhouse.
-defeated_you_string=_Your soldiers defeated the enemy at the guardhouse.
-
-
-[idle]
-pics=../../../tribes/atlanteans/guardhouse/guardhouse_i_??.png
-hotspot=35 42

=== removed file 'global/militarysites/guardhouse.atlanteans/menu.png'
Binary files global/militarysites/guardhouse.atlanteans/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/guardhouse.atlanteans/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/high_tower.atlanteans'
=== removed file 'global/militarysites/high_tower.atlanteans/conf'
--- global/militarysites/high_tower.atlanteans/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/high_tower.atlanteans/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=medium
-max_soldiers=5
-heal_per_second=170
-conquers=9
-vision_range=21
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your high tower discovered an aggressor.
-attack_string=_Your high tower is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the high tower.
-defeated_you_string=_Your soldiers defeated the enemy at the high tower.
-
-
-[idle]
-pics=../../../tribes/atlanteans/high_tower/high_tower_i_??.png
-hotspot=55 90

=== removed file 'global/militarysites/high_tower.atlanteans/menu.png'
Binary files global/militarysites/high_tower.atlanteans/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/high_tower.atlanteans/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/outpost.empire'
=== removed file 'global/militarysites/outpost.empire/conf'
--- global/militarysites/outpost.empire/conf	2014-03-14 13:33:31 +0000
+++ global/militarysites/outpost.empire/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=medium
-max_soldiers=3
-heal_per_second=100
-conquers=7
-buildable=no
-prefer_heroes=false
-occupied_string=
-aggressor_string=_Your outpost discovered an aggressor.
-attack_string=_Your outpost is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the outpost.
-defeated_you_string=_Your soldiers defeated the enemy at the outpost.
-
-
-[idle]
-pics=../../../tribes/empire/outpost/outpost_i_??.png
-hotspot=60 80

=== removed file 'global/militarysites/outpost.empire/menu.png'
Binary files global/militarysites/outpost.empire/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/outpost.empire/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed file 'global/militarysites/outpost.empire/outpost_b_00.png'
Binary files global/militarysites/outpost.empire/outpost_b_00.png	2009-11-22 23:46:28 +0000 and global/militarysites/outpost.empire/outpost_b_00.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/sentry.barbarians'
=== removed file 'global/militarysites/sentry.barbarians/conf'
--- global/militarysites/sentry.barbarians/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/sentry.barbarians/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=small
-heal_per_second=80
-conquers=6
-max_soldiers=2
-buildable=no
-prefer_heroes=false
-occupied_string=
-aggressor_string=_Your sentry discovered an aggressor.
-attack_string=_Your sentry is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the sentry.
-defeated_you_string=_Your soldiers defeated the enemy at the sentry.
-
-
-[idle]
-pics=../../../tribes/barbarians/sentry/sentry_i_??.png
-hotspot=39 40
-fps=10

=== removed file 'global/militarysites/sentry.barbarians/menu.png'
Binary files global/militarysites/sentry.barbarians/menu.png	2010-12-04 13:52:49 +0000 and global/militarysites/sentry.barbarians/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/sentry.empire'
=== removed file 'global/militarysites/sentry.empire/conf'
--- global/militarysites/sentry.empire/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/sentry.empire/conf	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-size=small
-heal_per_second=80
-conquers=6
-max_soldiers=2
-buildable=no
-prefer_heroes=false
-occupied_string=
-aggressor_string=_Your sentry discovered an aggressor.
-attack_string=_Your sentry is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the sentry.
-defeated_you_string=_Your soldiers defeated the enemy at the sentry.
-
-
-[idle]
-pics=../../../tribes/empire/sentry/sentry_i_??.png
-hotspot=40 63

=== removed file 'global/militarysites/sentry.empire/menu.png'
Binary files global/militarysites/sentry.empire/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/sentry.empire/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/small_tower.atlanteans'
=== removed file 'global/militarysites/small_tower.atlanteans/conf'
--- global/militarysites/small_tower.atlanteans/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/small_tower.atlanteans/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=small
-heal_per_second=100
-conquers=5
-vision_range=13
-max_soldiers=3
-buildable=no
-prefer_heroes=false
-occupied_string=
-aggressor_string=_Your small tower discovered an aggressor.
-attack_string=_Your small tower is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the small tower.
-defeated_you_string=_Your soldiers defeated the enemy at the small tower.
-
-
-[idle]
-pics=../../../tribes/atlanteans/small_tower/small_tower_i_??.png
-hotspot=41 63

=== removed file 'global/militarysites/small_tower.atlanteans/menu.png'
Binary files global/militarysites/small_tower.atlanteans/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/small_tower.atlanteans/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/tower.atlanteans'
=== removed file 'global/militarysites/tower.atlanteans/conf'
--- global/militarysites/tower.atlanteans/conf	2014-03-17 17:23:26 +0000
+++ global/militarysites/tower.atlanteans/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=medium
-max_soldiers=4
-heal_per_second=120
-conquers=9
-vision_range=17
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your tower discovered an aggressor.
-attack_string=_Your tower is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the tower.
-defeated_you_string=_Your soldiers defeated the enemy at the tower.
-
-
-[idle]
-pics=../../../tribes/atlanteans/tower/tower_i_??.png
-hotspot=55 70

=== removed file 'global/militarysites/tower.atlanteans/menu.png'
Binary files global/militarysites/tower.atlanteans/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/tower.atlanteans/menu.png	1970-01-01 00:00:00 +0000 differ
=== removed directory 'global/militarysites/tower.empire'
=== removed file 'global/militarysites/tower.empire/conf'
--- global/militarysites/tower.empire/conf	2014-03-14 13:33:31 +0000
+++ global/militarysites/tower.empire/conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-size=medium
-max_soldiers=5
-heal_per_second=150
-conquers=9
-vision_range=19
-buildable=no
-prefer_heroes=true
-occupied_string=
-aggressor_string=_Your tower discovered an aggressor.
-attack_string=_Your tower is under attack.
-defeated_enemy_string=_The enemy defeated your soldiers at the tower.
-defeated_you_string=_Your soldiers defeated the enemy at the tower.
-
-
-[idle]
-pics=../../../tribes/empire/tower/tower_i_??.png
-hotspot=55 92

=== removed file 'global/militarysites/tower.empire/menu.png'
Binary files global/militarysites/tower.empire/menu.png	2009-11-22 23:46:28 +0000 and global/militarysites/tower.empire/menu.png	1970-01-01 00:00:00 +0000 differ
=== modified file 'maps/MP Scenarios/Island Hopping.wmf/scripting/first_island.lua'
--- maps/MP Scenarios/Island Hopping.wmf/scripting/first_island.lua	2014-07-28 11:22:56 +0000
+++ maps/MP Scenarios/Island Hopping.wmf/scripting/first_island.lua	2015-10-18 20:57:50 +0000
@@ -45,7 +45,7 @@
       while castle_field == nil do
          sleep(7477)
          for idx, f in pairs(hill) do
-            if f.immovable and f.immovable.descr.name == "castle"
+            if f.immovable and f.immovable.descr.name == "atlanteans_castle"
             then
                castle_field = f
                started_claiming = game.time
@@ -60,7 +60,7 @@
       while true do
          sleep(1049)
          local imm = castle_field.immovable
-         if not imm or imm.descr.name ~= "castle" or imm.owner ~= claiming_player then
+         if not imm or imm.descr.name ~= "atlanteans_castle" or imm.owner ~= claiming_player then
             send_to_all(lost_control:format(claiming_player.name))
             break
          end

=== modified file 'maps/MP Scenarios/Island Hopping.wmf/scripting/hop_island.lua'
--- maps/MP Scenarios/Island Hopping.wmf/scripting/hop_island.lua	2014-07-28 18:15:47 +0000
+++ maps/MP Scenarios/Island Hopping.wmf/scripting/hop_island.lua	2015-10-18 20:57:50 +0000
@@ -51,7 +51,7 @@
 function hop_to_next_island(plr, island_idx)
    -- Place the new HQ
    local new_hq_field = _start_fields[island_idx + 1][plr.number]
-   local new_hq = plr:place_building("headquarters", new_hq_field, false, true)
+   local new_hq = plr:place_building("atlanteans_headquarters", new_hq_field, false, true)
 
    -- Transfer stuff from HQs
    for i=1,island_idx do
@@ -65,7 +65,7 @@
    end
 
    -- Transfer from existing warehouses
-   for idx,wh in ipairs(plr:get_buildings("warehouse")) do
+   for idx,wh in ipairs(plr:get_buildings("atlanteans_warehouse")) do
       local soldiers, workers, wares = _remove_content(wh)
       add_soldiers(new_hq, soldiers)
       add_workers(new_hq, workers)

=== modified file 'maps/MP Scenarios/Island Hopping.wmf/scripting/multiplayer_init.lua'
--- maps/MP Scenarios/Island Hopping.wmf/scripting/multiplayer_init.lua	2015-09-15 06:44:11 +0000
+++ maps/MP Scenarios/Island Hopping.wmf/scripting/multiplayer_init.lua	2015-10-18 20:57:50 +0000
@@ -55,34 +55,34 @@
 _finish_rewards = {
    { -- Island 1
       { -- 1st to finish
-         log = 25, planks = 15, stone = 10,
+         log = 25, planks = 15, granite = 10,
          spidercloth = 5, corn = 20,
       },
       { -- 2st to finish
-         log = 45, planks = 30, stone = 20,
+         log = 45, planks = 30, granite = 20,
          spidercloth = 7, corn = 25,
       },
       { -- 3rd to finish
-         log = 65, planks = 45, stone = 30,
+         log = 65, planks = 45, granite = 30,
          spidercloth = 9, corn = 30,
       },
       { -- 4th to finish
-         log = 85, planks = 50, stone = 40,
+         log = 85, planks = 50, granite = 40,
          spidercloth = 11, corn = 35,
       }
    },
    { -- Island 2
       { -- 1st to finish
-         coal = 20, ironore = 10, goldore = 10,
+         coal = 20, iron_ore = 10, gold_ore = 10,
       },
       { -- 2st to finish
-         coal = 30, ironore = 15, goldore = 15,
+         coal = 30, iron_ore = 15, gold_ore = 15,
       },
       { -- 3rd to finish
-         coal = 40, ironore = 20, goldore = 20,
+         coal = 40, iron_ore = 20, gold_ore = 20,
       },
       { -- 4th to finish
-         coal = 50, ironore = 25, goldore = 25,
+         coal = 50, iron_ore = 25, gold_ore = 25,
       }
    }
 }
@@ -138,32 +138,32 @@
    for idx, plr in ipairs(game.players) do
       local sf = map.player_slots[plr.number].starting_field
 
-      prefilled_buildings(plr, {"headquarters", sf.x, sf.y,
+      prefilled_buildings(plr, {"atlanteans_headquarters", sf.x, sf.y,
          wares = {
             diamond = 7,
-            ironore = 5,
+            iron_ore = 5,
             quartz = 9,
-            stone = 50,
-            spideryarn = 9,
+            granite = 50,
+            spider_silk = 9,
             log = 20,
             coal = 12,
             gold = 4,
-            goldyarn = 6,
+            gold_thread = 6,
             iron = 8,
             planks = 45,
             spidercloth = 5,
             blackroot = 5,
-            blackrootflour = 12,
-            bread = 8,
+            blackroot_flour = 12,
+            atlanteans_bread = 8,
             corn = 5,
-            cornflour = 12,
+            cornmeal = 12,
             fish = 3,
             meat = 3,
             smoked_fish = 6,
             smoked_meat = 6,
             water = 12,
             bread_paddle = 2,
-            bucket = 2,
+            buckets = 2,
             fire_tongs = 2,
             fishing_net = 4,
             hammer = 11,
@@ -175,23 +175,23 @@
             scythe = 4,
             shovel = 9,
             tabard = 5,
-            light_trident = 5,
+            trident_light = 5,
          },
          workers = {
-            armorsmith = 1,
-            blackroot_farmer = 1,
-            builder = 10,
-            carrier = 40,
-            charcoal_burner = 1,
-            fish_breeder = 1,
-            geologist = 4,
-            miner = 4,
-            sawyer = 1,
-            stonecutter = 2,
-            toolsmith = 2,
-            weaponsmith = 1,
-            woodcutter = 3,
-            horse = 5,
+            atlanteans_armorsmith = 1,
+            atlanteans_blackroot_farmer = 1,
+            atlanteans_builder = 10,
+            atlanteans_carrier = 40,
+            atlanteans_charcoal_burner = 1,
+            atlanteans_fishbreeder = 1,
+            atlanteans_geologist = 4,
+            atlanteans_miner = 4,
+            atlanteans_sawyer = 1,
+            atlanteans_stonecutter = 2,
+            atlanteans_toolsmith = 2,
+            atlanteans_weaponsmith = 1,
+            atlanteans_woodcutter = 3,
+            atlanteans_horse = 5,
          },
          soldiers = {
             [{0,0,0,0}] = 35,
@@ -203,7 +203,7 @@
 -- Disable some Buildings for all players
 function disable_unused_buildings()
    for idx, plr in ipairs(game.players) do
-      plr:forbid_buildings{"shipyard"}
+      plr:forbid_buildings{"atlanteans_shipyard"}
    end
 end
 

=== modified file 'maps/MP Scenarios/Smugglers.wmf/scripting/multiplayer_init.lua'
--- maps/MP Scenarios/Smugglers.wmf/scripting/multiplayer_init.lua	2015-03-21 13:18:02 +0000
+++ maps/MP Scenarios/Smugglers.wmf/scripting/multiplayer_init.lua	2015-10-18 20:57:50 +0000
@@ -61,7 +61,7 @@
    for idx,player in ipairs(game.players) do
       local sf = map.player_slots[player.number].starting_field
 
-      prefilled_buildings(player, { "headquarters", sf.x, sf.y,
+      prefilled_buildings(player, { "barbarians_headquarters", sf.x, sf.y,
          wares = {
             ax = 5,
             bread_paddle = 2,
@@ -77,34 +77,34 @@
             hammer = 12,
             hunting_spear = 2,
             iron = 12,
-            ironore = 5,
+            iron_ore = 5,
             kitchen_tools = 4,
             meal = 4,
             meat = 6,
             pick = 14,
-            pittabread = 8,
+            barbarians_bread = 8,
             ration = 12,
-            raw_stone = 40,
+            granite = 40,
             scythe = 6,
             shovel = 4,
             snack = 3,
-            thatchreed = 24,
+            thatch_reed = 24,
             log = 80,
          },
          workers = {
-            blacksmith = 2,
-            brewer = 1,
-            builder = 10,
-            carrier = 40,
-            charcoal_burner = 1,
-            gardener = 1,
-            geologist = 4,
-            ["lime-burner"] = 1,
-            lumberjack = 3,
-            miner = 4,
-            ranger = 1,
-            stonemason = 2,
-            ox = 5,
+            barbarians_blacksmith = 2,
+            barbarians_brewer = 1,
+            barbarians_builder = 10,
+            barbarians_carrier = 40,
+            barbarians_charcoal_burner = 1,
+            barbarians_gardener = 1,
+            barbarians_geologist = 4,
+            barbarians_lime_burner = 1,
+            barbarians_lumberjack = 3,
+            barbarians_miner = 4,
+            barbarians_ranger = 1,
+            barbarians_stonemason = 2,
+            barbarians_ox = 5,
          },
          soldiers = {
             [{0,0,0,0}] = 45,

=== modified file 'maps/MP Scenarios/Smugglers.wmf/scripting/smuggling.lua'
--- maps/MP Scenarios/Smugglers.wmf/scripting/smuggling.lua	2014-10-03 20:16:29 +0000
+++ maps/MP Scenarios/Smugglers.wmf/scripting/smuggling.lua	2015-10-18 20:57:50 +0000
@@ -10,7 +10,7 @@
 -- Find a warehouse for in the given area
 function find_warehouse(region)
    for idx,f in ipairs(region) do
-      if f.immovable and f.immovable.descr.type_name == "warehouse" then
+      if f.immovable and f.immovable.descr.type_name == "barbarians_warehouse" then
          return f.immovable
       end
    end
@@ -46,9 +46,11 @@
          break
       end
 
-      if not send_whf.immovable or send_whf.immovable.descr.type_name ~= "warehouse" or
+      if not send_whf.immovable or
+         send_whf.immovable.descr.type_name ~= "barbarians_warehouse" or
          send_whf.immovable.owner ~= send_plr or
-         not recv_whf.immovable or recv_whf.immovable.descr.type_name ~= "warehouse" or
+         not recv_whf.immovable or
+         recv_whf.immovable.descr.type_name ~= "barbarians_warehouse" or
          recv_whf.immovable.owner ~= recv_plr
       then
          send_to_all(smuggling_route_broken:bformat(

=== modified file 'maps/Plateau.wmf/scripting/init.lua'
--- maps/Plateau.wmf/scripting/init.lua	2014-10-02 09:39:55 +0000
+++ maps/Plateau.wmf/scripting/init.lua	2015-10-18 20:57:50 +0000
@@ -53,7 +53,7 @@
    o = add_campaign_objective(obj_capture_ancient_castle)
 
    -- Wait till we conquered the castle
-   while #p1:get_buildings"castle.atlanteans" < 1 do sleep(2345) end
+   while #p1:get_buildings"atlanteans_castle" < 1 do sleep(2345) end
    o.done = true
 
    scroll_smoothly_to(castle)

=== modified file 'maps/Plateau.wmf/scripting/initial_conditions.lua'
--- maps/Plateau.wmf/scripting/initial_conditions.lua	2014-08-26 17:25:00 +0000
+++ maps/Plateau.wmf/scripting/initial_conditions.lua	2015-10-18 20:57:50 +0000
@@ -1,206 +1,206 @@
 -- =======================================================================
---                                 Player 1                                 
+--                                 Player 1
 -- =======================================================================
 p1:allow_buildings("all")
 
-prefilled_buildings(p1, { "headquarters_interim", 65, 6, 
+prefilled_buildings(p1, { "barbarians_headquarters_interim", 65, 6,
    wares = {
-      ax = 6,
+      blackwood = 32,
+      barbarians_bread = 8,
       bread_paddle = 2,
-      blackwood = 32,
       coal = 12,
       fire_tongs = 2,
       fish = 6,
+      granite = 40,
       grout = 12,
       hammer = 12,
       hunting_spear = 2,
       iron = 12,
-      ironore = 5,
+      iron_ore = 5,
       kitchen_tools = 4,
+      log = 80,
       meal = 4,
       meat = 6,
       pick = 14,
-      pittabread = 8,
       ration = 12,
-      raw_stone = 40,
       scythe = 6,
       shovel = 4,
       snack = 3,
-      thatchreed = 24,
-      log = 80,
+      thatch_reed = 24,
+     ax = 6,
    },
    workers = {
-      carrier = 40,
-      blacksmith = 2,
-      brewer = 1,
-      builder = 10,
-      gardener = 1,
-      fisher = 2,
-      geologist = 4,
-      ["lime-burner"] = 1,
-      lumberjack = 3,
-      miner = 4,
-      ranger = 1,
-      stonemason = 2,
-      ox = 20, 
+      barbarians_carrier = 40,
+      barbarians_blacksmith = 2,
+      barbarians_brewer = 1,
+      barbarians_builder = 10,
+      barbarians_gardener = 1,
+      barbarians_fisher = 2,
+      barbarians_geologist = 4,
+      barbarians_lime_burner = 1,
+      barbarians_lumberjack = 3,
+      barbarians_miner = 4,
+      barbarians_ranger = 1,
+      barbarians_stonemason = 2,
+      barbarians_ox = 20,
    },
    soldiers = { [{0,0,0,0}] = 45 },
 })
 
 -- =======================================================================
---                                 Player 2                                 
+--                                 Player 2
 -- =======================================================================
 p2:forbid_buildings("all")
-p2:allow_buildings{ "lumberjacks_hut" }
+p2:allow_buildings{ "barbarians_lumberjacks_hut" }
 
 prefilled_buildings(p2,
-   { "warehouse", 45, 40, wares = {log = 20,}, workers = {
-      carrier = 40,
-      builder = 2,
-      lumberjack = 10,
+   { "barbarians_warehouse", 45, 40, wares = {log = 20,}, workers = {
+      barbarians_carrier = 40,
+      barbarians_builder = 2,
+      barbarians_lumberjack = 10,
    }},
-   { "donjon", 14, 67, soldiers = {
+   { "barbarians_tower", 14, 67, soldiers = {
       [{0,0,0,0}] = 1,
       [{2,0,0,0}] = 1,
       [{3,1,0,0}] = 1,
    }},
-   { "donjon", 31, 65, soldiers = {
+   { "barbarians_tower", 31, 65, soldiers = {
       [{2,1,0,0}] = 2,
       [{1,0,0,0}] = 1,
    }},
-   { "donjon", 53, 17, soldiers = {
+   { "barbarians_tower", 53, 17, soldiers = {
       [{0,0,0,0}] = 2,
       [{2,1,0,0}] = 1,
    }},
-   { "barrier", 40, 24, soldiers = {
+   { "barbarians_barrier", 40, 24, soldiers = {
       [{2,0,0,0}] = 2,
       [{0,0,0,1}] = 1,
    }},
-   { "barrier", 39, 53, soldiers = {
+   { "barbarians_barrier", 39, 53, soldiers = {
       [{2,0,0,0}] = 4,
    }},
-   { "barrier", 50, 44, soldiers = {
+   { "barbarians_barrier", 50, 44, soldiers = {
       [{0,0,0,0}] = 2,
       [{0,1,0,1}] = 1,
       [{3,1,0,1}] = 1,
    }},
-   { "barrier", 26, 75, soldiers = {
+   { "barbarians_barrier", 26, 75, soldiers = {
       [{3,1,0,0}] = 3,
       [{0,0,0,0}] = 1,
    }},
-   { "barrier", 43, 44, soldiers = {
+   { "barbarians_barrier", 43, 44, soldiers = {
       [{0,0,0,0}] = 2,
    }},
-   { "barrier", 20, 71, soldiers = {
+   { "barbarians_barrier", 20, 71, soldiers = {
       [{0,1,0,1}] = 1,
       [{1,0,0,0}] = 1,
       [{0,0,0,0}] = 1,
    }},
-   { "barrier", 50, 30, soldiers = {
-      [{0,0,0,0}] = 1,
-   }},
-   { "sentry", 43, 29, soldiers = {
-      [{0,0,0,0}] = 2,
-   }},
-   { "sentry", 42, 9, soldiers = {
-      [{0,0,0,0}] = 1,
-   }},
-   { "sentry", 30, 76, soldiers = {
-      [{0,0,0,0}] = 2,
-   }},
-   { "citadel", 47, 13, soldiers = {
+   { "barbarians_barrier", 50, 30, soldiers = {
+      [{0,0,0,0}] = 1,
+   }},
+   { "barbarians_sentry", 43, 29, soldiers = {
+      [{0,0,0,0}] = 2,
+   }},
+   { "barbarians_sentry", 42, 9, soldiers = {
+      [{0,0,0,0}] = 1,
+   }},
+   { "barbarians_sentry", 30, 76, soldiers = {
+      [{0,0,0,0}] = 2,
+   }},
+   { "barbarians_citadel", 47, 13, soldiers = {
       [{0,0,0,0}] = 2,
       [{1,0,0,0}] = 1,
       [{1,1,0,0}] = 1,
       [{2,0,0,0}] = 2,
       [{3,1,0,0}] = 3,
    }},
-   { "fortress", 42, 72, soldiers = {
+   { "barbarians_fortress", 42, 72, soldiers = {
       [{0,0,0,0}] = 2,
       [{1,0,0,0}] = 1,
       [{1,1,0,0}] = 1,
       [{2,0,0,0}] = 2,
       [{3,1,0,0}] = 1,
    }},
-   { "high_tower.atlanteans", 52, 26, soldiers = {
+   { "atlanteans_tower_high", 52, 26, soldiers = {
       [{1,1,0,0}] = 1,
       [{2,0,0,0}] = 2,
       [{3,1,0,0}] = 1,
    }}
 )
 -- =======================================================================
---                                 Player 3                                 
+--                                 Player 3
 -- =======================================================================
 p3:forbid_buildings("all")
 p3:allow_buildings{
-   "lumberjacks_hut",
-   "charcoal_kiln",
-   "quarry",
-   "rangers_hut",
-   "hardener",
-   "lime_kiln",
-   "reed_yard",
-   "fishers_hut",
-   "well",
-   "tavern",
-   "hunters_hut",
-   "micro-brewery",
-   "farm",
-   "barrier",
-   "donjon",
-   "sentry",
+   "barbarians_lumberjacks_hut",
+   "barbarians_charcoal_kiln",
+   "barbarians_quarry",
+   "barbarians_rangers_hut",
+   "barbarians_wood_hardener",
+   "barbarians_lime_kiln",
+   "barbarians_reed_yard",
+   "barbarians_fishers_hut",
+   "barbarians_well",
+   "barbarians_tavern",
+   "barbarians_hunters_hut",
+   "barbarians_micro_brewery",
+   "barbarians_farm",
+   "barbarians_barrier",
+   "barbarians_tower",
+   "barbarians_sentry",
 }
 
-prefilled_buildings(p3, 
-   { "warehouse", 6, 44, wares = {
-         log = 200,
+prefilled_buildings(p3,
+   { "barbarians_warehouse", 6, 44, wares = {
+         coal = 40,
+         granite = 40,
          kitchen_tools = 4,
          pick = 14,
-         raw_stone = 40,
          scythe = 6,
          shovel = 4,
-         thatchreed = 24,
-         coal = 40,
-      }, 
+         thatch_reed = 24,
+         log = 200,
+      },
       workers = {
-         carrier = 40,
-         builder = 4,
-         lumberjack = 10,
-         charcoal_burner = 1,
-         brewer = 1,
-         farmer = 1,
-         gardener = 1,
-         fisher = 2,
-         geologist = 4,
-         ["lime-burner"] = 1,
-         ranger = 1,
-         hunter = 1,
-         gamekeeper = 1,
+         barbarians_carrier = 40,
+         barbarians_builder = 4,
+         barbarians_lumberjack = 10,
+         barbarians_charcoal_burner = 1,
+         barbarians_brewer = 1,
+         barbarians_farmer = 1,
+         barbarians_gardener = 1,
+         barbarians_fisher = 2,
+         barbarians_geologist = 4,
+         barbarians_lime_burner = 1,
+         barbarians_ranger = 1,
+         barbarians_hunter = 1,
+         barbarians_gamekeeper = 1,
       },
       soldiers = { [{0,0,0,0}] = 30 },
    },
-   { "barrier", 6, 51, soldiers = {
-      [{0,0,0,0}] = 2,
-      [{0,0,0,1}] = 1,
-   }},
-   { "tower.atlanteans", 79, 50, soldiers = {
-      [{0,0,0,0}] = 2,
-      [{0,0,0,1}] = 1,
-   }},
-   { "guardhouse.atlanteans", 7, 42, soldiers = {
-      [{0,0,0,0}] = 2,
-   }},
-   { "farm",  8, 48 },
-   { "farm",  4, 52 },
-   { "farm", 10, 49 }
+   { "barbarians_barrier", 6, 51, soldiers = {
+      [{0,0,0,0}] = 2,
+      [{0,0,0,1}] = 1,
+   }},
+   { "atlanteans_tower", 79, 50, soldiers = {
+      [{0,0,0,0}] = 2,
+      [{0,0,0,1}] = 1,
+   }},
+   { "atlanteans_guardhouse", 7, 42, soldiers = {
+      [{0,0,0,0}] = 2,
+   }},
+   { "barbarians_farm",  8, 48 },
+   { "barbarians_farm",  4, 52 },
+   { "barbarians_farm", 10, 49 }
 )
 
 -- =======================================================================
---                                 Player 4                                 
+--                                 Player 4
 -- =======================================================================
 p4:forbid_buildings("all")
-prefilled_buildings(p4, 
-   { "castle.atlanteans", 23, 19, soldiers = {
+prefilled_buildings(p4,
+   { "atlanteans_castle", 23, 19, soldiers = {
       [{0,0,0,0}] = 2,
       [{2,0,0,0}] = 2,
       [{0,1,0,0}] = 2,

=== modified file 'maps/Trident of Fire.wmf/scripting/initial_conditions.lua'
--- maps/Trident of Fire.wmf/scripting/initial_conditions.lua	2014-08-26 17:25:00 +0000
+++ maps/Trident of Fire.wmf/scripting/initial_conditions.lua	2015-10-18 20:57:50 +0000
@@ -3,97 +3,97 @@
 function init_human_player(player, f_hq, tribename)
 	player:allow_buildings("all")
 	if tribename == "barbarians" then
-			prefilled_buildings(player, 
-			{"headquarters_interim", f_hq.x, f_hq.y, 
+			prefilled_buildings(player,
+			{"barbarians_headquarters_interim", f_hq.x, f_hq.y,
 				wares = {
 					 log = 3,
 				},
 				workers = {
-					 blacksmith = 1,
-					 smelter = 1,
-					 builder = 2,
-					 carrier = 10,
-					 gardener = 1,
-					 geologist = 1,
-					 ["lime-burner"] = 1,
-					 lumberjack = 3,
-					 miner = 2,
-					 ranger = 2,
-					 stonemason = 1,
-					 hunter = 1,
-					 farmer = 1,
-					 fisher = 1,
-					 baker = 1,
-					 innkeeper = 1,
-					 charcoal_burner = 1
+					 barbarians_blacksmith = 1,
+					 barbarians_smelter = 1,
+					 barbarians_builder = 2,
+					 barbarians_carrier = 10,
+					 barbarians_gardener = 1,
+					 barbarians_geologist = 1,
+					 barbarians_lime_burner = 1,
+					 barbarians_lumberjack = 3,
+					 barbarians_miner = 2,
+					 barbarians_ranger = 2,
+					 barbarians_stonemason = 1,
+					 barbarians_hunter = 1,
+					 barbarians_farmer = 1,
+					 barbarians_fisher = 1,
+					 barbarians_baker = 1,
+					 barbarians_innkeeper = 1,
+					 barbarians_charcoal_burner = 1
 				},
 				soldiers = {
-					[{0,0,0,0}] = 3,		
+					[{0,0,0,0}] = 3,
 				}
 			}
 		)
 	end
 	if tribename == "empire" then
-		prefilled_buildings(player, { "headquarters_shipwreck", f_hq.x, f_hq.y,
+		prefilled_buildings(player, { "empire_headquarters_shipwreck", f_hq.x, f_hq.y,
 		wares = {
 			log = 2,
-			wood = 3,
+			planks = 3,
 		},
 		workers = {
-			 baker = 1,
-			 brewer = 2,
-			 builder = 2,
-			 carpenter = 1,
-			 carrier = 10,
-			 charcoal_burner = 1,
-			 farmer = 1,
-			 fisher = 1,
-			 forester = 2,
-			 geologist = 1,
-			 hunter = 1,
-			 innkeeper = 1,
-			 lumberjack = 2,
-			 miller = 1,
-			 miner = 3,
-			 smelter = 1,
-			 stonemason = 2,
-			 toolsmith = 1,
-			 vinefarmer =1
+			 empire_baker = 1,
+			 empire_brewer = 2,
+			 empire_builder = 2,
+			 empire_carpenter = 1,
+			 empire_carrier = 10,
+			 empire_charcoal_burner = 1,
+			 empire_farmer = 1,
+			 empire_fisher = 1,
+			 empire_forester = 2,
+			 empire_geologist = 1,
+			 empire_hunter = 1,
+			 empire_innkeeper = 1,
+			 empire_lumberjack = 2,
+			 empire_miller = 1,
+			 empire_miner = 3,
+			 empire_smelter = 1,
+			 empire_stonemason = 2,
+			 empire_toolsmith = 1,
+			 empire_vinefarmer =1
 		  },
 		  soldiers = {
 			 [{0,0,0,0}] = 3,
 		  }
 	   })
 
-	end		
+	end
 	if tribename == "atlanteans" then
-	    prefilled_buildings(player, { "headquarters", f_hq.x, f_hq.y,
+	    prefilled_buildings(player, { "atlanteans_headquarters", f_hq.x, f_hq.y,
 		    wares = {
 				log = 2,
 				planks = 2,
 				spidercloth = 1
 			},
 			workers = {
-				 baker = 1,          
-				 blackroot_farmer = 1,
-				 builder = 2,
-				 carrier = 10,
-				 charcoal_burner = 1,
-				 farmer = 1,
-				 fisher = 1,
-				 forester = 2,
-				 geologist = 1,
-				 hunter = 1,
-				 miller = 1,
-				 miner = 6,
-				 sawyer = 1,
-				 smelter = 1,
-				 smoker = 1,
-				 spiderbreeder = 1,
-				 stonecutter = 1,
-				 toolsmith = 1,
-				 woodcutter = 2,
-				 weaver = 1
+				 atlanteans_baker = 1,
+				 atlanteans_blackroot_farmer = 1,
+				 atlanteans_builder = 2,
+				 atlanteans_carrier = 10,
+				 atlanteans_charcoal_burner = 1,
+				 atlanteans_farmer = 1,
+				 atlanteans_fisher = 1,
+				 atlanteans_forester = 2,
+				 atlanteans_geologist = 1,
+				 atlanteans_hunter = 1,
+				 atlanteans_miller = 1,
+				 atlanteans_miner = 6,
+				 atlanteans_sawyer = 1,
+				 atlanteans_smelter = 1,
+				 atlanteans_smoker = 1,
+				 atlanteans_spiderbreeder = 1,
+				 atlanteans_stonecutter = 1,
+				 atlanteans_toolsmith = 1,
+				 atlanteans_woodcutter = 2,
+				 atlanteans_weaver = 1
 			},
 			soldiers = {
 				[{0,0,0,0}] = 3,
@@ -106,9 +106,9 @@
 function init_AI_player(player, f_hq, f_port, f_vineyard, f_shipyard, tribename)
 	if tribename == "barbarians" then
 		player:allow_buildings("all")
-		
-		prefilled_buildings(player, 
-			{ "port", f_hq.x, f_hq.y, 
+
+		prefilled_buildings(player,
+			{ "barbarians_port", f_hq.x, f_hq.y,
 			   wares = {
 				  ax = 6,
 				  bread_paddle = 2,
@@ -119,59 +119,59 @@
 				  hammer = 12,
 				  hunting_spear = 2,
 				  iron = 12,
-				  ironore = 5,
+				  iron_ore = 5,
 				  kitchen_tools = 4,
 				  meal = 4,
 				  meat = 6,
 				  pick = 14,
-				  pittabread = 8,
+				  barbarians_bread = 8,
 				  ration = 12,
-				  raw_stone = 80,
+				  granite = 80,
 				  scythe = 6,
 				  shovel = 4,
 				  snack = 3,
-				  thatchreed = 24,
+				  thatch_reed = 24,
 				  log = 150,
 			   },
 			   workers = {
-				  carrier = 40,
-				  blacksmith = 2,
-				  brewer = 1,
-				  builder = 10,
-				  gardener = 1,
-				  fisher = 2,
-				  geologist = 4,
-				  ["lime-burner"] = 1,
-				  lumberjack = 3,
-				  miner = 4,
-				  ranger = 1,
-				  stonemason = 2,
-				  ox = 20, 
+				  barbarians_carrier = 40,
+				  barbarians_blacksmith = 2,
+				  barbarians_brewer = 1,
+				  barbarians_builder = 10,
+				  barbarians_gardener = 1,
+				  barbarians_fisher = 2,
+				  barbarians_geologist = 4,
+				  barbarians_lime_burner = 1,
+				  barbarians_lumberjack = 3,
+				  barbarians_miner = 4,
+				  barbarians_ranger = 1,
+				  barbarians_stonemason = 2,
+				  barbarians_ox = 20,
 			   },
 			   soldiers = { [{0,0,0,0}] = 45 },
 			},
-			{ "port", f_port.x, f_port.y},
-			{ "shipyard", f_shipyard.x, f_shipyard.y, wares = {
+			{ "barbarians_port", f_port.x, f_port.y},
+			{ "barbarians_shipyard", f_shipyard.x, f_shipyard.y, wares = {
 				  blackwood = 10,
 				  cloth = 4,
 				  log = 2,
 			   },
 		 }
 		)
-	end	
-		
+	end
+
 	if tribename == "empire" then
 		player:allow_buildings("all")
 
-		prefilled_buildings(player, 
-			{ "port", f_hq.x, f_hq.y, 
+		prefilled_buildings(player,
+			{ "empire_port", f_hq.x, f_hq.y,
 			   wares = {
-				 helm = 4,
-				 wood_lance = 5,
-				 ax = 6,
+				 armor_helmet = 4,
+				 spear_wooden = 5,
+				 felling_ax = 6,
 				 bread_paddle = 2,
 				 basket = 2,
-				 bread = 8,
+				 empire_bread = 8,
 				 cloth = 5,
 				 coal = 12,
 				 fire_tongs = 2,
@@ -183,10 +183,10 @@
 				 hammer = 14,
 				 hunting_spear = 2,
 				 iron = 12,
-				 ironore = 5,
+				 iron_ore = 5,
 				 kitchen_tools = 4,
 				 marble = 60,
-				 marblecolumn = 6,
+				 marble_column = 6,
 				 meal = 4,
 				 meat = 6,
 				 pick = 14,
@@ -194,71 +194,71 @@
 				 saw = 2,
 				 scythe = 5,
 				 shovel = 6,
-				 stone = 50,
+				 granite = 50,
 				 log = 40,
 				 water = 12,
 				 wheat = 4,
 				 wine = 8,
-				 wood = 45,
+				 planks = 45,
 				 wool = 2,
 			   },
 			   workers = {
-				 armorsmith = 1,
-				 brewer = 1,
-				 builder = 10,
-				 carrier = 40,
-				 charcoal_burner = 1,
-				 geologist = 4,
-				 lumberjack = 3,
-				 miner = 4,
-				 ["master-miner"] = 1,
-				 stonemason = 2,
-				 toolsmith = 2,
-				 weaponsmith = 1,
-				 donkey = 5,
+				 empire_armorsmith = 1,
+				 empire_brewer = 1,
+				 empire_builder = 10,
+				 empire_carrier = 40,
+				 empire_charcoal_burner = 1,
+				 empire_geologist = 4,
+				 empire_lumberjack = 3,
+				 empire_miner = 4,
+				 empire_miner_master = 1,
+				 empire_stonemason = 2,
+				 empire_toolsmith = 2,
+				 empire_weaponsmith = 1,
+				 empire_donkey = 5,
 			   },
 			   soldiers = { [{0,0,0,0}] = 45 },
 			},
-			{ "port", f_port.x, f_port.y},
-			{ "shipyard", f_shipyard.x, f_shipyard.y, 
+			{ "empire_port", f_port.x, f_port.y},
+			{ "empire_shipyard", f_shipyard.x, f_shipyard.y,
 			   wares = {
 				 cloth = 4,
 				 log = 2,
-				 wood = 10,
+				 planks = 10,
 			   }
 		   },
-		   { "vineyard", f_vineyard.x, f_vineyard.y}
+		   { "empire_vineyard", f_vineyard.x, f_vineyard.y}
 		)
 	end
 	if tribename == "atlanteans" then
 		player:allow_buildings("all")
 
-		prefilled_buildings(player, { "port", f_hq.x, f_hq.y, 
+		prefilled_buildings(player, { "atlanteans_port", f_hq.x, f_hq.y,
 		   wares = {
 			 diamond = 7,
-			 ironore = 5,
+			 iron_ore = 5,
 			 quartz = 9,
-			 stone = 50,
-			 spideryarn = 9,
+			 granite = 50,
+			 spider_silk = 9,
 			 log = 100,
 			 coal = 12,
 			 gold = 4,
-			 goldyarn = 6,
+			 gold_thread = 6,
 			 iron = 8,
 			 planks = 50,
 			 spidercloth = 5,
 			 blackroot = 5,
-			 blackrootflour = 12,
-			 bread = 8,
+			 blackroot_flour = 12,
+			 atlanteans_bread = 8,
 			 corn = 5,
-			 cornflour = 12,
+			 cornmeal = 12,
 			 fish = 3,
 			 meat = 3,
 			 smoked_fish = 6,
 			 smoked_meat = 6,
 			 water = 12,
 			 bread_paddle = 2,
-			 bucket = 2,
+			 buckets = 2,
 			 fire_tongs = 2,
 			 fishing_net = 4,
 			 hammer = 11,
@@ -270,34 +270,34 @@
 			 scythe = 4,
 			 shovel = 9,
 			 tabard = 5,
-			 light_trident = 5,
+			 trident_light = 5,
 		   },
 		   workers = {
-			 armorsmith = 1,
-			 blackroot_farmer = 1,
-			 builder = 10,
-			 carrier = 40,
-			 charcoal_burner = 1,
-			 fish_breeder = 1,
-			 geologist = 4,
-			 miner = 4,
-			 sawyer = 1,
-			 stonecutter = 2,
-			 toolsmith = 2,
-			 weaponsmith = 1,
-			 woodcutter = 3,
-			 horse = 5,
+			 atlanteans_armorsmith = 1,
+			 atlanteans_blackroot_farmer = 1,
+			 atlanteans_builder = 10,
+			 atlanteans_carrier = 40,
+			 atlanteans_charcoal_burner = 1,
+			 atlanteans_fishbreeder = 1,
+			 atlanteans_geologist = 4,
+			 atlanteans_miner = 4,
+			 atlanteans_sawyer = 1,
+			 atlanteans_stonecutter = 2,
+			 atlanteans_toolsmith = 2,
+			 atlanteans_weaponsmith = 1,
+			 atlanteans_woodcutter = 3,
+			 atlanteans_horse = 5,
 		   },
 		   soldiers = { [{0,0,0,0}] = 45 },
 			},
-			{ "port", f_port.x, f_port.y},
-		   { "shipyard", f_shipyard.x, f_shipyard.y, wares = {
+			{ "atlanteans_port", f_port.x, f_port.y},
+		   { "atlanteans_shipyard", f_shipyard.x, f_shipyard.y, wares = {
 			  planks = 10,
 			  spidercloth = 4,
 			  log = 2,
 		   }}
 		)
-	end	
+	end
 	return true
 end
 

=== modified file 'maps/Trident of Fire.wmf/scripting/map_editing.lua'
--- maps/Trident of Fire.wmf/scripting/map_editing.lua	2014-04-26 13:55:11 +0000
+++ maps/Trident of Fire.wmf/scripting/map_editing.lua	2015-10-18 20:57:50 +0000
@@ -7,9 +7,9 @@
 			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("aspen_summer_sapling", map:get_field(field.x,field.y))
+						map:place_immovable("aspen_summer_sapling", map:get_field(field.x,field.y), "world")
 					else
-						map:place_immovable("oak_summer_sapling", map:get_field(field.x,field.y))
+						map:place_immovable("oak_summer_sapling", map:get_field(field.x,field.y), "world")
 					end
 					sleep(750)
 				end

=== renamed directory 'po/tribes' => 'po/help'
=== renamed file 'po/tribes/tribes.pot' => 'po/help/help.pot'
=== modified file 'scripting/formatting.lua'
--- scripting/formatting.lua	2015-05-11 16:49:40 +0000
+++ scripting/formatting.lua	2015-10-18 20:57:50 +0000
@@ -6,6 +6,44 @@
 -- Most of these functions are simple wrapper functions that make working with
 -- widelands rich text formatting system more bearable.
 
+
+-- RST
+-- .. function:: localize_list(items, listtype)
+--
+--    Turns an array of string items into a localized string list with
+--    appropriate concatenation.
+--
+--    e.g. localize_list({"foo", "bar", baz"}, "or") will return _"foo, bar or baz"
+--
+--    :arg items:    An array of strings
+--    :arg listtype: The type of concatenation to use.
+--                   Legal values are "&", "and", "or", and ";"
+--    :returns: The concatenated list string, using localized concatenation operators.
+--
+-- Same algorithm as in src/base/i18n
+function localize_list(items, listtype)
+	local result = ""
+	for i, item in pairs(items) do
+		if (i == 1) then
+			result = item
+		elseif (i == #items) then
+			if (listtype == "&") then
+				result = _"%1$s & %2$s":bformat(result, item)
+			elseif (listtype == "or") then
+				result = _"%1$s or %2$s":bformat(result, item)
+			elseif (listtype == ",") then
+				result = _"%1$s, %2$s":bformat(result, item)
+			else
+				result = _"%1$s and %2$s":bformat(result, item)
+		end
+		else
+			result = _"%1$s, %2$s":bformat(result, item)
+		end
+	end
+	return result
+end
+
+
 -- RST
 -- .. function:: rt(text_or_options[, text = nil])
 --

=== modified file 'scripting/infrastructure.lua'
--- scripting/infrastructure.lua	2014-07-16 21:01:34 +0000
+++ scripting/infrastructure.lua	2015-10-18 20:57:50 +0000
@@ -47,7 +47,7 @@
          r = p:place_road(start, table.unpack(moves))
          start = r.end_flag
          if create_carriers then
-            r:set_workers("carrier", 1)
+            r:set_workers(p.tribe.carrier, 1)
          end
          moves = {}
       end
@@ -89,6 +89,7 @@
 --          :meth:`wl.map.Warehouse.set_workers`.  Note that ProductionSites
 --          are filled with workers by default.
 --    :type b1_descr: :class:`array`
+-- TODO(GunChleoc) this should produce an error message if a building/ware/worker doesn't exist.
 function prefilled_buildings(p, ...)
    for idx,bdescr in ipairs({...}) do
       b = p:place_building(bdescr[1], wl.Game().map:get_field(bdescr[2],bdescr[3]), false, true)

=== modified file 'scripting/win_conditions/collectors.lua'
--- scripting/win_conditions/collectors.lua	2015-08-06 07:18:24 +0000
+++ scripting/win_conditions/collectors.lua	2015-10-18 20:57:50 +0000
@@ -43,53 +43,53 @@
       barbarians = {
          gold = 3,
          ax = 2,
-         sharpax = 3,
-         broadax = 4,
-         bronzeax = 4,
-         battleax = 6,
-         warriorsax = 10,
-         helm = 2,
-         mask = 3,
-         warhelm = 6,
+         ax_sharp = 3,
+         ax_broad = 4,
+         ax_bronze = 4,
+         ax_battle = 6,
+         ax_warriors = 10,
+         helmet = 2,
+         helmet_mask = 3,
+         helmet_warhelm = 6,
       },
       barbarians_order = {
-         "gold", "ax", "sharpax", "broadax", "bronzeax", "battleax",
-         "warriorsax", "helm", "mask", "warhelm",
+         "gold", "ax", "ax_sharp", "ax_broad", "ax_bronze", "ax_battle",
+         "ax_warriors", "helmet", "helmet_mask", "helmet_warhelm",
       },
 
       empire = {
          gold = 3,
-         wood_lance = 1,
-         lance = 3,
-         advanced_lance = 4,
-         heavy_lance = 7,
-         war_lance = 8,
-         helm = 2,
+         spear_wooden = 1,
+         spear = 3,
+         spear_advanced = 4,
+         spear_heavy = 7,
+         spear_war = 8,
+         armor_helmet = 2,
          armor = 3,
-         chain_armor = 4,
-         plate_armor = 8,
+         armor_chain = 4,
+         armor_gilded = 8,
       },
       empire_order = {
-         "gold", "wood_lance", "lance", "advanced_lance", "heavy_lance",
-         "war_lance", "helm", "armor", "chain_armor", "plate_armor"
+         "gold", "spear_wooden", "spear", "spear_advanced", "spear_heavy",
+         "spear_war", "armor_helmet", "armor", "armor_chain", "armor_gilded"
       },
 
       atlanteans = {
          gold = 3,
-         light_trident = 2,
-         long_trident = 3,
-         steel_trident = 4,
-         double_trident = 7,
-         heavy_double_trident = 8,
-         steel_shield = 4,
-         advanced_shield = 7,
+         trident_light = 2,
+         trident_long = 3,
+         trident_steel = 4,
+         trident_double = 7,
+         trident_heavy_double = 8,
+         shield_steel = 4,
+         shield_advanced = 7,
          tabard = 1,
-         golden_tabard = 5,
+         tabard_golden = 5,
       },
       atlanteans_order = {
-         "gold", "light_trident", "long_trident", "steel_trident",
-         "double_trident", "heavy_double_trident", "steel_shield",
-         "advanced_shield", "tabard", "golden_tabard"
+         "gold", "trident_light", "trident_long", "trident_steel",
+         "trident_double", "trident_heavy_double", "shield_steel",
+         "shield_advanced", "tabard", "tabard_golden"
        },
    }
 
@@ -97,7 +97,7 @@
    local function _calc_points(plr)
       set_textdomain("win_conditions")
       local bs = array_combine(
-         plr:get_buildings("headquarters"), plr:get_buildings("warehouse"), plr:get_buildings("port")
+         plr:get_buildings(plr.tribe_name .. "_headquarters"), plr:get_buildings(plr.tribe_name .. "_warehouse"), plr:get_buildings(plr.tribe_name .. "_port")
       )
 
       local points = 0
@@ -110,8 +110,9 @@
          end
          local lpoints = count * value
          points = points + lpoints
-         local warename = wl.Game():get_ware_description(plr.tribe_name, ware).descname
-         -- TRANSLATORS: For example: 'gold (3 P) x 4 = 12 P", P meaning "Points'
+
+         local warename = wl.Game():get_ware_description(ware).descname
+         -- TRANSLATORS: For example: 'gold (3 P) x 4 = 12 P', P meaning 'Points'
          descr[#descr+1] = listitem_bullet(_"%1$s (%2$i P) x %3$i = %4$i P"):bformat(
             warename, value, count, lpoints
          )

=== modified file 'src/ai/CMakeLists.txt'
--- src/ai/CMakeLists.txt	2014-07-16 08:23:42 +0000
+++ src/ai/CMakeLists.txt	2015-10-18 20:57:50 +0000
@@ -10,9 +10,8 @@
     defaultai.h
   DEPENDS
     base_macros
-    economy
     base_log
-    profile
     base_i18n
     logic
+    scripting_lua_table
 )

=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2015-08-19 19:29:56 +0000
+++ src/ai/ai_help_structs.h	2015-10-18 20:57:50 +0000
@@ -241,7 +241,7 @@
 	bool near_border_;
 	uint8_t unowned_mines_pots_nearby_;
 	uint8_t trees_nearby_;
-	uint8_t stones_nearby_;
+	uint8_t rocks_nearby_;
 	int16_t water_nearby_;
 	int16_t distant_water_;
 	int8_t fish_nearby_;
@@ -284,11 +284,11 @@
 	     // explanation of starting values
 	     // this is done to save some work for AI (CPU utilization)
 	     // base rules are:
-	     // count of stones can only decrease, so  amount of stones
+		  // count of rocks can only decrease, so  amount of rocks
 	     // is recalculated only when previous count is positive
 	     // count of water fields are stable, so if the current count is
 	     // non-negative, water is not recaldulated
-	     stones_nearby_(1),
+	     rocks_nearby_(1),
 	     water_nearby_(-1),
 	     distant_water_(0),
 	     fish_nearby_(-1),
@@ -357,7 +357,7 @@
 	bool recruitment_;  // is "producing" workers?
 	bool is_buildable_;
 	bool need_trees_;   // lumberjack = true
-	bool need_stones_;  // quarry = true
+	bool need_rocks_;  // quarry = true
 	bool mines_water_;  // wells
 	bool need_water_;   // fisher, fish_breeder = true
 	bool is_hunter_;    // need to identify hunters

=== modified file 'src/ai/ai_hints.cc'
--- src/ai/ai_hints.cc	2015-05-07 20:46:32 +0000
+++ src/ai/ai_hints.cc	2015-10-18 20:57:50 +0000
@@ -19,39 +19,34 @@
 
 #include "ai/ai_hints.h"
 
-#include "profile/profile.h"
-
-BuildingHints::BuildingHints(Section* const section)
-   : log_producer_(section ? section->get_bool("logproducer") : false),
-     stone_producer_(section ? section->get_bool("stoneproducer") : false),
-     needs_water_(section ? section->get_bool("needs_water") : false),
-     mines_water_(section ? section->get_bool("mines_water") : false),
-     recruitment_(section ? section->get_bool("recruitment") : false),
-     space_consumer_(section ? section->get_bool("space_consumer") : false),
-     expansion_(section ? section->get_bool("expansion") : false),
-     fighting_(section ? section->get_bool("fighting") : false),
-     mountain_conqueror_(section ? section->get_bool("mountain_conqueror") : false),
-     prohibited_till_(section ? section->get_natural("prohibited_till", 0) : 0),
-     forced_after_(section ? section->get_natural("forced_after", 864000) : 0),  // 10 days default
-     mines_percent_(section ? section->get_int("mines_percent", 100) : 0),
-     trainingsite_type_(TrainingSiteType::kNoTS)
-
-{
-	if (section) {
-		if (section->has_val("renews_map_resource"))
-			renews_map_resource_ = section->get_string("renews_map_resource");
-		if (section->has_val("mines"))
-			mines_ = section->get_string("mines");
-	}
-	if (section) {
-		if (!section->has_val("trainingsite_type")) {
-			trainingsite_type_ =  TrainingSiteType::kNoTS;
-		} else {
-			if (!strcmp(section->get_string("trainingsite_type", "basic"), "basic")) {
-				trainingsite_type_ =  TrainingSiteType::kBasic;
-			} else {
-				trainingsite_type_ =  TrainingSiteType::kAdvanced;
-			}
+#include <memory>
+
+BuildingHints::BuildingHints(std::unique_ptr<LuaTable> table)
+	: renews_map_resource_(table->has_key("renews_map_resource") ?
+									  table->get_string("renews_map_resource") : ""),
+	  mines_(table->has_key("mines") ? table->get_string("mines") : ""),
+	  log_producer_(table->has_key("logproducer") ? table->get_bool("logproducer") : false),
+	  granite_producer_(table->has_key("graniteproducer") ? table->get_bool("graniteproducer") : false),
+	  needs_water_(table->has_key("needs_water") ? table->get_bool("needs_water") : false),
+	  mines_water_(table->has_key("mines_water") ? table->get_bool("mines_water") : false),
+	  recruitment_(table->has_key("recruitment") ? table->get_bool("recruitment") : false),
+	  space_consumer_(table->has_key("space_consumer") ? table->get_bool("space_consumer") : false),
+	  expansion_(table->has_key("expansion") ? table->get_bool("expansion") : false),
+	  fighting_(table->has_key("fighting") ? table->get_bool("fighting") : false),
+	  mountain_conqueror_(table->has_key("mountain_conqueror") ?
+									 table->get_bool("mountain_conqueror") : false),
+	  shipyard_(table->has_key("shipyard") ? table->get_bool("shipyard") : false),
+	  prohibited_till_(table->has_key("prohibited_till") ? table->get_int("prohibited_till") : 0),
+	  // 10 days default
+	  forced_after_(table->has_key("forced_after") ? table->get_int("forced_after") : 864000),
+	  mines_percent_(table->has_key("mines_percent") ? table->get_int("mines_percent") : 100),
+	  trainingsite_type_(TrainingSiteType::kNoTS) {
+
+	if (table->has_key("trainingsite_type")) {
+		if (table->get_string("trainingsite_type") == "basic") {
+			trainingsite_type_ =  TrainingSiteType::kBasic;
+		} else if (table->get_string("trainingsite_type") == "advanced") {
+			trainingsite_type_ =  TrainingSiteType::kAdvanced;
 		}
 	}
 }

=== modified file 'src/ai/ai_hints.h'
--- src/ai/ai_hints.h	2015-03-26 06:59:37 +0000
+++ src/ai/ai_hints.h	2015-10-18 20:57:50 +0000
@@ -20,11 +20,13 @@
 #ifndef WL_AI_AI_HINTS_H
 #define WL_AI_AI_HINTS_H
 
+#include <memory>
 #include <stdint.h>
 #include <string>
 
+#include "base/log.h"
 #include "base/macros.h"
-#include "base/log.h"
+#include "scripting/lua_table.h"
 
 class Section;
 
@@ -34,7 +36,8 @@
 /// buildings conf file. It is used to tell the computer player about the
 /// special properties of a building.
 struct BuildingHints {
-	BuildingHints(Section*);
+	BuildingHints(std::unique_ptr<LuaTable>);
+	~BuildingHints() {}
 
 	bool renews_map_resource() const {
 		return !renews_map_resource_.empty();
@@ -56,8 +59,8 @@
 		return log_producer_;
 	}
 
-	bool is_stoneproducer() const {
-		return stone_producer_;
+	bool is_graniteproducer() const {
+		return granite_producer_;
 	}
 
 	bool mines_water() const {
@@ -85,6 +88,10 @@
 		return mountain_conqueror_;
 	}
 
+	bool is_shipyard() const {
+		return shipyard_;
+	}
+
 	uint32_t get_prohibited_till() const {
 		return prohibited_till_;
 	}
@@ -105,7 +112,7 @@
 	std::string renews_map_resource_;
 	std::string mines_;
 	bool log_producer_;
-	bool stone_producer_;
+	bool granite_producer_;
 	bool needs_water_;
 	bool mines_water_;
 	bool recruitment_;  // whether building recruits special workers
@@ -113,6 +120,7 @@
 	bool expansion_;
 	bool fighting_;
 	bool mountain_conqueror_;
+	bool shipyard_;
 	int32_t prohibited_till_;
 	int32_t forced_after_;
 	uint8_t mines_percent_;

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2015-08-28 19:09:59 +0000
+++ src/ai/defaultai.cc	2015-10-18 20:57:50 +0000
@@ -46,10 +46,10 @@
 #include "logic/ship.h"
 #include "logic/soldier.h"
 #include "logic/trainingsite.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
+#include "logic/tribes/tribes.h"
 #include "logic/warehouse.h"
 #include "logic/world/world.h"
-#include "profile/profile.h"
 
 // following is in miliseconds (widelands counts time in ms)
 // constexpr int kFieldUpdateInterval = 2000;
@@ -385,27 +385,30 @@
 	player_ = game().get_player(player_number());
 	tribe_ = &player_->tribe();
 	log("ComputerPlayer(%d): initializing (%u)\n", player_number(), type_);
-	WareIndex const nr_wares = tribe_->get_nrwares();
-	wares.resize(nr_wares);
 
-	for (WareIndex i = 0; i < nr_wares; ++i) {
+	wares.resize(game().tribes().nrwares());
+	for (WareIndex i = 0; i < static_cast<WareIndex>(game().tribes().nrwares()); ++i) {
 		wares.at(i).producers_ = 0;
 		wares.at(i).consumers_ = 0;
-		wares.at(i).preciousness_ = tribe_->get_ware_descr(i)->preciousness();
+		wares.at(i).preciousness_ = game().tribes().get_ware_descr(i)->preciousness(tribe_->name());
 	}
 
-	// collect information about the different buildings our tribe can construct
-	BuildingIndex const nr_buildings = tribe_->get_nrbuildings();
-	const World& world = game().world();
-
-	for (BuildingIndex i = 0; i < nr_buildings; ++i) {
-		const BuildingDescr& bld = *tribe_->get_building_descr(i);
+	const BuildingIndex& nr_buildings = game().tribes().nrbuildings();
+
+
+	// Collect information about the different buildings that our tribe can have
+	for (BuildingIndex building_index = 0; building_index < nr_buildings; ++building_index) {
+		const BuildingDescr& bld = *tribe_->get_building_descr(building_index);
+		if (!tribe_->has_building(building_index) && bld.type() != MapObjectType::MILITARYSITE) {
+			continue;
+		}
+
 		const std::string& building_name = bld.name();
 		const BuildingHints& bh = bld.hints();
 		buildings_.resize(buildings_.size() + 1);
 		BuildingObserver& bo = buildings_.back();
 		bo.name = building_name.c_str();
-		bo.id = i;
+		bo.id = building_index;
 		bo.desc = &bld;
 		bo.type = BuildingObserver::BORING;
 		bo.cnt_built_ = 0;
@@ -424,7 +427,7 @@
 		bo.unconnected_ = 0;
 		bo.is_buildable_ = bld.is_buildable();
 		bo.need_trees_ = bh.is_logproducer();
-		bo.need_stones_ = bh.is_stoneproducer();
+		bo.need_rocks_ = bh.is_graniteproducer();
 		bo.need_water_ = bh.get_needs_water();
 		bo.mines_water_ = bh.mines_water();
 		bo.recruitment_ = bh.for_recruitment();
@@ -466,7 +469,7 @@
 			if (bo.type == BuildingObserver::MINE) {
 				// get the resource needed by the mine
 				if (bh.get_mines()) {
-					bo.mines_ = world.get_resource(bh.get_mines());
+					bo.mines_ = game().world().get_resource(bh.get_mines());
 				}
 
 				bo.mines_percent_ = bh.get_mines_percent();
@@ -491,11 +494,7 @@
 				bo.is_fisher_ = false;
 			}
 
-			if (building_name == "shipyard") {
-				bo.is_shipyard_ = true;
-			} else {
-				bo.is_shipyard_ = false;
-			}
+			bo.is_shipyard_ = bh.is_shipyard();
 
 			// now we find out if the upgrade of the building is a full substitution
 			// (produces all wares as current one)
@@ -543,9 +542,7 @@
 				if (tribe_->ware_index("log") == temp_buildcosts.first ||
 				    tribe_->ware_index("blackwood") == temp_buildcosts.first ||
 				    tribe_->ware_index("planks") == temp_buildcosts.first ||
-				    tribe_->ware_index("wood") == temp_buildcosts.first ||
-				    tribe_->ware_index("raw_stone") == temp_buildcosts.first ||
-				    tribe_->ware_index("stone") == temp_buildcosts.first)
+				    tribe_->ware_index("granite") == temp_buildcosts.first)
 					continue;
 
 				bo.critical_built_mat_.push_back(temp_buildcosts.first);
@@ -589,7 +586,7 @@
 
 
 	// atlanteans they consider water as a resource
-	// (together with mines, stones and wood)
+	// (together with mines, rocks and wood)
 	if (tribe_->name() == "atlanteans") {
 		resource_necessity_water_needed_ = true;
 	}
@@ -992,16 +989,16 @@
 			}
 		}
 
-		// stones are not renewable, we will count them only if previous state is nonzero
-		if (field.stones_nearby_ > 0 && gametime % 3 == 0) {
+		// Rocks are not renewable, we will count them only if previous state is nonzero
+		if (field.rocks_nearby_ > 0 && gametime % 3 == 0) {
 
-			field.stones_nearby_ =
+			field.rocks_nearby_ =
 				map.find_immovables(Area<FCoords>(map.get_fcoords(field.coords), 6),
 					nullptr,
-		            FindImmovableAttribute(MapObjectDescr::get_attribute_id("granite")));
+						FindImmovableAttribute(MapObjectDescr::get_attribute_id("rocks")));
 
-			// adding 10 if stones found
-			field.stones_nearby_ = (field.stones_nearby_ > 0) ? field.stones_nearby_ + 10:0;
+			// adding 10 if rocks found
+			field.rocks_nearby_ = (field.rocks_nearby_ > 0) ? field.rocks_nearby_ + 10:0;
 		}
 
 		// ground water is not renewable and its amount can only fall, we will count them only if
@@ -1140,10 +1137,10 @@
 	uint16_t fishers_count = 0;  // used for atlanteans only
 
 	// Reset statistics for all buildings
-	for (uint32_t i = 0; i < buildings_.size(); ++i) {
-		buildings_.at(i).current_stats_ = 0;
-		buildings_.at(i).unoccupied_ = false;
-		buildings_.at(i).unconnected_ = 0;
+	for (BuildingObserver& bo : buildings_) {
+		bo.current_stats_ = 0;
+		bo.unoccupied_ = false;
+		bo.unconnected_ = 0;
 	}
 
 	// Check all available productionsites
@@ -1210,10 +1207,10 @@
 	}
 
 	// Scale statistics down
-	for (uint32_t i = 0; i < buildings_.size(); ++i) {
-		if ((buildings_.at(i).cnt_built_ - buildings_.at(i).unconnected_) > 0) {
-			buildings_.at(i).current_stats_ /=
-			   (buildings_.at(i).cnt_built_ - buildings_.at(i).unconnected_);
+	for (BuildingObserver& bo : buildings_) {
+		if ((bo.cnt_built_ - bo.unconnected_) > 0) {
+			bo.current_stats_ /=
+				(bo.cnt_built_ - bo.unconnected_);
 		}
 	}
 }
@@ -1385,9 +1382,7 @@
 	// testing big military buildings, whether critical construction
 	// material is available (at least in amount of
 	// 2/3 of default target amount)
-	for (uint32_t j = 0; j < buildings_.size(); ++j) {
-
-		BuildingObserver& bo = buildings_.at(j);
+	for (BuildingObserver& bo : buildings_) {
 		if (!bo.buildable(*player_)) {
 			continue;
 		}
@@ -1413,8 +1408,7 @@
 	}
 
 	//Resetting output_needed_ in building observer
-	for (uint32_t j = 0; j < buildings_.size(); ++j) {
-		BuildingObserver& bo = buildings_.at(j);
+	for (BuildingObserver& bo : buildings_) {
 		if (bo.type == BuildingObserver::PRODUCTIONSITE || bo.type == BuildingObserver::MINE){
 			bo.output_needed_ = ExtendedBool::kUnset;
 		}
@@ -1449,9 +1443,7 @@
 		int32_t const maxsize = player_->get_buildcaps(bf->coords) & BUILDCAPS_SIZEMASK;
 
 		// For every field test all buildings
-		for (uint32_t j = 0; j < buildings_.size(); ++j) {
-			BuildingObserver& bo = buildings_.at(j);
-
+		for (BuildingObserver& bo : buildings_) {
 			if (!bo.buildable(*player_)) {
 				continue;
 			}
@@ -1499,7 +1491,7 @@
 			if (bo.type == BuildingObserver::PRODUCTIONSITE) {
 
 				// exclude spots on border
-				if (bf->near_border_ && !bo.need_trees_ && !bo.need_stones_ && !bo.is_fisher_) {
+				if (bf->near_border_ && !bo.need_trees_ && !bo.need_rocks_ && !bo.is_fisher_) {
 					continue;
 				}
 
@@ -1578,15 +1570,15 @@
 						}
 					}
 
-				} else if (bo.need_stones_) {
+				} else if (bo.need_rocks_) {
 
-					// quaries are generally to be built everywhere where stones are
-					// no matter the need for stones, as stones are considered an obstacle
+					// Quarries are generally to be built everywhere where rocks are
+					// no matter the need for granite, as rocks are considered an obstacle
 					// to expansion
 					if (bo.cnt_under_construction_ > 0) {
 						continue;
 					}
-					prio = bf->stones_nearby_;
+					prio = bf->rocks_nearby_;
 
 					// value is initialized with 1 but minimal value that can be
 					// calculated is 11
@@ -1944,7 +1936,7 @@
 				}
 
 				if (expansion_mode == MilitaryStrategy::kResourcesOrDefense &&
-				    !(bf->unowned_mines_pots_nearby_ || bf->stones_nearby_ || bf->water_nearby_ ||
+				    !(bf->unowned_mines_pots_nearby_ || bf->rocks_nearby_ || bf->water_nearby_ ||
 				      (bf->distant_water_ && resource_necessity_water_needed_) || bf->enemy_nearby_)) {
 					continue;
 				}
@@ -1969,10 +1961,10 @@
 
 
 				// calculating other sub scores
-				// for resources (mines, water, stones)
+				// for resources (mines, water, rocks)
 				int32_t prio_for_resources = 0;
 				prio_for_resources += 2 * (bf->unowned_mines_pots_nearby_ * resource_necessity_mines_) / 100 +
-						bf->stones_nearby_ + (bf->water_nearby_ * resource_necessity_water_) / 100;
+						bf->rocks_nearby_ + (bf->water_nearby_ * resource_necessity_water_) / 100;
 				// special bonus due to remote water for atlanteans
 				if (resource_necessity_water_needed_) {
 					prio_for_resources += (bf->distant_water_ * resource_necessity_water_) / 100 / 3;
@@ -2214,8 +2206,8 @@
 
 		if (!mineable_fields.empty()) {
 
-			for (uint32_t i = 0; i < buildings_.size() && productionsites.size() > 8; ++i) {
-				BuildingObserver& bo = buildings_.at(i);
+			for (BuildingObserver& bo : buildings_) {
+				if (productionsites.size() <= 8) break;
 
 				if (!bo.buildable(*player_) || bo.type != BuildingObserver::MINE) {
 					continue;
@@ -3134,13 +3126,13 @@
 	}
 
 	// Quarry handling
-	if (site.bo->need_stones_) {
+	if (site.bo->need_rocks_) {
 
 		if (map.find_immovables(
 		       Area<FCoords>(map.get_fcoords(site.site->get_position()), 6),
 		       nullptr,
 
-		       FindImmovableAttribute(MapObjectDescr::get_attribute_id("granite"))) == 0) {
+		       FindImmovableAttribute(MapObjectDescr::get_attribute_id("rocks"))) == 0) {
 			// destruct the building and it's flag (via flag destruction)
 			// the destruction of the flag avoids that defaultAI will have too many
 			// unused roads - if needed the road will be rebuild directly.
@@ -3155,7 +3147,7 @@
 
 		if (site.unoccupied_till_ + 6 * 60 * 1000 < gametime &&
 		    site.site->get_statistics_percent() == 0) {
-			// it is possible that there are stones but quary is not able to mine them
+			// it is possible that there are rocks but quarry is not able to mine them
 			site.bo->last_dismantle_time_ = game().get_gametime();
 			flags_to_be_removed.push_back(site.site->base_flag().get_position());
 			if (connected_to_wh) {
@@ -3619,7 +3611,7 @@
 	for (uint32_t m = 0; m < bo.outputs_.size(); ++m) {
 		WareIndex wt(static_cast<size_t>(bo.outputs_.at(m)));
 
-		uint16_t target = tribe_->get_ware_descr(wt)->default_target_quantity() / 3;
+		uint16_t target = tribe_->get_ware_descr(wt)->default_target_quantity(tribe_->name()) / 3;
 		// at least  1
 		target = std::max<uint16_t>(target, 1);
 
@@ -4091,9 +4083,9 @@
 		late_initialization();
 	}
 
-	for (uint32_t i = 0; i < buildings_.size(); ++i) {
-		if (!strcmp(buildings_.at(i).name, name)) {
-			return buildings_.at(i);
+	for (BuildingObserver& bo : buildings_) {
+		if (!strcmp(bo.name, name)) {
+			return bo;
 		}
 	}
 
@@ -4314,25 +4306,25 @@
 		score += 1;
 	}
 
-	// here we check for surface stones + trees
+	// here we check for surface rocks + trees
 	std::vector<ImmovableFound> immovables;
 	// Search in a radius of range
 	map.find_immovables(Area<FCoords>(map.get_fcoords(candidate_spot), 10), &immovables);
 
-	int32_t const stone_attr = MapObjectDescr::get_attribute_id("granite");
-	uint16_t stones = 0;
+	int32_t const rocks_attr = MapObjectDescr::get_attribute_id("rocks");
+	uint16_t rocks = 0;
 	int32_t const tree_attr = MapObjectDescr::get_attribute_id("tree");
 	uint16_t trees = 0;
 
 	for (uint32_t j = 0; j < immovables.size(); ++j) {
-		if (immovables.at(j).object->has_attribute(stone_attr)) {
-			++stones;
+		if (immovables.at(j).object->has_attribute(rocks_attr)) {
+			++rocks;
 		}
 		if (immovables.at(j).object->has_attribute(tree_attr)) {
 			++trees;
 		}
 	}
-	if (stones > 1) {
+	if (rocks > 1) {
 		score += 1;
 	}
 	if (trees > 1) {
@@ -4364,8 +4356,6 @@
 		const uint8_t spot_score = spot_scoring(so.ship->exp_port_spaces()->front());
 
 		if ((gametime / 10) % 8 < spot_score) {  // we build a port here
-			// const Coords last_portspace = so.ship->exp_port_spaces()->front();
-			// remote_ports_coords.insert(coords_hash(last_portspace));
 			game().send_player_ship_construct_port(*so.ship, so.ship->exp_port_spaces()->front());
 			so.last_command_time = gametime;
 			so.waiting_for_command_ = false;
@@ -5117,9 +5107,9 @@
 	}
 
 	for (EconomyObserver* observer : economies) {
-		WareIndex nritems = observer->economy.owner().tribe().get_nrwares();
+		WareIndex nritems = player_->egbase().tribes().nrwares();
 		for (Widelands::WareIndex id = 0; id < nritems; ++id) {
-			const uint16_t default_target = tribe_->get_ware_descr(id)->default_target_quantity();
+			const uint16_t default_target = tribe_->get_ware_descr(id)->default_target_quantity(tribe_->name());
 
 			game().send_player_command(*new Widelands::CmdSetWareTargetQuantity(
 			                              gametime,
@@ -5179,26 +5169,27 @@
 	// we test following materials
 	const std::vector<std::string> materials = {"coal",
 	                                            "log",
-	                                            "ironore",
+	                                            "iron_ore",
 	                                            "iron",
 	                                            "marble",
-	                                            "plank",
+	                                            "planks",
 	                                            "water",
-	                                            "goldore",
+	                                            "gold_ore",
 	                                            "granite",
 	                                            "fish",
 	                                            "diamond",
-	                                            "stone",
 	                                            "corn",
 	                                            "wheat",
 	                                            "grape",
 	                                            "quartz",
-	                                            "bread",
+	                                            "atlanteans_bread",
+	                                            "barbarians_bread",
+	                                            "empire_bread",
 	                                            "meat"};
 	std::string summary = "";
 	for (uint32_t j = 0; j < materials.size(); ++j) {
 		WareIndex const index = tribe_->ware_index(materials.at(j));
-		if (index == INVALID_INDEX) {
+		if (!tribe_->has_ware(index)) {
 			continue;
 		}
 		if (get_warehoused_stock(index) > 0) {

=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h	2015-09-04 06:16:58 +0000
+++ src/ai/defaultai.h	2015-10-18 20:57:50 +0000
@@ -229,7 +229,7 @@
 
 	void
 	consider_productionsite_influence(BuildableField&, Widelands::Coords, const BuildingObserver&);
-	// considering wood, stones, mines, water, fishes for candidate for colonization (new port)
+	// considering trees, rocks, mines, water, fishes for candidate for colonization (new port)
 	uint8_t spot_scoring(Widelands::Coords candidate_spot);
 
 	EconomyObserver* get_economy_observer(Widelands::Economy&);

=== modified file 'src/base/md5.h'
--- src/base/md5.h	2014-09-20 09:37:47 +0000
+++ src/base/md5.h	2015-10-18 20:57:50 +0000
@@ -91,7 +91,7 @@
 	/// This function consumes new data. It buffers it and calculates one MD5
 	/// block when the buffer is full.
 	///
-	/// \param data data to compute chksum for
+	/// \param newdata data to compute chksum for
 	/// \param size size of data
 	void data(const void * const newdata, const size_t size) {
 		assert(can_handle_data);

=== modified file 'src/economy/economy.cc'
--- src/economy/economy.cc	2015-10-11 10:36:03 +0000
+++ src/economy/economy.cc	2015-10-18 20:57:50 +0000
@@ -35,7 +35,7 @@
 #include "logic/game.h"
 #include "logic/player.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 
 namespace Widelands {
@@ -45,8 +45,8 @@
 	m_request_timerid(0)
 {
 	const TribeDescr & tribe = player.tribe();
-	WareIndex const nr_wares   = tribe.get_nrwares();
-	WareIndex const nr_workers = tribe.get_nrworkers();
+	WareIndex const nr_wares   = player.egbase().tribes().nrwares();
+	WareIndex const nr_workers = player.egbase().tribes().nrworkers();
 	m_wares.set_nrwares(nr_wares);
 	m_workers.set_nrwares(nr_workers);
 
@@ -55,8 +55,12 @@
 	m_ware_target_quantities   = new TargetQuantity[nr_wares];
 	for (WareIndex i = 0; i < nr_wares; ++i) {
 		TargetQuantity tq;
-		tq.permanent =
-			tribe.get_ware_descr(i)->default_target_quantity();
+		if (tribe.has_ware(i)) {
+			tq.permanent =
+				tribe.get_ware_descr(i)->default_target_quantity(tribe.name());
+		} else {
+			tq.permanent = 0;
+		}
 		tq.last_modified = 0;
 		m_ware_target_quantities[i] = tq;
 	}
@@ -381,7 +385,7 @@
 */
 void Economy::remove_wares(WareIndex const id, uint32_t const count)
 {
-	assert(id < m_owner.tribe().get_nrwares());
+	assert(m_owner.egbase().tribes().ware_exists(id));
 	//log("%p: remove(%i, %i) from %i\n", this, id, count, m_wares.stock(id));
 
 	m_wares.remove(id, count);
@@ -559,19 +563,20 @@
 */
 void Economy::_merge(Economy & e)
 {
-	for (WareIndex i = m_owner.tribe().get_nrwares(); i;) {
-		--i;
-		TargetQuantity other_tq = e.m_ware_target_quantities[i];
-		TargetQuantity & this_tq = m_ware_target_quantities[i];
-		if (this_tq.last_modified < other_tq.last_modified)
+	for (const WareIndex& ware_index : m_owner.tribe().wares()) {
+		TargetQuantity other_tq = e.m_ware_target_quantities[ware_index];
+		TargetQuantity& this_tq = m_ware_target_quantities[ware_index];
+		if (this_tq.last_modified < other_tq.last_modified) {
 			this_tq = other_tq;
+		}
 	}
-	for (WareIndex i = m_owner.tribe().get_nrworkers(); i;) {
-		--i;
-		TargetQuantity other_tq = e.m_worker_target_quantities[i];
-		TargetQuantity & this_tq = m_worker_target_quantities[i];
-		if (this_tq.last_modified < other_tq.last_modified)
+
+	for (const WareIndex& worker_index : m_owner.tribe().workers()) {
+		TargetQuantity other_tq = e.m_worker_target_quantities[worker_index];
+		TargetQuantity& this_tq = m_worker_target_quantities[worker_index];
+		if (this_tq.last_modified < other_tq.last_modified) {
 			this_tq = other_tq;
+		}
 	}
 
 	//  If the options window for e is open, but not the one for *this, the user
@@ -612,13 +617,12 @@
 
 	Economy & e = *new Economy(m_owner);
 
-	for (WareIndex i = m_owner.tribe().get_nrwares  (); i;) {
-		--i;
-		e.m_ware_target_quantities[i] = m_ware_target_quantities[i];
+	for (const WareIndex& ware_index : m_owner.tribe().wares()) {
+		e.m_ware_target_quantities[ware_index] = m_ware_target_quantities[ware_index];
 	}
-	for (WareIndex i = m_owner.tribe().get_nrworkers(); i;) {
-		--i;
-		e.m_worker_target_quantities[i] = m_worker_target_quantities[i];
+
+	for (const WareIndex& worker_index : m_owner.tribe().workers()) {
+		e.m_worker_target_quantities[worker_index] = m_worker_target_quantities[worker_index];
 	}
 
 	for (const OPtr<Flag> temp_flag : flags) {
@@ -992,17 +996,11 @@
 	if (!warehouses().size())
 		return;
 
-	const TribeDescr & tribe = owner().tribe();
-	for
-		(WareIndex index = 0;
-		 index < tribe.get_nrworkers(); ++index)
-	{
-		if (!owner().is_worker_type_allowed(index))
-			continue;
-		if (!tribe.get_worker_descr(index)->is_buildable())
-			continue;
-
-		_create_requested_worker(game, index);
+	for (const WareIndex& worker_index : owner().tribe().workers()) {
+		if (owner().is_worker_type_allowed(worker_index) &&
+			 owner().tribe().get_worker_descr(worker_index)->is_buildable()) {
+			_create_requested_worker(game, worker_index);
+		}
 	}
 }
 

=== modified file 'src/economy/economy_data_packet.cc'
--- src/economy/economy_data_packet.cc	2014-10-12 07:35:42 +0000
+++ src/economy/economy_data_packet.cc	2015-10-18 20:57:50 +0000
@@ -23,7 +23,7 @@
 #include "io/fileread.h"
 #include "io/filewrite.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
 
@@ -37,52 +37,50 @@
 		uint16_t const packet_version = fr.unsigned_16();
 		if (packet_version == kCurrentPacketVersion) {
 			try {
-				const TribeDescr & tribe = m_eco->owner().tribe();
+				const TribeDescr& tribe = m_eco->owner().tribe();
 				while (Time const last_modified = fr.unsigned_32()) {
 					char const * const type_name = fr.c_string();
 					uint32_t const permanent = fr.unsigned_32();
 					WareIndex i = tribe.ware_index(type_name);
-					if (i != INVALID_INDEX) {
-						if (tribe.get_ware_descr(i)->default_target_quantity() ==
-							 std::numeric_limits<uint32_t>::max())
+					if (tribe.has_ware(i)) {
+						if (tribe.get_ware_descr(i)->default_target_quantity(tribe.name()) == kInvalidWare) {
 							log("WARNING: target quantity configured for %s, "
 								 "which should not have target quantity, "
 								 "ignoring\n",
 								 type_name);
-						else {
-							Economy::TargetQuantity & tq =
-								m_eco->m_ware_target_quantities[i];
-							if (tq.last_modified)
-								throw GameDataError
-									("duplicated entry for %s", type_name);
-							tq.permanent         = permanent;
-							tq.last_modified     = last_modified;
+						} else {
+							Economy::TargetQuantity& tq = m_eco->m_ware_target_quantities[i];
+							if (tq.last_modified) {
+								throw GameDataError("duplicated entry for %s", type_name);
+							}
+							tq.permanent = permanent;
+							tq.last_modified = last_modified;
 						}
-					} else if ((i = tribe.worker_index(type_name)) != INVALID_INDEX) {
-						if
-							(tribe.get_worker_descr(i)->default_target_quantity()
-							 ==
-							 std::numeric_limits<uint32_t>::max())
+					} else {
+						i = tribe.worker_index(type_name);
+						if (tribe.has_worker(i)) {
+							if (tribe.get_worker_descr(i)->default_target_quantity() == kInvalidWare) {
+								log
+										("WARNING: target quantity configured for %s, "
+										 "which should not have target quantity, "
+										 "ignoring\n",
+										 type_name);
+							} else {
+								Economy::TargetQuantity& tq = m_eco->m_worker_target_quantities[i];
+								if (tq.last_modified) {
+									throw GameDataError("duplicated entry for %s", type_name);
+								}
+								tq.permanent = permanent;
+								tq.last_modified = last_modified;
+							}
+						} else {
 							log
-								("WARNING: target quantity configured for %s, "
-								 "which should not have target quantity, "
-								 "ignoring\n",
-								 type_name);
-						else {
-							Economy::TargetQuantity & tq =
-								m_eco->m_worker_target_quantities[i];
-							if (tq.last_modified)
-								throw GameDataError
-									("duplicated entry for %s", type_name);
-							tq.permanent         = permanent;
-							tq.last_modified     = last_modified;
+								("WARNING: target quantity configured for \"%s\", "
+								 "which is not a ware or worker type defined in tribe "
+								 "%s, ignoring\n",
+								 type_name, tribe.name().c_str());
 						}
-					} else
-						log
-							("WARNING: target quantity configured for \"%s\", "
-							 "which is not a ware or worker type defined in tribe "
-							 "%s, ignoring\n",
-							 type_name, tribe.name().c_str());
+					}
 				}
 			} catch (const WException & e) {
 				throw GameDataError("target quantities: %s", e.what());
@@ -100,23 +98,21 @@
 {
 	fw.unsigned_16(kCurrentPacketVersion);
 	const TribeDescr & tribe = m_eco->owner().tribe();
-	for (WareIndex i = tribe.get_nrwares(); i;) {
-		--i;
+	for (const WareIndex& ware_index : tribe.wares()) {
 		const Economy::TargetQuantity & tq =
-			m_eco->m_ware_target_quantities[i];
+			m_eco->m_ware_target_quantities[ware_index];
 		if (Time const last_modified = tq.last_modified) {
 			fw.unsigned_32(last_modified);
-			fw.c_string(tribe.get_ware_descr(i)->name());
+			fw.c_string(tribe.get_ware_descr(ware_index)->name());
 			fw.unsigned_32(tq.permanent);
 		}
 	}
-	for (WareIndex i = tribe.get_nrworkers(); i;) {
-		--i;
+	for (const WareIndex& worker_index : tribe.workers()) {
 		const Economy::TargetQuantity & tq =
-			m_eco->m_worker_target_quantities[i];
+			m_eco->m_worker_target_quantities[worker_index];
 		if (Time const last_modified = tq.last_modified) {
 			fw.unsigned_32(last_modified);
-			fw.c_string(tribe.get_worker_descr(i)->name());
+			fw.c_string(tribe.get_worker_descr(worker_index)->name());
 			fw.unsigned_32(tq.permanent);
 		}
 	}

=== modified file 'src/economy/flag.cc'
--- src/economy/flag.cc	2015-01-27 13:25:30 +0000
+++ src/economy/flag.cc	2015-10-18 20:57:50 +0000
@@ -31,7 +31,7 @@
 #include "logic/game.h"
 #include "logic/instances.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "logic/worker.h"
 

=== modified file 'src/economy/idleworkersupply.cc'
--- src/economy/idleworkersupply.cc	2014-09-10 10:18:46 +0000
+++ src/economy/idleworkersupply.cc	2015-10-18 20:57:50 +0000
@@ -26,7 +26,7 @@
 #include "logic/player.h"
 #include "logic/requirements.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "logic/worker.h"
 
@@ -95,7 +95,7 @@
 {
 	assert
 		(req.get_type() != wwWORKER ||
-		 req.get_index() < m_worker.descr().tribe().get_nrworkers());
+		 m_worker.owner().tribe().has_worker(req.get_index()));
 	if
 		(req.get_type() == wwWORKER &&
 		 m_worker.descr().can_act_as(req.get_index()) &&

=== modified file 'src/economy/portdock.cc'
--- src/economy/portdock.cc	2015-10-04 18:30:05 +0000
+++ src/economy/portdock.cc	2015-10-18 20:57:50 +0000
@@ -476,8 +476,7 @@
 PortDock::Loader::Loader() : m_warehouse(0) {
 }
 
-void PortDock::Loader::load(FileRead & fr)
-{
+void PortDock::Loader::load(FileRead & fr) {
 	PlayerImmovable::Loader::load(fr);
 
 	PortDock& pd = get<PortDock>();

=== modified file 'src/economy/request.cc'
--- src/economy/request.cc	2014-10-12 07:35:42 +0000
+++ src/economy/request.cc	2015-10-18 20:57:50 +0000
@@ -31,7 +31,7 @@
 #include "logic/player.h"
 #include "logic/productionsite.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "logic/worker.h"
 #include "map_io/map_object_loader.h"
@@ -69,16 +69,14 @@
 	m_last_request_time(m_required_time)
 {
 	assert(m_type == wwWARE || m_type == wwWORKER);
-	if (w == wwWARE && _target.owner().tribe().get_nrwares() <= index)
-		throw wexception
-			("creating ware request with index %u, but tribe has only %u "
-			 "ware types",
-			 index, _target.owner().tribe().get_nrwares  ());
-	if (w == wwWORKER && _target.owner().tribe().get_nrworkers() <= index)
-		throw wexception
-			("creating worker request with index %u, but tribe has only %u "
-			 "worker types",
-			 index, _target.owner().tribe().get_nrworkers());
+	if (w == wwWARE && !_target.owner().egbase().tribes().ware_exists(index))
+		throw wexception
+			("creating ware request with index %u, but the ware for this index doesn't exist",
+			 index);
+	if (w == wwWORKER && !_target.owner().egbase().tribes().worker_exists(index))
+		throw wexception
+			("creating worker request with index %u, but the worker for this index doesn't exist",
+			 index);
 	if (m_economy)
 		m_economy->add_request(*this);
 }
@@ -114,12 +112,12 @@
 			const TribeDescr& tribe = m_target.owner().tribe();
 			char const* const type_name = fr.c_string();
 			WareIndex const wai = tribe.ware_index(type_name);
-			if (wai != INVALID_INDEX) {
+			if (tribe.has_ware(wai)) {
 				m_type = wwWARE;
 				m_index = wai;
 			} else {
 				WareIndex const woi = tribe.worker_index(type_name);
-				if (woi != INVALID_INDEX) {
+				if (tribe.has_worker(woi)) {
 					m_type = wwWORKER;
 					m_index = woi;
 				} else {
@@ -183,16 +181,16 @@
 {
 	fw.unsigned_16(kCurrentPacketVersion);
 
-	//  Target and econmy should be set. Same is true for callback stuff.
+	//  Target and economy should be set. Same is true for callback stuff.
 
 	assert(m_type == wwWARE || m_type == wwWORKER);
-	const TribeDescr & tribe = m_target.owner().tribe();
-	assert(m_type != wwWARE   || m_index < tribe.get_nrwares  ());
-	assert(m_type != wwWORKER || m_index < tribe.get_nrworkers());
-	fw.c_string
-		(m_type == wwWARE                        ?
-		 tribe.get_ware_descr  (m_index)->name() :
-		 tribe.get_worker_descr(m_index)->name());
+	if (m_type == wwWARE) {
+		assert(game.tribes().ware_exists(m_index));
+		fw.c_string(game.tribes().get_ware_descr(m_index)->name());
+	} else if (m_type == wwWORKER) {
+		assert(game.tribes().worker_exists(m_index));
+		fw.c_string(game.tribes().get_worker_descr(m_index)->name());
+	}
 
 	fw.unsigned_32(m_count);
 

=== modified file 'src/economy/road.cc'
--- src/economy/road.cc	2015-01-24 11:04:49 +0000
+++ src/economy/road.cc	2015-10-18 20:57:50 +0000
@@ -28,7 +28,7 @@
 #include "logic/game.h"
 #include "logic/instances.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 
 namespace Widelands {
 
@@ -358,7 +358,7 @@
 		slot.carrier_request =
 			new Request
 				(*this,
-				 owner().tribe().safe_worker_index("carrier"),
+				 owner().tribe().carrier(),
 				 Road::_request_carrier_callback,
 				 wwWORKER);
 	else

=== modified file 'src/economy/ware_instance.cc'
--- src/economy/ware_instance.cc	2015-04-15 12:59:16 +0000
+++ src/economy/ware_instance.cc	2015-10-18 20:57:50 +0000
@@ -33,7 +33,7 @@
 #include "io/filewrite.h"
 #include "logic/game.h"
 #include "logic/ship.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "logic/worker.h"
 #include "map_io/map_object_loader.h"
@@ -544,7 +544,7 @@
 ==============================
 */
 
-constexpr uint8_t kCurrentPacketVersion = 1;
+constexpr uint8_t kCurrentPacketVersion = 2;
 
 WareInstance::Loader::Loader() :
 	m_location(0),
@@ -600,7 +600,6 @@
 {
 	fw.unsigned_8(HeaderWareInstance);
 	fw.unsigned_8(kCurrentPacketVersion);
-	fw.c_string(descr().tribe().name());
 	fw.c_string(descr().name());
 
 	MapObject::save(egbase, mos, fw);
@@ -617,24 +616,21 @@
 }
 
 MapObject::Loader * WareInstance::load
-	(EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr)
+	(EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr,
+	 const TribesLegacyLookupTable& lookup_table)
 {
 	try {
 		uint8_t packet_version = fr.unsigned_8();
 
-		if (packet_version == kCurrentPacketVersion) {
-
-			const std::string tribename = fr.c_string();
-			const std::string warename = fr.c_string();
-
-			egbase.manually_load_tribe(tribename);
-
-			const TribeDescr * tribe = egbase.get_tribe(tribename);
-			if (!tribe)
-				throw wexception("unknown tribe '%s'", tribename.c_str());
-
-			WareIndex wareindex = tribe->ware_index(warename);
-			const WareDescr * descr = tribe->get_ware_descr(wareindex);
+		// Some maps may contain ware info, so we need compatibility here.
+		if (1 <= packet_version && packet_version <= kCurrentPacketVersion) {
+			std::string warename = fr.c_string();
+			if (packet_version == 1) {
+				warename = lookup_table.lookup_ware(warename, fr.c_string());
+			}
+
+			WareIndex wareindex = egbase.tribes().ware_index(warename);
+			const WareDescr * descr = egbase.tribes().get_ware_descr(wareindex);
 
 			std::unique_ptr<Loader> loader(new Loader);
 			loader->init(egbase, mol, *new WareInstance(wareindex, descr));

=== modified file 'src/economy/ware_instance.h'
--- src/economy/ware_instance.h	2014-09-10 10:18:46 +0000
+++ src/economy/ware_instance.h	2015-10-18 20:57:50 +0000
@@ -24,6 +24,7 @@
 #include "logic/instances.h"
 #include "logic/ware_descr.h"
 #include "logic/widelands.h"
+#include "map_io/tribes_legacy_lookup_table.h"
 
 namespace Widelands {
 
@@ -124,7 +125,8 @@
 	}
 
 	void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override;
-	static MapObject::Loader* load(EditorGameBase&, MapObjectLoader&, FileRead&);
+	static MapObject::Loader* load(EditorGameBase&, MapObjectLoader&, FileRead&,
+											 const TribesLegacyLookupTable& lookup_table);
 };
 }
 

=== modified file 'src/economy/wares_queue.cc'
--- src/economy/wares_queue.cc	2015-04-11 21:03:05 +0000
+++ src/economy/wares_queue.cc	2015-10-18 20:57:50 +0000
@@ -27,7 +27,7 @@
 #include "logic/editor_game_base.h"
 #include "logic/game.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
 

=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2015-09-04 06:16:58 +0000
+++ src/editor/editorinteractive.cc	2015-10-18 20:57:50 +0000
@@ -39,7 +39,7 @@
 #include "graphic/graphic.h"
 #include "logic/map.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribes.h"
 #include "logic/world/resource_description.h"
 #include "logic/world/world.h"
 #include "map_io/widelands_map_loader.h"
@@ -59,11 +59,8 @@
 
 // Load all tribes from disk.
 void load_all_tribes(Widelands::EditorGameBase* egbase, UI::ProgressWindow* loader_ui) {
-	for (const std::string& tribename : Widelands::TribeDescr::get_all_tribenames()) {
-		ScopedTimer timer((boost::format("Loading %s took %%ums.") % tribename).str());
-		loader_ui->stepf(_("Loading tribe: %s"), tribename.c_str());
-		egbase->manually_load_tribe(tribename);
-	}
+	loader_ui->step(_("Loading tribes"));
+	egbase->tribes();
 }
 
 }  // namespace
@@ -207,7 +204,7 @@
 	}
 
 	ml->load_map_complete(egbase(), true);
-	loader_ui.step(_("Loading graphics..."));
+
 	egbase().load_graphics(loader_ui);
 
 	register_overlays();
@@ -605,7 +602,6 @@
 
 				load_all_tribes(&editor, &loader_ui);
 
-				loader_ui.step(_("Loading graphics..."));
 				editor.load_graphics(loader_ui);
 				loader_ui.step(std::string());
 			} else {

=== modified file 'src/editor/map_generator.cc'
--- src/editor/map_generator.cc	2015-09-03 07:52:26 +0000
+++ src/editor/map_generator.cc	2015-10-18 20:57:50 +0000
@@ -105,16 +105,13 @@
 			(fc,
 			 bobCategory->get_immovable
 			 	(static_cast<size_t>(rng.rand() / (kMaxElevation / num))),
-			 nullptr);
+			 MapObjectDescr::OwnerType::kWorld);
 
 	if (set_moveable && (num = bobCategory->num_critters()))
-		egbase_.create_bob
-			(fc,
-			 egbase_.world().get_bob
-			 	(bobCategory->get_critter
-			 	 	(static_cast<size_t>(rng.rand() / (kMaxElevation / num)))
-			 	 .c_str()),
-			 nullptr);
+		egbase_.create_critter(
+		   fc, egbase_.world().get_bob(
+		          bobCategory->get_critter(static_cast<size_t>(rng.rand() / (kMaxElevation / num)))
+		             .c_str()));
 }
 
 void MapGenerator::generate_resources(uint32_t const* const random1,

=== modified file 'src/editor/tools/editor_place_immovable_tool.cc'
--- src/editor/tools/editor_place_immovable_tool.cc	2014-09-10 14:08:25 +0000
+++ src/editor/tools/editor_place_immovable_tool.cc	2015-10-18 20:57:50 +0000
@@ -66,7 +66,7 @@
 			(!mr.location().field->get_immovable()
 			        &&
 			        (mr.location().field->nodecaps() & Widelands::MOVECAPS_WALK))
-				egbase.create_immovable(mr.location(), *i, nullptr);
+				egbase.create_immovable(mr.location(), *i);
 			++i;
 		} while (mr.advance(map));
 	}
@@ -97,7 +97,7 @@
 			immovable->remove(egbase);
 		}
 		if (!i->empty())
-			egbase.create_immovable(mr.location(), *i, nullptr);
+			egbase.create_immovable(mr.location(), *i);
 
 		++i;
 	} while (mr.advance(map));

=== modified file 'src/editor/ui_menus/categorized_item_selection_menu.h'
--- src/editor/ui_menus/categorized_item_selection_menu.h	2015-03-01 09:21:20 +0000
+++ src/editor/ui_menus/categorized_item_selection_menu.h	2015-10-18 20:57:50 +0000
@@ -84,12 +84,12 @@
 	UI::TabPanel* tab_panel = new UI::TabPanel(this, 0, 0, nullptr);
 	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);
+	for (uint32_t category_index = 0; category_index < categories.size(); ++category_index) {
+		const Widelands::EditorCategory& category = *categories.get_mutable(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()) {
+		for (size_t j = 0; j < descriptions_.size(); ++j) {
+			if (descriptions_.get_mutable(j)->editor_category().name() != category.name()) {
 				continue;
 			}
 			item_indices.push_back(j);
@@ -113,7 +113,7 @@
 			}
 			assert(horizontal != nullptr);
 
-			UI::Checkbox* cb = create_checkbox(horizontal, *descriptions_.get(i));
+			UI::Checkbox* cb = create_checkbox(horizontal, *descriptions_.get_mutable(i));
 			cb->set_state(tool_->is_enabled(i));
 			cb->changedto.connect(boost::bind(&CategorizedItemSelectionMenu::selected, this, i, _1));
 			checkboxes_[i] = cb;
@@ -165,7 +165,7 @@
 	for (int i = 0; j; ++i) {
 		if (tool_->is_enabled(i)) {
 			buf += " ";
-			buf += descriptions_.get(i)->descname();
+			buf += descriptions_.get_mutable(i)->descname();
 			--j;
 		}
 	}

=== modified file 'src/editor/ui_menus/editor_player_menu.cc'
--- src/editor/ui_menus/editor_player_menu.cc	2015-10-11 07:53:58 +0000
+++ src/editor/ui_menus/editor_player_menu.cc	2015-10-18 20:57:50 +0000
@@ -29,7 +29,7 @@
 #include "logic/constants.h"
 #include "logic/map.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribes.h"
 #include "logic/warehouse.h"
 #include "profile/profile.h"
 #include "ui_basic/editbox.h"
@@ -61,7 +61,8 @@
 		 g_gr->images().get("pics/but1.png"),
 		 g_gr->images().get("pics/scrollbar_down.png"),
 		 _("Remove last player"),
-		 1 < parent.egbase().map().get_nrplayers())
+		 1 < parent.egbase().map().get_nrplayers()),
+	m_tribenames(eia().egbase().tribes().get_all_tribenames())
 {
 	m_add_player.sigclicked.connect(boost::bind(&EditorPlayerMenu::clicked_add_player, boost::ref(*this)));
 	m_remove_last_player.sigclicked.connect
@@ -71,18 +72,6 @@
 	int32_t const width   = 20;
 	int32_t       posy    = 0;
 
-	// Initializing the descnames for the tribes.
-	for (const std::string& tribename : Widelands::TribeDescr::get_all_tribenames()) {
-		std::string tribepath("tribes/" + tribename);
-		// get translated tribesname
-		Profile prof
-			((tribepath + "/conf").c_str(), nullptr, "tribe_" + tribename);
-		Section & global = prof.get_safe_section("tribe");
-		const char* descname = global.get_safe_string("name");
-		m_tribenames.push_back(tribename);
-		m_tribe_descnames.insert(std::make_pair(tribename, descname));
-	}
-
 	set_inner_size(375, 135);
 
 	UI::Textarea * ta = new UI::Textarea(this, 0, 0, _("Number of Players"));
@@ -181,7 +170,9 @@
 			m_selected_tribes[p - 1] = m_tribenames[0];
 			map.set_scenario_player_tribe(p, m_selected_tribes[p - 1]);
 		}
-		m_plr_set_tribes_buts[p - 1]->set_title(m_tribe_descnames.find(m_selected_tribes[p - 1])->second);
+
+		m_plr_set_tribes_buts[p - 1]
+				->set_title(eia().egbase().tribes().tribeinfo(m_selected_tribes[p - 1]).descname);
 
 		// Set default AI and closeable to false (always default - should be changed by hand)
 		map.set_scenario_player_ai(p, "");
@@ -263,13 +254,16 @@
 void EditorPlayerMenu::player_tribe_clicked(uint8_t n) {
 	EditorInteractive& menu = eia();
 	if (!menu.is_player_tribe_referenced(n + 1)) {
-		if (!Widelands::TribeDescr::exists_tribe(m_selected_tribes[n + 1]))
+		if (!Widelands::Tribes::tribe_exists(m_selected_tribes[n + 1])) {
 			throw wexception
 				("Map defines tribe %s, but it does not exist!", m_selected_tribes[n + 1].c_str());
+		}
 		uint32_t i;
-		for (i = 0; i < m_tribenames.size(); ++i)
-			if (m_tribenames[i] == m_selected_tribes[n + 1])
+		for (i = 0; i < m_tribenames.size(); ++i) {
+			if (m_tribenames[i] == m_selected_tribes[n + 1]) {
 				break;
+			}
+		}
 		m_selected_tribes[n + 1] = i == m_tribenames.size() - 1 ? m_tribenames[0] : m_tribenames[++i];
 		menu.egbase().map().set_scenario_player_tribe(n + 1, m_selected_tribes[n + 1]);
 		menu.set_need_save(true);
@@ -350,7 +344,7 @@
 		// so that this tribe can not be changed
 		egbase.add_player
 			(n, 0, // TODO(SirVer): initialization index makes no sense here
-			 m_tribe_descnames.find(m_selected_tribes[n])->second,
+			 eia().egbase().tribes().tribeinfo(m_selected_tribes[n]).descname,
 			 m_plr_names[n - 1]->text());
 
 		p = egbase.get_player(n);
@@ -365,9 +359,8 @@
 	if (!imm) {
       // place HQ
 		const Widelands::TribeDescr & tribe = p->tribe();
-		const Widelands::BuildingIndex idx =
-			tribe.building_index("headquarters");
-		if (idx == Widelands::INVALID_INDEX)
+		const Widelands::BuildingIndex idx = tribe.headquarters();
+		if (!tribe.has_building(idx))
 			throw wexception("Tribe %s lacks headquarters", tribe.name().c_str());
 		// Widelands::Warehouse & headquarter = dynamic_cast<Widelands::Warehouse &>
 		//         (egbase.warp_building(starting_pos, player_number, idx));

=== modified file 'src/editor/ui_menus/editor_player_menu.h'
--- src/editor/ui_menus/editor_player_menu.h	2015-09-03 12:33:57 +0000
+++ src/editor/ui_menus/editor_player_menu.h	2015-10-18 20:57:50 +0000
@@ -58,9 +58,6 @@
 
 	std::vector<std::string> m_tribenames;
 
-	/// tribename, descname
-	std::map<std::string, std::string> m_tribe_descnames;
-
 	/// List of the tribes currently selected for all players
 	std::string m_selected_tribes[MAX_PLAYERS];
 

=== modified file 'src/game_io/game_interactive_player_packet.cc'
--- src/game_io/game_interactive_player_packet.cc	2014-10-12 07:35:42 +0000
+++ src/game_io/game_interactive_player_packet.cc	2015-10-18 20:57:50 +0000
@@ -24,7 +24,7 @@
 #include "logic/game.h"
 #include "logic/game_data_error.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "wui/interactive_player.h"
 #include "wui/mapview.h"
 #include "wui/overlay_manager.h"

=== modified file 'src/game_io/game_player_info_packet.cc'
--- src/game_io/game_player_info_packet.cc	2014-10-12 07:35:42 +0000
+++ src/game_io/game_player_info_packet.cc	2015-10-18 20:57:50 +0000
@@ -25,12 +25,12 @@
 #include "logic/game.h"
 #include "logic/game_data_error.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "wui/interactive_player.h"
 
 namespace Widelands {
 
-constexpr uint16_t kCurrentPacketVersion = 16;
+constexpr uint16_t kCurrentPacketVersion = 17;
 
 void GamePlayerInfoPacket::read
 	(FileSystem & fs, Game & game, MapObjectLoader *) {
@@ -42,7 +42,6 @@
 			uint32_t const max_players = fr.unsigned_16();
 			for (uint32_t i = 1; i < max_players + 1; ++i) {
 				game.remove_player(i);
-
 				if (fr.unsigned_8()) {
 					bool const see_all = fr.unsigned_8();
 
@@ -54,11 +53,13 @@
 
 					Widelands::TeamNumber team = fr.unsigned_8();
 					char const * const tribe_name = fr.c_string();
+
 					std::string const name = fr.c_string();
+
 					game.add_player(plnum, 0, tribe_name, name, team);
-
 					Player & player = game.player(plnum);
 					player.set_see_all(see_all);
+
 					player.set_ai(fr.c_string());
 					player.read_statistics(fr);
 

=== modified file 'src/graphic/CMakeLists.txt'
--- src/graphic/CMakeLists.txt	2015-02-09 05:57:08 +0000
+++ src/graphic/CMakeLists.txt	2015-10-18 20:57:50 +0000
@@ -198,7 +198,6 @@
     io_stream
     logic
     notifications
-    profile
     scripting_lua_table
     sound
     wui_overlay_manager

=== modified file 'src/graphic/animation.cc'
--- src/graphic/animation.cc	2015-10-05 17:44:26 +0000
+++ src/graphic/animation.cc	2015-10-18 20:57:50 +0000
@@ -42,7 +42,6 @@
 #include "io/filesystem/layered_filesystem.h"
 #include "logic/bob.h"
 #include "logic/instances.h"
-#include "profile/profile.h"
 #include "scripting/lua_table.h"
 #include "sound/sound_handler.h"
 
@@ -116,7 +115,6 @@
 class NonPackedAnimation : public Animation {
 public:
 	virtual ~NonPackedAnimation() {}
-	NonPackedAnimation(const string& directory, Section & section);
 	NonPackedAnimation(const LuaTable& table);
 
 	// Implements Animation.
@@ -154,78 +152,70 @@
 	string sound_effect_;
 };
 
-NonPackedAnimation::NonPackedAnimation(const string& directory, Section& section)
-		: frametime_(FRAME_LENGTH),
-		  hasplrclrs_(false) {
-	// 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 = section.get_int("fps");
-	if (fps < 0)
-		throw wexception("fps is %i, must be non-negative", fps);
-	if (fps > 0)
-		frametime_ = 1000 / fps;
-
-	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.
-	string picnametempl;
-	if (char const * const pics = section.get_string("pics")) {
-		picnametempl = directory + pics;
-	} else {
-		picnametempl = directory + section.get_name();
-	}
-	// Strip the .png extension if it has one.
-	boost::replace_all(picnametempl, ".png", "");
-
-	NumberGlob glob(picnametempl);
-	string filename_wo_ext;
-	while (glob.next(&filename_wo_ext)) {
-		const string filename = filename_wo_ext + ".png";
-		if (!g_fs->file_exists(filename))
-			break;
-		image_files_.push_back(filename);
-
-		const string pc_filename = filename_wo_ext + "_pc.png";
-		if (g_fs->file_exists(pc_filename)) {
-			hasplrclrs_ = true;
-			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");
+	try {
+		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_);
+		}
+
+		const std::string templatedirname = table.get_string("directory");
+		const std::string templatefilename = table.get_string("template");
+
+		//  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 for a PNG file with that
+		//  name, increments the number and continues on until it cannot find any
+		//  file. Then it is assumed that there are no more frames in the animation.
+		std::string picnametempl = templatedirname + templatefilename;
+
+		// Strip the .png extension if it has one.
+		boost::replace_all(picnametempl, ".png", "");
+
+		NumberGlob glob(picnametempl);
+		string filename_wo_ext;
+		while (glob.next(&filename_wo_ext)) {
+			const std::string filename = filename_wo_ext + ".png";
+			if (!g_fs->file_exists(filename)) {
+				break;
+			}
+			image_files_.push_back(filename);
+
+			const std::string pc_filename = filename_wo_ext + "_pc.png";
+			if (g_fs->file_exists(pc_filename)) {
+				hasplrclrs_ = true;
+				pc_mask_image_files_.push_back(pc_filename);
+			} else if (hasplrclrs_) {
+				throw wexception("Animation in directory %s is missing player color file: %s",
+									  templatedirname.c_str(), pc_filename.c_str());
+			}
+		}
+
+		if (image_files_.empty()) {
+			throw wexception("Animation %s without pictures in directory %s. "
+								  "Make sure that the directory has a trailing slash. "
+								  "The template should look similar to this: idle_?? for idle_00.png etc.",
+								  templatefilename.c_str(), templatedirname.c_str());
+		} else if (table.has_key("fps")) {
+			if (image_files_.size() == 1) {
+				throw wexception("Animation %s with one picture in directory %s must not have 'fps'",
+									  templatefilename.c_str(), templatedirname.c_str());
+			}
+			frametime_ = 1000 / get_positive_int(table, "fps");
+		}
+		assert(!image_files_.empty());
+		assert(pc_mask_image_files_.size() == image_files_.size() || pc_mask_image_files_.empty());
+
+	} catch (const LuaError& e) {
+		throw wexception("Error in animation table: %s", e.what());
 	}
 }
 
@@ -368,77 +358,6 @@
 	m_animations[5] = dir6;
 }
 
-
-/**
- * Load direction animations of the given name.
- *
- * If a section of the given name exists, it is expected to contain a 'dirpics'
- * key and assorted information of the old direction animation format.
- *
- * Otherwise, sections with the names 'name_??', with ?? replaced
- * by nw, ne, e, se, sw, and w are expected to exist and describe
- * the corresponding animations.
- *
- * @param optional No error if animations do not exist
- */
-void DirAnimations::parse
-	(Widelands::MapObjectDescr & b,
-	 const string & directory,
-	 Profile & prof,
-	 const string & name,
-	 bool optional,
-	 const string & default_dirpics)
-{
-	if (Section * section = prof.get_section(name)) {
-		// NOTE: deprecate this format eventually
-		char dirpictempl[256];
-		char * repl;
-
-		snprintf
-			(dirpictempl, sizeof(dirpictempl), "%s",
-			 section->get_string("dirpics", default_dirpics.c_str()));
-		repl = strstr(dirpictempl, "!!");
-		if (!repl)
-			throw wexception
-				("DirAnimations dirpics name templates %s does not contain !!",
-				 dirpictempl);
-		strncpy(repl, "%s", 2);
-
-		for (int32_t dir = 0; dir < 6; ++dir) {
-			static char const * const dirstrings[6] =
-				{"ne", "e", "se", "sw", "w", "nw"};
-
-			// Fake the section name here, so that the animation loading code is
-			// using the correct glob pattern to load the images from.
-			char pictempl[256];
-			snprintf(pictempl, sizeof(pictempl), dirpictempl, dirstrings[dir]);
-			section->set_name(pictempl);
-			m_animations[dir] = g_gr->animations().load(directory, *section);
-
-			char animname[256];
-			snprintf(animname, sizeof(animname), "%s_%s", name.c_str(), dirstrings[dir]);
-			b.add_animation(animname, m_animations[dir]);
-		}
-	} else {
-		for (int32_t dir = 0; dir < 6; ++dir) {
-			static char const * const dirstrings[6] =
-				{"ne", "e", "se", "sw", "w", "nw"};
-
-			char animname[256];
-			snprintf(animname, sizeof(animname), "%s_%s", name.c_str(), dirstrings[dir]);
-			Section * dirsection = prof.get_section(animname);
-			if (dirsection) {
-				m_animations[dir] = g_gr->animations().load(directory, *dirsection);
-				b.add_animation(animname, m_animations[dir]);
-			} else {
-				if (!optional)
-					throw wexception("DirAnimations: did not find section %s", animname);
-			}
-		}
-	}
-}
-
-
 /*
 ==============================================================================
 
@@ -447,11 +366,6 @@
 ==============================================================================
 */
 
-uint32_t AnimationManager::load(const string& directory, Section & s) {
-	m_animations.push_back(new NonPackedAnimation(directory, s));
-	return m_animations.size();
-}
-
 uint32_t AnimationManager::load(const LuaTable& table) {
 	m_animations.push_back(new NonPackedAnimation(table));
 	return m_animations.size();

=== modified file 'src/graphic/animation.h'
--- src/graphic/animation.h	2015-10-06 16:42:53 +0000
+++ src/graphic/animation.h	2015-10-18 20:57:50 +0000
@@ -96,18 +96,12 @@
 public:
 	~AnimationManager();
 	/**
-	 * Loads an animation, graphics sound and everything.
-	 *
-	 * The animation resides in the given directory and is described by the
-	 * given section.
-	 *
-	 * This function looks for image files as defined by the 'pics' key. If this
-	 * is not present, it will try \<sectionname\>_??.png
-	 *
-	 * \param directory     which directory to look in for image and sound files
-	 * \param s             conffile section to search for data on this animation
+	 * Loads an animation, graphics sound and everything from a Lua table.
+	 *
+	 * The Lua table must contain a table 'pictures' with image paths and a 'hotspot' table.
+	 *
+	 * Optional parameters in the Lua table are 'fps' and 'sound_effect'.
 	*/
-	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

=== modified file 'src/graphic/diranimations.h'
--- src/graphic/diranimations.h	2014-09-19 12:54:54 +0000
+++ src/graphic/diranimations.h	2015-10-18 20:57:50 +0000
@@ -28,23 +28,12 @@
 
 namespace Widelands {struct MapObjectDescr;}
 
-class Profile;
-class Section;
-
 /// Manages a set of 6 animations, one for each possible direction.
 struct 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);
 
-	void parse
-		(Widelands::MapObjectDescr &,
-		 const std::string           & directory,
-		 Profile                     &,
-		 const std::string & name,
-		 bool optional = false,
-		 const std::string & default_dirpics = std::string());
-
 	uint32_t get_animation(Widelands::Direction const dir) const {
 		return m_animations[dir - 1];
 	}

=== modified file 'src/graphic/game_renderer.cc'
--- src/graphic/game_renderer.cc	2015-02-08 18:16:41 +0000
+++ src/graphic/game_renderer.cc	2015-10-18 20:57:50 +0000
@@ -317,7 +317,7 @@
 					if
 						(f_pl.constructionsite.becomes)
 					{
-						const Player::ConstructionsiteInformation & csinf = f_pl.constructionsite;
+						const ConstructionsiteInformation & csinf = f_pl.constructionsite;
 						// draw the partly finished constructionsite
 						uint32_t anim_idx;
 						try {

=== modified file 'src/graphic/gl/dither_program.cc'
--- src/graphic/gl/dither_program.cc	2015-03-01 09:21:20 +0000
+++ src/graphic/gl/dither_program.cc	2015-10-18 20:57:50 +0000
@@ -145,8 +145,8 @@
 		return;
 	}
 	const Widelands::TerrainDescription& other_terrain_description =
-	   terrains.get_unmutable(other_terrain);
-	if (terrains.get_unmutable(my_terrain).dither_layer() <
+	   terrains.get(other_terrain);
+	if (terrains.get(my_terrain).dither_layer() <
 	    other_terrain_description.dither_layer()) {
 		const FloatPoint texture_offset =
 		   other_terrain_description.get_texture(gametime).texture_coordinates().top_left();
@@ -270,6 +270,6 @@
 		}
 	}
 
-	const Texture& texture = terrains.get_unmutable(0).get_texture(0);
+	const Texture& texture = terrains.get(0).get_texture(0);
 	gl_draw(texture.get_gl_texture(), texture.texture_coordinates().w, texture.texture_coordinates().h);
 }

=== modified file 'src/graphic/gl/terrain_program.cc'
--- src/graphic/gl/terrain_program.cc	2015-03-01 09:21:20 +0000
+++ src/graphic/gl/terrain_program.cc	2015-10-18 20:57:50 +0000
@@ -170,7 +170,7 @@
 		   fields_to_draw.calculate_index(field.fx + (field.fy & 1) - 1, field.fy + 1);
 		if (bln_index != -1) {
 			const FloatPoint texture_offset =
-			   terrains.get_unmutable(field.ter_d).get_texture(gametime).texture_coordinates().top_left();
+			   terrains.get(field.ter_d).get_texture(gametime).texture_coordinates().top_left();
 			add_vertex(fields_to_draw.at(current_index), texture_offset);
 			add_vertex(fields_to_draw.at(bln_index), texture_offset);
 			add_vertex(fields_to_draw.at(brn_index), texture_offset);
@@ -180,13 +180,13 @@
 		const int rn_index = fields_to_draw.calculate_index(field.fx + 1, field.fy);
 		if (rn_index != -1) {
 			const FloatPoint texture_offset =
-			   terrains.get_unmutable(field.ter_r).get_texture(gametime).texture_coordinates().top_left();
+			   terrains.get(field.ter_r).get_texture(gametime).texture_coordinates().top_left();
 			add_vertex(fields_to_draw.at(current_index), texture_offset);
 			add_vertex(fields_to_draw.at(brn_index), texture_offset);
 			add_vertex(fields_to_draw.at(rn_index), texture_offset);
 		}
 	}
 
-	const Texture& texture = terrains.get_unmutable(0).get_texture(0);
+	const Texture& texture = terrains.get(0).get_texture(0);
 	gl_draw(texture.get_gl_texture(), texture.texture_coordinates().w, texture.texture_coordinates().h);
 }

=== modified file 'src/graphic/rendertarget.cc'
--- src/graphic/rendertarget.cc	2015-09-09 18:49:58 +0000
+++ src/graphic/rendertarget.cc	2015-10-18 20:57:50 +0000
@@ -25,7 +25,7 @@
 #include "graphic/graphic.h"
 #include "graphic/surface.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "wui/overlay_manager.h"
 
 using Widelands::BaseImmovable;

=== modified file 'src/logic/CMakeLists.txt'
--- src/logic/CMakeLists.txt	2015-07-05 11:07:43 +0000
+++ src/logic/CMakeLists.txt	2015-10-18 20:57:50 +0000
@@ -144,7 +144,6 @@
     militarysite.h
     nodecaps.h
     objective.h
-    parse_map_object_types.h
     partially_finished_building.cc
     partially_finished_building.h
     path.cc
@@ -184,9 +183,12 @@
     training_attribute.h
     trainingsite.cc
     trainingsite.h
-    tribe.cc
-    tribe.h
-    tribe_basic_info.h
+    tribes/tribe_basic_info.h
+    tribes/tribe_basic_info.cc
+    tribes/tribe_descr.cc
+    tribes/tribe_descr.h
+    tribes/tribes.h
+    tribes/tribes.cc
     walkingdir.cc
     walkingdir.h
     ware_descr.cc

=== modified file 'src/logic/bob.cc'
--- src/logic/bob.cc	2015-04-11 21:03:05 +0000
+++ src/logic/bob.cc	2015-10-18 20:57:50 +0000
@@ -20,6 +20,7 @@
 #include "logic/bob.h"
 
 #include <cstdlib>
+#include <memory>
 
 #include <stdint.h>
 
@@ -27,6 +28,7 @@
 #include "base/wexception.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"
@@ -40,42 +42,39 @@
 #include "logic/player.h"
 #include "logic/ship.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/widelands_geometry_io.h"
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
-#include "profile/profile.h"
 #include "wui/mapviewpixelconstants.h"
 
 
 namespace Widelands {
 
-BobDescr::BobDescr(MapObjectType object_type, const std::string& init_name,
-                  const std::string& init_descname,
-                  TribeDescr const* tribe)
+BobDescr::BobDescr(const std::string& init_descname, const MapObjectType init_type,
+						 MapObjectDescr::OwnerType owner_type, const LuaTable& table)
 	:
-	MapObjectDescr(object_type, init_name, init_descname),
-	owner_tribe_    (tribe)
+	MapObjectDescr(init_type,  table.get_string("name"), init_descname),
+	owner_type_   (owner_type),
+	// Only tribe bobs have a vision range, since it would be irrelevant for world bobs.
+	vision_range_ (owner_type == MapObjectDescr::OwnerType::kTribe ? table.get_int("vision_range") : 0)
 {
+	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)));
+	}
+	assert(is_animation_known("idle"));
 }
 
 /**
  * Only tribe bobs have a vision range, since it would be irrelevant
  * for world bobs.
  *
- * Currently, all bobs use the tribe's default vision range.
- *
  * \returns radius (in fields) of area that the bob can see
  */
 uint32_t BobDescr::vision_range() const
 {
-	if (owner_tribe_) {
-		if (upcast(const ShipDescr, ship, this))
-			return ship->vision_range();
-		return owner_tribe_->get_bob_vision_range();
-	}
-
-	return 0;
+	return vision_range_;
 }
 
 /**

=== modified file 'src/logic/bob.h'
--- src/logic/bob.h	2015-02-08 18:16:41 +0000
+++ src/logic/bob.h	2015-10-18 20:57:50 +0000
@@ -55,16 +55,17 @@
 public:
 	friend struct MapBobdataPacket;
 
-	BobDescr(MapObjectType type,
-	         const std::string& init_name,
-	         const std::string& init_descname,
-	         TribeDescr const* tribe);
+	BobDescr(const std::string& init_descname,
+				const MapObjectType type,
+				MapObjectDescr::OwnerType owner_type,
+				const LuaTable& table);
+
 	~BobDescr() override {}
 
 	Bob& create(EditorGameBase&, Player* owner, const Coords&) const;
 
-	TribeDescr const* get_owner_tribe() const {
-		return owner_tribe_;
+	MapObjectDescr::OwnerType get_owner_type() const {
+		return owner_type_;
 	}
 
 	virtual uint32_t movecaps() const {
@@ -76,7 +77,8 @@
 	virtual Bob& create_object() const = 0;
 
 private:
-	const TribeDescr* const owner_tribe_;  //  nullptr if world bob
+	const MapObjectDescr::OwnerType owner_type_;
+	const uint32_t vision_range_;
 	DISALLOW_COPY_AND_ASSIGN(BobDescr);
 };
 

=== modified file 'src/logic/buildcost.cc'
--- src/logic/buildcost.cc	2014-09-20 09:37:47 +0000
+++ src/logic/buildcost.cc	2015-10-18 20:57:50 +0000
@@ -22,35 +22,10 @@
 #include "base/wexception.h"
 #include "io/fileread.h"
 #include "io/filewrite.h"
-#include "logic/tribe.h"
-#include "profile/profile.h"
+#include "logic/tribes/tribe_descr.h"
 
 namespace Widelands {
 
-void Buildcost::parse(const TribeDescr & tribe, Section & buildcost_s)
-{
-	while (Section::Value const * const val = buildcost_s.get_next_val())
-		try {
-			WareIndex const idx = tribe.ware_index(val->get_name());
-			if (idx != INVALID_INDEX) {
-				if (count(idx))
-					throw wexception
-						("a buildcost item of this ware type has already been "
-						 "defined");
-				int32_t const value = val->get_int();
-				if (value < 1 || 255 < value)
-					throw wexception("count is out of range 1 .. 255");
-				insert(std::pair<WareIndex, uint8_t>(idx, value));
-			} else
-				throw wexception
-					("tribe does not define a ware type with this name");
-		} catch (const WException & e) {
-			throw wexception
-				("[buildcost] \"%s=%s\": %s",
-				 val->get_name(), val->get_string(), e.what());
-		}
-}
-
 /**
  * Compute the total buildcost.
  */
@@ -79,7 +54,7 @@
 			break;
 
 		WareIndex index = tribe.ware_index(name);
-		if (index == INVALID_INDEX) {
+		if (!tribe.has_ware(index)) {
 			log("buildcost: tribe %s does not define ware %s", tribe.name().c_str(), name.c_str());
 			fr.unsigned_8();
 		} else {

=== modified file 'src/logic/buildcost.h'
--- src/logic/buildcost.h	2015-02-08 18:16:41 +0000
+++ src/logic/buildcost.h	2015-10-18 20:57:50 +0000
@@ -33,7 +33,6 @@
 class TribeDescr;
 
 struct Buildcost : std::map<WareIndex, uint8_t> {
-	void parse(const TribeDescr & tribe, Section & buildcost_s);
 
 	uint32_t total() const;
 

=== modified file 'src/logic/building.cc'
--- src/logic/building.cc	2015-02-05 11:26:01 +0000
+++ src/logic/building.cc	2015-10-18 20:57:50 +0000
@@ -21,6 +21,7 @@
 
 #include <cstdio>
 #include <cstring>
+#include <memory>
 #include <sstream>
 
 #include <boost/algorithm/string.hpp>
@@ -44,9 +45,9 @@
 #include "logic/map.h"
 #include "logic/player.h"
 #include "logic/productionsite.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
+#include "logic/tribes/tribes.h"
 #include "logic/worker.h"
-#include "profile/profile.h"
 #include "sound/sound_handler.h"
 #include "wui/interactive_player.h"
 
@@ -54,129 +55,120 @@
 
 static const int32_t BUILDING_LEAVE_INTERVAL = 1000;
 
-
 BuildingDescr::BuildingDescr
-	(const MapObjectType _type, char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 const TribeDescr & _descr)
+	(const std::string& init_descname, const MapObjectType _type,
+	 const LuaTable& table, const EditorGameBase& egbase)
 	:
-	MapObjectDescr(_type, _name, _descname),
-	m_tribe         (_descr),
-	m_buildable     (true),
-	m_icon     (nullptr),
+	MapObjectDescr(_type, table.get_string("name"), init_descname),
+	egbase_         (egbase),
+	m_buildable     (false),
+	m_icon          (nullptr),
 	m_size          (BaseImmovable::SMALL),
 	m_mine          (false),
 	m_port          (false),
-	m_hints         (prof.get_section("aihints")),
-	m_global        (false),
+	m_enhancement   (INVALID_INDEX),
+	m_enhanced_from (INVALID_INDEX),
+	m_enhanced_building(false),
+	m_hints         (table.get_table("aihints")),
 	m_vision_range  (0)
 {
-	using boost::iequals;
+	i18n::Textdomain td("tribes");
 
 	try {
-		const auto& size = global_s.get_safe_string("size");
-		if      (iequals(size, "small"))
+		const std::string size = table.get_string("size");
+		if (boost::iequals(size, "small")) {
 			m_size = BaseImmovable::SMALL;
-		else if (iequals(size, "medium"))
+		} else if (boost::iequals(size, "medium")) {
 			m_size = BaseImmovable::MEDIUM;
-		else if (iequals(size, "big"))
+		} else if (boost::iequals(size, "big")) {
 			m_size = BaseImmovable::BIG;
-		else if (iequals(size, "mine")) {
+		} else if (boost::iequals(size, "mine")) {
 			m_size = BaseImmovable::SMALL;
 			m_mine = true;
-		} else if (iequals(size, "port")) {
+		} else if (boost::iequals(size, "port")) {
 			m_size = BaseImmovable::BIG;
 			m_port = true;
-		} else
+		} else {
 			throw GameDataError
 				("expected %s but found \"%s\"",
-				 "{\"small\"|\"medium\"|\"big\"|\"port\"|\"mine\"}", size);
+				 "{\"small\"|\"medium\"|\"big\"|\"port\"|\"mine\"}", size.c_str());
+		}
 	} catch (const WException & e) {
 		throw GameDataError("size: %s", e.what());
 	}
 
-	m_helptext_script = directory + "/help.lua";
-	if (!g_fs->file_exists(m_helptext_script))
-		m_helptext_script = "";
-
 	// Parse build options
-	m_buildable = global_s.get_bool("buildable", true);
-	m_destructible = global_s.get_bool("destructible", true);
-	m_enhancement = INVALID_INDEX;
-
-	if (Section::Value const * const enVal = global_s.get_next_val("enhancement"))
-	{
-		std::string const target_name = enVal->get_string();
-		if (target_name == name())
+	m_destructible = table.has_key("destructible") ? table.get_bool("destructible") : true;
+
+	if (table.has_key("enhancement")) {
+		const std::string enh = table.get_string("enhancement");
+
+		if (enh == name()) {
 			throw wexception("enhancement to same type");
-		BuildingIndex const en_i = tribe().building_index(target_name);
-		if (en_i != INVALID_INDEX) {
+		}
+		BuildingIndex const en_i = egbase_.tribes().building_index(enh);
+		if (egbase_.tribes().building_exists(en_i)) {
 			m_enhancement = en_i;
 
 			//  Merge the enhancements workarea info into this building's
 			//  workarea info.
-			const BuildingDescr * tmp_enhancement =
-				tribe().get_building_descr(en_i);
+			const BuildingDescr * tmp_enhancement = egbase_.tribes().get_building_descr(en_i);
 			for (std::pair<uint32_t, std::set<std::string>> area : tmp_enhancement->m_workarea_info)
 			{
 				std::set<std::string> & strs = m_workarea_info[area.first];
 				for (std::string str : area.second)
 					strs.insert(str);
 			}
-		} else
+		} else {
 			throw wexception
 				("\"%s\" has not been defined as a building type (wrong declaration order?)",
-				target_name.c_str());
-	}
-
-	m_enhanced_building = global_s.get_bool("enhanced_building", false);
-	m_global = directory.find("global/") < directory.size();
+				enh.c_str());
+		}
+	}
+
+	if (table.has_key("buildcost")) {
+		m_buildable = true;
+		try {
+			m_buildcost =
+					ImmovableDescr::parse_buildcost(table.get_table("buildcost"), egbase_.tribes());
+			m_return_dismantle = ImmovableDescr::parse_buildcost(
+											table.get_table("return_on_dismantle"), egbase_.tribes());
+		} catch (const WException & e) {
+			throw wexception
+					("A buildable building must define \"buildcost\" and \"return_on_dismantle\": %s",
+					 e.what());
+		}
+	}
+	if (table.has_key("enhancement_cost")) {
+		m_enhanced_building = true;
+		try {
+			m_enhance_cost = ImmovableDescr::parse_buildcost(
+									  table.get_table("enhancement_cost"), egbase_.tribes());
+			m_return_enhanced = ImmovableDescr::parse_buildcost(
+										  table.get_table("return_on_dismantle_on_enhanced"), egbase_.tribes());
+		} catch (const WException & e) {
+			throw wexception
+					("An enhanced building must define \"enhancement_cost\""
+					 "and \"return_on_dismantle_on_enhanced\": %s", e.what());
+		}
+	}
+
+	directory_ = table.get_string("directory");
+
 	if (m_buildable || m_enhanced_building) {
 		//  get build icon
-		m_icon_fname  = directory;
-		m_icon_fname += "/menu.png";
-
-		//  build animation
-		if (Section * const build_s = prof.get_section("build")) {
-			if (build_s->get_int("fps", -1) != -1)
-				throw wexception("fps defined for build animation!");
-			if (!is_animation_known("build"))
-				add_animation("build", g_gr->animations().load(directory, *build_s));
-		}
-
-		// Get costs
-		if (m_buildable) {
-			Section & buildcost_s = prof.get_safe_section("buildcost");
-			m_buildcost.parse(m_tribe, buildcost_s);
-			Section & returnsect_s = prof.get_safe_section("return_on_dismantle");
-			m_return_dismantle.parse(m_tribe, returnsect_s);
-		}
-
-		if (m_enhanced_building) {
-			Section & en_buildcost_s = prof.get_safe_section("enhancement_cost");
-			m_enhance_cost.parse(m_tribe, en_buildcost_s);
-			Section & en_returnsect_s = prof.get_safe_section("return_on_dismantle_on_enhanced");
-			m_return_enhanced.parse(m_tribe, en_returnsect_s);
-		}
-	} else if (m_global) {
-		//  get build icon for global buildings (for statistics window)
-		m_icon_fname  = directory;
-		m_icon_fname += "/menu.png";
-	}
-
-	{ //  parse basic animation data
-		Section & idle_s = prof.get_safe_section("idle");
-		if (!is_animation_known("idle"))
-			add_animation("idle", g_gr->animations().load(directory, idle_s));
-		if (Section * unoccupied = prof.get_section("unoccupied"))
-			if (!is_animation_known("unoccupied"))
-				add_animation("unoccupied", g_gr->animations().load(directory, *unoccupied));
-		if (Section * empty = prof.get_section("empty"))
-			if (!is_animation_known("empty"))
-				add_animation("empty", g_gr->animations().load(directory, *empty));
-	}
-
-	m_vision_range = global_s.get_int("vision_range");
+		m_icon_fname = table.get_string("icon");
+	}
+
+	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)));
+	}
+
+	if (table.has_key("vision_range")) {
+		m_vision_range = table.get_int("vision_range");
+	}
+	assert(is_animation_known("idle"));
 }
 
 
@@ -248,8 +240,8 @@
 Building & BuildingDescr::create_constructionsite() const
 {
 	BuildingDescr const * const descr =
-		m_tribe.get_building_descr
-			(m_tribe.safe_building_index("constructionsite"));
+		egbase_.tribes().get_building_descr
+			(egbase_.tribes().safe_building_index("constructionsite"));
 	ConstructionSite & csite =
 		dynamic_cast<ConstructionSite&>(descr->create_object());
 	csite.set_building(*this);
@@ -267,14 +259,14 @@
 */
 
 Building::Building(const BuildingDescr & building_descr) :
-PlayerImmovable(building_descr),
-m_optionswindow(nullptr),
-m_flag         (nullptr),
-m_anim(0),
-m_animstart(0),
-m_leave_time(0),
-m_defeating_player(0),
-m_seeing(false)
+	PlayerImmovable(building_descr),
+	m_optionswindow(nullptr),
+	m_flag         (nullptr),
+	m_anim(0),
+	m_animstart(0),
+	m_leave_time(0),
+	m_defeating_player(0),
+	m_seeing(false)
 {}
 
 Building::~Building()
@@ -499,11 +491,10 @@
 {
 	const bool fire           = burn_on_destroy();
 	const Coords pos          = m_position;
-	const TribeDescr & t     = descr().tribe();
 	PlayerImmovable::destroy(egbase);
 	// We are deleted. Only use stack variables beyond this point
 	if (fire)
-		egbase.create_immovable(pos, "destroyed_building", &t);
+		egbase.create_immovable(pos, "destroyed_building", MapObjectDescr::OwnerType::kTribe);
 }
 
 
@@ -827,8 +818,9 @@
 
 void Building::add_worker(Worker & worker) {
 	if (!get_workers().size()) {
-		if (worker.descr().name() != "builder")
+		if (owner().tribe().safe_worker_index(worker.descr().name()) != owner().tribe().builder()) {
 			set_seeing(true);
+		}
 	}
 	PlayerImmovable::add_worker(worker);
 	workers_changed();

=== modified file 'src/logic/building.h'
--- src/logic/building.h	2015-02-08 18:16:41 +0000
+++ src/logic/building.h	2015-10-18 20:57:50 +0000
@@ -36,6 +36,7 @@
 #include "logic/wareworker.h"
 #include "logic/widelands.h"
 #include "logic/workarea_info.h"
+#include "scripting/lua_table.h"
 
 namespace UI {class Window;}
 struct BuildingHints;
@@ -59,19 +60,17 @@
 /*
  * Common to all buildings!
  */
-struct BuildingDescr : public MapObjectDescr {
+class BuildingDescr : public MapObjectDescr {
+public:
 	using FormerBuildings = std::vector<BuildingIndex>;
 
-	BuildingDescr
-		(MapObjectType type, char const * _name, char const * _descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 const TribeDescr &);
+	BuildingDescr(const std::string& init_descname, MapObjectType type,
+					  const LuaTable& t, const EditorGameBase& egbase);
 	~BuildingDescr() override {}
 
 	bool is_buildable   () const {return m_buildable;}
 	bool is_destructible() const {return m_destructible;}
 	bool is_enhanced    () const {return m_enhanced_building;}
-	bool global() const {return m_global;}
 
 	/**
 	 * The build cost for direct construction
@@ -92,6 +91,8 @@
 	 * The returned wares for a enhaced building
 	 */
 	const Buildcost & returned_wares_enhanced() const {return m_return_enhanced;}
+
+	std::string directory() const {return directory_;}
 	const Image* get_icon() const {return m_icon;}
 	std::string icon_name() const {return m_icon_fname;}
 	int32_t get_size() const {return m_size;}
@@ -102,6 +103,10 @@
 	// Returns the enhancement this building can become or
 	// INVALID_INDEX if it cannot be enhanced.
 	const BuildingIndex & enhancement() const {return m_enhancement;}
+	// Returns the building from which this building can be enhanced or
+	// INVALID_INDEX if it cannot be built as an enhanced building.
+	const BuildingIndex& enhanced_from() const {return m_enhanced_from;}
+	void set_enhanced_from(const BuildingIndex& index) {m_enhanced_from = index;}
 
 	/// Create a building of this type in the game. Calls init, which does
 	/// different things for different types of buildings (such as conquering
@@ -122,10 +127,7 @@
 
 	virtual uint32_t get_conquers() const;
 	virtual uint32_t vision_range() const;
-	bool has_help_text() const {return m_helptext_script != "";}
-	std::string helptext_script() const {return m_helptext_script;}
 
-	const TribeDescr & tribe() const {return m_tribe;}
 	WorkareaInfo m_workarea_info;
 
 	virtual int32_t suitability(const Map &, FCoords) const;
@@ -136,23 +138,23 @@
 	Building & create_constructionsite() const;
 
 private:
-	const TribeDescr & m_tribe;
+	const EditorGameBase& egbase_;
 	bool          m_buildable;       // the player can build this himself
 	bool          m_destructible;    // the player can destruct this himself
 	Buildcost     m_buildcost;
 	Buildcost     m_return_dismantle; // Returned wares on dismantle
 	Buildcost     m_enhance_cost;     // cost for enhancing
 	Buildcost     m_return_enhanced;   // Returned ware for dismantling an enhanced building
+	std::string   directory_;         // The directory where the init files are located
 	const Image*     m_icon;       // if buildable: picture in the build dialog
 	std::string   m_icon_fname; // filename for this icon
 	int32_t       m_size;            // size of the building
 	bool          m_mine;
 	bool          m_port;
 	BuildingIndex  m_enhancement;
+	BuildingIndex  m_enhanced_from; // The building this building was enhanced from, or INVALID_INDEX
 	bool          m_enhanced_building; // if it is one, it is bulldozable
 	BuildingHints m_hints;             // hints (knowledge) for computer players
-	bool          m_global;            // whether this is a "global" building
-	std::string   m_helptext_script;
 
 	// for migration, 0 is the default, meaning get_conquers() + 4
 	uint32_t m_vision_range;
@@ -161,7 +163,7 @@
 
 
 class Building : public PlayerImmovable {
-	friend struct BuildingDescr;
+	friend class BuildingDescr;
 	friend class MapBuildingdataPacket;
 
 	MO_DESCR(BuildingDescr)
@@ -177,7 +179,7 @@
 	using FormerBuildings = std::vector<BuildingIndex>;
 
 public:
-	Building(const BuildingDescr &);
+	Building(const BuildingDescr&);
 	virtual ~Building();
 
 	void load_finish(EditorGameBase &) override;

=== modified file 'src/logic/carrier.h'
--- src/logic/carrier.h	2014-09-10 08:55:04 +0000
+++ src/logic/carrier.h	2015-10-18 20:57:50 +0000
@@ -25,17 +25,11 @@
 
 namespace Widelands {
 
-struct CarrierDescr : public WorkerDescr {
-	CarrierDescr(char const* const _name,
-	              char const* const _descname,
-	              const std::string& directory,
-	              Profile& prof,
-	              Section& global_s,
-	              const TribeDescr& _tribe)
-		:
-		WorkerDescr(MapObjectType::CARRIER, _name, _descname, directory, prof, global_s, _tribe)
-	{
-	}
+class CarrierDescr : public WorkerDescr {
+public:
+	CarrierDescr(const std::string& init_descname,
+					 const LuaTable& table, const EditorGameBase& egbase) :
+		WorkerDescr(init_descname, MapObjectType::CARRIER, table, egbase) {}
 	~CarrierDescr() override {}
 
 protected:

=== modified file 'src/logic/constructionsite.cc'
--- src/logic/constructionsite.cc	2015-05-30 12:19:57 +0000
+++ src/logic/constructionsite.cc	2015-10-18 20:57:50 +0000
@@ -33,33 +33,22 @@
 #include "graphic/text_constants.h"
 #include "logic/editor_game_base.h"
 #include "logic/game.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/worker.h"
-#include "profile/profile.h"
 #include "sound/sound_handler.h"
 #include "ui_basic/window.h"
 #include "wui/interactive_gamebase.h"
 
 namespace Widelands {
 
-ConstructionSiteDescr::ConstructionSiteDescr
-	(char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 const TribeDescr & _tribe)
-	:
-	BuildingDescr(MapObjectType::CONSTRUCTIONSITE, _name, _descname, directory, prof, global_s, _tribe)
+ConstructionSiteDescr::ConstructionSiteDescr(const std::string& init_descname,
+															const LuaTable& table,
+															const EditorGameBase& egbase)
+	: BuildingDescr(init_descname, MapObjectType::CONSTRUCTIONSITE, table, egbase)
 {
 	add_attribute(MapObject::CONSTRUCTIONSITE);
-
-	{ // animation when a worker entered the site
-		Section & sec = prof.get_safe_section("idle_with_worker");
-		if (!is_animation_known("idle_with_worker"))
-			add_animation
-				("idle_with_worker", g_gr->animations().load(directory, sec));
-	}
 }
 
-
 Building & ConstructionSiteDescr::create_object() const {
 	return *new ConstructionSite(*this);
 }
@@ -129,7 +118,7 @@
 	if (!m_old_buildings.empty()) {
 		// Enhancement
 		BuildingIndex was_index = m_old_buildings.back();
-		const BuildingDescr* was_descr = descr().tribe().get_building_descr(was_index);
+		const BuildingDescr* was_descr = owner().tribe().get_building_descr(was_index);
 		m_info.was = was_descr;
 		buildcost = &m_building->enhancement_cost();
 	} else {
@@ -167,7 +156,7 @@
 
 	if (m_work_steps <= m_work_completed) {
 		// Put the real building in place
-		BuildingIndex becomes_idx = descr().tribe().building_index(m_building->name());
+		BuildingIndex becomes_idx = owner().tribe().building_index(m_building->name());
 		m_old_buildings.push_back(becomes_idx);
 		Building & b =
 			m_building->create(egbase, owner(), m_position, false, false, m_old_buildings);
@@ -267,7 +256,7 @@
 		WaresQueue * queue = iqueue;
 		if (queue->get_filled() > queue->get_max_fill()) {
 			queue->set_filled(queue->get_filled() - 1);
-			const WareDescr & wd = *descr().tribe().get_ware_descr(queue->get_ware());
+			const WareDescr & wd = *owner().tribe().get_ware_descr(queue->get_ware());
 			WareInstance & ware = *new WareInstance(queue->get_ware(), &wd);
 			ware.init(game);
 			worker.start_task_dropoff(game, ware);
@@ -388,7 +377,7 @@
 		dst.drawanimrect(pos, anim_idx, tanim - FRAME_LENGTH, get_owner(), Rect(Point(0, 0), w, h - lines));
 	else if (!m_old_buildings.empty()) {
 		BuildingIndex prev_idx = m_old_buildings.back();
-		const BuildingDescr* prev_building = descr().tribe().get_building_descr(prev_idx);
+		const BuildingDescr* prev_building = owner().tribe().get_building_descr(prev_idx);
 		//  Is the first picture but there was another building here before,
 		//  get its most fitting picture and draw it instead.
 		uint32_t prev_building_anim_idx;

=== modified file 'src/logic/constructionsite.h'
--- src/logic/constructionsite.h	2014-09-10 16:57:31 +0000
+++ src/logic/constructionsite.h	2015-10-18 20:57:50 +0000
@@ -24,7 +24,7 @@
 
 #include "base/macros.h"
 #include "logic/partially_finished_building.h"
-#include "logic/player.h"
+#include "scripting/lua_table.h"
 
 namespace Widelands {
 
@@ -32,6 +32,15 @@
 class Request;
 class WaresQueue;
 
+/// Per-player and per-field constructionsite information
+struct ConstructionsiteInformation {
+	ConstructionsiteInformation() : becomes(nullptr), was(nullptr), totaltime(0), completedtime(0) {}
+	const BuildingDescr* becomes; // Also works as a marker telling whether there is a construction site.
+	const BuildingDescr* was; // only valid if "becomes" is an enhanced building.
+	uint32_t totaltime;
+	uint32_t completedtime;
+};
+
 /*
 ConstructionSite
 ----------------
@@ -50,11 +59,9 @@
 Every tribe has exactly one ConstructionSiteDescr.
 The ConstructionSite's idling animation is the basic construction site marker.
 */
-struct ConstructionSiteDescr : public BuildingDescr {
-	ConstructionSiteDescr
-		(char const * name, char const * descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 const TribeDescr & tribe);
+class ConstructionSiteDescr : public BuildingDescr {
+public:
+	ConstructionSiteDescr(const std::string& init_descname, const LuaTable& t, const EditorGameBase& egbase);
 	~ConstructionSiteDescr() override {}
 
 	Building & create_object() const override;
@@ -73,7 +80,7 @@
 public:
 	ConstructionSite(const ConstructionSiteDescr & descr);
 
-	const Player::ConstructionsiteInformation & get_info() {return m_info;}
+	const ConstructionsiteInformation & get_info() {return m_info;}
 
 	WaresQueue & waresqueue(WareIndex) override;
 
@@ -104,7 +111,7 @@
 	int32_t     m_fetchfromflag;  // # of wares to fetch from flag
 
 	bool        m_builder_idle;   // used to determine whether the builder is idle
-	Player::ConstructionsiteInformation m_info; // asked for by player point of view for the gameview
+	ConstructionsiteInformation m_info; // asked for by player point of view for the gameview
 };
 
 }

=== modified file 'src/logic/critter.cc'
--- src/logic/critter.cc	2015-04-11 21:03:05 +0000
+++ src/logic/critter.cc	2015-10-18 20:57:50 +0000
@@ -35,43 +35,14 @@
 #include "logic/field.h"
 #include "logic/game.h"
 #include "logic/game_data_error.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/world/world.h"
-#include "map_io/one_world_legacy_lookup_table.h"
-#include "profile/profile.h"
+#include "map_io/world_legacy_lookup_table.h"
 #include "scripting/lua_table.h"
 
 
 namespace Widelands {
 
-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 const* const string = section->get_string(std::to_string(idx).c_str(), 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, MapObjectDescr& 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 CritterProgram::parse(const std::vector<std::string>& lines) {
 	for (const std::string& line : lines) {
 		try {
@@ -131,66 +102,10 @@
 ===========================================================================
 */
 
-CritterDescr::CritterDescr(char const* const _name,
-                                     char const* const _descname,
-                                     const std::string& directory,
-                                     Profile& prof,
-                                     Section& global_s,
-												 TribeDescr & _tribe)
-	:
-	BobDescr(MapObjectType::CRITTER, _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>());
-	}
-
-	const std::string defaultpics = (boost::format("%s_walk_!!_??.png") % _name).str();
-	m_walk_anims.parse(*this, directory, prof, "walk", false, defaultpics);
-
-	while (Section::Value const * const v = global_s.get_next_val("program")) {
-		std::string program_name = v->get_string();
-		std::transform
-			(program_name.begin(), program_name.end(), program_name.begin(),
-			 tolower);
-		CritterProgram * prog = nullptr;
-		try {
-			if (m_programs.count(program_name))
-				throw wexception("this program has already been declared");
-
-			prog = new CritterProgram(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;
-			throw wexception
-				("Parse error in program %s: %s", v->get_string(), e.what());
-		}
-	}
-}
-
-CritterDescr::CritterDescr(const LuaTable& table)
-	: BobDescr(MapObjectType::CRITTER, 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");
-	}
+CritterDescr::CritterDescr(const std::string& init_descname, const LuaTable& table)
+	: BobDescr(init_descname, MapObjectType::CRITTER, MapObjectDescr::OwnerType::kWorld, table)
+{
+	add_directional_animation(&m_walk_anims, "walk");
 
 	add_attributes(
 	   table.get_table("attributes")->array_entries<std::string>(), std::set<uint32_t>());
@@ -400,7 +315,7 @@
 MapObject::Loader* Critter::load(EditorGameBase& egbase,
 												  MapObjectLoader& mol,
                                       FileRead& fr,
-                                      const OneWorldLegacyLookupTable& lookup_table) {
+                                      const WorldLegacyLookupTable& lookup_table) {
 	std::unique_ptr<Loader> loader(new Loader);
 
 	try {
@@ -418,11 +333,8 @@
 				descr =
 					dynamic_cast<const CritterDescr*>(egbase.world().get_bob_descr(critter_name));
 			} else {
-				egbase.manually_load_tribe(owner);
-
-				if (const TribeDescr * tribe = egbase.get_tribe(owner))
-					descr = dynamic_cast<const CritterDescr *>
-						(tribe->get_bob_descr(critter_name));
+				throw GameDataError
+					("Tribes don't have critters %s/%s", owner.c_str(), critter_name.c_str());
 			}
 
 			if (!descr)
@@ -447,8 +359,10 @@
 	fw.unsigned_8(HeaderCritter);
 	fw.unsigned_8(kCurrentPacketVersion);
 
-	std::string owner =
-		descr().get_owner_tribe() ? descr().get_owner_tribe()->name() : "world";
+	const std::string owner =
+		descr().get_owner_type() == MapObjectDescr::OwnerType::kTribe ?
+				"" : // Tribes don't have critters
+				"world";
 	fw.c_string(owner);
 	fw.c_string(descr().name());
 

=== modified file 'src/logic/critter.h'
--- src/logic/critter.h	2014-09-14 11:31:58 +0000
+++ src/logic/critter.h	2015-10-18 20:57:50 +0000
@@ -25,7 +25,7 @@
 #include "graphic/diranimations.h"
 
 class LuaTable;
-class OneWorldLegacyLookupTable;
+class WorldLegacyLookupTable;
 
 namespace Widelands {
 
@@ -36,14 +36,7 @@
 // Description
 //
 struct CritterDescr : BobDescr {
-	CritterDescr
-		(char const* const _name,
-		 char const* const _descname,
-		 const std::string& directory,
-		 Profile& prof,
-		 Section& global_s,
-		 TribeDescr & _tribe);
-	CritterDescr(const LuaTable&);
+	CritterDescr(const std::string& init_descname, const LuaTable&);
 	~CritterDescr() override;
 
 	Bob & create_object() const override;
@@ -78,7 +71,7 @@
 	void save(EditorGameBase &, MapObjectSaver &, FileWrite &) override;
 
 	static MapObject::Loader*
-	load(EditorGameBase&, MapObjectLoader&, FileRead&, const OneWorldLegacyLookupTable& lookup_table);
+	load(EditorGameBase&, MapObjectLoader&, FileRead&, const WorldLegacyLookupTable& lookup_table);
 
 protected:
 	struct Loader : Bob::Loader {

=== modified file 'src/logic/description_maintainer.h'
--- src/logic/description_maintainer.h	2014-11-27 21:29:21 +0000
+++ src/logic/description_maintainer.h	2015-10-18 20:57:50 +0000
@@ -27,47 +27,40 @@
 #include <vector>
 
 #include "base/wexception.h"
+#include "logic/widelands.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
 	// index of the entry. Ownership is taken.
-	int32_t add(T* entry);
+	Widelands::WareIndex add(T* entry);
 
 	// Returns the number of entries in the container.
-	size_t get_nitems() const {return items_.size();}
-	// TODO(sirver): Remove get_nitems().
-
-	size_t size() const {return items_.size();}
+	Widelands::WareIndex size() const {return items_.size();}
 
 	// Returns the entry with the given 'name' if it exists or nullptr.
 	T* exists(const std::string& name) const;
 
-	// Returns the index of the entry with the given 'name' or -1 if the entry
+	// Returns the index of the entry with the given 'name' or INVALID_INDEX if the entry
 	// is not in the container.
-	int32_t get_index(const std::string& name) const {
-		// TODO(sirver): this should return INVALID_INDEX
+	Widelands::WareIndex get_index(const std::string& name) const {
 		NameToIndexMap::const_iterator i = name_to_index_.find(name);
-		if (i == name_to_index_.end())
-			return -1;
+		if (i == name_to_index_.end()) {
+			return Widelands::INVALID_INDEX;
+		}
 		return i->second;
 	}
 
 	// Returns the entry with the given 'idx' or nullptr if 'idx' is out of
-	// bound. Ownership is retained.
-	// TODO(sirver): remove get() and use get_mutable
-	T* get(const int32_t idx) const {
-		return (idx >= 0 && idx < static_cast<int32_t>(items_.size())) ? items_[idx].get() : nullptr;
-	}
-	T* get_mutable(const int32_t idx) const {
-		return get(idx);
+	// bounds. Ownership is retained.
+	T* get_mutable(const Widelands::WareIndex idx) const {
+		return (idx < items_.size()) ? items_[idx].get() : nullptr;
 	}
 
 	// Returns the entry at 'index'. If 'index' is out of bounds the result is
 	// undefined.
-	// TODO(sirver): this should be called get and the other should be called get_mutable.
-	T& get_unmutable(const uint32_t index) const {
-		assert(0 <= index && index < items_.size());
+	T& get(const Widelands::WareIndex index) const {
+		assert(index < items_.size());
 		return *items_.at(index);
 	}
 
@@ -79,19 +72,20 @@
 
 
 template <typename T>
-int32_t DescriptionMaintainer<T>::add(T * const item) {
+Widelands::WareIndex DescriptionMaintainer<T>::add(T * const item) {
 	if (exists(item->name()) != nullptr) {
 		throw wexception("Tried to add %s twice.", item->name().c_str());
 	}
 	int32_t index = items_.size();
+	assert(index < (Widelands::INVALID_INDEX - 2)); // allowing for kInvalidIndex
 	items_.emplace_back(item);
 	name_to_index_[item->name()] = index;
 	return index;
 }
 
 template <typename T> T* DescriptionMaintainer<T>::exists(const std::string& name) const {
-	int32_t index = get_index(name);
-	if (index < 0) return nullptr;
+	auto index = get_index(name);
+	if (index == Widelands::INVALID_INDEX) return nullptr;
 	return items_[index].get();
 }
 

=== modified file 'src/logic/dismantlesite.cc'
--- src/logic/dismantlesite.cc	2014-09-10 17:52:49 +0000
+++ src/logic/dismantlesite.cc	2015-10-18 20:57:50 +0000
@@ -32,18 +32,15 @@
 #include "graphic/rendertarget.h"
 #include "logic/editor_game_base.h"
 #include "logic/game.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/worker.h"
 #include "sound/sound_handler.h"
 
 namespace Widelands {
 
-DismantleSiteDescr::DismantleSiteDescr
-	(char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 const TribeDescr & _tribe)
-	:
-	BuildingDescr(MapObjectType::DISMANTLESITE, _name, _descname, directory, prof, global_s, _tribe)
+DismantleSiteDescr::DismantleSiteDescr(const std::string& init_descname,
+													const LuaTable& table, const EditorGameBase& egbase)
+	: BuildingDescr(init_descname, MapObjectType::DISMANTLESITE, table, egbase)
 {
 	add_attribute(MapObject::Attribute::CONSTRUCTIONSITE); // Yep, this is correct.
 }
@@ -134,7 +131,7 @@
 {
 	for (BuildingIndex former_idx : building->get_former_buildings()) {
 		const std::map<WareIndex, uint8_t> * return_wares;
-		const BuildingDescr* former_descr = building->descr().tribe().get_building_descr(former_idx);
+		const BuildingDescr* former_descr = building->owner().tribe().get_building_descr(former_idx);
 		if (former_idx != building->get_former_buildings().front()) {
 			return_wares = & former_descr->returned_wares_enhanced();
 		} else {
@@ -196,7 +193,7 @@
 			//update statistics
 			owner().ware_produced(wq.get_ware());
 
-			const WareDescr & wd = *descr().tribe().get_ware_descr(wq.get_ware());
+			const WareDescr & wd = *owner().tribe().get_ware_descr(wq.get_ware());
 			WareInstance & ware = *new WareInstance(wq.get_ware(), &wd);
 			ware.init(game);
 			worker.start_task_dropoff(game, ware);

=== modified file 'src/logic/dismantlesite.h'
--- src/logic/dismantlesite.h	2014-09-10 10:18:46 +0000
+++ src/logic/dismantlesite.h	2015-10-18 20:57:50 +0000
@@ -24,6 +24,7 @@
 #include "logic/building.h"
 #include "logic/partially_finished_building.h"
 #include "logic/player.h"
+#include "scripting/lua_table.h"
 
 namespace Widelands {
 
@@ -42,13 +43,9 @@
 */
 class DismantleSite;
 
-struct DismantleSiteDescr : public BuildingDescr {
-	DismantleSiteDescr(char const* name,
-	                    char const* descname,
-	                    const std::string& directory,
-	                    Profile&,
-	                    Section& global_s,
-							  const TribeDescr& tribe);
+class DismantleSiteDescr : public BuildingDescr {
+public:
+	DismantleSiteDescr(const std::string& init_descname, const LuaTable& t, const EditorGameBase& egbase);
 	~DismantleSiteDescr() override {}
 
 	Building& create_object() const override;

=== modified file 'src/logic/editor_game_base.cc'
--- src/logic/editor_game_base.cc	2015-02-09 05:57:08 +0000
+++ src/logic/editor_game_base.cc	2015-10-18 20:57:50 +0000
@@ -32,21 +32,20 @@
 #include "graphic/color.h"
 #include "graphic/font_handler.h"
 #include "graphic/graphic.h"
-#include "graphic/image_io.h"
-#include "graphic/texture_atlas.h"
-#include "io/filesystem/layered_filesystem.h"
 #include "logic/battle.h"
 #include "logic/building.h"
 #include "logic/constants.h"
 #include "logic/dismantlesite.h"
 #include "logic/findimmovable.h"
 #include "logic/game.h"
+#include "logic/game_data_error.h"
 #include "logic/instances.h"
 #include "logic/mapregion.h"
 #include "logic/player.h"
 #include "logic/playersmanager.h"
 #include "logic/roadtype.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
+#include "logic/tribes/tribes.h"
 #include "logic/ware_descr.h"
 #include "logic/worker.h"
 #include "logic/world/world.h"
@@ -86,9 +85,6 @@
 	delete map_;
 	delete player_manager_.release();
 
-	for (TribeDescr* tribe_descr : tribes_) {
-		delete tribe_descr;
-	}
 	if (g_gr) { // dedicated does not use the sound_handler
 		assert(this == g_sound_handler.egbase_);
 		g_sound_handler.egbase_ = nullptr;
@@ -127,6 +123,34 @@
 	return world_.get();
 }
 
+const Tribes& EditorGameBase::tribes() const {
+	// Const casts are evil, but this is essentially lazy evaluation and the
+	// caller should really not modify this.
+	return *const_cast<EditorGameBase*>(this)->mutable_tribes();
+}
+
+Tribes* EditorGameBase::mutable_tribes() {
+	if (!tribes_) {
+		// We need to make sure that the world is loaded first for some attribute checks in the worker programs.
+		world();
+
+		// Lazy initialization of Tribes. We need to create the pointer to the
+		// tribe immediately though, because the lua scripts need to have access
+		// to tribes through this method already.
+		ScopedTimer timer("Loading the tribes took %ums");
+		tribes_.reset(new Tribes(*this));
+
+		try {
+			lua_->run_script("tribes/init.lua");
+		} catch (const WException& e) {
+			log("Could not read tribes information: %s", e.what());
+			throw;
+		}
+	}
+	return tribes_.get();
+}
+
+
 InteractiveGameBase* EditorGameBase::get_igbase()
 {
 	return dynamic_cast<InteractiveGameBase *>(get_ibase());
@@ -151,24 +175,6 @@
 			name, team);
 }
 
-/// Load the given tribe into structure
-const TribeDescr & EditorGameBase::manually_load_tribe
-	(const std::string & tribe)
-{
-	for (const TribeDescr* tribe_descr : tribes_) {
-		if (tribe_descr->name() == tribe) {
-			return *tribe_descr;
-		}
-	}
-
-	TribeDescr & result = *new TribeDescr(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);
-	tribes_.push_back(&result);
-	return result;
-}
-
 Player* EditorGameBase::get_player(const int32_t n) const
 {
 	return player_manager_->get_player(n);
@@ -179,19 +185,6 @@
 	return player_manager_->player(n);
 }
 
-
-
-/// Returns a tribe description from the internally loaded list
-const TribeDescr * EditorGameBase::get_tribe(const std::string& tribename) const
-{
-	for (const TribeDescr* tribe : tribes_) {
-		if (tribe->name() == tribename) {
-			return tribe;
-		}
-	}
-	return nullptr;
-}
-
 void EditorGameBase::inform_players_about_ownership
 	(MapIndex const i, PlayerNumber const new_owner)
 {
@@ -236,36 +229,15 @@
 
 
 /**
- * Load and prepare detailled game data.
+ * Load and prepare detailed game data.
  * This happens once just after the host has started the game and before the
  * graphics are loaded.
  */
 void EditorGameBase::postload()
 {
-	uint32_t id;
-	int32_t pid;
-
 	// Postload tribes
-	id = 0;
-	while (id < tribes_.size()) {
-		for (pid = 1; pid <= MAX_PLAYERS; ++pid)
-			if (const Player * const plr = get_player(pid))
-				if (&plr->tribe() == tribes_[id])
-					break;
-
-		if
-			(pid <= MAX_PLAYERS
-			 ||
-			 !dynamic_cast<const Game *>(this))
-		{ // if this is editor, load the tribe anyways
-			// the tribe is used, postload it
-			tribes_[id]->postload(*this);
-			++id;
-		} else {
-			delete tribes_[id]; // the tribe is no longer used, remove it
-			tribes_.erase(tribes_.begin() + id);
-		}
-	}
+	assert(tribes_);
+	tribes_->postload();
 
 	// TODO(unknown): postload players? (maybe)
 }
@@ -276,43 +248,11 @@
  * This function needs to be called once at startup when the graphics system is ready.
  * If the graphics system is to be replaced at runtime, the function must be called after that has happened.
  */
-void EditorGameBase::load_graphics(UI::ProgressWindow & loader_ui)
+void EditorGameBase::load_graphics(UI::ProgressWindow& loader_ui)
 {
-	loader_ui.step(_("Loading world data"));
-
-	for (TribeDescr* tribe_descr : tribes_) {
-		loader_ui.stepf(_("Loading tribes"));
-		tribe_descr->load_graphics();
-	}
-
-	// Construct and hold on to the texture atlas that contains all road images.
-	TextureAtlas ta;
-
-	// These will be deleted at the end of the method.
-	std::vector<std::unique_ptr<Texture>> individual_textures_;
-	for (auto* tribe : tribes_) {
-		for (const std::string& texture_path : tribe->normal_road_paths()) {
-			individual_textures_.emplace_back(load_image(texture_path, g_fs));
-			ta.add(*individual_textures_.back());
-		}
-		for (const std::string& texture_path : tribe->busy_road_paths()) {
-			individual_textures_.emplace_back(load_image(texture_path, g_fs));
-			ta.add(*individual_textures_.back());
-		}
-	}
-
-	std::vector<std::unique_ptr<Texture>> textures;
-	road_texture_ = ta.pack(&textures);
-
-	size_t next_texture_to_move = 0;
-	for (auto* tribe : tribes_) {
-		for (size_t i = 0; i < tribe->normal_road_paths().size(); ++i) {
-			tribe->add_normal_road_texture(std::move(textures.at(next_texture_to_move++)));
-		}
-		for (size_t i = 0; i < tribe->busy_road_paths().size(); ++i) {
-			tribe->add_busy_road_texture(std::move(textures.at(next_texture_to_move++)));
-		}
-	}
+	assert(tribes_);
+	loader_ui.step(_("Loading graphics"));
+	tribes_->load_graphics();
 }
 
 /**
@@ -378,43 +318,26 @@
 
 /**
  * Instantly create a bob at the given x/y location.
- *
- * idx is the bob type.
  */
 Bob & EditorGameBase::create_bob(Coords c, const BobDescr & descr, Player * owner)
 {
 	return descr.create(*this, owner, c);
 }
 
-
-Bob & EditorGameBase::create_bob
-	(Coords const c,
-	 int const idx, TribeDescr const * const tribe, Player * owner)
-{
-	const BobDescr & descr =
-		*
-		(tribe ?
-		 tribe->get_bob_descr(idx)
-		 :
-		 world().get_bob_descr(idx));
-
-	return create_bob(c, descr, owner);
+/**
+ * Instantly create a critter at the given x/y location.
+ *
+ */
+
+Bob& EditorGameBase::create_critter(Coords const c, int const bob_type_idx, Player* owner) {
+	return create_bob(c, *world().get_bob_descr(bob_type_idx), owner);
 }
 
-Bob & EditorGameBase::create_bob
-	(Coords c, const std::string & name, const Widelands::TribeDescr * const tribe,
-	 Player * owner)
-{
-	const BobDescr * descr =
-		tribe ?
-		tribe->get_bob_descr(name) :
-		world().get_bob_descr(name);
-
-	if (!descr)
-		throw wexception
-			("create_bob(%i,%i,%s,%s): bob not found",
-			 c.x, c.y, name.c_str(), tribe ? tribe->name().c_str() : "world");
-
+Bob& EditorGameBase::create_critter(Coords c, const std::string& name, Player* owner) {
+	const BobDescr* descr = world().get_bob_descr(name);
+	if (descr == nullptr)
+		throw GameDataError("create_critter(%i,%i,%s,%s): critter not found", c.x, c.y, name.c_str(),
+		                    owner->get_name().c_str());
 	return create_bob(c, *descr, owner);
 }
 
@@ -428,12 +351,12 @@
 ===============
 */
 Immovable & EditorGameBase::create_immovable
-	(Coords const c, uint32_t const idx, TribeDescr const * const tribe)
+	(Coords const c, uint32_t const idx, MapObjectDescr::OwnerType type)
 {
 	const ImmovableDescr & descr =
 		*
-		(tribe ?
-		 tribe->get_immovable_descr(idx)
+		(type == MapObjectDescr::OwnerType::kTribe ?
+		 tribes().get_immovable_descr(idx)
 		 :
 		 world().get_immovable_descr(idx));
 	assert(&descr);
@@ -443,20 +366,46 @@
 }
 
 Immovable & EditorGameBase::create_immovable
-	(Coords const c, const std::string & name, TribeDescr const * const tribe)
+	(Coords const c, const std::string & name, MapObjectDescr::OwnerType type)
 {
-	const int32_t idx =
-		tribe ?
-		tribe->get_immovable_index(name.c_str())
-		:
-		world().get_immovable_index(name.c_str());
-	if (idx < 0)
-		throw wexception
-			("EditorGameBase::create_immovable(%i, %i): %s is not defined for "
-			 "%s",
-			 c.x, c.y, name.c_str(), tribe ? tribe->name().c_str() : "world");
-
-	return create_immovable(c, idx, tribe);
+	WareIndex idx;
+	if (type == MapObjectDescr::OwnerType::kTribe) {
+		idx = tribes().immovable_index(name.c_str());
+		if (!tribes().immovable_exists(idx)) {
+			throw wexception
+				("EditorGameBase::create_immovable(%i, %i): %s is not defined for the tribes",
+				 c.x, c.y, name.c_str());
+		}
+	} else {
+		idx =  world().get_immovable_index(name.c_str());
+		if (idx == INVALID_INDEX) {
+			throw wexception
+				("EditorGameBase::create_immovable(%i, %i): %s is not defined for the world",
+				 c.x, c.y, name.c_str());
+		}
+	}
+	return create_immovable(c, idx, type);
+}
+
+/**
+ * Instantly create a ship at the given x/y location.
+ *
+ * idx is the bob type.
+ */
+
+Bob& EditorGameBase::create_ship(Coords const c, int const ship_type_idx, Player* owner) {
+	const BobDescr* descr = dynamic_cast<const BobDescr*>(tribes().get_ship_descr(ship_type_idx));
+	return create_bob(c, *descr, owner);
+}
+
+Bob& EditorGameBase::create_ship(Coords c, const std::string& name, Player* owner) {
+	try {
+		int idx = tribes().safe_ship_index(name);
+		return create_ship(c, idx, owner);
+	} catch (const GameDataError& e) {
+		throw GameDataError("create_ship(%i,%i,%s,%s): ship not found: %s", c.x, c.y, name.c_str(),
+		                    owner->get_name().c_str(), e.what());
+	}
 }
 
 /*

=== modified file 'src/logic/editor_game_base.h'
--- src/logic/editor_game_base.h	2015-06-10 06:46:40 +0000
+++ src/logic/editor_game_base.h	2015-10-18 20:57:50 +0000
@@ -26,7 +26,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "graphic/texture.h"
 #include "logic/bob.h"
 #include "logic/building.h"
 #include "logic/map.h"
@@ -44,12 +43,13 @@
 
 class Battle;
 class Bob;
-struct BuildingDescr;
+class BuildingDescr;
 class Immovable;
 class Map;
 struct ObjectManager;
 class Player;
 struct PlayerImmovable;
+class Tribes;
 class TribeDescr;
 struct Flag;
 struct AttackController;
@@ -138,14 +138,16 @@
 							 PlayerNumber,
 	                   bool loading = false,
 	                   Building::FormerBuildings former_buildings = Building::FormerBuildings());
-	Bob& create_bob(Coords, const BobDescr&, Player* owner = nullptr);
-	Bob& create_bob(Coords, int, TribeDescr const* const = nullptr, Player* owner = nullptr);
-	Bob& create_bob(Coords,
-	                const std::string& name,
-						 TribeDescr const* const = nullptr,
-	                Player* owner = nullptr);
-	Immovable& create_immovable(Coords, uint32_t idx, TribeDescr const*);
-	Immovable& create_immovable(Coords, const std::string& name, TribeDescr const*);
+	Bob& create_critter(Coords, int bob_type_idx, Player* owner = nullptr);
+	Bob& create_critter(Coords, const std::string& name, Player* owner = nullptr);
+	Immovable& create_immovable(Coords,
+										 uint32_t idx,
+										 MapObjectDescr::OwnerType = MapObjectDescr::OwnerType::kWorld);
+	Immovable& create_immovable(Coords,
+										 const std::string& name,
+										 MapObjectDescr::OwnerType = MapObjectDescr::OwnerType::kWorld);
+	Bob& create_ship(Coords, int ship_type_idx, Player* owner = nullptr);
+	Bob& create_ship(Coords, const std::string& name, Player* owner = nullptr);
 
 	int32_t get_gametime() const {
 		return gametime_;
@@ -161,14 +163,6 @@
 	void* get_trackpointer(uint32_t serial);
 	void remove_trackpointer(uint32_t serial);
 
-	// Manually load a tribe into memory. Used by the editor
-	const TribeDescr& manually_load_tribe(const std::string& tribe);
-	const TribeDescr& manually_load_tribe(PlayerNumber const p) {
-		return manually_load_tribe(map().get_scenario_player_tribe(p));
-	}
-	// Get a tribe from the loaded list, when known or nullptr.
-	TribeDescr const* get_tribe(const std::string& name) const;
-
 	void inform_players_about_ownership(MapIndex, PlayerNumber);
 	void inform_players_about_immovable(MapIndex, MapObjectDescr const*);
 	void inform_players_about_road(FCoords, MapObjectDescr const*);
@@ -207,11 +201,16 @@
 	// Returns the world that can be modified. Prefer world() whenever possible.
 	World* mutable_world();
 
-protected:
-	using TribeVector = std::vector<TribeDescr*>;
-	TribeVector tribes_;
+	// Returns the tribes.
+	const Tribes& tribes() const;
+
+	// Returns the mutable tribes. Prefer tribes() whenever possible.
+	Tribes* mutable_tribes();
 
 private:
+	/// Common function for create_critter and create_ship.
+	Bob& create_bob(Coords, const BobDescr&, Player* owner = nullptr);
+
 	/// \param preferred_player
 	///  When conquer is false, this can be used to prefer a player over other
 	///  players, when lost land is reassigned. This can for example be used to
@@ -257,14 +256,13 @@
 	std::unique_ptr<PlayersManager> player_manager_;
 
 	std::unique_ptr<World> world_;
+	std::unique_ptr<Tribes> tribes_;
 	InteractiveBase* ibase_;
 	Map* map_;
 
 	uint32_t lasttrackserial_;
 	std::map<uint32_t, void*> trackpointers_;
 
-	std::unique_ptr<Texture> road_texture_;
-
 	DISALLOW_COPY_AND_ASSIGN(EditorGameBase);
 };
 

=== modified file 'src/logic/expedition_bootstrap.cc'
--- src/logic/expedition_bootstrap.cc	2015-04-15 12:59:16 +0000
+++ src/logic/expedition_bootstrap.cc	2015-10-18 20:57:50 +0000
@@ -132,7 +132,7 @@
 	workers_.emplace_back
 		(new ExpeditionWorker
 		 (new Request(*warehouse,
-						  warehouse->owner().tribe().safe_worker_index("builder"),
+						  warehouse->owner().tribe().builder(),
 						  ExpeditionBootstrap::worker_callback, wwWORKER))
 	);
 

=== modified file 'src/logic/findimmovable.h'
--- src/logic/findimmovable.h	2014-07-28 16:59:54 +0000
+++ src/logic/findimmovable.h	2015-10-18 20:57:50 +0000
@@ -27,7 +27,7 @@
 namespace Widelands {
 
 struct BaseImmovable;
-struct ImmovableDescr;
+class ImmovableDescr;
 class Player;
 
 struct FindImmovable {

=== modified file 'src/logic/game.cc'
--- src/logic/game.cc	2015-10-04 18:30:05 +0000
+++ src/logic/game.cc	2015-10-18 20:57:50 +0000
@@ -56,7 +56,7 @@
 #include "logic/single_player_game_controller.h"
 #include "logic/soldier.h"
 #include "logic/trainingsite.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "map_io/widelands_map_loader.h"
 #include "network/network.h"
 #include "profile/profile.h"
@@ -226,17 +226,21 @@
 		throw wexception("could not load \"%s\"", mapname);
 	UI::ProgressWindow loaderUI;
 
-	loaderUI.step (_("Preloading a map"));
+	loaderUI.step (_("Preloading map"));
 	maploader->preload_map(true);
 	std::string const background = map().get_background();
 	if (!background.empty()) {
 		loaderUI.set_background(background);
 	}
+	loaderUI.step(_("Loading world"));
+	world();
+	loaderUI.step(_("Loading tribes"));
+	tribes();
 
 	// We have to create the players here.
 	PlayerNumber const nr_players = map().get_nrplayers();
 	iterate_player_numbers(p, nr_players) {
-		loaderUI.stepf (_("Adding player %u"), p);
+		loaderUI.stepf(_("Adding player %u"), p);
 		add_player
 			(p,
 			 0,
@@ -250,7 +254,7 @@
 		(new InteractivePlayer
 		 	(*this, g_options.pull_section("global"), 1, false));
 
-	loaderUI.step (_("Loading a map"));
+	loaderUI.step(_("Loading map"));
 	maploader->load_map_complete(*this, true);
 	maploader.reset();
 
@@ -286,6 +290,17 @@
 	std::unique_ptr<MapLoader> maploader
 		(map().get_correct_loader(settings.mapfilename));
 	maploader->preload_map(settings.scenario);
+
+	if (loaderUI) {
+		loaderUI->step(_("Loading world"));
+	}
+	world();
+
+	if (loaderUI) {
+		loaderUI->step(_("Loading tribes"));
+	}
+	tribes();
+
 	std::string const background = map().get_background();
 	if (loaderUI) {
 		if (!background.empty()) {
@@ -637,11 +652,6 @@
 
 	EditorGameBase::cleanup_for_load();
 
-	for (TribeDescr* tribe : tribes_) {
-		delete tribe;
-	}
-
-	tribes_.clear();
 	cmdqueue().flush();
 
 	// Statistics
@@ -743,7 +753,7 @@
 void Game::send_player_build
 	(int32_t const pid, Coords const coords, BuildingIndex const id)
 {
-	assert(id != INVALID_INDEX);
+	assert(tribes().building_exists(id));
 	send_player_command (*new CmdBuild(get_gametime(), pid, coords, id));
 }
 
@@ -788,7 +798,7 @@
 void Game::send_player_enhance_building
 	(Building & building, BuildingIndex const id)
 {
-	assert(id != INVALID_INDEX);
+	assert(building.owner().tribe().has_building(id));
 
 	send_player_command
 		(*new CmdEnhanceBuilding
@@ -984,22 +994,16 @@
 		for (uint32_t j = 0; j < plr->get_nr_economies(); ++j) {
 			Economy * const eco = plr->get_economy_by_number(j);
 			const TribeDescr & tribe = plr->tribe();
-			WareIndex const tribe_wares = tribe.get_nrwares();
-			for
-				(WareIndex wareid = 0;
-				 wareid < tribe_wares;
-				 ++wareid)
-				wastock += eco->stock_ware(wareid);
-			WareIndex const tribe_workers = tribe.get_nrworkers();
-			for
-				(WareIndex workerid = 0;
-				 workerid < tribe_workers;
-				 ++workerid)
-				if
-					(!
-					 dynamic_cast<CarrierDescr const *>
-					 	(tribe.get_worker_descr(workerid)))
-					wostock += eco->stock_worker(workerid);
+
+			for (const WareIndex& ware_index : tribe.wares()) {
+				wastock += eco->stock_ware(ware_index);
+			}
+
+			for (const WareIndex& worker_index : tribe.workers()) {
+				if (tribe.get_worker_descr(worker_index)->type() != MapObjectType::CARRIER) {
+					wostock += eco->stock_worker(worker_index);
+				}
+			}
 		}
 		nr_wares  [p - 1] = wastock;
 		nr_workers[p - 1] = wostock;

=== modified file 'src/logic/game_settings.h'
--- src/logic/game_settings.h	2015-02-06 16:37:25 +0000
+++ src/logic/game_settings.h	2015-10-18 20:57:50 +0000
@@ -25,7 +25,7 @@
 #include <vector>
 
 #include "io/filesystem/layered_filesystem.h"
-#include "logic/tribe_basic_info.h"
+#include "logic/tribes/tribe_basic_info.h"
 #include "logic/widelands.h"
 #include "scripting/lua_interface.h"
 #include "scripting/lua_table.h"

=== modified file 'src/logic/immovable.cc'
--- src/logic/immovable.cc	2015-10-04 18:30:05 +0000
+++ src/logic/immovable.cc	2015-10-18 20:57:50 +0000
@@ -47,13 +47,13 @@
 #include "logic/mapfringeregion.h"
 #include "logic/player.h"
 #include "logic/terrain_affinity.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.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 "map_io/tribes_legacy_lookup_table.h"
+#include "map_io/world_legacy_lookup_table.h"
 #include "notifications/notifications.h"
-#include "profile/profile.h"
 #include "scripting/lua_table.h"
 #include "sound/sound_handler.h"
 #include "wui/interactive_base.h"
@@ -134,49 +134,6 @@
 ==============================================================================
 */
 
-ImmovableProgram::ImmovableProgram(const std::string& directory,
-								   Profile& prof,
-								   const std::string& _name,
-											  ImmovableDescr& 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 (!strcmp(v->get_name(), "animate")) {
-			// Copying, as next_word() modifies the string..... Awful design.
-			std::unique_ptr<char []> arguments(new char[strlen(v->get_string()) + 1]);
-			strncpy(arguments.get(), v->get_string(), strlen(v->get_string()) + 1);
-
-			char* full_line = arguments.get();
-			bool reached_end;
-			char * const animation_name = next_word(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 (!strcmp(v->get_name(), "transform")) {
-			action = new ActTransform(v->get_string(), immovable);
-		} else if (!strcmp(v->get_name(), "grow")) {
-			action = new ActGrow(v->get_string(), immovable);
-		} else if (!strcmp(v->get_name(), "remove")) {
-			action = new ActRemove(v->get_string(), immovable);
-		} else if (!strcmp(v->get_name(), "seed")) {
-			action = new ActSeed(v->get_string(), immovable);
-		} else if (!strcmp(v->get_name(), "playFX")) {
-			action = new ActPlayFX(directory, v->get_string(), immovable);
-		} else if (!strcmp(v->get_name(), "construction")) {
-			action = new ActConstruction(v->get_string(), immovable, directory, prof);
-		} else {
-			throw GameDataError("unknown command type \"%s\"", v->get_name());
-		}
-		m_actions.push_back(action);
-	}
-	if (m_actions.empty())
-		throw GameDataError("no actions");
-}
-
 ImmovableProgram::ImmovableProgram(const std::string& init_name,
 								   const std::vector<std::string>& lines,
 											  ImmovableDescr* immovable)
@@ -201,9 +158,13 @@
 			action = new ActRemove(arguments.get(), *immovable);
 		} else if (parts[0] == "seed") {
 			action = new ActSeed(arguments.get(), *immovable);
+		} else if (parts[0] == "playFX") {
+			action = new ActPlayFX(arguments.get(), *immovable);
+		} else if (parts[0] == "construction") {
+			action = new ActConstruction(arguments.get(), *immovable);
 		} else {
 			throw GameDataError(
-			   "unknown or (here)not support command type \"%s\"", parts[0].c_str());
+				"unknown command type \"%s\" in immovable \"%s\"", parts[0].c_str(), immovable->name().c_str());
 		}
 		m_actions.push_back(action);
 	}
@@ -219,91 +180,57 @@
 ==============================================================================
 */
 
+Buildcost ImmovableDescr::parse_buildcost(std::unique_ptr<LuaTable> table, const Tribes& tribes) {
+	Buildcost result;
+	for (const std::string& warename : table->keys<std::string>()) {
+		int32_t value(-1);
+		try {
+			WareIndex const idx = tribes.safe_ware_index(warename);
+			if (result.count(idx)) {
+				throw GameDataError(
+				   "a buildcost item of this ware type has already been defined: %s", warename.c_str());
+			}
+			value = table->get_int(warename);
+			uint8_t const count = value;
+			if (count != value) {
+				throw GameDataError("count is out of range 1 .. 255");
+			}
+			result.insert(std::pair<WareIndex, uint8_t>(idx, count));
+		} catch (const WException& e) {
+			throw GameDataError("[buildcost] \"%s=%d\": %s", warename.c_str(), value, e.what());
+		}
+	}
+	return result;
+}
+
 /**
- * Parse an immovable from its conf file.
+ * Parse a common immovable functions from init file.
  */
-ImmovableDescr::ImmovableDescr
-	(char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 TribeDescr const * const owner_tribe)
-:
-	MapObjectDescr(MapObjectType::IMMOVABLE, _name, _descname),
-	m_size          (BaseImmovable::NONE),
-	m_owner_tribe   (owner_tribe)
-{
-	using boost::iequals;
-
-	if (global_s.has_val("size")) {
-		const auto& size = global_s.get_string("size");
-		try {
-			if      (iequals(size, "small"))
-				m_size = BaseImmovable::SMALL;
-			else if (iequals(size, "medium"))
-				m_size = BaseImmovable::MEDIUM;
-			else if (iequals(size, "big"))
-				m_size = BaseImmovable::BIG;
-			else
-				throw GameDataError
-					("expected %s but found \"%s\"",
-					 "{\"small\"|\"medium\"|\"big\"}", size);
-		} catch (const WException & e) {
-			throw GameDataError("size: %s", e.what());
-		}
-	}
-
-	// 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, {MapObject::Attribute::RESI});
-	}
-
-	//  parse the programs
-	while (Section::Value const * const v = global_s.get_next_val("program")) {
-		std::string program_name = v->get_string();
-		std::transform
-			(program_name.begin(), program_name.end(), program_name.begin(),
-			 tolower);
-		try {
-			if (m_programs.count(program_name))
-				throw GameDataError("this program has already been declared");
-			m_programs[program_name] =
-				new ImmovableProgram(directory, prof, program_name, *this);
-		} catch (const std::exception & e) {
-			throw GameDataError
-				("program %s: %s", program_name.c_str(), e.what());
-		}
-	}
-
-	make_sure_default_program_is_there();
-
-	if (owner_tribe) {
-		// shipconstruction has a cost associated.
-		if (Section * buildcost_s = prof.get_section("buildcost")) {
-			m_buildcost.parse(*owner_tribe, *buildcost_s);
-		}
-	}
-}
-
-ImmovableDescr::ImmovableDescr(const LuaTable& table, const World& world) :
+ImmovableDescr::ImmovableDescr(const std::string& init_descname,
+										 const LuaTable& table,
+										 MapObjectDescr::OwnerType input_type) :
 	MapObjectDescr(
-	MapObjectType::IMMOVABLE, table.get_string("name"), table.get_string("descname")),
+	MapObjectType::IMMOVABLE, table.get_string("name"), init_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>(), {MapObject::Attribute::RESI});
+	owner_type_(input_type) {
+	if (table.has_key("size")) {
+		m_size = string_to_size(table.get_string("size"));
+	}
+
+	if (table.has_key("terrain_affinity")) {
+		terrain_affinity_.reset(new TerrainAffinity(*table.get_table("terrain_affinity"), name()));
+	}
+
+	if (table.has_key("attributes")) {
+		add_attributes(table.get_table("attributes")->
+							array_entries<std::string>(), {MapObject::Attribute::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)));
 	}
-
-	if (table.has_key("terrain_affinity")) {
-		terrain_affinity_.reset(new TerrainAffinity(*table.get_table("terrain_affinity"), name()));
-	}
+	assert(is_animation_known("idle"));
 
 	std::unique_ptr<LuaTable> programs = table.get_table("programs");
 	for (const std::string& program_name : programs->keys<std::string>()) {
@@ -315,15 +242,34 @@
 		}
 	}
 
+	make_sure_default_program_is_there();
+}
+
+/**
+ * Parse a world immovable from its init file.
+ */
+ImmovableDescr::ImmovableDescr(const std::string& init_descname, const LuaTable& table, const World& world) :
+	ImmovableDescr(init_descname, table, MapObjectDescr::OwnerType::kWorld) {
+
 	int editor_category_index =
-	   world.editor_immovable_categories().get_index(table.get_string("editor_category"));
-	if (editor_category_index < 0) {
+			world.editor_immovable_categories().get_index(table.get_string("editor_category"));
+	if (editor_category_index == Widelands::INVALID_INDEX) {
 		throw GameDataError("Unknown editor_category: %s\n",
 							  table.get_string("editor_category").c_str());
 	}
-	editor_category_ = world.editor_immovable_categories().get(editor_category_index);
+	editor_category_ = world.editor_immovable_categories().get_mutable(editor_category_index);
+}
 
-	make_sure_default_program_is_there();
+/**
+ * Parse a tribes immovable from its init file.
+ */
+ImmovableDescr::ImmovableDescr(const std::string& init_descname,
+										 const LuaTable& table,
+										 const Tribes& tribes) :
+	ImmovableDescr(init_descname, table, MapObjectDescr::OwnerType::kTribe) {
+	if (table.has_key("buildcost")) {
+		m_buildcost = ImmovableDescr::parse_buildcost(table.get_table("buildcost"), tribes);
+	}
 }
 
 const EditorCategory& ImmovableDescr::editor_category() const {
@@ -713,10 +659,12 @@
 	fw.unsigned_8(HeaderImmovable);
 	fw.unsigned_8(kCurrentPacketVersionImmovable);
 
-	if (const TribeDescr * const tribe = descr().get_owner_tribe())
-		fw.string(tribe->name());
-	else
+	if (descr().owner_type() == MapObjectDescr::OwnerType::kTribe) {
+		if (get_owner() == nullptr) log(" Tribe immovable has no owner!! ");
+		fw.c_string("tribes");
+	} else {
 		fw.c_string("world");
+	}
 
 	fw.string(descr().name());
 
@@ -748,8 +696,9 @@
 }
 
 MapObject::Loader * Immovable::load
-	(EditorGameBase & egbase, MapObjectLoader & mol,
-	 FileRead & fr, const OneWorldLegacyLookupTable& lookup_table)
+	(EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr,
+	 const WorldLegacyLookupTable& world_lookup_table,
+	 const TribesLegacyLookupTable& tribes_lookup_table)
 {
 	std::unique_ptr<Loader> loader(new Loader);
 
@@ -759,31 +708,30 @@
 		// Supporting older versions for map loading
 		if (1 <= packet_version && packet_version <= kCurrentPacketVersionImmovable) {
 
-			const std::string owner_name = fr.c_string();
-			const std::string old_name = fr.c_string();
+			const std::string owner_type = fr.c_string();
+			std::string name = fr.c_string();
 			Immovable * imm = nullptr;
 
-			if (owner_name != "world") { //  It is a tribe immovable.
-				egbase.manually_load_tribe(owner_name);
-
-				if (TribeDescr const * const tribe = egbase.get_tribe(owner_name)) {
-					int32_t const idx = tribe->get_immovable_index(old_name);
-					if (idx != -1)
-						imm = new Immovable(*tribe->get_immovable_descr(idx));
-					else
-						throw GameDataError
-							("tribe %s does not define immovable type \"%s\"",
-							 owner_name.c_str(), old_name.c_str());
-				} else
-					throw wexception("unknown tribe %s", owner_name.c_str());
+			if (owner_type != "world") { //  It is a tribe immovable.
+				// Needed for map compatibility
+				if (packet_version < 7) {
+					name = tribes_lookup_table.lookup_immovable(owner_type, name);
+				}
+				const WareIndex idx = egbase.tribes().immovable_index(name);
+				if (idx != Widelands::INVALID_INDEX) {
+					imm = new Immovable(*egbase.tribes().get_immovable_descr(idx));
+				} else {
+					throw GameDataError
+						("tribes do not define immovable type \"%s\"", name.c_str());
+				}
 			} else { //  world immovable
 				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\"", new_name.c_str());
-
+				name = world_lookup_table.lookup_immovable(name);
+				const WareIndex idx = world.get_immovable_index(name.c_str());
+				if (idx == Widelands::INVALID_INDEX) {
+					throw GameDataError
+						("world does not define immovable type \"%s\"", name.c_str());
+				}
 				imm = new Immovable(*world.get_immovable_descr(idx));
 			}
 
@@ -837,13 +785,10 @@
 }
 
 
-ImmovableProgram::ActPlayFX::ActPlayFX
-	(const std::string & directory, char * parameters, const ImmovableDescr &)
-{
+ImmovableProgram::ActPlayFX::ActPlayFX(char* parameters, const ImmovableDescr&) {
 	try {
 		bool reached_end;
-		std::string filename = next_word(parameters, reached_end);
-		name = directory + "/" + filename;
+		name = next_word(parameters, reached_end);
 
 		if (!reached_end) {
 			char * endp;
@@ -855,7 +800,9 @@
 		} else
 			priority = 127;
 
-		g_sound_handler.load_fx_if_needed(directory, filename, name);
+		g_sound_handler.load_fx_if_needed(FileSystem::fs_dirname(name),
+													 FileSystem::fs_filename(name.c_str()),
+													 name);
 	} catch (const WException & e) {
 		throw GameDataError("playFX: %s", e.what());
 	}
@@ -902,8 +849,8 @@
 					if (segments[0] == "world")
 						tribe = false;
 					else if (segments[0] == "tribe") {
-						if (!descr.get_owner_tribe())
-							throw GameDataError("scope \"tribe\", but have no owner tribe");
+						if (descr.owner_type() != MapObjectDescr::OwnerType::kTribe)
+							throw GameDataError("scope \"tribe\" does not match the immovable type");
 						tribe = true;
 					} else
 						throw GameDataError
@@ -931,14 +878,13 @@
 	if (probability == 0 || game.logic_rand() % 256 < probability) {
 		Player * player = immovable.get_owner();
 		Coords const c = immovable.get_position();
-		TribeDescr const * const owner_tribe =
-			tribe ? immovable.descr().get_owner_tribe() : nullptr;
+		MapObjectDescr::OwnerType owner_type = immovable.descr().owner_type();
 		immovable.remove(game); //  Now immovable is a dangling reference!
 
 		if (bob) {
-			game.create_bob(c, type_name, owner_tribe, player);
+			game.create_ship(c, type_name, player);
 		} else {
-			Immovable & imm = game.create_immovable(c, type_name, owner_tribe);
+			Immovable & imm = game.create_immovable(c, type_name, owner_type);
 			if (player)
 				imm.set_owner(player);
 		}
@@ -962,11 +908,10 @@
 			case ':': {
 				*p = '\0';
 				++p;
-				TribeDescr const * const owner_tribe = descr.get_owner_tribe();
-				if (!owner_tribe)
+				if (descr.owner_type() != MapObjectDescr::OwnerType::kTribe)
 					throw GameDataError
 						(
-						 "immovable type not in tribe but target type has scope "
+						 "immovable type not in tribes but target type has scope "
 						 "(\"%s\")",
 						 parameters);
 				else if (strcmp(parameters, "world"))
@@ -998,10 +943,10 @@
 	const ImmovableDescr& descr = immovable.descr();
 
 	if (logic_rand_as_double(&game) <
-		probability_to_grow(descr.terrain_affinity(), f, map, game.world().terrains())) {
-		TribeDescr const* const owner_tribe = tribe ? descr.get_owner_tribe() : nullptr;
+		 probability_to_grow(descr.terrain_affinity(), f, map, game.world().terrains())) {
+		MapObjectDescr::OwnerType owner_type = descr.owner_type();
 		immovable.remove(game);  //  Now immovable is a dangling reference!
-		game.create_immovable(f, type_name, owner_tribe);
+		game.create_immovable(f, type_name, owner_type);
 	} else {
 		immovable.program_step(game);
 	}
@@ -1040,18 +985,16 @@
 ImmovableProgram::ActSeed::ActSeed(char * parameters, ImmovableDescr & descr)
 {
 	try {
-		tribe = true;
 		probability = 0;
 		for (char * p = parameters;;)
 			switch (*p) {
 			case ':': {
 				*p = '\0';
 				++p;
-				TribeDescr const * const owner_tribe = descr.get_owner_tribe();
-				if (!owner_tribe)
+				if (descr.owner_type() != MapObjectDescr::OwnerType::kTribe)
 					throw GameDataError
 						(
-						 "immovable type not in tribe but target type has scope "
+						 "immovable type not in tribes but target type has scope "
 						 "(\"%s\")",
 						 parameters);
 				else if (strcmp(parameters, "world"))
@@ -1060,7 +1003,6 @@
 						 "scope \"%s\" given for target type (must be "
 						 "\"world\")",
 						 parameters);
-				tribe = false;
 				parameters = p;
 				break;
 			}
@@ -1113,23 +1055,20 @@
 
 		const FCoords new_location = map.get_fcoords(mr.location());
 		if (!new_location.field->get_immovable() &&
-			(new_location.field->nodecaps() & MOVECAPS_WALK) &&
-			logic_rand_as_double(&game) <
-			   probability_to_grow(
-				  descr.terrain_affinity(), new_location, map, game.world().terrains())) {
-			game.create_immovable(
-			   mr.location(), type_name, tribe ? immovable.descr().get_owner_tribe() : nullptr);
+		    (new_location.field->nodecaps() & MOVECAPS_WALK) &&
+		    logic_rand_as_double(&game) <
+		       probability_to_grow(
+		          descr.terrain_affinity(), new_location, map, game.world().terrains())) {
+			game.create_immovable(mr.location(), type_name, descr.owner_type());
 		}
 	}
 
 	immovable.program_step(game);
 }
 
-ImmovableProgram::ActConstruction::ActConstruction
-	(char * parameters, ImmovableDescr & descr, const std::string & directory, Profile & prof)
-{
+ImmovableProgram::ActConstruction::ActConstruction(char* parameters, ImmovableDescr& descr) {
 	try {
-		if (!descr.get_owner_tribe())
+		if (descr.owner_type() != MapObjectDescr::OwnerType::kTribe)
 			throw GameDataError("only usable for tribe immovable");
 
 		std::vector<std::string> params = split_string(parameters, " ");
@@ -1141,14 +1080,12 @@
 		m_decaytime = atoi(params[2].c_str());
 
 		std::string animation_name = params[0];
-		if (descr.is_animation_known(animation_name))
-			m_animid = descr.get_animation(animation_name);
-		else {
-			m_animid =
-				g_gr->animations().load(directory, prof.get_safe_section(animation_name));
+		if (!descr.is_animation_known(animation_name)) {
+			throw GameDataError("unknown animation \"%s\" in immovable program for immovable \"%s\"",
+									  animation_name.c_str(), descr.name().c_str());
+		}
+		m_animid = descr.get_animation(animation_name);
 
-			descr.add_animation(animation_name, m_animid);
-		}
 	} catch (const WException & e) {
 		throw GameDataError("construction: %s", e.what());
 	}
@@ -1160,7 +1097,7 @@
 	const char * name() const override {return "construction";}
 	void save(FileWrite & fw, Immovable & imm) override {
 		fw.unsigned_8(kCurrentPacketVersionConstructionData);
-		delivered.save(fw, *imm.descr().get_owner_tribe());
+		delivered.save(fw, imm.get_owner()->tribe());
 	}
 
 	static ActConstructionData * load(FileRead & fr, Immovable & imm) {
@@ -1169,7 +1106,7 @@
 		try {
 			uint8_t packet_version = fr.unsigned_8();
 			if (packet_version == kCurrentPacketVersionConstructionData) {
-				d->delivered.load(fr, *imm.descr().get_owner_tribe());
+				d->delivered.load(fr, imm.get_owner()->tribe());
 			} else {
 				throw UnhandledVersionError(packet_version, kCurrentPacketVersionConstructionData);
 			}
@@ -1457,6 +1394,7 @@
 
 	try {
 		uint8_t packet_version = fr.unsigned_8();
+
 		if (packet_version == kCurrentPacketVersionPlayerImmovable) {
 			PlayerNumber owner_number = fr.unsigned_8();
 

=== modified file 'src/logic/immovable.h'
--- src/logic/immovable.h	2015-10-04 18:30:05 +0000
+++ src/logic/immovable.h	2015-10-18 20:57:50 +0000
@@ -21,6 +21,7 @@
 #define WL_LOGIC_IMMOVABLE_H
 
 #include <memory>
+#include <unordered_map>
 
 #include "base/macros.h"
 #include "graphic/animation.h"
@@ -31,7 +32,8 @@
 #include "notifications/notifications.h"
 
 class LuaTable;
-class OneWorldLegacyLookupTable;
+class TribesLegacyLookupTable;
+class WorldLegacyLookupTable;
 class Profile;
 
 namespace Widelands {
@@ -39,6 +41,7 @@
 class Economy;
 class Map;
 class TerrainAffinity;
+class Tribes;
 class WareInstance;
 class Worker;
 class World;
@@ -106,16 +109,18 @@
 struct ImmovableActionData;
 
 /**
- * Immovable represents a standard immovable such as trees or stones.
+ * Immovable represents a standard immovable such as trees or rocks.
  */
-struct ImmovableDescr : public MapObjectDescr {
+class ImmovableDescr : public MapObjectDescr {
+public:
 	using Programs = std::map<std::string, ImmovableProgram *>;
 
-	ImmovableDescr
-		(char const * name, char const * descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 TribeDescr const * const);
-	ImmovableDescr(const LuaTable&, const World&);
+	static Buildcost parse_buildcost(std::unique_ptr<LuaTable> table, const Tribes& tribes);
+
+	/// World immovable
+	ImmovableDescr(const std::string& init_descname, const LuaTable&, const World& world);
+	/// Tribes immovable
+	ImmovableDescr(const std::string& init_descname, const LuaTable&, const Tribes& tribes);
 	~ImmovableDescr() override;
 
 	int32_t get_size() const {return m_size;}
@@ -123,7 +128,7 @@
 
 	Immovable & create(EditorGameBase &, Coords) const;
 
-	TribeDescr const * get_owner_tribe() const {return m_owner_tribe;}
+	MapObjectDescr::OwnerType owner_type() const {return owner_type_;}
 
 	const Buildcost & buildcost() const {return m_buildcost;}
 
@@ -143,15 +148,17 @@
 	int32_t     m_size;
 	Programs    m_programs;
 
-	/// The tribe to which this ImmovableDescr belongs or 0 if it is a
-	/// world immovable
-	const TribeDescr * const m_owner_tribe;
+	/// Whether this ImmovableDescr belongs to a tribe or the world
+	const MapObjectDescr::OwnerType owner_type_;
 
 	/// Buildcost for externally constructible immovables (for ship construction)
 	/// \see ActConstruction
 	Buildcost m_buildcost;
 
 private:
+	 // Common constructor functions for tribes and world.
+	ImmovableDescr(const std::string& init_descname, const LuaTable&, MapObjectDescr::OwnerType type);
+
 	// Adds a default program if none was defined.
 	void make_sure_default_program_is_there();
 
@@ -161,7 +168,7 @@
 };
 
 class Immovable : public BaseImmovable {
-	friend struct ImmovableDescr;
+	friend class ImmovableDescr;
 	friend struct ImmovableProgram;
 	friend class Map;
 
@@ -261,7 +268,8 @@
 	void save(EditorGameBase &, MapObjectSaver &, FileWrite &) override;
 	static MapObject::Loader * load
 		(EditorGameBase &, MapObjectLoader &, FileRead &,
-		 const OneWorldLegacyLookupTable& lookup_table);
+		 const WorldLegacyLookupTable& world_lookup_table,
+		 const TribesLegacyLookupTable& tribes_lookup_table);
 
 private:
 	void increment_program_pointer();

=== modified file 'src/logic/immovable_program.h'
--- src/logic/immovable_program.h	2014-09-14 11:31:58 +0000
+++ src/logic/immovable_program.h	2015-10-18 20:57:50 +0000
@@ -122,7 +122,6 @@
 		void execute(Game &, Immovable &) const override;
 	private:
 		std::string type_name;
-		bool        tribe;
 		uint8_t probability;
 	};
 
@@ -142,7 +141,7 @@
 	/// Plays the specified soundFX with the specified priority. Whether the
 	/// soundFX is actually played is determined by the sound handler.
 	struct ActPlayFX : public Action {
-		ActPlayFX(const std::string & directory, char * parameters, const ImmovableDescr &);
+		ActPlayFX(char* parameters, const ImmovableDescr &);
 		void execute(Game &, Immovable &) const override;
 	private:
 		std::string name;
@@ -163,7 +162,7 @@
 	 *       Time until construction decays one step if no progress has been made.
 	 */
 	struct ActConstruction : public Action {
-		ActConstruction(char * parameters, ImmovableDescr &, const std::string & directory, Profile &);
+		ActConstruction(char* parameters, ImmovableDescr&);
 		void execute(Game &, Immovable &) const override;
 
 		Duration buildtime() const {return m_buildtime;}

=== modified file 'src/logic/instances.cc'
--- src/logic/instances.cc	2015-05-10 15:25:34 +0000
+++ src/logic/instances.cc	2015-10-18 20:57:50 +0000
@@ -232,30 +232,40 @@
 	MapObject::HIGHEST_FIXED_ATTRIBUTE;
 MapObjectDescr::AttribMap MapObjectDescr::s_dyn_attribs;
 
+
+bool MapObjectDescr::is_animation_known(const std::string & animname) const {
+	return (m_anims.count(animname) == 1);
+}
+
 /**
  * Add this animation for this map object under this name
  */
-bool MapObjectDescr::is_animation_known(const std::string & animname) const {
-	for (const std::pair<std::string, uint32_t>& anim : m_anims) {
-		if (anim.first == animname) {
-			return true;
-		}
-	}
-	return false;
-}
-
 void MapObjectDescr::add_animation
 	(const std::string & animname, uint32_t const anim)
 {
+	if (is_animation_known(animname)) {
 #ifndef NDEBUG
-	for (const std::pair<std::string, uint32_t>& temp_anim : m_anims) {
-		if (temp_anim.first == animname) {
-			throw wexception
-				("adding already existing animation \"%s\"", animname.c_str());
-		}
-	}
+		throw GameDataError
+			("Tried to add already existing animation \"%s\"", animname.c_str());
+#else
+		log("Warning: tried to add already existing animation \"%s\"", animname.c_str());
 #endif
-	m_anims.insert(std::pair<std::string, uint32_t>(animname, anim));
+	} else {
+		m_anims.insert(std::pair<std::string, uint32_t>(animname, anim));
+	}
+}
+
+void MapObjectDescr::add_directional_animation(DirAnimations* anims, const std::string& prefix) {
+	static char const* const dirstrings[6] = {"ne", "e", "se", "sw", "w", "nw"};
+	for (int32_t dir = 1; dir <= 6; ++dir) {
+		const std::string anim_name = prefix + std::string("_") + dirstrings[dir - 1];
+		try {
+			anims->set_animation(dir, get_animation(anim_name));
+		} catch (const MapObjectDescr::AnimationNonexistent&) {
+			throw GameDataError("MO: no directional animation '%s'",
+									  anim_name.c_str());
+		}
+	}
 }
 
 std::string MapObjectDescr::get_animation_name(uint32_t const anim) const {
@@ -297,7 +307,7 @@
 void MapObjectDescr::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);
+		uint32_t const attrib = get_attribute_id(attribute, true);
 		if (attrib < MapObject::HIGHEST_FIXED_ATTRIBUTE) {
 			if (!allowed_special.count(attrib)) {
 				throw GameDataError("bad attribute \"%s\"", attribute.c_str());
@@ -309,22 +319,27 @@
 
 /**
  * Lookup an attribute by name. If the attribute name hasn't been encountered
- * before, we add it to the map.
+ * before and add_if_not_exists = true, we add it to the map. Else, throws exception.
  */
-uint32_t MapObjectDescr::get_attribute_id(const std::string & name) {
+uint32_t MapObjectDescr::get_attribute_id(const std::string & name, bool add_if_not_exists) {
 	AttribMap::iterator it = s_dyn_attribs.find(name);
 
-	if (it != s_dyn_attribs.end())
+	if (it != s_dyn_attribs.end()) {
 		return it->second;
+	}
 
-	if      (name == "worker")
+	if (name == "worker") {
 		return MapObject::WORKER;
-	else if (name == "resi")
+	} else if (name == "resi") {
 		return MapObject::RESI;
-
-	++s_dyn_attribhigh;
-	s_dyn_attribs[name] = s_dyn_attribhigh;
-
+	}
+
+	if (!add_if_not_exists) {
+		throw GameDataError("get_attribute_id: attribute '%s' not found!\n", name.c_str());
+	} else {
+		++s_dyn_attribhigh;
+		s_dyn_attribs[name] = s_dyn_attribhigh;
+	}
 	assert(s_dyn_attribhigh != 0); // wrap around seems *highly* unlikely ;)
 
 	return s_dyn_attribhigh;

=== modified file 'src/logic/instances.h'
--- src/logic/instances.h	2015-02-25 20:45:20 +0000
+++ src/logic/instances.h	2015-10-18 20:57:50 +0000
@@ -89,6 +89,11 @@
  */
 struct MapObjectDescr {
 
+	enum class OwnerType {
+		kWorld,
+		kTribe
+	};
+
 	MapObjectDescr(const MapObjectType init_type,
 					 const std::string& init_name,
 					 const std::string& init_descname)
@@ -119,12 +124,15 @@
 
 	std::string get_animation_name(uint32_t) const; ///< needed for save, debug
 	bool has_attribute(uint32_t) const;
-	static uint32_t get_attribute_id(const std::string & name);
+	static uint32_t get_attribute_id(const std::string & name, bool add_if_not_exists = false);
 	static std::string get_attribute_name(uint32_t id);
 
 	bool is_animation_known(const std::string & name) const;
 	void add_animation(const std::string & name, uint32_t anim);
 
+	/// Sets the directional animations in 'anims' with the animations '<prefix>_(ne|e|se|sw|w|nw)'.
+	void add_directional_animation(DirAnimations* anims, const std::string& prefix);
+
 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.

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2015-10-02 07:02:00 +0000
+++ src/logic/map.cc	2015-10-18 20:57:50 +0000
@@ -42,7 +42,7 @@
 #include "logic/pathfield.h"
 #include "logic/player.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/world/terrain_description.h"
 #include "logic/world/world.h"
 #include "map_io/s2map.h"
@@ -335,7 +335,7 @@
 	// Set first tribe found as the "basic" tribe
 	// <undefined> (as set before) is useless and will lead to a
 	// crash -> Widelands will search for tribe "<undefined>"
-	set_scenario_player_tribe(1, TribeDescr::get_all_tribenames()[0]);
+	set_scenario_player_tribe(1, Tribes::get_all_tribenames()[0]);
 	set_scenario_player_name(1, (boost::format(_("Player %u")) % 1).str());
 	set_scenario_player_ai(1, "");
 	set_scenario_player_closeable(1, false);

=== modified file 'src/logic/message.h'
--- src/logic/message.h	2014-09-30 07:55:22 +0000
+++ src/logic/message.h	2015-10-18 20:57:50 +0000
@@ -37,7 +37,7 @@
 		kGeologists,
 		kGeologistsCoal,
 		kGeologistsGold,
-		kGeologistsGranite,
+		kGeologistsStones,
 		kGeologistsIron,
 		kGeologistsWater,
 		kScenario,

=== modified file 'src/logic/militarysite.cc'
--- src/logic/militarysite.cc	2015-09-07 12:12:32 +0000
+++ src/logic/militarysite.cc	2015-10-18 20:57:50 +0000
@@ -21,6 +21,7 @@
 
 #include <clocale>
 #include <cstdio>
+#include <memory>
 
 #include <boost/format.hpp>
 
@@ -36,37 +37,37 @@
 #include "logic/message_queue.h"
 #include "logic/player.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/worker.h"
-#include "profile/profile.h"
 
 namespace Widelands {
 
-MilitarySiteDescr::MilitarySiteDescr
-	(char        const * const _name,
-	 char        const * const _descname,
-	 const std::string & directory, Profile & prof,  Section & global_s,
-	 const TribeDescr & _tribe,
-	 const World& world)
+MilitarySiteDescr::MilitarySiteDescr(const std::string& init_descname,
+												 const LuaTable& table,
+												 const EditorGameBase& egbase)
 	:
 	ProductionSiteDescr
-		(MapObjectType::MILITARYSITE, _name, _descname, directory, prof, global_s, _tribe, world),
+		(init_descname, "", MapObjectType::MILITARYSITE, table, egbase),
 	m_conquer_radius     (0),
 	m_num_soldiers       (0),
 	m_heal_per_second    (0)
 {
-	m_conquer_radius      = global_s.get_safe_int("conquers");
-	m_num_soldiers        = global_s.get_safe_int("max_soldiers");
-	m_heal_per_second     = global_s.get_safe_int("heal_per_second");
+	i18n::Textdomain td("tribes");
+
+	m_conquer_radius      = table.get_int("conquers");
+	m_num_soldiers        = table.get_int("max_soldiers");
+	m_heal_per_second     = table.get_int("heal_per_second");
 
 	if (m_conquer_radius > 0)
 		m_workarea_info[m_conquer_radius].insert(descname() + " conquer");
-	m_prefers_heroes_at_start = global_s.get_safe_bool("prefer_heroes");
-	m_occupied_str = global_s.get_safe_string("occupied_string");
-	m_aggressor_str = global_s.get_safe_string("aggressor_string");
-	m_attack_str = global_s.get_safe_string("attack_string");
-	m_defeated_enemy_str = global_s.get_safe_string("defeated_enemy_string");
-	m_defeated_you_str = global_s.get_safe_string("defeated_you_string");
+	m_prefers_heroes_at_start = table.get_bool("prefer_heroes");
+
+	std::unique_ptr<LuaTable> items_table = table.get_table("messages");
+	m_occupied_str = _(items_table->get_string("occupied"));
+	m_aggressor_str = _(items_table->get_string("aggressor"));
+	m_attack_str = _(items_table->get_string("attack"));
+	m_defeated_enemy_str = _(items_table->get_string("defeated_enemy"));
+	m_defeated_you_str = _(items_table->get_string("defeated_you"));
 }
 
 /**
@@ -397,7 +398,7 @@
 			m_normal_soldier_request.reset
 				(new Request
 					(*this,
-					 descr().tribe().safe_worker_index("soldier"),
+					 owner().tribe().soldier(),
 					 MilitarySite::request_soldier_callback,
 					 wwWORKER));
 			m_normal_soldier_request->set_requirements (m_soldier_requirements);
@@ -453,7 +454,7 @@
 		m_upgrade_soldier_request.reset
 				(new Request
 				(*this,
-				descr().tribe().safe_worker_index("soldier"),
+				owner().tribe().soldier(),
 				MilitarySite::request_soldier_callback,
 				wwWORKER));
 
@@ -880,29 +881,16 @@
 		// The enemy conquers the building
 		// In fact we do not conquer it, but place a new building of same type at
 		// the old location.
-		Player            * enemyplayer = enemy.get_owner();
-		const TribeDescr & enemytribe  = enemyplayer->tribe();
-
-		// Add suffix to all descr in former buildings in cases
-		// the new owner comes from another tribe
-		Building::FormerBuildings former_buildings;
-		for (BuildingIndex former_idx : m_old_buildings) {
-			const BuildingDescr * old_descr = descr().tribe().get_building_descr(former_idx);
-			std::string bldname = old_descr->name();
-			// Has this building already a suffix? == conquered building?
-			std::string::size_type const dot = bldname.rfind('.');
-			if (dot >= bldname.size()) {
-				// Add suffix, if the new owner uses another tribe than we.
-				if (enemytribe.name() != owner().tribe().name())
-					bldname += "." + owner().tribe().name();
-			} else if (enemytribe.name() == bldname.substr(dot + 1, bldname.size()))
-				bldname = bldname.substr(0, dot);
-			BuildingIndex bldi = enemytribe.safe_building_index(bldname.c_str());
-			former_buildings.push_back(bldi);
-		}
+
+		Building::FormerBuildings former_buildings = m_old_buildings;
+
+		// The enemy conquers the building
+		// In fact we do not conquer it, but place a new building of same type at
+		// the old location.
+		Player* enemyplayer = enemy.get_owner();
 
 		// Now we destroy the old building before we place the new one.
-		set_defeating_player(enemy.owner().player_number());
+		set_defeating_player(enemyplayer->player_number());
 		schedule_destroy(game);
 
 		enemyplayer->force_building(coords, former_buildings);

=== modified file 'src/logic/militarysite.h'
--- src/logic/militarysite.h	2014-09-19 12:54:54 +0000
+++ src/logic/militarysite.h	2015-10-18 20:57:50 +0000
@@ -27,17 +27,16 @@
 #include "logic/productionsite.h"
 #include "logic/requirements.h"
 #include "logic/soldiercontrol.h"
+#include "scripting/lua_table.h"
 
 namespace Widelands {
 
 class Soldier;
 class World;
 
-struct MilitarySiteDescr : public ProductionSiteDescr {
-	MilitarySiteDescr
-		(char const * name, char const * descname,
-		 const std::string & directory, Profile &,  Section & global_s,
-		 const TribeDescr & tribe, const World& world);
+class MilitarySiteDescr : public ProductionSiteDescr {
+public:
+	MilitarySiteDescr(const std::string& init_descname, const LuaTable& t, const EditorGameBase& egbase);
 	~MilitarySiteDescr() override {}
 
 	Building & create_object() const override;

=== removed file 'src/logic/parse_map_object_types.h'
--- src/logic/parse_map_object_types.h	2015-02-05 11:10:14 +0000
+++ src/logic/parse_map_object_types.h	1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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 WL_LOGIC_PARSE_MAP_OBJECT_TYPES_H
-#define WL_LOGIC_PARSE_MAP_OBJECT_TYPES_H
-
-#include <cstring>
-
-#define PARSE_MAP_OBJECT_TYPES_BEGIN(kind)                                    \
-   if (Section * const section = root_conf.get_section(kind " types")) {      \
-      while (Section::Value const * const v = section->get_next_val()) {      \
-         char const * const     _name = v->get_name  ();                      \
-         char const * const _descname = v->get_string();                      \
-         if (names.count(_name))                                              \
-				throw GameDataError                                             \
-               ("object name \"%s\" is already used", _name);                 \
-         names.insert(_name);                                                 \
-         path += _name;                                                       \
-         path += "/conf";                                                     \
-         try {                                                                \
-            Profile prof(path.c_str(), "global");                             \
-            path.resize(path.size() - strlen("conf"));                        \
-            Section & global_s = prof.get_safe_section("global");             \
-
-#define PARSE_MAP_OBJECT_TYPES_END                                            \
-            prof.check_used();                                                \
-         } catch (const std::exception & e) {                                 \
-				throw GameDataError                                             \
-               ("%s=\"%s\": %s", _name, _descname, e.what());                 \
-         }                                                                    \
-         path.resize(base_path_size);                                         \
-      }                                                                       \
-   }
-
-#endif  // end of include guard: WL_LOGIC_PARSE_MAP_OBJECT_TYPES_H

=== modified file 'src/logic/partially_finished_building.cc'
--- src/logic/partially_finished_building.cc	2014-11-30 18:49:38 +0000
+++ src/logic/partially_finished_building.cc	2015-10-18 20:57:50 +0000
@@ -24,7 +24,7 @@
 #include "economy/wares_queue.h"
 #include "logic/game.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/worker.h"
 #include "sound/sound_handler.h"
 
@@ -112,7 +112,7 @@
 	m_builder_request =
 		new Request
 			(*this,
-			 descr().tribe().safe_worker_index("builder"),
+			 owner().tribe().builder(),
 			 PartiallyFinishedBuilding::request_builder_callback,
 			 wwWORKER);
 }

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc	2015-10-04 18:30:05 +0000
+++ src/logic/player.cc	2015-10-18 20:57:50 +0000
@@ -48,7 +48,7 @@
 #include "logic/soldier.h"
 #include "logic/soldiercontrol.h"
 #include "logic/trainingsite.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "profile/profile.h"
 #include "scripting/lua_table.h"
@@ -112,7 +112,7 @@
  * filled with the BuildingDescr.
  */
 void find_former_buildings
-	(const Widelands::TribeDescr & tribe_descr, const Widelands::BuildingIndex bi,
+	(const Tribes& tribes, const Widelands::BuildingIndex bi,
 	 Widelands::Building::FormerBuildings* former_buildings)
 {
 	assert(former_buildings && former_buildings->empty());
@@ -120,17 +120,13 @@
 
 	for (;;) {
 		Widelands::BuildingIndex oldest_idx = former_buildings->front();
-		const Widelands::BuildingDescr * oldest = tribe_descr.get_building_descr(oldest_idx);
+		const Widelands::BuildingDescr * oldest = tribes.get_building_descr(oldest_idx);
 		if (!oldest->is_enhanced()) {
 			break;
 		}
-		for
-			(Widelands::BuildingIndex i = 0;
-			 i < tribe_descr.get_nrbuildings();
-			 ++i)
-		{
-			const Widelands::BuildingDescr* ob = tribe_descr.get_building_descr(i);
-			if (ob->enhancement() == oldest_idx) {
+		for (BuildingIndex i = 0; i < tribes.nrbuildings(); ++i) {
+			const BuildingDescr* building_descr = tribes.get_building_descr(i);
+			if (building_descr->enhancement() == oldest_idx) {
 				former_buildings->insert(former_buildings->begin(), i);
 				break;
 			}
@@ -159,17 +155,34 @@
 	m_civil_blds_lost    (0),
 	m_civil_blds_defeated(0),
 	m_fields            (nullptr),
-	m_allowed_worker_types  (tribe_descr.get_nrworkers  (), true),
-	m_allowed_building_types(tribe_descr.get_nrbuildings(), true),
+	m_allowed_worker_types(the_egbase.tribes().nrworkers(), true),
+	m_allowed_building_types(the_egbase.tribes().nrbuildings(), true),
 	m_ai(""),
-	m_current_produced_statistics(tribe_descr.get_nrwares    ()),
-	m_current_consumed_statistics(tribe_descr.get_nrwares    ()),
-	m_ware_productions  (tribe_descr.get_nrwares    ()),
-	m_ware_consumptions  (tribe_descr.get_nrwares    ()),
-	m_ware_stocks  (tribe_descr.get_nrwares          ())
+	m_current_produced_statistics(the_egbase.tribes().nrwares()),
+	m_current_consumed_statistics(the_egbase.tribes().nrwares()),
+	m_ware_productions(the_egbase.tribes().nrwares()),
+	m_ware_consumptions(the_egbase.tribes().nrwares()),
+	m_ware_stocks(the_egbase.tribes().nrwares())
 {
 	set_name(name);
 
+	// Disallow workers that the player's tribe doesn't have.
+	for (size_t worker_index = 0; worker_index < m_allowed_worker_types.size(); ++worker_index) {
+		if (!tribe().has_worker(static_cast<WareIndex>(worker_index))) {
+			m_allowed_worker_types[worker_index] = false;
+		}
+	}
+
+	// Disallow buildings that the player's tribe doesn't have and
+	// that aren't militarysites that the tribe could conquer.
+	for (size_t i = 0; i < m_allowed_building_types.size(); ++i) {
+		const BuildingIndex& building_index = static_cast<BuildingIndex>(i);
+		const BuildingDescr& descr = *tribe().get_building_descr(building_index);
+		if (!tribe().has_building(building_index) && descr.type() != MapObjectType::MILITARYSITE) {
+			m_allowed_building_types[i] = false;
+		}
+	}
+
 	// Subscribe to NoteImmovables.
 	immovable_subscriber_ =
 		Notifications::subscribe<NoteImmovable>([this](const NoteImmovable& note) {
@@ -197,7 +210,7 @@
 void Player::create_default_infrastructure() {
 	const Map & map = egbase().map();
 	if (map.get_starting_pos(m_plnum)) {
-		const TribeDescr::Initialization & initialization =
+		const TribeBasicInfo::Initialization & initialization =
 			tribe().initialization(m_initialization_index);
 
 		Game & game = dynamic_cast<Game&>(egbase());
@@ -502,7 +515,7 @@
 {
 	Map & map = egbase().map();
 	BuildingIndex idx = former_buildings.back();
-	const BuildingDescr* descr = tribe().get_building_descr(idx);
+	const BuildingDescr* descr = egbase().tribes().get_building_descr(idx);
 	terraform_for_building(egbase(), player_number(), location, descr);
 	FCoords flag_loc;
 	map.get_brn(map.get_fcoords(location), &flag_loc);
@@ -520,7 +533,7 @@
 	Map & map = egbase().map();
 	if (!former_buildings.empty()) {
 		BuildingIndex idx = former_buildings.back();
-		const BuildingDescr * descr = tribe().get_building_descr(idx);
+		const BuildingDescr * descr = egbase().tribes().get_building_descr(idx);
 		terraform_for_building(egbase(), player_number(), location, descr);
 	}
 	FCoords flag_loc;
@@ -546,33 +559,35 @@
 	int32_t buildcaps;
 
 	// Validate building type
-	if (idx >= tribe().get_nrbuildings())
-		return nullptr;
-	const BuildingDescr & descr = *tribe().get_building_descr(idx);
-
-	if (!descr.is_buildable())
-		return nullptr;
-
+	if (!tribe().has_building(idx)) {
+		return nullptr;
+	}
+
+	const BuildingDescr* descr = egbase().tribes().get_building_descr(idx);
+
+	if (!descr->is_buildable()) {
+		return nullptr;
+	}
 
 	// Validate build position
 	const Map & map = egbase().map();
 	map.normalize_coords(c);
 	buildcaps = get_buildcaps(map.get_fcoords(c));
 
-	if (descr.get_ismine()) {
+	if (descr->get_ismine()) {
 		if (!(buildcaps & BUILDCAPS_MINE))
 			return nullptr;
 	} else {
-		if ((buildcaps & BUILDCAPS_SIZEMASK) < descr.get_size() - BaseImmovable::SMALL + 1)
+		if ((buildcaps & BUILDCAPS_SIZEMASK) < descr->get_size() - BaseImmovable::SMALL + 1)
 			return nullptr;
-		if (descr.get_isport() && !(buildcaps & BUILDCAPS_PORT))
+		if (descr->get_isport() && !(buildcaps & BUILDCAPS_PORT))
 			return nullptr;
 	}
 
 	if (constructionsite)
 		return &egbase().warp_constructionsite(c, m_plnum, idx, false, former_buildings);
 	else {
-		return &descr.create(egbase(), *this, c, false, false, former_buildings);
+		return &descr->create(egbase(), *this, c, false, false, former_buildings);
 	}
 }
 
@@ -774,16 +789,13 @@
 void Player::flagaction(Flag & flag)
 {
 	if (&flag.owner() == this) { //  Additional security check.
-		flag.add_flag_job
-			(dynamic_cast<Game&>(egbase()),
-			 tribe().worker_index("geologist"),
-			 "expedition");
+		flag.add_flag_job(dynamic_cast<Game&>(egbase()), tribe().geologist(), "expedition");
 	}
 }
 
 
 void Player::allow_worker_type(WareIndex const i, bool const allow) {
-	assert(i < m_allowed_worker_types.size());
+	assert(i < static_cast<int>(m_allowed_worker_types.size()));
 	assert(!allow || tribe().get_worker_descr(i)->is_buildable());
 	m_allowed_worker_types[i] = allow;
 }
@@ -1141,27 +1153,22 @@
  */
 void Player::sample_statistics()
 {
-	assert (m_ware_productions.size() == tribe().get_nrwares());
-	assert (m_ware_consumptions.size() == tribe().get_nrwares());
-	assert (m_ware_stocks.size() == tribe().get_nrwares());
+	assert (m_ware_productions.size() == egbase().tribes().nrwares());
+	assert (m_ware_consumptions.size() == egbase().tribes().nrwares());
+	assert (m_ware_stocks.size() == egbase().tribes().nrwares());
 
 	//calculate stocks
-	std::vector<uint32_t> stocks(tribe().get_nrwares());
+	std::vector<uint32_t> stocks(egbase().tribes().nrwares());
 
 	const uint32_t nrecos = get_nr_economies();
 	for (uint32_t i = 0; i < nrecos; ++i) {
 		const std::vector<Widelands::Warehouse *> & warehouses =
 			get_economy_by_number(i)->warehouses();
 
-		for
-			(std::vector<Widelands::Warehouse *>::const_iterator it =
-			 warehouses.begin();
-			 it != warehouses.end();
-			 ++it)
-		{
-			const Widelands::WareList & wares = (*it)->get_wares();
-			for (uint32_t id = 0; id < stocks.size(); ++id) {
-				stocks[id] += wares.stock(WareIndex(static_cast<size_t>(id)));
+		for (Widelands::Warehouse * warehouse : warehouses) {
+			const Widelands::WareList& wares = warehouse->get_wares();
+			for (size_t id = 0; id < stocks.size(); ++id) {
+				stocks[id] += wares.stock(WareIndex(id));
 			}
 		}
 	}
@@ -1184,8 +1191,8 @@
  * A ware was produced. Update the corresponding statistics.
  */
 void Player::ware_produced(WareIndex const wareid) {
-	assert (m_ware_productions.size() == tribe().get_nrwares());
-	assert(wareid < tribe().get_nrwares());
+	assert (m_ware_productions.size() == egbase().tribes().nrwares());
+	assert(egbase().tribes().ware_exists(wareid));
 
 	++m_current_produced_statistics[wareid];
 }
@@ -1199,8 +1206,8 @@
  * \param count the number of consumed wares
  */
 void Player::ware_consumed(WareIndex const wareid, uint8_t const count) {
-	assert (m_ware_consumptions.size() == tribe().get_nrwares());
-	assert(wareid < tribe().get_nrwares());
+	assert (m_ware_consumptions.size() == egbase().tribes().nrwares());
+	assert(egbase().tribes().ware_exists(wareid));
 
 	m_current_consumed_statistics[wareid] += count;
 }
@@ -1212,8 +1219,7 @@
 const std::vector<uint32_t> * Player::get_ware_production_statistics
 		(WareIndex const ware) const
 {
-	assert(ware < m_ware_productions.size());
-
+	assert(ware < static_cast<int>(m_ware_productions.size()));
 	return &m_ware_productions[ware];
 }
 
@@ -1224,7 +1230,7 @@
 const std::vector<uint32_t> * Player::get_ware_consumption_statistics
 		(WareIndex const ware) const {
 
-	assert(ware < m_ware_consumptions.size());
+	assert(ware < static_cast<int>(m_ware_consumptions.size()));
 
 	return &m_ware_consumptions[ware];
 }
@@ -1232,7 +1238,7 @@
 const std::vector<uint32_t> * Player::get_ware_stock_statistics
 		(WareIndex const ware) const
 {
-	assert(ware < m_ware_stocks.size());
+	assert(ware < static_cast<int>(m_ware_stocks.size()));
 
 	return &m_ware_stocks[ware];
 }
@@ -1242,7 +1248,7 @@
 }
 
 Player::BuildingStatsVector* Player::get_mutable_building_statistics(const BuildingIndex& i) {
-	BuildingIndex const nr_buildings = tribe().get_nrbuildings();
+	BuildingIndex const nr_buildings = egbase().tribes().nrbuildings();
 	if (m_building_stats.size() < nr_buildings)
 		m_building_stats.resize(nr_buildings);
 	return &m_building_stats[i];
@@ -1260,8 +1266,14 @@
 		constructionsite ?
 		constructionsite->building().name() : building.descr().name();
 
+	const size_t nr_buildings = egbase().tribes().nrbuildings();
+
+	// Get the valid vector for this
+	if (m_building_stats.size() < nr_buildings)
+		m_building_stats.resize(nr_buildings);
+
 	std::vector<BuildingStats>& stat =
-	   *get_mutable_building_statistics(tribe().building_index(building_name.c_str()));
+		*get_mutable_building_statistics(egbase().tribes().building_index(building_name.c_str()));
 
 	if (ownership == NoteImmovable::Ownership::GAINED) {
 		BuildingStats new_building;
@@ -1309,8 +1321,8 @@
 
 	for (uint16_t i = 0; i < nr_wares; ++i) {
 		std::string name = fr.c_string();
-		WareIndex idx = tribe().ware_index(name);
-		if (idx == INVALID_INDEX) {
+		WareIndex idx = egbase().tribes().ware_index(name);
+		if (!egbase().tribes().ware_exists(idx)) {
 			log
 				("Player %u statistics: unknown ware name %s",
 				 player_number(), name.c_str());
@@ -1332,8 +1344,8 @@
 
 	for (uint16_t i = 0; i < nr_wares; ++i) {
 		std::string name = fr.c_string();
-		WareIndex idx = tribe().ware_index(name);
-		if (idx == INVALID_INDEX) {
+		WareIndex idx = egbase().tribes().ware_index(name);
+		if (!egbase().tribes().ware_exists(idx)) {
 			log
 				("Player %u consumption statistics: unknown ware name %s",
 				player_number(), name.c_str());
@@ -1355,8 +1367,8 @@
 
 	for (uint16_t i = 0; i < nr_wares; ++i) {
 		std::string name = fr.c_string();
-		WareIndex idx = tribe().ware_index(name);
-		if (idx == INVALID_INDEX) {
+		WareIndex idx = egbase().tribes().ware_index(name);
+		if (!egbase().tribes().ware_exists(idx)) {
 			log
 				("Player %u stock statistics: unknown ware name %s",
 				player_number(), name.c_str());
@@ -1386,7 +1398,7 @@
 
 	for (uint8_t i = 0; i < m_current_produced_statistics.size(); ++i) {
 		fw.c_string
-			(tribe().get_ware_descr(i)->name());
+			(egbase().tribes().get_ware_descr(i)->name());
 		fw.unsigned_32(m_current_produced_statistics[i]);
 		for (uint32_t j = 0; j < m_ware_productions[i].size(); ++j)
 			fw.unsigned_32(m_ware_productions[i][j]);
@@ -1398,7 +1410,7 @@
 
 	for (uint8_t i = 0; i < m_current_consumed_statistics.size(); ++i) {
 		fw.c_string
-			(tribe().get_ware_descr(i)->name());
+			(egbase().tribes().get_ware_descr(i)->name());
 		fw.unsigned_32(m_current_consumed_statistics[i]);
 		for (uint32_t j = 0; j < m_ware_consumptions[i].size(); ++j)
 			fw.unsigned_32(m_ware_consumptions[i][j]);
@@ -1409,7 +1421,7 @@
 	fw.unsigned_16(m_ware_stocks[0].size());
 
 	for (uint8_t i = 0; i < m_ware_stocks.size(); ++i) {
-		fw.c_string(tribe().get_ware_descr(i)->name());
+		fw.c_string(egbase().tribes().get_ware_descr(i)->name());
 		for (uint32_t j = 0; j < m_ware_stocks[i].size(); ++j)
 			fw.unsigned_32(m_ware_stocks[i][j]);
 	}

=== modified file 'src/logic/player.h'
--- src/logic/player.h	2015-04-11 21:03:05 +0000
+++ src/logic/player.h	2015-10-18 20:57:50 +0000
@@ -26,10 +26,11 @@
 #include "graphic/color.h"
 #include "logic/building.h"
 #include "logic/constants.h"
+#include "logic/constructionsite.h"
 #include "logic/editor_game_base.h"
 #include "logic/mapregion.h"
 #include "logic/message_queue.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "logic/widelands.h"
 
@@ -128,15 +129,6 @@
 	void set_see_all(bool const t) {m_see_all = t; m_view_changed = true;}
 	bool see_all() const {return m_see_all;}
 
-	/// Per-player and per-field constructionsite information
-	struct ConstructionsiteInformation {
-		ConstructionsiteInformation() : becomes(nullptr), was(nullptr), totaltime(0), completedtime(0) {}
-		const BuildingDescr * becomes; // Also works as a marker telling whether there is a construction site.
-		const BuildingDescr * was; // only valid if "becomes" is an enhanced building.
-		uint32_t               totaltime;
-		uint32_t               completedtime;
-	};
-
 	/// Per-player field information.
 	struct Field {
 		Field() :
@@ -592,7 +584,7 @@
 };
 
 void find_former_buildings
-	(const TribeDescr & tribe_descr, const BuildingIndex bi,
+	(const Tribes& tribes, const BuildingIndex bi,
 	 Building::FormerBuildings* former_buildings);
 
 }

=== modified file 'src/logic/playercommand.cc'
--- src/logic/playercommand.cc	2015-04-15 12:13:52 +0000
+++ src/logic/playercommand.cc	2015-10-18 20:57:50 +0000
@@ -33,7 +33,7 @@
 #include "logic/player.h"
 #include "logic/ship.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/widelands_geometry_io.h"
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
@@ -1313,11 +1313,10 @@
 void CmdSetWareTargetQuantity::execute(Game & game)
 {
 	Player & player = game.player(sender());
-	if
-		(economy  () < player.get_nr_economies() &&
-		 ware_type() < player.tribe().get_nrwares())
+	if (economy() < player.get_nr_economies() && game.tribes().ware_exists(ware_type())) {
 		player.get_economy_by_number(economy())->set_ware_target_quantity
-			(ware_type(),  m_permanent, duetime());
+			(ware_type(), m_permanent, duetime());
+	}
 }
 
 constexpr uint16_t kCurrentPacketVersionSetWareTargetQuantity = 2;
@@ -1374,12 +1373,9 @@
 {
 	Player & player = game.player(sender());
 	const TribeDescr & tribe = player.tribe();
-	if
-		(economy  () < player.get_nr_economies() &&
-		 ware_type() < tribe.get_nrwares())
-	{
-		const int32_t count =
-			tribe.get_ware_descr(ware_type())->default_target_quantity();
+	if (economy() < player.get_nr_economies() && game.tribes().ware_exists(ware_type())) {
+		const int count =
+			tribe.get_ware_descr(ware_type())->default_target_quantity(tribe.name());
 		player.get_economy_by_number(economy())->set_ware_target_quantity
 			(ware_type(),  count, duetime());
 	}
@@ -1433,11 +1429,10 @@
 void CmdSetWorkerTargetQuantity::execute(Game & game)
 {
 	Player & player = game.player(sender());
-	if
-		(economy  () < player.get_nr_economies() &&
-		 ware_type() < player.tribe().get_nrwares())
+	if (economy() < player.get_nr_economies() && game.tribes().ware_exists(ware_type())) {
 		player.get_economy_by_number(economy())->set_worker_target_quantity
 			(ware_type(),  m_permanent, duetime());
+	}
 }
 
 constexpr uint16_t kCurrentPacketVersionSetWorkerTargetQuantity = 2;
@@ -1494,12 +1489,9 @@
 {
 	Player & player = game.player(sender());
 	const TribeDescr & tribe = player.tribe();
-	if
-		(economy  () < player.get_nr_economies() &&
-		 ware_type() < tribe.get_nrwares())
-	{
-		const int32_t count =
-			tribe.get_ware_descr(ware_type())->default_target_quantity();
+	if (economy() < player.get_nr_economies() && game.tribes().ware_exists(ware_type())) {
+		const int count =
+			tribe.get_ware_descr(ware_type())->default_target_quantity(tribe.name());
 		player.get_economy_by_number(economy())->set_worker_target_quantity
 			(ware_type(),  count, duetime());
 	}
@@ -1922,19 +1914,18 @@
 				return;
 			}
 
-			const TribeDescr & tribe = warehouse->descr().tribe();
 			if (m_isworker) {
-				if (!(m_ware < tribe.get_nrworkers())) {
+				if (!(game.tribes().worker_exists(m_ware))) {
 					log
-						("Cmd_SetStockPolicy: sender %u, worker %u out of bounds\n",
+						("Cmd_SetStockPolicy: sender %u, worker %u does not exist\n",
 						 sender(), m_ware);
 					return;
 				}
 				warehouse->set_worker_policy(m_ware, m_policy);
 			} else {
-				if (!(m_ware < tribe.get_nrwares())) {
+				if (!(game.tribes().ware_exists(m_ware))) {
 					log
-						("Cmd_SetStockPolicy: sender %u, ware %u out of bounds\n",
+						("Cmd_SetStockPolicy: sender %u, ware %u does not exist\n",
 						 sender(), m_ware);
 					return;
 				}

=== modified file 'src/logic/playersmanager.cc'
--- src/logic/playersmanager.cc	2014-09-20 09:37:47 +0000
+++ src/logic/playersmanager.cc	2015-10-18 20:57:50 +0000
@@ -89,7 +89,7 @@
 		(m_egbase,
 		 player_number,
 		 initialization_index,
-		 m_egbase.manually_load_tribe(tribe),
+		 *m_egbase.tribes().get_tribe_descr(m_egbase.tribes().tribe_index(tribe)),
 		 name);
 	p->set_team_number(team);
 	if (player_number <= UserSettings::highest_playernum()) {

=== modified file 'src/logic/production_program.cc'
--- src/logic/production_program.cc	2015-10-11 15:18:55 +0000
+++ src/logic/production_program.cc	2015-10-18 20:57:50 +0000
@@ -19,8 +19,10 @@
 
 #include "logic/production_program.h"
 
+#include <memory>
 #include <sstream>
 
+#include <boost/algorithm/string.hpp>
 #include <boost/format.hpp>
 
 #include "base/i18n.h"
@@ -31,6 +33,7 @@
 #include "economy/wares_queue.h"
 #include "graphic/graphic.h"
 #include "helper.h"
+#include "io/filesystem/layered_filesystem.h"
 #include "logic/checkstep.h"
 #include "logic/findimmovable.h"
 #include "logic/findnode.h"
@@ -43,32 +46,16 @@
 #include "logic/soldier.h"
 #include "logic/soldiercontrol.h"
 #include "logic/trainingsite.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.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"
 
 namespace Widelands {
 
 namespace {
 
-/**
- * Convert std::string to any sstream-compatible type
- *
- * \see http://www.experts-exchange.com/Programming/
- *    Programming_Languages/Cplusplus/Q_20670737.html
- * \author AssafLavie on http://www.experts-exchange.com
- */
-// TODO(sirver): Use boost::lexical_cast<>
-template <typename T> T string_to_type(const std::string& s) {
-	std::istringstream iss(s);
-	T x;
-	iss >> x;
-	return x;
-}
-
 /// Matches the string that candidate points to against the string that
 /// template points to. Stops at when reaching a null character or the
 /// character terminator. If a match is found, candidate is moved beyond the
@@ -137,24 +124,35 @@
 }
 
 ProductionProgram::ActReturn::Condition * create_economy_condition
-	(char * & parameters, const TribeDescr & tribe)
+	(char * & parameters, const Tribes& tribes)
 {
 	try {
 		if (match_force_skip(parameters, "needs"))
 			try {
 				bool reached_end;
 				char const * const type_name = next_word(parameters, reached_end);
-				WareIndex index = tribe.ware_index(type_name);
-				if (index != INVALID_INDEX) {
-					tribe.set_ware_type_has_demand_check(index);
+				const WareIndex& wareindex = tribes.ware_index(type_name);
+				if (tribes.ware_exists(wareindex)) {
+					for (int i = 0; i < static_cast<int>(tribes.nrtribes()); ++i) {
+						const TribeDescr& tribe_descr = *tribes.get_tribe_descr(i);
+						if (tribe_descr.has_ware(wareindex)) {
+							tribes.set_ware_type_has_demand_check(wareindex, tribe_descr.name());
+						}
+					}
 					return
 						new ProductionProgram::ActReturn::EconomyNeedsWare
-							(index);
-				} else if ((index = tribe.worker_index(type_name)) != INVALID_INDEX) {
-					tribe.set_worker_type_has_demand_check(index);
+							(wareindex);
+				} else if (tribes.worker_exists(tribes.worker_index(type_name))) {
+					const WareIndex& workerindex = tribes.worker_index(type_name);
+					for (int i = 0; i < static_cast<int>(tribes.nrtribes()); ++i) {
+						const TribeDescr* tribe_descr = tribes.get_tribe_descr(i);
+						if (tribe_descr->has_worker(workerindex)) {
+							tribes.set_worker_type_has_demand_check(workerindex);
+						}
+					}
 					return
 						new ProductionProgram::ActReturn::EconomyNeedsWorker
-							(index);
+							(workerindex);
 				} else
 					throw GameDataError
 						("expected %s but found \"%s\"",
@@ -172,12 +170,12 @@
 
 
 ProductionProgram::ActReturn::Condition * create_site_condition
-	(char * & parameters, const ProductionSiteDescr & descr)
+	(char * & parameters, const ProductionSiteDescr & descr, const Tribes& tribes)
 {
 	try {
 		if (match_force_skip(parameters, "has"))
 			return
-				new ProductionProgram::ActReturn::SiteHas(parameters, descr);
+				new ProductionProgram::ActReturn::SiteHas(parameters, descr, tribes);
 		else
 			throw GameDataError
 				("expected %s but found \"%s\"", "\"has\"", parameters);
@@ -218,10 +216,10 @@
 }
 
 void ProductionProgram::parse_ware_type_group
-	(char            * & parameters,
-	 WareTypeGroup   & group,
-	 const TribeDescr & tribe,
-	 const BillOfMaterials  & inputs)
+	(char * & parameters,
+	 WareTypeGroup& group,
+	 const Tribes& tribes,
+	 const BillOfMaterials& inputs)
 {
 	std::set<WareIndex>::iterator last_insert_pos = group.first.end();
 	uint8_t count     = 1;
@@ -235,7 +233,7 @@
 		char const terminator = *parameters;
 		*parameters = '\0';
 
-		WareIndex const ware_index = tribe.safe_ware_index(ware);
+		WareIndex const ware_index = tribes.safe_ware_index(ware);
 
 		for (BillOfMaterials::const_iterator input_it = inputs.begin(); input_it != inputs.end(); ++input_it) {
 			if (input_it == inputs.end()) {
@@ -257,7 +255,7 @@
 				 "wrong order of ware types within group: ware type %s appears "
 				 "after ware type %s (fix order!)",
 				 ware,
-				 tribe.get_ware_descr(*group.first.begin())->name().c_str());
+				 tribes.get_ware_descr(*group.first.begin())->name().c_str());
 		last_insert_pos = group.first.insert(last_insert_pos, ware_index);
 		*parameters = terminator;
 		switch (terminator) {
@@ -308,14 +306,14 @@
 
 // Just a dummy to satisfy the superclass interface. Returns an empty string.
 std::string ProductionProgram::ActReturn::Negation::description
-	(const TribeDescr &) const
+	(const Tribes&) const
 {
 	return "";
 }
 
 // Just a dummy to satisfy the superclass interface. Returns an empty string.
 std::string ProductionProgram::ActReturn::Negation::description_negation
-	(const TribeDescr &) const
+	(const Tribes&) const
 {
 	return "";
 }
@@ -327,21 +325,19 @@
 	return ps.get_economy()->needs_ware(ware_type);
 }
 std::string ProductionProgram::ActReturn::EconomyNeedsWare::description
-	(const TribeDescr & tribe) const
+	(const Tribes& tribes) const
 {
-	// TODO(GunChleoc): We can make this more elegant if we add another definition to the conf files,
-	// so for "Log"; we will also have "logs" (numberless plural)
 	/** TRANSLATORS: e.g. Completed/Skipped/Did not start ... because the economy needs the ware ‘%s’*/
 	std::string result =  (boost::format(_("the economy needs the ware ‘%s’"))
-			  % tribe.get_ware_descr(ware_type)->descname()).str();
+			  % tribes.get_ware_descr(ware_type)->descname()).str();
 	return result;
 }
 std::string ProductionProgram::ActReturn::EconomyNeedsWare::description_negation
-	(const TribeDescr & tribe) const
+	(const Tribes& tribes) const
 {
 	/** TRANSLATORS: e.g. Completed/Skipped/Did not start ... because the economy doesn’t need the ware ‘%s’*/
 	std::string result = (boost::format(_("the economy doesn’t need the ware ‘%s’"))
-			  % tribe.get_ware_descr(ware_type)->descname()).str();
+			  % tribes.get_ware_descr(ware_type)->descname()).str();
 	return result;
 }
 
@@ -351,30 +347,30 @@
 	return ps.get_economy()->needs_worker(worker_type);
 }
 std::string ProductionProgram::ActReturn::EconomyNeedsWorker::description
-	(const TribeDescr & tribe) const
+	(const Tribes& tribes) const
 {
 	/** TRANSLATORS: e.g. Completed/Skipped/Did not start ... because the economy needs the worker ‘%s’*/
 	std::string result = (boost::format(_("the economy needs the worker ‘%s’"))
-			  % tribe.get_worker_descr(worker_type)->descname()).str();
+			  % tribes.get_worker_descr(worker_type)->descname()).str();
 	return result;
 }
 
 std::string ProductionProgram::ActReturn::EconomyNeedsWorker::description_negation
-	(const TribeDescr & tribe) const
+	(const Tribes& tribes) const
 {
 	/** TRANSLATORS: e.g. Completed/Skipped/Did not start ...*/
 	/** TRANSLATORS:      ... because the economy doesn’t need the worker ‘%s’*/
 	std::string result = (boost::format(_("the economy doesn’t need the worker ‘%s’"))
-			  % tribe.get_worker_descr(worker_type)->descname()).str();
+			  % tribes.get_worker_descr(worker_type)->descname()).str();
 	return result;
 }
 
 
 ProductionProgram::ActReturn::SiteHas::SiteHas
-	(char * & parameters, const ProductionSiteDescr & descr)
+	(char * & parameters, const ProductionSiteDescr & descr, const Tribes& tribes)
 {
 	try {
-		parse_ware_type_group(parameters, group, descr.tribe(), descr.inputs());
+		parse_ware_type_group(parameters, group, tribes, descr.inputs());
 	} catch (const WException & e) {
 		throw GameDataError
 			("has ware_type1[,ware_type2[,...]][:N]: %s", e.what());
@@ -397,11 +393,11 @@
 
 
 std::string ProductionProgram::ActReturn::SiteHas::description
-	(const TribeDescr & tribe) const
+	(const Tribes& tribes) const
 {
 	std::vector<std::string> condition_list;
 	for (const WareIndex& temp_ware : group.first) {
-		condition_list.push_back(tribe.get_ware_descr(temp_ware)->descname());
+		condition_list.push_back(tribes.get_ware_descr(temp_ware)->descname());
 	}
 	std::string condition = i18n::localize_list(condition_list, i18n::ConcatenateWith::AND);
 	if (1 < group.second) {
@@ -419,11 +415,11 @@
 }
 
 std::string ProductionProgram::ActReturn::SiteHas::description_negation
-	(const TribeDescr & tribe) const
+	(const Tribes& tribes) const
 {
 	std::vector<std::string> condition_list;
 	for (const WareIndex& temp_ware : group.first) {
-		condition_list.push_back(tribe.get_ware_descr(temp_ware)->descname());
+		condition_list.push_back(tribes.get_ware_descr(temp_ware)->descname());
 	}
 	std::string condition = i18n::localize_list(condition_list, i18n::ConcatenateWith::AND);
 	if (1 < group.second) {
@@ -451,14 +447,14 @@
 	return false;
 }
 std::string ProductionProgram::ActReturn::WorkersNeedExperience::description
-	(const TribeDescr &) const
+	(const Tribes&) const
 {
 	/** TRANSLATORS: 'Completed/Skipped/Did not start ... because a worker needs experience'. */
 	return _("a worker needs experience");
 }
 
 std::string ProductionProgram::ActReturn::WorkersNeedExperience::description_negation
-	(const TribeDescr &) const
+	(const Tribes&) const
 {
 	/** TRANSLATORS: 'Completed/Skipped/Did not start ... because the workers need no experience'. */
 	return _("the workers need no experience");
@@ -467,15 +463,15 @@
 
 ProductionProgram::ActReturn::Condition *
 ProductionProgram::ActReturn::create_condition
-	(char * & parameters, const ProductionSiteDescr & descr)
+	(char * & parameters, const ProductionSiteDescr & descr, const Tribes& tribes)
 {
 	try {
 		if      (match_force_skip(parameters, "not"))
-			return new ActReturn::Negation (parameters, descr);
+			return new ActReturn::Negation (parameters, descr, tribes);
 		else if (match_force_skip(parameters, "economy"))
-			return create_economy_condition(parameters, descr.tribe());
+			return create_economy_condition(parameters, tribes);
 		else if (match_force_skip(parameters, "site"))
-			return create_site_condition   (parameters, descr);
+			return create_site_condition   (parameters, descr, tribes);
 		else if (match_force_skip(parameters, "workers"))
 			return create_workers_condition(parameters);
 		else
@@ -489,7 +485,7 @@
 
 
 ProductionProgram::ActReturn::ActReturn
-	(char * parameters, const ProductionSiteDescr & descr)
+	(char* parameters, const ProductionSiteDescr& descr, const Tribes& tribes)
 {
 	try {
 		if      (match(parameters, "failed"))    m_result = Failed;
@@ -504,7 +500,7 @@
 			if      (match_force_skip(parameters, "when")) {
 				m_is_when = true;
 				for (;;) {
-					m_conditions.push_back(create_condition(parameters, descr));
+					m_conditions.push_back(create_condition(parameters, descr, tribes));
 					if (*parameters) {
 						skip(parameters);
 						if (!match_force_skip(parameters, "and"))
@@ -519,7 +515,7 @@
 					if (!*parameters)
 						throw GameDataError
 							("expected condition at end of input");
-					m_conditions.push_back(create_condition(parameters, descr));
+					m_conditions.push_back(create_condition(parameters, descr, tribes));
 					if (*parameters) {
 						skip(parameters);
 						if (!match_force_skip(parameters, "or"))
@@ -560,14 +556,14 @@
 				if (!condition->evaluate(ps)) { //  A condition is false,
 					return ps.program_step(game); //  continue program.
 				}
-				condition_list.push_back(condition->description(ps.owner().tribe()));
+				condition_list.push_back(condition->description(game.tribes()));
 			}
 		} else { //  "unless a or b or ..." (all conditions must be false)
 			for (const Condition * condition : m_conditions) {
 				if (condition->evaluate(ps)) { //  A condition is true,
 					return ps.program_step(game); //  continue program.
 				}
-				condition_list.push_back(condition->description_negation(ps.owner().tribe()));
+				condition_list.push_back(condition->description_negation(game.tribes()));
 			}
 		}
 		std::string condition_string = i18n::localize_list(condition_list, i18n::ConcatenateWith::AND);
@@ -679,7 +675,7 @@
 }
 
 void ProductionProgram::ActCall::execute
-	(Game & game, ProductionSite & ps) const
+	(Game& game, ProductionSite& ps) const
 {
 	ProgramResult const program_result =
 		static_cast<ProgramResult>(ps.top_state().phase);
@@ -707,7 +703,10 @@
 }
 
 ProductionProgram::ActWorker::ActWorker(
-		char* parameters, const std::string& production_program_name, ProductionSiteDescr* descr)
+		char* parameters,
+		const std::string& production_program_name,
+		ProductionSiteDescr* descr,
+		const Tribes& tribes)
 {
 	try {
 		m_program = parameters;
@@ -715,7 +714,7 @@
 		//  Quote form "void ProductionSite::program_act(Game &)":
 		//  "Always main worker is doing stuff"
 		const WorkerDescr & main_worker_descr =
-			*descr->tribe().get_worker_descr(descr->working_positions()[0].first);
+			*tribes.get_worker_descr(descr->working_positions()[0].first);
 
 		//  This will fail unless the main worker has a program with the given
 		//  name, so it also validates the parameter.
@@ -742,7 +741,7 @@
 }
 
 void ProductionProgram::ActWorker::execute
-	(Game & game, ProductionSite & ps) const
+	(Game& game, ProductionSite& ps) const
 {
 	// Always main worker is doing stuff
 	ps.m_working_positions[0].worker->update_task_buildingwork(game);
@@ -807,7 +806,7 @@
 	}
 }
 
-void ProductionProgram::ActCheckMap::execute(Game & game, ProductionSite & ps) const
+void ProductionProgram::ActCheckMap::execute(Game& game, ProductionSite& ps) const
 {
 	switch (m_feature) {
 		case SEAFARING: {
@@ -825,7 +824,7 @@
 }
 
 ProductionProgram::ActAnimate::ActAnimate(
-	char* parameters, const std::string& directory, Profile& prof, ProductionSiteDescr* descr) {
+	char* parameters, ProductionSiteDescr* descr) {
 	try {
 		bool reached_end;
 		char * const animation_name = next_word(parameters, reached_end);
@@ -835,8 +834,7 @@
 		if (descr->is_animation_known(animation_name))
 			m_id = descr->get_animation(animation_name);
 		else {
-			m_id = g_gr->animations().load(directory.c_str(), prof.get_safe_section(animation_name));
-			descr->add_animation(animation_name, m_id);
+			throw GameDataError("Unknown animation '%s'", animation_name);
 		}
 		if (!reached_end) { //  The next parameter is the duration.
 			char * endp;
@@ -854,7 +852,7 @@
 }
 
 void ProductionProgram::ActAnimate::execute
-	(Game & game, ProductionSite & ps) const
+	(Game& game, ProductionSite & ps) const
 {
 	ps.start_animation(game, m_id);
 	return
@@ -863,14 +861,13 @@
 
 
 ProductionProgram::ActConsume::ActConsume
-	(char * parameters, const ProductionSiteDescr & descr)
+	(char * parameters, const ProductionSiteDescr& descr, const Tribes& tribes)
 {
 	try {
-		const TribeDescr & tribe = descr.tribe();
 		for (;;) {
 			m_groups.resize(m_groups.size() + 1);
 			parse_ware_type_group
-				(parameters, *m_groups.rbegin(), tribe, descr.inputs());
+				(parameters, *m_groups.rbegin(), tribes, descr.inputs());
 			if (!*parameters)
 				break;
 			force_skip(parameters);
@@ -987,10 +984,9 @@
 
 
 ProductionProgram::ActProduce::ActProduce
-	(char * parameters, const ProductionSiteDescr & descr)
+	(char* parameters, const ProductionSiteDescr& descr, const Tribes& tribes)
 {
 	try {
-		const TribeDescr & tribe = descr.tribe();
 		for (bool more = true; more; ++parameters) {
 			m_items.resize(m_items.size() + 1);
 			std::pair<WareIndex, uint8_t> & item = *m_items.rbegin();
@@ -1029,11 +1025,11 @@
 			if
 				(!
 				 descr.is_output_ware_type
-				 	(item.first = tribe.safe_ware_index(ware)))
+					(item.first = tribes.safe_ware_index(ware)))
 				throw GameDataError
 					(
-					 "%s is not declared as an output (\"output=%s\" was not "
-					 "found in the [global] section)",
+					 "%s is not declared as an output (\"%s\" was not "
+					 "found in the \"outputs\" table)",
 					 ware, ware);
 		}
 	} catch (const WException & e) {
@@ -1084,10 +1080,9 @@
 
 
 ProductionProgram::ActRecruit::ActRecruit
-	(char * parameters, const ProductionSiteDescr & descr)
+	(char* parameters, const ProductionSiteDescr& descr, const Tribes& tribes)
 {
 	try {
-		const TribeDescr & tribe = descr.tribe();
 		for (bool more = true; more; ++parameters) {
 			m_items.resize(m_items.size() + 1);
 			std::pair<WareIndex, uint8_t> & item = *m_items.rbegin();
@@ -1126,11 +1121,11 @@
 			if
 				(!
 				 descr.is_output_worker_type
-				 	(item.first = tribe.safe_worker_index(worker)))
+					(item.first = tribes.safe_worker_index(worker)))
 				throw GameDataError
 					(
-					 "%s is not declared as an output (\"output=%s\" was not "
-					 "found in the [global] section)",
+					 "%s is not declared as an output (\"%s\" was not "
+					 "found in the \"outputs\" table)",
 					 worker, worker);
 		}
 	} catch (const WException & e) {
@@ -1523,13 +1518,12 @@
 	return ps.program_step(game);
 }
 
-ProductionProgram::ActPlayFX::ActPlayFX
-	(const std::string & directory, char * parameters)
-{
+ProductionProgram::ActPlayFX::ActPlayFX(char * parameters) {
 	try {
 		bool reached_end;
-		std::string filename = next_word(parameters, reached_end);
-		name = directory + "/" + filename;
+		const std::string& filepath = next_word(parameters, reached_end);
+		const std::string& filename = next_word(parameters, reached_end);
+		name = filepath + "/" + filename;
 
 		if (!reached_end) {
 			char * endp;
@@ -1541,7 +1535,7 @@
 		} else
 			priority = 127;
 
-		g_sound_handler.load_fx_if_needed(directory, filename, name);
+		g_sound_handler.load_fx_if_needed(filepath, filename, name);
 	} catch (const WException & e) {
 		throw GameDataError("playFX: %s", e.what());
 	}
@@ -1564,7 +1558,7 @@
 
 		objectname = params[0];
 		workerprogram = params[1];
-		radius = string_to_type<uint32_t>(params[2]);
+		radius = boost::lexical_cast<uint32_t>(params[2]);
 
 		std::set<std::string> & building_radius_infos = descr->m_workarea_info[radius];
 		std::string description = descr->name() + ' ' + production_program_name;
@@ -1577,9 +1571,9 @@
 }
 
 const ImmovableDescr & ProductionProgram::ActConstruct::get_construction_descr
-	(ProductionSite & psite) const
+	(const Tribes& tribes) const
 {
-	const ImmovableDescr * descr = psite.descr().tribe().get_immovable_descr(objectname);
+	const ImmovableDescr * descr = tribes.get_immovable_descr(tribes.immovable_index(objectname));
 	if (!descr)
 		throw wexception("ActConstruct: immovable '%s' does not exist", objectname.c_str());
 
@@ -1587,10 +1581,10 @@
 }
 
 
-void ProductionProgram::ActConstruct::execute(Game & g, ProductionSite & psite) const
+void ProductionProgram::ActConstruct::execute(Game & game, ProductionSite & psite) const
 {
 	ProductionSite::State & state = psite.top_state();
-	const ImmovableDescr & descr = get_construction_descr(psite);
+	const ImmovableDescr & descr = get_construction_descr(game.tribes());
 
 	// Early check for no resources
 	const Buildcost & buildcost = descr.buildcost();
@@ -1604,27 +1598,27 @@
 	}
 
 	if (available_resource == INVALID_INDEX) {
-		psite.program_end(g, Failed);
+		psite.program_end(game, Failed);
 		return;
 	}
 
 	// Look for an appropriate object in the given radius
 	std::vector<ImmovableFound> immovables;
 	CheckStepWalkOn cstep(MOVECAPS_WALK, true);
-	Area<FCoords> area (g.map().get_fcoords(psite.base_flag().get_position()), radius);
+	Area<FCoords> area (game.map().get_fcoords(psite.base_flag().get_position()), radius);
 	if
-		(g.map().find_reachable_immovables
+		(game.map().find_reachable_immovables
 		 (area, &immovables, cstep, FindImmovableByDescr(descr)))
 	{
 		state.objvar = immovables[0].object;
 
-		psite.m_working_positions[0].worker->update_task_buildingwork(g);
+		psite.m_working_positions[0].worker->update_task_buildingwork(game);
 		return;
 	}
 
 	// No object found, look for a field where we can build
 	std::vector<Coords> fields;
-	Map  & map = g.map();
+	Map  & map = game.map();
 	FindNodeAnd fna;
 	fna.add(FindNodeShore());
 	fna.add(FindNodeImmovableSize(FindNodeImmovableSize::sizeNone));
@@ -1658,12 +1652,12 @@
 
 		state.coord = best_coords;
 
-		psite.m_working_positions[0].worker->update_task_buildingwork(g);
+		psite.m_working_positions[0].worker->update_task_buildingwork(game);
 		return;
 	}
 
 	psite.molog("construct: no object or buildable field\n");
-	psite.program_end(g, Failed);
+	psite.program_end(game, Failed);
 }
 
 bool ProductionProgram::ActConstruct::get_building_work
@@ -1687,7 +1681,7 @@
 			return false;
 		}
 	} else {
-		const ImmovableDescr & descr = get_construction_descr(psite);
+		const ImmovableDescr & descr = get_construction_descr(game.tribes());
 		remaining = descr.buildcost();
 	}
 
@@ -1706,7 +1700,7 @@
 
 	// Second step: give ware to worker
 	WareInstance* ware =
-	   new WareInstance(wq->get_ware(), psite.descr().tribe().get_ware_descr(wq->get_ware()));
+		new WareInstance(wq->get_ware(), game.tribes().get_ware_descr(wq->get_ware()));
 	ware->init(game);
 	worker.set_carried_ware(game, ware);
 	wq->set_filled(wq->get_filled() - 1);
@@ -1726,47 +1720,61 @@
 	psite.program_end(game, Failed);
 }
 
-ProductionProgram::ProductionProgram(
-		const std::string& directory, Profile& prof, const std::string& _name,
-		const std::string& _descname, const World& world,
+
+ProductionProgram::ProductionProgram(const std::string& _name,
+		const std::string& _descname,
+		std::unique_ptr<LuaTable> actions_table,
+		const EditorGameBase& egbase,
 		ProductionSiteDescr* building)
 	: m_name(_name), m_descname(_descname) {
-	Section& program_s = prof.get_safe_section(_name.c_str());
-	while (Section::Value* const v = program_s.get_next_val()) {
+
+	for (const std::string& action_string : actions_table->array_entries<std::string>()) {
+		std::vector<std::string> parts;
+		boost::split(parts, action_string, boost::is_any_of("="));
+		if (parts.size() != 2) {
+			throw GameDataError("invalid line: \"%s\" in production program \"%s\" for building \"%s\"",
+									  action_string.c_str(), _name.c_str(), building->name().c_str());
+		}
+		std::unique_ptr<char []> arguments(new char[parts[1].size() + 1]);
+		strncpy(arguments.get(), parts[1].c_str(), parts[1].size() + 1);
+
 		ProductionProgram::Action* action;
-		if (!strcmp(v->get_name(), "return"))
-			action = new ActReturn(v->get_string(), *building);
-		else if (!strcmp(v->get_name(), "call"))
-			action = new ActCall(v->get_string(), *building);
-		else if (!strcmp(v->get_name(), "sleep"))
-			action = new ActSleep(v->get_string());
-		else if (!strcmp(v->get_name(), "animate"))
-			action = new ActAnimate(v->get_string(), directory, prof, building);
-		else if (!strcmp(v->get_name(), "consume"))
-			action = new ActConsume(v->get_string(), *building);
-		else if (!strcmp(v->get_name(), "produce"))
-			action = new ActProduce(v->get_string(), *building);
-		else if (!strcmp(v->get_name(), "recruit"))
-			action = new ActRecruit(v->get_string(), *building);
-		else if (!strcmp(v->get_name(), "worker"))
-			action = new ActWorker(v->get_string(), _name, building);
-		else if (!strcmp(v->get_name(), "mine"))
-			action = new ActMine(v->get_string(), world, _name, building);
-		else if (!strcmp(v->get_name(), "check_soldier"))
-			action = new ActCheckSoldier(v->get_string());
-		else if (!strcmp(v->get_name(), "train"))
-			action = new ActTrain(v->get_string());
-		else if (!strcmp(v->get_name(), "playFX"))
-			action = new ActPlayFX(directory, v->get_string());
-		else if (!strcmp(v->get_name(), "construct"))
-			action = new ActConstruct(v->get_string(), _name, building);
-		else if (!strcmp(v->get_name(), "check_map"))
-			action = new ActCheckMap(v->get_string());
+
+		if (boost::iequals(parts[0], "return"))
+			action = new ActReturn(arguments.get(), *building, egbase.tribes());
+		else if (boost::iequals(parts[0], "call"))
+			action = new ActCall(arguments.get(), *building);
+		else if (boost::iequals(parts[0], "sleep"))
+			action = new ActSleep(arguments.get());
+		else if (boost::iequals(parts[0], "animate"))
+		action = new ActAnimate(arguments.get(), building);
+		else if (boost::iequals(parts[0], "consume"))
+			action = new ActConsume(arguments.get(), *building, egbase.tribes());
+		else if (boost::iequals(parts[0], "produce"))
+			action = new ActProduce(arguments.get(), *building, egbase.tribes());
+		else if (boost::iequals(parts[0], "recruit"))
+			action = new ActRecruit(arguments.get(), *building, egbase.tribes());
+		else if (boost::iequals(parts[0], "worker"))
+			action = new ActWorker(arguments.get(), _name, building, egbase.tribes());
+		else if (boost::iequals(parts[0], "mine"))
+			action = new ActMine(arguments.get(), egbase.world(), _name, building);
+		else if (boost::iequals(parts[0], "check_soldier"))
+			action = new ActCheckSoldier(arguments.get());
+		else if (boost::iequals(parts[0], "train"))
+			action = new ActTrain(arguments.get());
+		else if (boost::iequals(parts[0], "playFX"))
+			action = new ActPlayFX(arguments.get());
+		else if (boost::iequals(parts[0], "construct"))
+			action = new ActConstruct(arguments.get(), _name, building);
+		else if (boost::iequals(parts[0], "check_map"))
+			action = new ActCheckMap(arguments.get());
 		else
-			throw GameDataError("unknown command type \"%s\"", v->get_name());
+			throw GameDataError("unknown command type \"%s\" in production program \"%s\" for building \"%s\"",
+									  arguments.get(), _name.c_str(), building->name().c_str());
 		m_actions.push_back(action);
 	}
 	if (m_actions.empty())
-		throw GameDataError("no actions");
+		throw GameDataError("no actions in production program \"%s\" for building \"%s\"",
+								  _name.c_str(), building->name().c_str());
 }
 }

=== modified file 'src/logic/production_program.h'
--- src/logic/production_program.h	2015-02-08 18:16:41 +0000
+++ src/logic/production_program.h	2015-10-18 20:57:50 +0000
@@ -22,6 +22,7 @@
 
 #include <cassert>
 #include <cstring>
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -31,17 +32,17 @@
 #include "base/log.h"
 #include "base/macros.h"
 #include "logic/bill_of_materials.h"
+#include "logic/editor_game_base.h"
 #include "logic/program_result.h"
 #include "logic/training_attribute.h"
 #include "logic/widelands.h"
-
-class Profile;
+#include "scripting/lua_table.h"
 
 namespace Widelands {
 
 class Game;
-struct ImmovableDescr;
-struct ProductionSiteDescr;
+class ImmovableDescr;
+class ProductionSiteDescr;
 class ProductionSite;
 class TribeDescr;
 class Worker;
@@ -83,7 +84,7 @@
 	static void parse_ware_type_group
 		(char            * & parameters,
 		 WareTypeGroup   & group,
-		 const TribeDescr & tribe,
+		 const Tribes& tribes,
 		 const BillOfMaterials  & inputs);
 
 	/// Returns from the program.
@@ -135,29 +136,29 @@
 	/// Note: If the execution reaches the end of the program. the return value
 	/// is implicitly set to Completed.
 	struct ActReturn : public Action {
-		ActReturn(char * parameters, const ProductionSiteDescr &);
+		ActReturn(char* parameters, const ProductionSiteDescr&, const Tribes& tribes);
 		virtual ~ActReturn();
 		void execute(Game &, ProductionSite &) const override;
 
 		struct Condition {
 			virtual ~Condition();
 			virtual bool evaluate(const ProductionSite &) const = 0;
-			virtual std::string description(const TribeDescr &) const = 0;
-			virtual std::string description_negation(const TribeDescr &) const = 0;
+			virtual std::string description(const Tribes&) const = 0;
+			virtual std::string description_negation(const Tribes&) const = 0;
 		};
 		static Condition * create_condition
-			(char * & parameters, const ProductionSiteDescr &);
+			(char * & parameters, const ProductionSiteDescr&, const Tribes& tribes);
 		struct Negation : public Condition {
 			Negation
-				(char * & parameters, const ProductionSiteDescr & descr)
-				: operand(create_condition(parameters, descr))
+				(char * & parameters, const ProductionSiteDescr& descr, const Tribes& tribes)
+				: operand(create_condition(parameters, descr, tribes))
 			{}
 			virtual ~Negation();
 			bool evaluate(const ProductionSite &) const override;
 			// Just a dummy to satisfy the superclass interface. Do not use.
-			std::string description(const TribeDescr &) const override;
+			std::string description(const Tribes&) const override;
 			// Just a dummy to satisfy the superclass interface. Do not use.
-			std::string description_negation(const TribeDescr &) const override;
+			std::string description_negation(const Tribes&) const override;
 		private:
 			Condition * const operand;
 		};
@@ -166,8 +167,8 @@
 		struct EconomyNeedsWare : public Condition {
 			EconomyNeedsWare(const WareIndex& i) : ware_type(i) {}
 			bool evaluate(const ProductionSite &) const override;
-			std::string description(const TribeDescr &) const override;
-			std::string description_negation(const TribeDescr &) const override;
+			std::string description(const Tribes& tribes) const override;
+			std::string description_negation(const Tribes& tribes) const override;
 		private:
 			WareIndex ware_type;
 		};
@@ -176,8 +177,8 @@
 		struct EconomyNeedsWorker : public Condition {
 			EconomyNeedsWorker(const WareIndex& i) : worker_type(i) {}
 			bool evaluate(const ProductionSite &) const override;
-			std::string description(const TribeDescr &) const override;
-			std::string description_negation(const TribeDescr &) const override;
+			std::string description(const Tribes& tribes) const override;
+			std::string description_negation(const Tribes& tribes) const override;
 		private:
 			WareIndex worker_type;
 		};
@@ -186,10 +187,10 @@
 		/// wares, combining from any of the types specified, in its input
 		/// queues.
 		struct SiteHas : public Condition {
-			SiteHas(char * & parameters, const ProductionSiteDescr &);
+			SiteHas(char* & parameters, const ProductionSiteDescr&, const Tribes& tribes);
 			bool evaluate(const ProductionSite &) const override;
-			std::string description(const TribeDescr &) const override;
-			std::string description_negation(const TribeDescr &) const override;
+			std::string description(const Tribes& tribes) const override;
+			std::string description_negation(const Tribes& tribes) const override;
 		private:
 			WareTypeGroup group;
 		};
@@ -198,8 +199,8 @@
 		/// become upgraded.
 		struct WorkersNeedExperience : public Condition {
 			bool evaluate(const ProductionSite &) const override;
-			std::string description(const TribeDescr &) const override;
-			std::string description_negation(const TribeDescr &) const override;
+			std::string description(const Tribes&) const override;
+			std::string description_negation(const Tribes&) const override;
 		};
 
 		using Conditions = std::vector<Condition *>;
@@ -240,7 +241,7 @@
 	///         program (with the same effect as executing "return=skipped").
 	///       * If handling_method is "repeat", the command is repeated.
 	struct ActCall : public Action {
-		ActCall(char * parameters, const ProductionSiteDescr &);
+		ActCall(char* parameters, const ProductionSiteDescr&);
 		void execute(Game &, ProductionSite &) const override;
 	private:
 		ProductionProgram             * m_program;
@@ -256,8 +257,8 @@
 	///       The name of a program defined in the productionsite's main worker.
 	struct ActWorker : public Action {
 		ActWorker(char* parameters,
-		          const std::string& production_program_name,
-		          ProductionSiteDescr*);
+					 const std::string& production_program_name,
+					 ProductionSiteDescr*, const Tribes& tribes);
 		void execute(Game &, ProductionSite &) const override;
 		bool get_building_work(Game &, ProductionSite &, Worker &) const override;
 		void building_work_failed(Game &, ProductionSite &, Worker &) const override;
@@ -320,7 +321,7 @@
 	/// animation will not be stopped by this command. It will run until another
 	/// animation is started.)
 	struct ActAnimate : public Action {
-		ActAnimate(char* parameters, const std::string& directory, Profile&, ProductionSiteDescr*);
+		ActAnimate(char* parameters, ProductionSiteDescr*);
 		void execute(Game &, ProductionSite &) const override;
 	private:
 		uint32_t m_id;
@@ -371,7 +372,7 @@
 	/// types of a group are sorted.
 	// TODO(unknown): change this!
 	struct ActConsume : public Action {
-		ActConsume(char * parameters, const ProductionSiteDescr &);
+		ActConsume(char* parameters, const ProductionSiteDescr&, const Tribes& tribes);
 		void execute(Game &, ProductionSite &) const override;
 		using Groups = std::vector<WareTypeGroup>;
 		const Groups & groups() const {return m_groups;}
@@ -395,7 +396,7 @@
 	/// produced wares are of the type specified in the group. How the produced
 	/// wares are handled is defined by the productionsite.
 	struct ActProduce : public Action {
-		ActProduce(char * parameters, const ProductionSiteDescr &);
+		ActProduce(char* parameters, const ProductionSiteDescr&, const Tribes& tribes);
 		void execute(Game &, ProductionSite &) const override;
 		bool get_building_work(Game &, ProductionSite &, Worker &) const override;
 		using Items = std::vector<std::pair<WareIndex, uint8_t>>;
@@ -420,7 +421,7 @@
 	/// The recruited workers are of the type specified in the group. How the
 	/// recruited workers are handled is defined by the productionsite.
 	struct ActRecruit : public Action {
-		ActRecruit(char * parameters, const ProductionSiteDescr &);
+		ActRecruit(char* parameters, const ProductionSiteDescr&, const Tribes& tribes);
 		void execute(Game &, ProductionSite &) const override;
 		bool get_building_work(Game &, ProductionSite &, Worker &) const override;
 		using Items = std::vector<std::pair<WareIndex, uint8_t>>;
@@ -467,17 +468,16 @@
 	///    parameters ::= soundFX [priority]
 	/// Parameter semantics:
 	///    directory:
-	///       The directory of the productionsite.
+	///       The directory of the sound effect.
 	///    soundFX:
-	///       The filename of an soundFX (relative to the productionsite's
-	///       directory).
+	///       The base filename of a soundFX (without path, running numbers or file extension)
 	///    priority:
 	///       An integer. If omitted, 127 is used.
 	///
 	/// Plays the specified soundFX with the specified priority. Whether the
 	/// soundFX is actually played is determined by the sound handler.
 	struct ActPlayFX : public Action {
-		ActPlayFX(const std::string & directory, char * parameters);
+		ActPlayFX(char * parameters);
 		void execute(Game &, ProductionSite &) const override;
 	private:
 		std::string name;
@@ -504,7 +504,7 @@
 		bool get_building_work(Game &, ProductionSite &, Worker &) const override;
 		void building_work_failed(Game &, ProductionSite &, Worker &) const override;
 
-		const ImmovableDescr & get_construction_descr(ProductionSite &) const;
+		const ImmovableDescr& get_construction_descr(const Tribes& tribes) const;
 
 	private:
 		std::string objectname;
@@ -512,12 +512,12 @@
 		uint32_t radius;
 	};
 
-	ProductionProgram(const std::string& directory,
-	                  Profile&,
-	                  const std::string& name,
-	                  const std::string& descname,
-	                  const World&,
-	                  ProductionSiteDescr*);
+	ProductionProgram(const std::string& _name,
+							const std::string& _descname,
+							std::unique_ptr<LuaTable> actions_table,
+							const EditorGameBase& egbase,
+							ProductionSiteDescr* building);
+
 	~ProductionProgram() {
 		for (Action * action : m_actions) {
 			delete action;

=== modified file 'src/logic/productionsite.cc'
--- src/logic/productionsite.cc	2015-09-03 13:09:49 +0000
+++ src/logic/productionsite.cc	2015-10-18 20:57:50 +0000
@@ -20,6 +20,8 @@
 
 #include "logic/productionsite.h"
 
+#include <memory>
+
 #include <boost/format.hpp>
 
 #include "base/i18n.h"
@@ -36,10 +38,9 @@
 #include "logic/map.h"
 #include "logic/player.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warelist.h"
 #include "logic/world/world.h"
-#include "profile/profile.h"
 
 namespace Widelands {
 
@@ -54,104 +55,141 @@
 */
 
 ProductionSiteDescr::ProductionSiteDescr
-	(MapObjectType _type, char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 const TribeDescr & _tribe, const World& world)
-	:
-	BuildingDescr(_type, _name, _descname, directory, prof, global_s, _tribe)
+	(const std::string& init_descname, const char* msgctxt, MapObjectType _type,
+	 const LuaTable& table, const EditorGameBase& egbase)
+	: BuildingDescr(init_descname, _type, table, egbase),
+	  m_out_of_resource_title(""),
+	  m_out_of_resource_message(""),
+	  out_of_resource_productivity_threshold_(100)
 {
-	Section * const section = prof.get_section("out_of_resource_notification");
-	if (section != nullptr)
-	{
-		m_out_of_resource_title = section->get_string("title", "");
-		m_out_of_resource_message = section->get_string("message", "");
-		out_of_resource_productivity_threshold_ = section->get_natural("productivity_threshold", 100);
-	}
-	else
-	{
-		m_out_of_resource_title = "";
-		m_out_of_resource_message = "";
-		out_of_resource_productivity_threshold_ = 100;
-	}
-	while
-		(Section::Value const * const op = global_s.get_next_val("output"))
-		try {
-			WareIndex idx = tribe().ware_index(op->get_string());
-			if (idx != INVALID_INDEX) {
-				if (m_output_ware_types.count(idx))
-					throw wexception("this ware type has already been declared as an output");
-				m_output_ware_types.insert(idx);
-			} else if ((idx = tribe().worker_index(op->get_string())) != INVALID_INDEX) {
-				if (m_output_worker_types.count(idx))
-					throw wexception("this worker type has already been declared as an output");
-				m_output_worker_types.insert(idx);
-			} else
-				throw wexception("tribe does not define a ware or worker type with this name");
-		} catch (const WException & e) {
-			throw wexception("output \"%s\": %s", op->get_string(), e.what());
-		}
-
-	if (Section * const s = prof.get_section("inputs"))
-		while (Section::Value const * const val = s->get_next_val())
-			try {
-				WareIndex const idx = tribe().ware_index(val->get_name());
-				if (idx != INVALID_INDEX) {
+	i18n::Textdomain td("tribes");
+	std::unique_ptr<LuaTable> items_table;
+
+	if (table.has_key("out_of_resource_notification")) {
+		items_table = table.get_table("out_of_resource_notification");
+		m_out_of_resource_title = _(items_table->get_string("title"));
+		m_out_of_resource_message = pgettext_expr(msgctxt, items_table->get_string("message").c_str());
+		if (items_table->has_key("productivity_threshold")) {
+			out_of_resource_productivity_threshold_ = items_table->get_int("productivity_threshold");
+		}
+	}
+
+	if (table.has_key("outputs")) {
+		for (const std::string& output : table.get_table("outputs")->array_entries<std::string>()) {
+			try {
+				WareIndex idx = egbase.tribes().ware_index(output);
+				if (egbase.tribes().ware_exists(idx)) {
+					if (m_output_ware_types.count(idx)) {
+						throw wexception("this ware type has already been declared as an output");
+					}
+					m_output_ware_types.insert(idx);
+				} else {
+					idx = egbase.tribes().worker_index(output);
+					if (egbase.tribes().worker_exists(idx)) {
+						if (m_output_worker_types.count(idx)) {
+							throw wexception("this worker type has already been declared as an output");
+						}
+						m_output_worker_types.insert(idx);
+					} else {
+						throw wexception("tribes do not define a ware or worker type with this name");
+					}
+				}
+			} catch (const WException & e) {
+				throw wexception("output \"%s\": %s", output.c_str(), e.what());
+			}
+		}
+	}
+
+	if (table.has_key("inputs")) {
+		items_table = table.get_table("inputs");
+		for (const std::string& ware_name : items_table->keys<std::string>()) {
+			int amount = items_table->get_int(ware_name);
+			try {
+				if (amount < 1 || 255 < amount) {
+					throw wexception("count is out of range 1 .. 255");
+				}
+				WareIndex const idx = egbase.tribes().ware_index(ware_name);
+				if (egbase.tribes().ware_exists(idx)) {
 					for (const WareAmount& temp_inputs : inputs()) {
 						if (temp_inputs.first == idx) {
 							throw wexception("duplicated");
 						}
 					}
-					int32_t const value = val->get_int();
-					if (value < 1 || 255 < value)
-						throw wexception("count is out of range 1 .. 255");
-					m_inputs.push_back(std::pair<WareIndex, uint8_t>(idx, value));
-				} else
+					m_inputs.push_back(std::pair<WareIndex, uint8_t>(idx, amount));
+				} else {
 					throw wexception
-						("tribe does not define a ware type with this name");
+						("tribes do not define a ware type with this name");
+				}
 			} catch (const WException & e) {
-				throw wexception("input \"%s=%s\": %s", val->get_name(), val->get_string(), e.what());
+				throw wexception("input \"%s=%d\": %s", ware_name.c_str(), amount, e.what());
 			}
+		}
+	}
+
 
 	// Are we only a production site?
 	// If not, we might not have a worker
-	if (Section * const working_positions_s = prof.get_section("working positions"))
-		while (Section::Value const * const v = working_positions_s->get_next_val())
+	if (table.has_key("working_positions")) {
+		items_table = table.get_table("working_positions");
+		for (const std::string& worker_name : items_table->keys<std::string>()) {
+			int amount = items_table->get_int(worker_name);
 			try {
-				WareIndex const woi = tribe().worker_index(v->get_name());
-				if (woi != INVALID_INDEX) {
+				if (amount < 1 || 255 < amount) {
+					throw wexception("count is out of range 1 .. 255");
+				}
+				WareIndex const woi = egbase.tribes().worker_index(worker_name);
+				if (egbase.tribes().worker_exists(woi)) {
 					for (const WareAmount& wp : working_positions()) {
 						if (wp.first == woi) {
 							throw wexception("duplicated");
 						}
 					}
-					m_working_positions.push_back(std::pair<WareIndex, uint32_t>(woi, v->get_positive()));
-				} else
+					m_working_positions.push_back(std::pair<WareIndex, uint32_t>(woi, amount));
+				} else {
 					throw wexception("invalid");
+				}
 			} catch (const WException & e) {
-				throw wexception("%s=\"%s\": %s", v->get_name(), v->get_string(), e.what());
+				throw wexception("%s=\"%d\": %s", worker_name.c_str(), amount, e.what());
 			}
-	if (working_positions().empty() && !global_s.has_val("max_soldiers"))
+		}
+	}
+
+	if (working_positions().empty() && !table.has_key("max_soldiers")) {
 		throw wexception("no working/soldier positions");
+	}
 
 	// Get programs
-	if (Section * const programs_s = prof.get_section("programs"))
-	while (Section::Value const * const v = programs_s->get_next_val()) {
-		std::string program_name = v->get_name();
-		std::transform
-			(program_name.begin(), program_name.end(), program_name.begin(),
-			 tolower);
-		try {
-			if (m_programs.count(program_name))
-				throw wexception("this program has already been declared");
-			m_programs[program_name] =
-				new ProductionProgram
-					(directory, prof, program_name, v->get_string(), world, this);
-		} catch (const std::exception & e) {
-			throw wexception("program %s: %s", program_name.c_str(), e.what());
+	if (table.has_key("programs")) {
+		items_table = table.get_table("programs");
+		for (std::string program_name : items_table->keys<std::string>()) {
+			std::transform
+				(program_name.begin(), program_name.end(), program_name.begin(),
+				 tolower);
+			try {
+				if (m_programs.count(program_name)) {
+					throw wexception("this program has already been declared");
+				}
+				std::unique_ptr<LuaTable> program_table = items_table->get_table(program_name);
+				m_programs[program_name] =
+						new ProductionProgram(program_name, program_table->get_string("descname"),
+													 program_table->get_table("actions"),
+													 egbase, this);
+			} catch (const std::exception & e) {
+				throw wexception("program %s: %s", program_name.c_str(), e.what());
+			}
 		}
 	}
 }
 
+ProductionSiteDescr::ProductionSiteDescr
+	(const std::string& init_descname,
+	 const char* msgctxt,
+	 const LuaTable& table,
+	 const EditorGameBase& egbase)
+	: ProductionSiteDescr(init_descname, msgctxt, MapObjectType::PRODUCTIONSITE, table, egbase)
+{}
+
+
 ProductionSiteDescr::~ProductionSiteDescr()
 {
 	while (m_programs.size()) {
@@ -253,7 +291,7 @@
 bool ProductionSite::has_workers(BuildingIndex targetSite, Game & /* game */)
 {
 	// bld holds the description of the building we want to have
-	if (upcast(ProductionSiteDescr const, bld, descr().tribe().get_building_descr(targetSite))) {
+	if (upcast(ProductionSiteDescr const, bld, owner().tribe().get_building_descr(targetSite))) {
 		// if he has workers
 		if (bld->nr_working_positions()) {
 			WareIndex need = bld->working_positions()[0].first;
@@ -262,7 +300,7 @@
 					return false; // no one is in this house
 				} else {
 					WareIndex have = working_positions()[i].worker->descr().worker_index();
-					if (descr().tribe().get_worker_descr(have)->can_act_as(need)) {
+					if (owner().tribe().get_worker_descr(have)->can_act_as(need)) {
 						return true; // he found a lead worker
 					}
 				}
@@ -570,16 +608,16 @@
 		}
 		if (!worker_placed) {
 			// Find the next smaller version of this worker
-			WareIndex nuwo    = psite.descr().tribe().get_nrworkers();
-			WareIndex current = WareIndex(static_cast<size_t>(0));
-			for (; current < nuwo; ++current) {
-				WorkerDescr const * worker = psite.descr().tribe().get_worker_descr(current);
-				if (worker->becomes() == idx) {
-					idx = current;
+			for (WareIndex i = 0;  i < static_cast<int>(game.tribes().nrworkers()); ++i) {
+				const WorkerDescr& worker_descr = *game.tribes().get_worker_descr(i);
+				if (worker_descr.becomes() == idx) {
+					idx = i;
+					worker_placed = true;
 					break;
 				}
 			}
-			if (current == nuwo)
+
+			if (!worker_placed)
 				throw
 					wexception
 						("Something went wrong! No fitting place for worker %s in %s at (%u, %u) found!",
@@ -749,7 +787,7 @@
 		{
 			WareIndex const ware_index = ware_type_with_count.first;
 			const WareDescr & ware_ware_descr =
-				*descr().tribe().get_ware_descr(ware_type_with_count.first);
+				*owner().tribe().get_ware_descr(ware_type_with_count.first);
 			{
 				WareInstance & ware =
 					*new WareInstance(ware_index, &ware_ware_descr);
@@ -771,7 +809,7 @@
 			*m_recruited_workers.rbegin();
 		{
 			const WorkerDescr & worker_descr =
-				*descr().tribe().get_worker_descr(worker_type_with_count.first);
+				*owner().tribe().get_worker_descr(worker_type_with_count.first);
 			{
 				Worker & recruit =
 					dynamic_cast<Worker&>(worker_descr.create_object());
@@ -793,7 +831,7 @@
 	for (WaresQueue * queue : m_input_queues) {
 		if (queue->get_filled() > queue->get_max_fill()) {
 			queue->set_filled(queue->get_filled() - 1);
-			const WareDescr & wd = *descr().tribe().get_ware_descr(queue->get_ware());
+			const WareDescr & wd = *owner().tribe().get_ware_descr(queue->get_ware());
 			WareInstance & ware = *new WareInstance(queue->get_ware(), &wd);
 			ware.init(game);
 			worker.start_task_dropoff(game, ware);

=== modified file 'src/logic/productionsite.h'
--- src/logic/productionsite.h	2015-06-10 06:46:40 +0000
+++ src/logic/productionsite.h	2015-10-18 20:57:50 +0000
@@ -31,13 +31,14 @@
 #include "logic/building.h"
 #include "logic/production_program.h"
 #include "logic/program_result.h"
+#include "scripting/lua_table.h"
 
 namespace Widelands {
 
-struct WareDescr;
 struct ProductionProgram;
+class Request;
 class Soldier;
-class Request;
+class WareDescr;
 class WaresQueue;
 class WorkerDescr;
 
@@ -52,13 +53,15 @@
  * A production site can have one (or more) input wares types. Every input
  * wares type has an associated store.
  */
-struct ProductionSiteDescr : public BuildingDescr {
+class ProductionSiteDescr : public BuildingDescr {
+public:
 	friend struct ProductionProgram; // To add animations
 
-	ProductionSiteDescr
-		(MapObjectType type, char const * name, char const * descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 const TribeDescr &, const World&);
+	ProductionSiteDescr(const std::string& init_descname, const char* msgctxt, MapObjectType type,
+							  const LuaTable& t, const EditorGameBase& egbase);
+	ProductionSiteDescr(const std::string& init_descname, const char* msgctxt,
+							  const LuaTable& t, const EditorGameBase& egbase);
+
 	~ProductionSiteDescr() override;
 
 	Building & create_object() const override;

=== modified file 'src/logic/ship.cc'
--- src/logic/ship.cc	2015-10-18 18:31:35 +0000
+++ src/logic/ship.cc	2015-10-18 20:57:50 +0000
@@ -39,35 +39,25 @@
 #include "logic/mapregion.h"
 #include "logic/path.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "logic/widelands_geometry_io.h"
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
-#include "profile/profile.h"
 #include "wui/interactive_gamebase.h"
 
 namespace Widelands {
 
-ShipDescr::ShipDescr(const char* given_name,
-                     const char* gdescname,
-                     const std::string& directory,
-                     Profile& prof,
-                     Section& global_s,
-                     const TribeDescr& gtribe)
-   : BobDescr(MapObjectType::SHIP, 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");
-	if (sinking_s)
-		add_animation("sinking", g_gr->animations().load(directory, *sinking_s));
-
-	m_capacity = global_s.get_natural("capacity", 20);
-	m_vision_range = global_s.get_natural("vision_range", 7);
+ShipDescr::ShipDescr(const std::string& init_descname, const LuaTable& table)
+	:
+	BobDescr(init_descname, MapObjectType::SHIP, MapObjectDescr::OwnerType::kTribe, table) {
+
+	i18n::Textdomain td("tribes");
+
+	// Read the sailing animations
+	add_directional_animation(&m_sail_anims, "sail");
+
+	m_capacity = table.has_key("capacity") ? table.get_int("capacity") : 20;
 }
 
 uint32_t ShipDescr::movecaps() const {
@@ -869,7 +859,7 @@
 /// @note only called via player command
 void Ship::exp_construct_port(Game&, const Coords& c) {
 	assert(m_expedition);
-	BuildingIndex port_idx = get_owner()->tribe().safe_building_index("port");
+	BuildingIndex port_idx = get_owner()->tribe().port();
 	get_owner()->force_csite(c, port_idx);
 	m_ship_state = EXP_COLONIZING;
 }
@@ -1003,7 +993,7 @@
 ==============================
 */
 
-constexpr uint8_t kCurrentPacketVersion = 4;
+constexpr uint8_t kCurrentPacketVersion = 5;
 
 Ship::Loader::Loader() : m_lastdock(0), m_destination(0) {
 }
@@ -1101,21 +1091,29 @@
 	try {
 		// The header has been peeled away by the caller
 		uint8_t const packet_version = fr.unsigned_8();
-		if (packet_version == kCurrentPacketVersion) {
-			std::string owner = fr.c_string();
-			std::string name = fr.c_string();
-			const ShipDescr* descr = nullptr;
-
-			egbase.manually_load_tribe(owner);
-
-			if (const TribeDescr* tribe = egbase.get_tribe(owner))
-				descr = dynamic_cast<const ShipDescr*>(tribe->get_bob_descr(name));
-
-			if (!descr)
-				throw GameDataError("undefined ship %s/%s", owner.c_str(), name.c_str());
-
-			loader->init(egbase, mol, descr->create_object());
-			loader->load(fr);
+		if (1 <= packet_version && packet_version <= kCurrentPacketVersion) {
+			try {
+				const ShipDescr* descr = nullptr;
+				// Removing this will break the test suite
+				if (packet_version < 5) {
+					std::string tribe_name = fr.c_string();
+					fr.c_string(); // This used to be the ship's name, which we don't need any more.
+					if (!(egbase.tribes().tribe_exists(tribe_name))) {
+						throw GameDataError("Tribe %s does not exist for ship", tribe_name.c_str());
+					}
+					const WareIndex& tribe_index = egbase.tribes().tribe_index(tribe_name);
+					const TribeDescr& tribe_descr = *egbase.tribes().get_tribe_descr(tribe_index);
+					descr = egbase.tribes().get_ship_descr(tribe_descr.ship());
+				} else {
+					std::string name = fr.c_string();
+					const WareIndex& ship_index = egbase.tribes().safe_ship_index(name);
+					descr = egbase.tribes().get_ship_descr(ship_index);
+				}
+				loader->init(egbase, mol, descr->create_object());
+				loader->load(fr);
+			} catch (const WException& e) {
+				throw GameDataError("Failed to load ship: %s", e.what());
+			}
 		} else {
 			throw UnhandledVersionError(packet_version, kCurrentPacketVersion);
 		}
@@ -1129,8 +1127,6 @@
 void Ship::save(EditorGameBase& egbase, MapObjectSaver& mos, FileWrite& fw) {
 	fw.unsigned_8(HeaderShip);
 	fw.unsigned_8(kCurrentPacketVersion);
-
-	fw.c_string(descr().get_owner_tribe()->name());
 	fw.c_string(descr().name());
 
 	Bob::save(egbase, mos, fw);

=== modified file 'src/logic/ship.h'
--- src/logic/ship.h	2015-10-04 18:30:05 +0000
+++ src/logic/ship.h	2015-10-18 20:57:50 +0000
@@ -57,11 +57,9 @@
 	}
 };
 
-struct ShipDescr : BobDescr {
-	ShipDescr
-		(char const * name, char const * descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 const TribeDescr &);
+class ShipDescr : public BobDescr {
+public:
+	ShipDescr(const std::string& init_descname, const LuaTable& t);
 	~ShipDescr() override {}
 
 	Bob & create_object() const override;
@@ -70,13 +68,10 @@
 	const DirAnimations & get_sail_anims() const {return m_sail_anims;}
 
 	uint32_t get_capacity() const {return m_capacity;}
-	uint32_t vision_range() const {return m_vision_range;}
-
 
 private:
 	DirAnimations m_sail_anims;
 	uint32_t m_capacity;
-	uint32_t m_vision_range;
 	DISALLOW_COPY_AND_ASSIGN(ShipDescr);
 };
 

=== modified file 'src/logic/single_player_game_settings_provider.cc'
--- src/logic/single_player_game_settings_provider.cc	2015-03-01 09:21:20 +0000
+++ src/logic/single_player_game_settings_provider.cc	2015-10-18 20:57:50 +0000
@@ -22,11 +22,11 @@
 #include <boost/format.hpp>
 
 #include "ai/computer_player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribes.h"
 
 
 SinglePlayerGameSettingsProvider::SinglePlayerGameSettingsProvider() {
-	s.tribes = Widelands::TribeDescr::get_all_tribe_infos();
+	s.tribes = Widelands::Tribes::get_all_tribeinfos();
 	s.scenario = false;
 	s.multiplayer = false;
 	s.playernum = 0;

=== modified file 'src/logic/soldier.cc'
--- src/logic/soldier.cc	2015-04-14 18:34:40 +0000
+++ src/logic/soldier.cc	2015-10-18 20:57:50 +0000
@@ -21,6 +21,7 @@
 
 #include <cstdio>
 #include <list>
+#include <memory>
 
 #include <boost/format.hpp>
 
@@ -47,11 +48,10 @@
 #include "logic/message_queue.h"
 #include "logic/militarysite.h"
 #include "logic/player.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
-#include "profile/profile.h"
 #include "wui/mapviewpixelconstants.h"
 
 namespace Widelands {
@@ -73,58 +73,40 @@
 constexpr int kRetreatWhenHealthDropsBelowThisPercentage = 50;
 }  // namespace
 
-SoldierDescr::SoldierDescr
-	(char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 const TribeDescr & _tribe)
-	:
-	WorkerDescr(MapObjectType::SOLDIER, _name, _descname, directory, prof, global_s, _tribe)
+SoldierDescr::SoldierDescr(const std::string& init_descname,
+									const LuaTable& table,
+									const EditorGameBase& egbase) :
+	WorkerDescr(init_descname, MapObjectType::SOLDIER, table, egbase)
 {
 	add_attribute(MapObject::Attribute::SOLDIER);
 
-	m_base_hp = global_s.get_safe_positive("hp");
+	m_base_hp = table.get_int("hp");
 
-	try { //  parse attack
-		const char * const attack = global_s.get_safe_string("attack");
-		std::vector<std::string> list(split_string(attack, "-"));
-		if (list.size() != 2)
-			throw GameDataError
-				("expected %s but found \"%s\"", "\"min-max\"", attack);
-		for (std::string& temp_str : list) {
-			remove_spaces(temp_str);
-		}
-		char * endp;
-		m_min_attack = strtol(list[0].c_str(), &endp, 0);
-		if (*endp || 0 == m_min_attack)
-			throw GameDataError
-				("expected %s but found \"%s\"",
-				 "positive integer", list[0].c_str());
-		m_max_attack = strtol(list[1].c_str(), &endp, 0);
-		if (*endp || m_max_attack < m_min_attack)
-			throw GameDataError
-				("expected positive integer >= %u but found \"%s\"",
-				 m_min_attack, list[1].c_str());
-	} catch (const WException & e) {
-		throw GameDataError("attack: %s", e.what());
+	// Parse attack
+	std::unique_ptr<LuaTable> items_table = table.get_table("attack");
+	m_min_attack = items_table->get_int("minimum");
+	m_max_attack = items_table->get_int("maximum");
+	if (m_min_attack > m_max_attack) {
+		throw GameDataError("Minimum attack %d is greater than maximum attack %d.", m_min_attack, m_max_attack);
 	}
 
 	// Parse defend
-	m_defense           = global_s.get_safe_int("defense");
+	m_defense           = table.get_int("defense");
 
 	// Parse evade
-	m_evade             = global_s.get_safe_int("evade");
+	m_evade             = table.get_int("evade");
 
 	// Parse increases per level
-	m_hp_incr           = global_s.get_safe_int("hp_incr_per_level");
-	m_attack_incr       = global_s.get_safe_int("attack_incr_per_level");
-	m_defense_incr      = global_s.get_safe_int("defense_incr_per_level");
-	m_evade_incr        = global_s.get_safe_int("evade_incr_per_level");
+	m_hp_incr           = table.get_int("hp_incr_per_level");
+	m_attack_incr       = table.get_int("attack_incr_per_level");
+	m_defense_incr      = table.get_int("defense_incr_per_level");
+	m_evade_incr        = table.get_int("evade_incr_per_level");
 
 	// Parse max levels
-	m_max_hp_level      = global_s.get_safe_int("max_hp_level");
-	m_max_attack_level  = global_s.get_safe_int("max_attack_level");
-	m_max_defense_level = global_s.get_safe_int("max_defense_level");
-	m_max_evade_level   = global_s.get_safe_int("max_evade_level");
+	m_max_hp_level      = table.get_int("max_hp_level");
+	m_max_attack_level  = table.get_int("max_attack_level");
+	m_max_defense_level = table.get_int("max_defense_level");
+	m_max_evade_level   = table.get_int("max_evade_level");
 
 	// Load the filenames
 	m_hp_pics_fn     .resize(m_max_hp_level      + 1);
@@ -132,99 +114,39 @@
 	m_defense_pics_fn.resize(m_max_defense_level + 1);
 	m_evade_pics_fn  .resize(m_max_evade_level   + 1);
 
-	std::string dir = directory;
-	dir += "/";
 	for (uint32_t i = 0; i <= m_max_hp_level;      ++i) {
-		m_hp_pics_fn[i] = dir;
-		m_hp_pics_fn[i] += global_s.get_safe_string((boost::format("hp_level_%u_pic")
-																	% i).str());
-
+		m_hp_pics_fn[i] = table.get_string((boost::format("hp_level_%u_pic") % i).str());
 	}
 	for (uint32_t i = 0; i <= m_max_attack_level;  ++i) {
-		m_attack_pics_fn[i] = dir;
-		m_attack_pics_fn[i] += global_s.get_safe_string((boost::format("attack_level_%u_pic")
-																		 % i).str());
+		m_attack_pics_fn[i] = table.get_string((boost::format("attack_level_%u_pic") % i).str());
 	}
 	for (uint32_t i = 0; i <= m_max_defense_level; ++i) {
-		m_defense_pics_fn[i] = dir;
-		m_defense_pics_fn[i] += global_s.get_safe_string((boost::format("defense_level_%u_pic")
-																		  % i).str());
+		m_defense_pics_fn[i] = table.get_string((boost::format("defense_level_%u_pic") % i).str());
 	}
 	for (uint32_t i = 0; i <= m_max_evade_level;   ++i) {
-		m_evade_pics_fn[i] = dir;
-		m_evade_pics_fn[i] += global_s.get_safe_string((boost::format("evade_level_%u_pic")
-																		% i).str());
-	}
-
-	{  ///  Battle animations
-		/// attack_success_*-> soldier is attacking and hit his opponent
-		/// attack_failure_*-> soldier is attacking and miss hit, defender evades
-		/// evade_success_* -> soldier is defending and opponent misses
-		/// evade_failure_* -> soldier is defending and opponent hits
-		/// die_*           -> soldier is dying
-		m_attack_success_w_name =
-			load_animations_from_string
-				(directory, prof, global_s, "attack_success_w");
-		m_attack_success_e_name =
-			load_animations_from_string
-				(directory, prof, global_s, "attack_success_e");
-		m_attack_failure_w_name =
-			load_animations_from_string
-				(directory, prof, global_s, "attack_failure_w");
-		m_attack_failure_e_name =
-			load_animations_from_string
-				(directory, prof, global_s, "attack_failure_e");
-		m_evade_success_w_name =
-			load_animations_from_string
-				(directory, prof, global_s, "evade_success_w");
-		m_evade_success_e_name =
-			load_animations_from_string
-				(directory, prof, global_s, "evade_success_e");
-		m_evade_failure_w_name =
-			load_animations_from_string
-				(directory, prof, global_s, "evade_failure_w");
-		m_evade_failure_e_name =
-			load_animations_from_string
-				(directory, prof, global_s, "evade_failure_e");
-		m_die_w_name =
-			load_animations_from_string
-				(directory, prof, global_s, "die_w");
-		m_die_e_name =
-			load_animations_from_string
-				(directory, prof, global_s, "die_e");
-	}
-
-}
-
-std::vector<std::string> SoldierDescr::load_animations_from_string
-	(const std::string & directory, Profile & prof,
-	 Section & global_s, const char * anim_name)
-{
-	std::vector<std::string> list;
-	try {
-		const char * anim_string = global_s.get_safe_string(anim_name);
-		list = split_string(anim_string, ",");
-		if (list.size() < 1)
-			throw GameDataError
-				("expected %s but found \"%s\"",
-				 "\"anim_name[,another_anim,...]\"", anim_string);
-
-		// Sanitation
-		for (std::string& temp_str : list) {
-			remove_spaces(temp_str);
-
-			// Check that section exists
-			Section &
-				anim_s = prof.get_safe_section(temp_str.c_str());
-
-			add_animation
-				(temp_str.c_str(), g_gr->animations().load(directory, anim_s));
-		}
-	} catch (const WException & e) {
-		throw GameDataError("%s : %s", anim_name, e.what());
-	}
-
-	return list;
+		m_evade_pics_fn[i] = table.get_string((boost::format("evade_level_%u_pic") % i).str());
+	}
+
+	//  Battle animations
+	// attack_success_*-> soldier is attacking and hit his opponent
+	add_battle_animation(table.get_table("attack_success_w"), &m_attack_success_w_name);
+	add_battle_animation(table.get_table("attack_success_e"), &m_attack_success_e_name);
+
+	// attack_failure_*-> soldier is attacking and miss hit, defender evades
+	add_battle_animation(table.get_table("attack_failure_w"), &m_attack_failure_w_name);
+	add_battle_animation(table.get_table("attack_failure_e"), &m_attack_failure_e_name);
+
+	// evade_success_* -> soldier is defending and opponent misses
+	add_battle_animation(table.get_table("evade_success_w"), &m_evade_success_w_name);
+	add_battle_animation(table.get_table("evade_success_e"), &m_evade_success_e_name);
+
+	// evade_failure_* -> soldier is defending and opponent hits
+	add_battle_animation(table.get_table("evade_failure_w"), &m_evade_failure_w_name);
+	add_battle_animation(table.get_table("evade_failure_e"), &m_evade_failure_e_name);
+
+	// die_*           -> soldier is dying
+	add_battle_animation(table.get_table("die_w"), &m_die_w_name);
+	add_battle_animation(table.get_table("die_e"), &m_die_e_name);
 }
 
 /**
@@ -316,8 +238,11 @@
 		uint32_t i = game.logic_rand() % m_die_e_name.size();
 		run = m_die_e_name[i];
 	}
-
-	return get_animation(run.c_str());
+	if (!is_animation_known(run)) {
+		log("Missing animation '%s' for soldier %s. Reverting to idle.\n", run.c_str(), name().c_str());
+		run = "idle";
+	}
+	return get_animation(run);
 }
 
 /**
@@ -325,6 +250,15 @@
  */
 Bob & SoldierDescr::create_object() const {return *new Soldier(*this);}
 
+void SoldierDescr::add_battle_animation(std::unique_ptr<LuaTable> table, std::vector<std::string>* result) {
+	for (const std::string& anim_name: table->array_entries<std::string>()) {
+		if (!is_animation_known(anim_name)) {
+			throw GameDataError("Trying to add unknown battle animation: %s", anim_name.c_str());
+		}
+		result->push_back(anim_name);
+	}
+}
+
 /*
 ==============================
 
@@ -661,7 +595,7 @@
 	(const TribeDescr & tribe, uint32_t & w, uint32_t & h)
 {
 	const SoldierDescr * soldierdesc = static_cast<const SoldierDescr *>
-		(tribe.get_worker_descr(tribe.worker_index("soldier")));
+		(tribe.get_worker_descr(tribe.soldier()));
 	const Image* hppic = soldierdesc->get_hp_level_pic(0);
 	const Image* attackpic = soldierdesc->get_attack_level_pic(0);
 	const Image* defensepic = soldierdesc->get_defense_level_pic(0);
@@ -978,7 +912,7 @@
 		if (upcast(Warehouse, wh, enemy)) {
 			Requirements noreq;
 			defenders = wh->count_workers
-				(game, wh->descr().tribe().worker_index("soldier"), noreq);
+				(game, wh->owner().tribe().soldier(), noreq);
 		}
 		//  Any enemy soldier at baseflag count as defender.
 		std::vector<Bob *> soldiers;

=== modified file 'src/logic/soldier.h'
--- src/logic/soldier.h	2015-09-07 12:12:32 +0000
+++ src/logic/soldier.h	2015-10-18 20:57:50 +0000
@@ -20,6 +20,8 @@
 #ifndef WL_LOGIC_SOLDIER_H
 #define WL_LOGIC_SOLDIER_H
 
+#include <memory>
+
 #include "base/macros.h"
 #include "logic/training_attribute.h"
 #include "logic/worker.h"
@@ -39,12 +41,12 @@
 
 #define HP_FRAMECOLOR RGBColor(255, 255, 255)
 
-struct SoldierDescr : public WorkerDescr {
+class SoldierDescr : public WorkerDescr {
+public:
 	friend class Economy;
-	SoldierDescr
-		(char const * const _name, char const * const _descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 const TribeDescr &);
+
+	SoldierDescr(const std::string& init_descname,
+					 const LuaTable& t, const EditorGameBase& egbase);
 	~SoldierDescr() override {}
 
 	void load_graphics() override;
@@ -125,11 +127,10 @@
 	std::vector<std::string> m_evade_failure_e_name;
 	std::vector<std::string> m_die_e_name;
 
-	std::vector<std::string> load_animations_from_string
-			(const std::string & directory, Profile & prof, Section & global_s,
-			 const char * anim_name);
-
 private:
+	// Reads list of animation names from the table and pushes them into result.
+	void add_battle_animation(std::unique_ptr<LuaTable> table, std::vector<std::string>* result);
+
 	DISALLOW_COPY_AND_ASSIGN(SoldierDescr);
 };
 

=== modified file 'src/logic/terrain_affinity.cc'
--- src/logic/terrain_affinity.cc	2015-08-15 09:57:27 +0000
+++ src/logic/terrain_affinity.cc	2015-10-18 20:57:50 +0000
@@ -84,7 +84,7 @@
 
 	const auto average = [&terrain_humidity, &terrain_fertility, &terrain_temperature, &terrains](
 	   const int terrain_index) {
-		const TerrainDescription& t = terrains.get_unmutable(terrain_index);
+		const TerrainDescription& t = terrains.get(terrain_index);
 		terrain_humidity += t.humidity() / 6.;
 		terrain_temperature += t.temperature() / 6.;
 		terrain_fertility += t.fertility() / 6.;

=== modified file 'src/logic/trainingsite.cc'
--- src/logic/trainingsite.cc	2015-08-31 19:56:12 +0000
+++ src/logic/trainingsite.cc	2015-10-18 20:57:50 +0000
@@ -20,6 +20,7 @@
 #include "logic/trainingsite.h"
 
 #include <cstdio>
+#include <memory>
 
 #include <boost/format.hpp>
 
@@ -32,24 +33,20 @@
 #include "logic/player.h"
 #include "logic/production_program.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/worker.h"
-#include "profile/profile.h"
-
 
 namespace Widelands {
 
 const uint32_t TrainingSite::training_state_multiplier = 12;
 
 TrainingSiteDescr::TrainingSiteDescr
-	(char const * const _name, char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 const TribeDescr & _tribe, const World& world)
+	(const std::string& init_descname, const LuaTable& table, const EditorGameBase& egbase)
 	:
 	ProductionSiteDescr
-		(MapObjectType::TRAININGSITE, _name, _descname, directory, prof, global_s, _tribe, world),
-	m_num_soldiers      (global_s.get_safe_int("soldier_capacity")),
-	m_max_stall         (global_s.get_safe_int("trainer_patience")),
+		(init_descname, "", MapObjectType::TRAININGSITE, table, egbase),
+	m_num_soldiers      (table.get_int("soldier_capacity")),
+	m_max_stall         (table.get_int("trainer_patience")),
 
 	m_train_hp          (false),
 	m_train_attack      (false),
@@ -69,25 +66,35 @@
 	//  sections starting with the name of each soldier type.
 	//  These sections also seem redundant. Eliminate them (having the
 	//  programs should be enough).
-	if (Section * const s = prof.get_section("soldier hp")) {
+	std::unique_ptr<LuaTable> items_table;
+	if (table.has_key("soldier hp")) {
+		items_table = table.get_table("soldier hp");
 		m_train_hp      = true;
-		m_min_hp        = s->get_safe_int("min_level");
-		m_max_hp        = s->get_safe_int("max_level");
-	}
-	if (Section * const s = prof.get_section("soldier attack")) {
-		m_train_attack  = true;
-		m_min_attack    = s->get_safe_int("min_level");
-		m_max_attack    = s->get_safe_int("max_level");
-	}
-	if (Section * const s = prof.get_section("soldier defense")) {
-		m_train_defense = true;
-		m_min_defense   = s->get_safe_int("min_level");
-		m_max_defense   = s->get_safe_int("max_level");
-	}
-	if (Section * const s = prof.get_section("soldier evade")) {
-		m_train_evade   = true;
-		m_min_evade     = s->get_safe_int("min_level");
-		m_max_evade     = s->get_safe_int("max_level");
+		m_min_hp = items_table->get_int("min_level");
+		m_max_hp = items_table->get_int("max_level");
+		add_training_inputs(*items_table.get(), &food_hp_, &weapons_hp_);
+	}
+
+	if (table.has_key("soldier attack")) {
+		items_table = table.get_table("soldier attack");
+		m_train_attack      = true;
+		m_min_attack = items_table->get_int("min_level");
+		m_max_attack = items_table->get_int("max_level");
+		add_training_inputs(*items_table.get(), &food_attack_, &weapons_attack_);
+	}
+	if (table.has_key("soldier defense")) {
+		items_table = table.get_table("soldier defense");
+		m_train_defense      = true;
+		m_min_defense = items_table->get_int("min_level");
+		m_max_defense = items_table->get_int("max_level");
+		add_training_inputs(*items_table.get(), &food_defense_, &weapons_defense_);
+	}
+	if (table.has_key("soldier evade")) {
+		items_table = table.get_table("soldier evade");
+		m_train_evade      = true;
+		m_min_evade = items_table->get_int("min_level");
+		m_max_evade = items_table->get_int("max_level");
+		add_training_inputs(*items_table.get(), &food_evade_, &weapons_evade_);
 	}
 }
 
@@ -146,6 +153,28 @@
 	return m_max_stall;
 }
 
+void TrainingSiteDescr::add_training_inputs(
+		const LuaTable& table,
+		std::vector<std::vector<std::string>>* food,
+		std::vector<std::string>* weapons) {
+
+	if (table.has_key("food")) {
+		std::unique_ptr<LuaTable> food_table = table.get_table("food");
+		for (const int key : food_table->keys<int>()) {
+			std::vector<std::string> food_vector;
+			for (const std::string& food_item : food_table->get_table(key)->array_entries<std::string>()) {
+				food_vector.push_back(food_item);
+			}
+			food->push_back(food_vector);
+		}
+	}
+	if (table.has_key("weapons")) {
+		for (const std::string& weapon : table.get_table("weapons")->array_entries<std::string>()) {
+			weapons->push_back(weapon);
+		}
+	}
+}
+
 /*
 =============================
 
@@ -280,7 +309,7 @@
 			m_soldier_request =
 				new Request
 					(*this,
-					 descr().tribe().safe_worker_index("soldier"),
+					 owner().tribe().soldier(),
 					 TrainingSite::request_soldier_callback,
 					 wwWORKER);
 

=== modified file 'src/logic/trainingsite.h'
--- src/logic/trainingsite.h	2015-06-29 19:22:13 +0000
+++ src/logic/trainingsite.h	2015-10-18 20:57:50 +0000
@@ -31,11 +31,9 @@
 
 class World;
 
-struct TrainingSiteDescr : public ProductionSiteDescr {
-	TrainingSiteDescr
-		(char const * name, char const * descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 const TribeDescr & tribe, const World& world);
+class TrainingSiteDescr : public ProductionSiteDescr {
+public:
+	TrainingSiteDescr(const std::string& init_descname, const LuaTable& table, const EditorGameBase& egbase);
 	~TrainingSiteDescr() override {}
 
 	Building & create_object() const override;
@@ -52,11 +50,40 @@
 	int32_t get_max_level(TrainingAttribute) const;
 	int32_t get_max_stall() const;
 
+	const std::vector<std::vector<std::string>>& get_food_hp() const {
+		return food_hp_;
+	}
+	const std::vector<std::vector<std::string>>& get_food_attack() const {
+		return food_attack_;
+	}
+	const std::vector<std::vector<std::string>>& get_food_defense() const {
+		return food_defense_;
+	}
+	const std::vector<std::vector<std::string>>& get_food_evade() const {
+		return food_evade_;
+	}
+	const std::vector<std::string>& get_weapons_hp() const {
+		return weapons_hp_;
+	}
+	const std::vector<std::string>& get_weapons_attack() const {
+		return weapons_attack_;
+	}
+	const std::vector<std::string>& get_weapons_defense() const {
+		return weapons_defense_;
+	}
+	const std::vector<std::string>& get_weapons_evade() const {
+		return weapons_evade_;
+	}
+
 private:
+	// Read the table to add needed food and weapons for training a property.
+	// Properties are hp, attack, defense, and evade.
+	void add_training_inputs(const LuaTable& table,
+			std::vector<std::vector<std::string>>* food, std::vector<std::string>* weapons);
+
 	//  TODO(unknown): These variables should be per soldier type. They should be in a
 	//  struct and there should be a vector, indexed by Soldier_Index,
 	//  with that struct structs as element type.
-
 	/** Maximum number of soldiers for a training site*/
 	uint32_t m_num_soldiers;
 	/** Number of rounds w/o successful training, after which a soldier is kicked out.**/
@@ -88,6 +115,16 @@
 	/** Maximum evasion a soldier can acquire at this site*/
 	int32_t m_max_evade;
 
+	// For building help
+	std::vector<std::vector<std::string>> food_hp_;
+	std::vector<std::vector<std::string>> food_attack_;
+	std::vector<std::vector<std::string>> food_defense_;
+	std::vector<std::vector<std::string>> food_evade_;
+	std::vector<std::string> weapons_hp_;
+	std::vector<std::string> weapons_attack_;
+	std::vector<std::string> weapons_defense_;
+	std::vector<std::string> weapons_evade_;
+
 	// Re-use of m_inputs to get the resources
 	// TrainingMap m_programs;
 	DISALLOW_COPY_AND_ASSIGN(TrainingSiteDescr);

=== added directory 'src/logic/tribes'
=== added file 'src/logic/tribes/tribe_basic_info.cc'
--- src/logic/tribes/tribe_basic_info.cc	1970-01-01 00:00:00 +0000
+++ src/logic/tribes/tribe_basic_info.cc	2015-10-18 20:57:50 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2002, 2006-2015 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.
+ *
+ */
+
+#include "logic/tribes/tribe_basic_info.h"
+
+#include <memory>
+
+#include "base/i18n.h"
+#include "logic/game_data_error.h"
+#include "scripting/lua_interface.h"
+
+TribeBasicInfo::TribeBasicInfo(std::unique_ptr<LuaTable> table) {
+	try {
+		i18n::Textdomain td("tribes");
+		name = table->get_string("name");
+		author = _(table->get_string("author"));
+		descname = _(table->get_string("descname"));
+		tooltip = _(table->get_string("tooltip"));
+		icon = table->get_string("icon");
+		std::unique_ptr<LuaTable> starting_conditions = table->get_table("starting_conditions");
+		LuaInterface lua;
+
+		for (const std::string& script_path : starting_conditions->array_entries<std::string>())
+		{
+			std::unique_ptr<LuaTable> script_table = lua.run_script(script_path);
+			script_table->do_not_warn_about_unaccessed_keys();
+			initializations.push_back(Initialization(script_path, script_table->get_string("descname")));
+		}
+	} catch (const WException & e) {
+		throw Widelands::GameDataError
+			("reading basic info for tribe \"%s\": %s",
+			 name.c_str(), e.what());
+	}
+}

=== renamed file 'src/logic/tribe_basic_info.h' => 'src/logic/tribes/tribe_basic_info.h'
--- src/logic/tribe_basic_info.h	2014-09-14 11:31:58 +0000
+++ src/logic/tribes/tribe_basic_info.h	2015-10-18 20:57:50 +0000
@@ -17,25 +17,44 @@
  *
  */
 
-#ifndef WL_LOGIC_TRIBE_BASIC_INFO_H
-#define WL_LOGIC_TRIBE_BASIC_INFO_H
+#ifndef WL_LOGIC_TRIBES_TRIBE_BASIC_INFO_H
+#define WL_LOGIC_TRIBES_TRIBE_BASIC_INFO_H
 
+#include <memory>
 #include <string>
 #include <vector>
 
 #include <stdint.h>
 
+#include "scripting/lua_table.h"
+
 /// Basic information about the tribe that is determined only from the conf
 /// file and needed before the actual game.
 struct TribeBasicInfo {
+
+	/// Script path and localized name for a starting condition
+	struct Initialization {
+		Initialization(std::string init_script, std::string init_descname) :
+			script(init_script),
+			descname(init_descname) {}
+		std::string script;
+		std::string descname;
+	};
+
+	TribeBasicInfo(std::unique_ptr<LuaTable> table);
+
+	/// Internal name to reference this tribe
 	std::string name;
-
-	/// Relative position of this tribe in a list of tribes.
-	uint8_t uiposition;
-
-	using Initialization = std::pair<std::string, std::string>;
-	using Initializations = std::vector<Initialization>;
-	Initializations initializations;
+	/// Who designed this tribe
+	std::string author;
+	/// Name to present to the user
+	std::string descname;
+	/// Basic information about this tribe
+	std::string tooltip;
+	/// Filepath of the tribe's icon
+	std::string icon;
+
+	std::vector<Initialization> initializations;
 };
 
-#endif  // end of include guard: WL_LOGIC_TRIBE_BASIC_INFO_H
+#endif  // end of include guard: WL_LOGIC_TRIBES_TRIBE_BASIC_INFO_H

=== renamed file 'src/logic/tribe.cc' => 'src/logic/tribes/tribe_descr.cc'
--- src/logic/tribe.cc	2015-02-09 05:57:08 +0000
+++ src/logic/tribes/tribe_descr.cc	2015-10-18 20:57:50 +0000
@@ -17,7 +17,7 @@
  *
  */
 
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 
 #include <algorithm>
 #include <iostream>
@@ -30,10 +30,6 @@
 #include "base/macros.h"
 #include "base/wexception.h"
 #include "graphic/graphic.h"
-#include "helper.h"
-#include "io/fileread.h"
-#include "io/filesystem/disk_filesystem.h"
-#include "io/filesystem/filesystem.h"
 #include "io/filesystem/layered_filesystem.h"
 #include "logic/carrier.h"
 #include "logic/constructionsite.h"
@@ -43,7 +39,6 @@
 #include "logic/game_data_error.h"
 #include "logic/immovable.h"
 #include "logic/militarysite.h"
-#include "logic/parse_map_object_types.h"
 #include "logic/ship.h"
 #include "logic/soldier.h"
 #include "logic/trainingsite.h"
@@ -51,404 +46,304 @@
 #include "logic/worker.h"
 #include "logic/world/resource_description.h"
 #include "logic/world/world.h"
-#include "profile/profile.h"
 #include "scripting/lua_interface.h"
 #include "scripting/lua_table.h"
 
-
-using namespace std;
-
 namespace Widelands {
 
 TribeDescr::TribeDescr
-	(const std::string & tribename, EditorGameBase & egbase)
-	: m_name(tribename)
-{
-	std::string path = "tribes/";
+	(const LuaTable& table, const TribeBasicInfo& info, const Tribes& init_tribes)
+	: name_(table.get_string("name")), descname_(info.descname), tribes_(init_tribes) {
+
 	try {
-		path            += tribename;
-
-		// Grab the localization textdomain.
-		// 'path' must be without final /
-		i18n::Textdomain textdomain(std::string("tribe_") + tribename);
-
-		path            += '/';
-		std::string::size_type base_path_size = path.size();
-
-		path += "conf";
-		Profile root_conf(path.c_str());
-		path.resize(base_path_size);
-
-		{
-			std::set<std::string> names; //  To enforce name uniqueness.
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("ship")
-				m_bobs.add
-					(new ShipDescr
-					 	(_name, _descname, path, prof, global_s, *this));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("ware")
-				m_wares.add
-					(new WareDescr
-					 	(*this, _name, _descname, path, prof, global_s));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-			const World& world = egbase.world();
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("immovable")
-				m_immovables.add
-					(new ImmovableDescr
-					 	(_name, _descname, path, prof, global_s, this));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-#define PARSE_SPECIAL_WORKER_TYPES(name, descr_type)                                               \
-	PARSE_MAP_OBJECT_TYPES_BEGIN(name)                                                              \
-	auto& worker_descr = *new descr_type(_name, _descname, path, prof, global_s, *this);      \
-	WareIndex const worker_idx = m_workers.add(&worker_descr);                                     \
-	if (worker_descr.is_buildable() && worker_descr.buildcost().empty())                            \
-		m_worker_types_without_cost.push_back(worker_idx);                                           \
-	PARSE_MAP_OBJECT_TYPES_END;
-
-			PARSE_SPECIAL_WORKER_TYPES("carrier", CarrierDescr);
-			PARSE_SPECIAL_WORKER_TYPES("soldier", SoldierDescr);
-
-#define PARSE_WORKER_TYPES(name)                                                                   \
-	PARSE_MAP_OBJECT_TYPES_BEGIN(name)                                                              \
-	auto& worker_descr =                                                                      \
-		*new WorkerDescr(MapObjectType::WORKER, _name, _descname, path, prof, global_s, *this);   \
-	WareIndex const worker_idx = m_workers.add(&worker_descr);                                     \
-	if (worker_descr.is_buildable() && worker_descr.buildcost().empty())                            \
-		m_worker_types_without_cost.push_back(worker_idx);                                           \
-	PARSE_MAP_OBJECT_TYPES_END;
-
-			PARSE_WORKER_TYPES("worker");
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("constructionsite")
-				m_buildings.add
-					(new ConstructionSiteDescr
-					 	(_name, _descname, path, prof, global_s, *this));
-			PARSE_MAP_OBJECT_TYPES_END;
-			safe_building_index("constructionsite"); // Check that it is defined.
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("dismantlesite")
-				m_buildings.add
-					(new DismantleSiteDescr
-					 	(_name, _descname, path, prof, global_s, *this));
-			PARSE_MAP_OBJECT_TYPES_END;
-			safe_building_index("dismantlesite"); // Check that it is defined.
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("warehouse")
-				m_buildings.add
-					(new WarehouseDescr
-					 	(_name, _descname, path, prof, global_s, *this));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("productionsite")
-				m_buildings.add(new ProductionSiteDescr(
-					MapObjectType::PRODUCTIONSITE, _name, _descname, path, prof, global_s, *this, world));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("militarysite")
-				m_buildings.add
-					(new MilitarySiteDescr
-					 	(_name, _descname, path, prof, global_s, *this, world));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-
-			// global militarysites are in /global not in /tribes
-			std::string temp                = path;
-			std::string::size_type sizetemp = base_path_size;
-			path           = "global/militarysites/";
-			base_path_size = path.size();
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("global militarysite")
-				m_buildings.add
-					(new MilitarySiteDescr
-					 	(_name, _descname, path, prof, global_s, *this, world));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-			// Reset path and base_path_size
-			path           = temp;
-			base_path_size = sizetemp;
-
-
-			PARSE_MAP_OBJECT_TYPES_BEGIN("trainingsite")
-				m_buildings.add
-					(new TrainingSiteDescr
-					 	(_name, _descname, path, prof, global_s, *this, world));
-			PARSE_MAP_OBJECT_TYPES_END;
-
-		}
-
+		m_initializations = info.initializations;
+
+		std::unique_ptr<LuaTable> items_table = table.get_table("animations");
+		frontier_animation_id_ = g_gr->animations().load(*items_table->get_table("frontier"));
+		flag_animation_id_ = g_gr->animations().load(*items_table->get_table("flag"));
+
+		items_table = table.get_table("roads");
+		const auto load_roads = [&items_table, this](
+			const std::string& road_type, std::vector<std::string>* images) {
+			std::vector<std::string> roads = items_table->get_table(road_type)->array_entries<std::string>();
+			for (const std::string& filename : roads) {
+				if (g_fs->file_exists(filename)) {
+					images->push_back(filename);
+				} else {
+					throw GameDataError("File '%s' for %s road texture doesn't exist",
+											  filename.c_str(),
+											  road_type.c_str());
+				}
+			}
+			if (images->empty()) {
+				throw GameDataError("Tribe has no %s roads.", road_type.c_str());
+			}
+		};
+		load_roads("normal", &normal_road_paths_);
+		load_roads("busy", &busy_road_paths_);
+
+		items_table = table.get_table("wares_order");
+		wares_order_coords_.resize(tribes_.nrwares());
+		int columnindex = 0;
+		for (const int key : items_table->keys<int>()) {
+			std::vector<WareIndex> column;
+			std::vector<std::string> warenames = items_table->get_table(key)->array_entries<std::string>();
+			for (size_t rowindex = 0; rowindex < warenames.size(); ++rowindex) {
+				try {
+					WareIndex wareindex = tribes_.safe_ware_index(warenames[rowindex]);
+					if (has_ware(wareindex)) {
+						throw GameDataError("Duplicate definition of ware '%s'", warenames[rowindex].c_str());
+					}
+					wares_.insert(wareindex);
+					column.push_back(wareindex);
+					wares_order_coords_[wareindex] = std::pair<uint32_t, uint32_t>(columnindex, rowindex);
+				} catch (const WException& e) {
+					throw GameDataError("Failed adding ware '%s: %s", warenames[rowindex].c_str(), e.what());
+				}
+			}
+			if (!column.empty()) {
+				wares_order_.push_back(column);
+				++columnindex;
+			}
+		}
+
+		items_table = table.get_table("workers_order");
+		workers_order_coords_.resize(tribes_.nrworkers());
+		columnindex = 0;
+		for (const int key : items_table->keys<int>()) {
+			std::vector<WareIndex> column;
+			std::vector<std::string> workernames = items_table->get_table(key)->array_entries<std::string>();
+			for (size_t rowindex = 0; rowindex < workernames.size(); ++rowindex) {
+				try {
+					WareIndex workerindex = tribes_.safe_worker_index(workernames[rowindex]);
+					if (has_worker(workerindex)) {
+						throw GameDataError("Duplicate definition of worker '%s'", workernames[rowindex].c_str());
+					}
+					workers_.insert(workerindex);
+					column.push_back(workerindex);
+					workers_order_coords_[workerindex] = std::pair<uint32_t, uint32_t>(columnindex, rowindex);
+
+					const WorkerDescr& worker_descr = *tribes_.get_worker_descr(workerindex);
+					if (worker_descr.is_buildable() && worker_descr.buildcost().empty()) {
+						worker_types_without_cost_.push_back(workerindex);
+					}
+				} catch (const WException& e) {
+					throw GameDataError("Failed adding worker '%s: %s", workernames[rowindex].c_str(), e.what());
+				}
+			}
+			if (!column.empty()) {
+				workers_order_.push_back(column);
+				++columnindex;
+			}
+		}
+
+		std::vector<std::string> immovables = table.get_table("immovables")->array_entries<std::string>();
+		for (const std::string& immovablename : immovables) {
+			try {
+				WareIndex index = tribes_.safe_immovable_index(immovablename);
+				if (immovables_.count(index) == 1) {
+					throw GameDataError("Duplicate definition of immovable '%s'", immovablename.c_str());
+				}
+				immovables_.insert(index);
+			} catch (const WException& e) {
+				throw GameDataError("Failed adding immovable '%s': %s", immovablename.c_str(), e.what());
+			}
+		}
+
+		for (const std::string& buildingname : table.get_table("buildings")->array_entries<std::string>()) {
+			try {
+				BuildingIndex index = tribes_.safe_building_index(buildingname);
+				if (has_building(index)) {
+					throw GameDataError("Duplicate definition of building '%s'", buildingname.c_str());
+				}
+				buildings_.push_back(index);
+
+				// Register construction materials
+				for (std::pair<WareIndex, uint8_t> build_cost : get_building_descr(index)->buildcost()) {
+					if (!is_construction_material(build_cost.first)) {
+						construction_materials_.emplace(build_cost.first);
+					}
+				}
+				for (std::pair<WareIndex, uint8_t> enhancement_cost :
+					  get_building_descr(index)->enhancement_cost()) {
+					if (!is_construction_material(enhancement_cost.first)) {
+						construction_materials_.emplace(enhancement_cost.first);
+					}
+				}
+			} catch (const WException& e) {
+				throw GameDataError("Failed adding building '%s': %s", buildingname.c_str(), e.what());
+			}
+		}
+
+		// Special types
+		builder_ = add_special_worker(table.get_string("builder"));
+		carrier_ = add_special_worker(table.get_string("carrier"));
+		carrier2_ = add_special_worker(table.get_string("carrier2"));
+		geologist_ = add_special_worker(table.get_string("geologist"));
+		soldier_ = add_special_worker(table.get_string("soldier"));
+
+		const std::string shipname = table.get_string("ship");
 		try {
-			{
-				Section & tribe_s = root_conf.get_safe_section("tribe");
-				tribe_s.get_string("author");
-				tribe_s.get_string("name"); // descriptive name
-				tribe_s.get_string("descr"); // long description
-				m_bob_vision_range = tribe_s.get_int("bob_vision_range");
-				m_carrier2         = tribe_s.get_string("carrier2");
-
-				/// Load and parse ware and worker categorization
-#define PARSE_ORDER_INFORMATION(w) /* w is ware or worker */ \
-	{ \
-		m_##w##s_order_coords.resize(m_##w##s.get_nitems()); \
-\
-		std::string categories_s \
-			(tribe_s.get_safe_string(#w "s_order")); \
-		for (boost::split_iterator<string::iterator> It1 = \
-			boost::make_split_iterator \
-				(categories_s, boost::token_finder(boost::is_any_of(";"))); \
-			It1 != boost::split_iterator<string::iterator>(); \
-			++It1) { \
-			vector<WareIndex> column; \
-			std::string column_s = boost::copy_range<std::string>(*It1); \
-			for (boost::split_iterator<string::iterator> It2 = \
-				boost::make_split_iterator \
-					(column_s, boost::token_finder(boost::is_any_of(","))); \
-				It2 != boost::split_iterator<string::iterator>(); \
-				++It2) { \
-				std::string instance_name = boost::copy_range<std::string>(*It2); \
-				boost::trim(instance_name); \
-				WareIndex id = safe_##w##_index(instance_name); \
-				column.push_back(id); \
-				/* it has been added to the column, but the column not */ \
-				/* yet to the array */ \
-				m_ ## w ## s_order_coords[id] = std::pair<uint32_t, uint32_t> \
-					(m_ ## w ## s_order.size(), column.size() - 1); \
-			} \
-			if (!column.empty()) m_##w##s_order.push_back(column); \
-		} \
-\
-		/* Check that every ##w## has been added */ \
-		for \
-			(WareIndex id = 0; \
-			 id < m_##w##s.get_nitems(); ++id) { \
-			if (id != m_ ## w ## s_order[m_ ## w ## s_order_coords[id].first] \
-					[m_##w##s_order_coords[id].second]) { \
-				log("Didn't find " #w " %s in " #w "s_order field of tribe %s!\n", \
-					  get_##w##_descr(id)->name().c_str(), name().c_str()); \
-			} \
-		} \
-	}
-
-				PARSE_ORDER_INFORMATION(ware);
-				PARSE_ORDER_INFORMATION(worker);
-			}
-
-			{
-				Section road_s = root_conf.get_safe_section("roads");
-				const auto load_roads = [&road_s, this](
-				   const std::string& prefix, std::vector<std::string>* images) {
-					for (int i = 0; i < 99; ++i) {
-						const char* img =
-						   road_s.get_string((boost::format("%s_%02i") % prefix % i).str().c_str(), nullptr);
-						if (img == nullptr) {
-							break;
-						}
-						if (!g_fs->file_exists(img)) {
-							throw new GameDataError("File %s for roadtype %s in tribe %s does not exist",
-							                        img,
-							                        prefix.c_str(),
-							                        m_name.c_str());
-						}
-						images->emplace_back(img);
-					}
-					if (images->empty()) {
-						throw new GameDataError(
-						   "No %s roads defined in tribe %s.", prefix.c_str(), m_name.c_str());
-					}
-				};
-				load_roads("normal", &m_normal_road_paths);
-				load_roads("busy", &m_busy_road_paths);
-			}
-
-			m_frontier_animation_id =
-			   g_gr->animations().load(path, root_conf.get_safe_section("frontier"));
-			m_flag_animation_id =
-			   g_gr->animations().load(path, root_conf.get_safe_section("flag"));
-
-			{
-				// Read initializations -- all scripts are initializations currently
-				for (const std::string& script :
-					  filter(g_fs->list_directory(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();
-					init.script = script;
-					init.descname = t->get_string("name");
-				}
-			}
-		} catch (const std::exception & e) {
-			throw GameDataError("root conf: %s", e.what());
+			ship_ = tribes_.safe_ship_index(shipname);
+		} catch (const WException& e) {
+			throw GameDataError("Failed adding ship '%s': %s", shipname.c_str(), e.what());
 		}
-	} catch (const WException & e) {
-		throw GameDataError("tribe %s: %s", tribename.c_str(), e.what());
+
+		headquarters_ = add_special_building(table.get_string("headquarters"));
+		port_ = add_special_building(table.get_string("port"));
+
+	} catch (const GameDataError& e) {
+		throw GameDataError("tribe %s: %s", name_.c_str(), e.what());
 	}
 }
 
 
-/*
-===============
-Load all logic data
-===============
-*/
-void TribeDescr::postload(EditorGameBase &) {
-	// TODO(unknown): move more loads to postload
-}
-
-/*
-===============
-Load tribe graphics
-===============
-*/
-void TribeDescr::load_graphics()
-{
-	for (WareIndex i = 0; i < m_workers.get_nitems(); ++i)
-		m_workers.get(i)->load_graphics();
-
-	for (WareIndex i = 0; i < m_wares.get_nitems  (); ++i)
-		m_wares.get(i)->load_graphics();
-
-	for
-		(BuildingIndex i = 0;
-		 i < m_buildings.get_nitems();
-		 ++i)
-		m_buildings.get(i)->load_graphics();
+/**
+  * Access functions
+  */
+
+const std::string& TribeDescr::name() const {return name_;}
+const std::string& TribeDescr::descname() const {return descname_;}
+
+size_t TribeDescr::get_nrbuildings() const {return buildings_.size();}
+size_t TribeDescr::get_nrwares() const {return wares_.size();}
+size_t TribeDescr::get_nrworkers() const {return workers_.size();}
+
+const std::vector<BuildingIndex> TribeDescr::buildings() const {return buildings_;}
+const std::set<WareIndex> TribeDescr::wares() const {return wares_;}
+const std::set<WareIndex> TribeDescr::workers() const {return workers_;}
+
+bool TribeDescr::has_building(const BuildingIndex& index) const {
+	return std::find(buildings_.begin(), buildings_.end(), index) != buildings_.end();
+}
+bool TribeDescr::has_ware(const WareIndex& index) const {
+	return wares_.count(index) == 1;
+}
+bool TribeDescr::has_worker(const WareIndex& index) const {
+	return workers_.count(index) == 1;
+}
+bool TribeDescr::has_immovable(int index) const {
+	return immovables_.count(index) == 1;
+}
+bool TribeDescr::is_construction_material(const WareIndex& index) const {
+	return construction_materials_.count(index) == 1;
+}
+
+BuildingIndex TribeDescr::building_index(const std::string & buildingname) const {
+	return tribes_.building_index(buildingname);
+}
+
+WareIndex TribeDescr::immovable_index(const std::string & immovablename) const {
+	return tribes_.immovable_index(immovablename);
+}
+WareIndex TribeDescr::ware_index(const std::string & warename) const {
+	return tribes_.ware_index(warename);
+}
+WareIndex TribeDescr::worker_index(const std::string & workername) const {
+	return tribes_.worker_index(workername);
+}
+
+BuildingIndex TribeDescr::safe_building_index(const std::string& buildingname) const {
+	return tribes_.safe_building_index(buildingname);
+}
+
+WareIndex TribeDescr::safe_ware_index(const std::string & warename) const {
+	return tribes_.safe_ware_index(warename);
+}
+WareIndex TribeDescr::safe_worker_index(const std::string& workername) const {
+	return tribes_.safe_worker_index(workername);
+}
+
+WareDescr const * TribeDescr::get_ware_descr(const WareIndex& index) const {
+	return tribes_.get_ware_descr(index);
+}
+WorkerDescr const* TribeDescr::get_worker_descr(const WareIndex& index) const {
+	return tribes_.get_worker_descr(index);
+}
+
+BuildingDescr const * TribeDescr::get_building_descr(const BuildingIndex& index) const {
+	return tribes_.get_building_descr(index);
+}
+ImmovableDescr const * TribeDescr::get_immovable_descr(int index) const {
+	return tribes_.get_immovable_descr(index);
+}
+
+WareIndex TribeDescr::builder() const {
+	assert(tribes_.worker_exists(builder_));
+	return builder_;
+}
+WareIndex TribeDescr::carrier() const {
+	assert(tribes_.worker_exists(carrier_));
+	return carrier_;
+}
+WareIndex TribeDescr::carrier2() const {
+	assert(tribes_.worker_exists(carrier2_));
+	return carrier2_;
+}
+WareIndex TribeDescr::geologist() const {
+	assert(tribes_.worker_exists(geologist_));
+	return geologist_;
+}
+WareIndex TribeDescr::soldier() const {
+	assert(tribes_.worker_exists(soldier_));
+	return soldier_;
+}
+WareIndex TribeDescr::ship() const {
+	assert(tribes_.ship_exists(ship_));
+	return ship_;
+}
+BuildingIndex TribeDescr::headquarters() const {
+	assert(tribes_.building_exists(headquarters_));
+	return headquarters_;
+}
+BuildingIndex TribeDescr::port() const {
+	assert(tribes_.building_exists(port_));
+	return port_;
+}
+const std::vector<WareIndex>& TribeDescr::worker_types_without_cost() const {
+	return worker_types_without_cost_;
+}
+
+uint32_t TribeDescr::frontier_animation() const {
+	return frontier_animation_id_;
+}
+
+uint32_t TribeDescr::flag_animation() const {
+	return flag_animation_id_;
 }
 
 const std::vector<std::string>& TribeDescr::normal_road_paths() const {
-	return m_normal_road_paths;
+	return normal_road_paths_;
 }
 
 const std::vector<std::string>& TribeDescr::busy_road_paths() const {
-	return m_busy_road_paths;
+	return busy_road_paths_;
 }
 
-
 void TribeDescr::add_normal_road_texture(std::unique_ptr<Texture> texture) {
-	m_road_textures.add_normal_road_texture(std::move(texture));
+	road_textures_.add_normal_road_texture(std::move(texture));
 }
 
 void TribeDescr::add_busy_road_texture(std::unique_ptr<Texture> texture) {
-	m_road_textures.add_busy_road_texture(std::move(texture));
+	road_textures_.add_busy_road_texture(std::move(texture));
 }
 
 const RoadTextures& TribeDescr::road_textures() const {
-	return m_road_textures;
-}
-
-
-/*
- * does this tribe exist?
- */
-bool TribeDescr::exists_tribe
-	(const std::string & name, TribeBasicInfo * const info)
-{
-	std::string buf = "tribes/";
-	buf            += name;
-	buf            += "/conf";
-
-	LuaInterface lua;
-	FileRead f;
-	if (f.try_open(*g_fs, buf)) {
-		if (info)
-			try {
-				Profile prof(buf.c_str());
-				info->name = name;
-				info->uiposition =
-					prof.get_safe_section("tribe").get_int("uiposition", 0);
-
-				std::string path = "tribes/" + name + "/scripting";
-				for (const std::string& script :
-					  filter(g_fs->list_directory(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")));
-				}
-			} catch (const WException & e) {
-				throw GameDataError
-					("reading basic info for tribe \"%s\": %s",
-					 name.c_str(), e.what());
-			}
-		return true;
-	}
-	return false;
-}
-
-struct TribeBasicComparator {
-	bool operator()(const TribeBasicInfo & t1, const TribeBasicInfo & t2) {
-		return t1.uiposition < t2.uiposition;
-	}
-};
-
-/**
- * Fills the given string vector with the names of all tribes that exist.
- */
-std::vector<std::string> TribeDescr::get_all_tribenames() {
-	std::vector<std::string> tribenames;
-
-	//  get all tribes
-	std::vector<TribeBasicInfo> tribes;
-	FilenameSet m_tribes = g_fs->list_directory("tribes");
-	for
-		(FilenameSet::iterator pname = m_tribes.begin();
-		 pname != m_tribes.end();
-		 ++pname)
-	{
-		TribeBasicInfo info;
-		if (TribeDescr::exists_tribe(pname->substr(7), &info))
-			tribes.push_back(info);
-	}
-
-	std::sort(tribes.begin(), tribes.end(), TribeBasicComparator());
-	for (const TribeBasicInfo& tribe : tribes) {
-		tribenames.push_back(tribe.name);
-	}
-	return tribenames;
-}
-
-
-std::vector<TribeBasicInfo> TribeDescr::get_all_tribe_infos() {
-	std::vector<TribeBasicInfo> tribes;
-
-	//  get all tribes
-	FilenameSet m_tribes = g_fs->list_directory("tribes");
-	for
-		(FilenameSet::iterator pname = m_tribes.begin();
-		 pname != m_tribes.end();
-		 ++pname)
-	{
-		TribeBasicInfo info;
-		if (TribeDescr::exists_tribe(pname->substr(7), &info))
-			tribes.push_back(info);
-	}
-
-	std::sort(tribes.begin(), tribes.end(), TribeBasicComparator());
-	return tribes;
-}
-
+	return road_textures_;
+}
 
 /*
 ==============
 Find the best matching indicator for the given amount.
 ==============
 */
-uint32_t TribeDescr::get_resource_indicator
-	(ResourceDescription const * const res, uint32_t const amount) const
-{
+WareIndex TribeDescr::get_resource_indicator
+	(ResourceDescription const * const res, uint32_t const amount) const {
 	if (!res || !amount) {
-		int32_t idx = get_immovable_index("resi_none");
-		if (idx == -1)
-			throw GameDataError
-				("tribe %s does not declare a resource indicator resi_none!",
-				 name().c_str());
+		WareIndex idx = immovable_index("resi_none");
+		if (!has_immovable(idx)) {
+			throw GameDataError("There is no resource indicator for resi_none!");
+		}
 		return idx;
 	}
 
@@ -456,107 +351,95 @@
 	int32_t num_indicators = 0;
 	for (;;) {
 		const std::string resi_filename = (boost::format("resi_%s%i") % res->name().c_str() % i).str();
-		if (get_immovable_index(resi_filename) == -1)
+		if (!has_immovable(immovable_index(resi_filename))) {
 			break;
+		}
 		++i;
 		++num_indicators;
 	}
 
-	if (!num_indicators)
-		throw GameDataError
-			("tribe %s does not declare a resource indicator for resource %s",
-			 name().c_str(),
-			 res->name().c_str());
+	if (!num_indicators) {
+		throw GameDataError("There is no resource indicator for resource %s", res->name().c_str());
+	}
 
 	int32_t bestmatch =
 		static_cast<int32_t>
 			((static_cast<float>(amount) / res->max_amount())
 			 *
 			 num_indicators);
-	if (bestmatch > num_indicators)
+	if (bestmatch > num_indicators) {
 		throw GameDataError
 			("Amount of %s is %i but max amount is %i",
 			 res->name().c_str(),
 			 amount,
 			 res->max_amount());
-	if (static_cast<int32_t>(amount) < res->max_amount())
+	}
+	if (static_cast<int32_t>(amount) < res->max_amount()) {
 		bestmatch += 1; // Resi start with 1, not 0
+	}
 
-	return get_immovable_index((boost::format("resi_%s%i")
+	return immovable_index((boost::format("resi_%s%i")
 										 % res->name().c_str()
 										 % bestmatch).str());
 }
 
-/*
- * Return the given ware or die trying
- */
-WareIndex TribeDescr::safe_ware_index(const std::string & warename) const {
-	const WareIndex result = ware_index(warename);
-	if (result == INVALID_INDEX) {
-		throw GameDataError("tribe %s does not define ware type \"%s\"", name().c_str(), warename.c_str());
-	}
-	return result;
-}
-
-WareIndex TribeDescr::ware_index(const std::string & warename) const {
-	WareIndex const wi = m_wares.get_index(warename);
-	return wi;
-}
-
-/*
- * Return the given worker or die trying
- */
-WareIndex TribeDescr::safe_worker_index(const std::string& workername) const {
-const WareIndex result = worker_index(workername);
-	if (result == INVALID_INDEX) {
-		throw GameDataError(
-		   "tribe %s does not define worker type \"%s\"", name().c_str(), workername.c_str());
-	}
-	return result;
-}
-
-/*
- * Return the given building or die trying
- */
-BuildingIndex TribeDescr::safe_building_index(char const* const buildingname) const {
-	const BuildingIndex result = building_index(buildingname);
-	if (result == INVALID_INDEX) {
-		throw GameDataError(
-		   "tribe %s does not define building type \"%s\"", name().c_str(), buildingname);
-	}
-	return result;
-}
 
 void TribeDescr::resize_ware_orders(size_t maxLength) {
 	bool need_resize = false;
 
-	//check if we actually need to resize
-	for (WaresOrder::iterator it = m_wares_order.begin(); it != m_wares_order.end(); ++it) {
+	// Check if we actually need to resize.
+	for (WaresOrder::iterator it = wares_order_.begin(); it != wares_order_.end(); ++it) {
 		if (it->size() > maxLength) {
 			need_resize = true;
 		  }
 	 }
 
-	//resize
+	// Build new smaller wares_order.
 	if (need_resize) {
-
-		//build new smaller wares_order
 		WaresOrder new_wares_order;
-		for (WaresOrder::iterator it = m_wares_order.begin(); it != m_wares_order.end(); ++it) {
+		for (WaresOrder::iterator it = wares_order_.begin(); it != wares_order_.end(); ++it) {
 			new_wares_order.push_back(std::vector<Widelands::WareIndex>());
 			for (std::vector<Widelands::WareIndex>::iterator it2 = it->begin(); it2 != it->end(); ++it2) {
 				if (new_wares_order.rbegin()->size() >= maxLength) {
 					new_wares_order.push_back(std::vector<Widelands::WareIndex>());
 				}
 				new_wares_order.rbegin()->push_back(*it2);
-				m_wares_order_coords[*it2].first = new_wares_order.size() - 1;
-				m_wares_order_coords[*it2].second = new_wares_order.rbegin()->size() - 1;
+				wares_order_coords_[*it2].first = new_wares_order.size() - 1;
+				wares_order_coords_[*it2].second = new_wares_order.rbegin()->size() - 1;
 			}
 		}
 
-		//remove old array
-		m_wares_order.clear();
-		m_wares_order = new_wares_order;
+		// Remove old array.
+		wares_order_.clear();
+		wares_order_ = new_wares_order;
+	}
+}
+
+/**
+  * Helper functions
+  */
+
+WareIndex TribeDescr::add_special_worker(const std::string& workername) {
+	try {
+		WareIndex worker = tribes_.safe_worker_index(workername);
+		if (!has_worker(worker)) {
+			throw GameDataError("This tribe doesn't have the worker '%s'", workername.c_str());
+		}
+		return worker;
+	} catch (const WException& e) {
+		throw GameDataError("Failed adding special worker '%s': %s", workername.c_str(), e.what());
+	}
+}
+
+BuildingIndex TribeDescr::add_special_building(const std::string& buildingname) {
+	try {
+		BuildingIndex building = tribes_.safe_building_index(buildingname);
+		if (!has_building(building)) {
+			throw GameDataError("This tribe doesn't have the building '%s'", buildingname.c_str());
+		}
+		return building;
+	} catch (const WException& e) {
+		throw GameDataError("Failed adding special building '%s': %s", buildingname.c_str(), e.what());
 	}
 }
 

=== renamed file 'src/logic/tribe.h' => 'src/logic/tribes/tribe_descr.h'
--- src/logic/tribe.h	2015-02-08 18:16:41 +0000
+++ src/logic/tribes/tribe_descr.h	2015-10-18 20:57:50 +0000
@@ -17,8 +17,8 @@
  *
  */
 
-#ifndef WL_LOGIC_TRIBE_H
-#define WL_LOGIC_TRIBE_H
+#ifndef WL_LOGIC_TRIBES_TRIBE_DESCR_H
+#define WL_LOGIC_TRIBES_TRIBE_DESCR_H
 
 #include <map>
 #include <memory>
@@ -26,14 +26,14 @@
 
 #include "base/macros.h"
 #include "graphic/animation.h"
-#include "graphic/texture.h"
-#include "logic/bob.h"
 #include "logic/building.h"
 #include "logic/description_maintainer.h"
+#include "logic/editor_game_base.h"
 #include "logic/immovable.h"
 #include "logic/road_textures.h"
-#include "logic/roadtype.h"
-#include "logic/tribe_basic_info.h"
+#include "logic/ship.h"
+#include "logic/tribes/tribe_basic_info.h"
+#include "logic/tribes/tribes.h"
 #include "logic/ware_descr.h"
 #include "logic/worker.h"
 
@@ -41,12 +41,12 @@
 
 class EditorGameBase;
 class ResourceDescription;
+class WareDescr;
 class Warehouse;
 class WorkerDescr;
 class World;
-struct BuildingDescr;
+class BuildingDescr;
 struct Event;
-struct WareDescr;
 
 /*
 Tribes
@@ -58,16 +58,54 @@
 */
 class TribeDescr {
 public:
-	TribeDescr(const std::string & name, EditorGameBase &);
-
-	//  Static function to check for tribes.
-	static bool exists_tribe
-		(const std::string & name, TribeBasicInfo * info = nullptr);
-	static std::vector<std::string> get_all_tribenames();
-	static std::vector<TribeBasicInfo> get_all_tribe_infos();
-
-
-	const std::string& name() const {return m_name;}
+	TribeDescr(const LuaTable& table, const TribeBasicInfo& info, const Tribes& init_tribes);
+
+	const std::string& name() const;
+	const std::string& descname() const;
+
+	size_t get_nrbuildings() const;
+	size_t get_nrwares() const;
+	size_t get_nrworkers() const;
+
+	const std::vector<BuildingIndex> buildings() const;
+	const std::set<WareIndex> wares() const;
+	const std::set<WareIndex> workers() const;
+
+	bool has_building(const BuildingIndex& index) const;
+	bool has_ware(const WareIndex& index) const;
+	bool has_worker(const WareIndex& index) const;
+	bool has_immovable(int index) const;
+	bool is_construction_material(const WareIndex& ware_index) const;
+
+	BuildingIndex building_index(const std::string & buildingname) const;
+	WareIndex immovable_index(const std::string & immovablename) const;
+	WareIndex ware_index(const std::string & warename) const;
+	WareIndex worker_index(const std::string & workername) const;
+
+	/// Return the given building or die trying
+	BuildingIndex safe_building_index(const std::string& buildingname) const;
+	/// Return the given ware or die trying
+	WareIndex safe_ware_index(const std::string & warename) const;
+	/// Return the given worker or die trying
+	WareIndex safe_worker_index(const std::string & workername) const;
+
+	BuildingDescr const * get_building_descr(const BuildingIndex& index) const;
+	ImmovableDescr const * get_immovable_descr(int index) const;
+	WareDescr const * get_ware_descr(const WareIndex& index) const;
+	WorkerDescr const * get_worker_descr(const WareIndex& index) const;
+
+	WareIndex builder() const;
+	WareIndex carrier() const;
+	WareIndex carrier2() const;
+	WareIndex geologist() const;
+	WareIndex soldier() const;
+	WareIndex ship() const;
+	BuildingIndex headquarters() const;
+	BuildingIndex port() const;
+	const std::vector<WareIndex>& worker_types_without_cost() const;
+
+	uint32_t frontier_animation() const;
+	uint32_t flag_animation() const;
 
 	// A vector of all texture images that can be used for drawing a
 	// (normal|busy) road. The images are guaranteed to exist.
@@ -82,144 +120,70 @@
 	// The road textures used for drawing roads.
 	const RoadTextures& road_textures() const;
 
-	WareIndex get_nrworkers() const {return m_workers.get_nitems();}
-	WorkerDescr const * get_worker_descr(const WareIndex& index) const {
-		return m_workers.get(index);
-	}
-	WareIndex worker_index(const std::string & workername) const {
-		return m_workers.get_index(workername);
-	}
-	WareIndex worker_index(char const * const workername) const {
-		return m_workers.get_index(workername);
-	}
-	WareIndex carrier2() const {
-		if (m_carrier2.size())
-			return worker_index(m_carrier2);
-		return worker_index("carrier");
-	}
-	WareIndex get_nrwares() const {return m_wares.get_nitems();}
-	WareIndex safe_ware_index(const std::string & warename) const;
-	WareIndex ware_index(const std::string & warename) const;
-	WareDescr const * get_ware_descr(const WareIndex& index) const {
-		return m_wares.get(index);
-	}
-	void set_ware_type_has_demand_check(const WareIndex& index) const {
-		m_wares.get(index)->set_has_demand_check();
-	}
-	void set_worker_type_has_demand_check(const WareIndex& index) const {
-		m_workers.get(index)->set_has_demand_check();
-	}
-	WareIndex safe_worker_index(const std::string & workername) const;
-	BuildingIndex get_nrbuildings() const {
-		return m_buildings.get_nitems();
-	}
-	BuildingIndex safe_building_index(char const * name) const;
-	BuildingDescr const * get_building_descr(const BuildingIndex& index) const
-	{
-		return m_buildings.get(index);
-	}
-	BuildingIndex building_index(const std::string & buildingname) const {
-		return m_buildings.get_index(buildingname);
-	}
-	BuildingIndex building_index(char const * const buildingname) const {
-		return m_buildings.get_index(buildingname);
-	}
-	int32_t get_immovable_index(char const * const l) const {
-		return m_immovables.get_index(l);
-	}
-	int32_t get_immovable_index(const std::string & l) const {
-		return m_immovables.get_index(l);
-	}
-	int32_t get_nr_immovables() {return m_immovables.get_nitems();}
-	ImmovableDescr const * get_immovable_descr(int32_t const index) const {
-		return m_immovables.get(index);
-	}
-	ImmovableDescr const * get_immovable_descr(const std::string & imm_name) const {
-		return m_immovables.get(get_immovable_index(imm_name.c_str()));
-	}
-	int32_t get_bob(char const * const l) const {return m_bobs.get_index(l);}
-	BobDescr const * get_bob_descr(uint16_t const index) const {
-		return m_bobs.get(index);
-	}
-	BobDescr const * get_bob_descr(const std::string & bob_name) const {
-		return m_bobs.exists(bob_name.c_str());
-	}
-	int32_t get_nr_bobs() {return m_bobs.get_nitems();}
-
-	const std::vector<WareIndex> & worker_types_without_cost() const {
-		return m_worker_types_without_cost;
-	}
-
-	uint32_t frontier_animation() const {
-		return m_frontier_animation_id;
-	}
-
-	uint32_t flag_animation() const {
-		return m_flag_animation_id;
-	}
-
-	uint32_t get_bob_vision_range() const {return m_bob_vision_range;}
-
-	uint32_t get_resource_indicator
+	WareIndex get_resource_indicator
 		(const ResourceDescription * const res, const uint32_t amount) const;
 
-	void postload(EditorGameBase &);
-	void load_graphics();
-
-	struct Initialization {
-		std::string script;
-		std::string descname;
-	};
-
 	// Returns the initalization at 'index' (which must not be out of bounds).
-	const Initialization & initialization(const uint8_t index) const {
+	const TribeBasicInfo::Initialization& initialization(const uint8_t index) const {
 		return m_initializations.at(index);
 	}
 
 	using WaresOrder = std::vector<std::vector<Widelands::WareIndex>>;
 	using WaresOrderCoords = std::vector<std::pair<uint32_t, uint32_t>>;
-	const WaresOrder & wares_order() const {return m_wares_order;}
+	const WaresOrder & wares_order() const {return wares_order_;}
 	const WaresOrderCoords & wares_order_coords() const {
-		return m_wares_order_coords;
+		return wares_order_coords_;
 	}
 
-	const WaresOrder & workers_order() const {return m_workers_order;}
+	const WaresOrder & workers_order() const {return workers_order_;}
 	const WaresOrderCoords & workers_order_coords() const {
-		return m_workers_order_coords;
+		return workers_order_coords_;
 	}
 
 	void resize_ware_orders(size_t maxLength);
 
 private:
-	const std::string m_name;
-
-	std::vector<std::string> m_normal_road_paths;
-	std::vector<std::string> m_busy_road_paths;
-	RoadTextures m_road_textures;
-
-	uint32_t m_frontier_animation_id;
-	uint32_t m_flag_animation_id;
-	uint32_t m_bob_vision_range;
-
-	DescriptionMaintainer<WorkerDescr> m_workers;
-	DescriptionMaintainer<BuildingDescr> m_buildings;
-	DescriptionMaintainer<WareDescr> m_wares;
-	DescriptionMaintainer<ImmovableDescr> m_immovables;  // The player immovables
-	DescriptionMaintainer<BobDescr> m_bobs;
-	std::string                       m_carrier2;
+	// Helper function for adding a special worker type (carriers etc.)
+	WareIndex add_special_worker(const std::string& workername);
+	// Helper function for adding a special building type (port etc.)
+	BuildingIndex add_special_building(const std::string& buildingname);
+
+	const std::string name_;
+	const std::string descname_;
+	const Tribes& tribes_;
+
+	uint32_t frontier_animation_id_;
+	uint32_t flag_animation_id_;
+	std::vector<std::string> normal_road_paths_;
+	std::vector<std::string> busy_road_paths_;
+	RoadTextures road_textures_;
+
+	std::vector<BuildingIndex>  buildings_;
+	std::set<WareIndex>         immovables_;  // The player immovables
+	std::set<WareIndex>         workers_;
+	std::set<WareIndex>         wares_;
+	std::set<WareIndex>         construction_materials_; // The wares that are used by construction sites
+	// Special units
+	WareIndex                   builder_;  // The builder for this tribe
+	WareIndex                   carrier_;  // The basic carrier for this tribe
+	WareIndex                   carrier2_; // Additional carrier for busy roads
+	WareIndex                   geologist_; // This tribe's geologist worker
+	WareIndex                   soldier_;  // The soldier that this tribe uses
+	WareIndex                   ship_;     // The ship that this tribe uses
+	BuildingIndex               headquarters_; // The tribe's default headquarters, needed by the editor
+	BuildingIndex               port_;     // The port that this tribe uses
+	std::vector<WareIndex>      worker_types_without_cost_;
 	// Order and positioning of wares in the warehouse display
-	WaresOrder                        m_wares_order;
-	WaresOrderCoords                  m_wares_order_coords;
-	WaresOrder                        m_workers_order;
-	WaresOrderCoords                  m_workers_order_coords;
-
-	std::vector<WareIndex> m_worker_types_without_cost;
-
-	std::vector<Initialization> m_initializations;
+	WaresOrder                  wares_order_;
+	WaresOrderCoords            wares_order_coords_;
+	WaresOrder                  workers_order_;
+	WaresOrderCoords            workers_order_coords_;
+
+	std::vector<TribeBasicInfo::Initialization> m_initializations;
 
 	DISALLOW_COPY_AND_ASSIGN(TribeDescr);
 };
 
 }
 
-#endif  // end of include guard: WL_LOGIC_TRIBE_H
+#endif  // end of include guard: WL_LOGIC_TRIBES_TRIBE_DESCR_H

=== added file 'src/logic/tribes/tribes.cc'
--- src/logic/tribes/tribes.cc	1970-01-01 00:00:00 +0000
+++ src/logic/tribes/tribes.cc	2015-10-18 20:57:50 +0000
@@ -0,0 +1,419 @@
+/*
+ * 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/tribes/tribes.h"
+
+#include <memory>
+
+#include "graphic/graphic.h"
+#include "graphic/image_io.h"
+#include "graphic/texture_atlas.h"
+#include "io/filesystem/layered_filesystem.h"
+#include "logic/game_data_error.h"
+
+namespace Widelands {
+
+Tribes::Tribes(EditorGameBase& egbase) :
+	egbase_(egbase),
+	buildings_(new DescriptionMaintainer<BuildingDescr>()),
+	immovables_(new DescriptionMaintainer<ImmovableDescr>()),
+	ships_(new DescriptionMaintainer<ShipDescr>()),
+	wares_(new DescriptionMaintainer<WareDescr>()),
+	workers_(new DescriptionMaintainer<WorkerDescr>()),
+	tribes_(new DescriptionMaintainer<TribeDescr>()) {
+}
+
+
+std::vector<std::string> Tribes::get_all_tribenames() {
+	std::vector<std::string> tribenames;
+	LuaInterface lua;
+	std::unique_ptr<LuaTable> table(lua.run_script("tribes/preload.lua"));
+	for (const int key : table->keys<int>()) {
+		std::unique_ptr<LuaTable> info = table->get_table(key);
+		info->do_not_warn_about_unaccessed_keys();
+		tribenames.push_back(info->get_string("name"));
+	}
+	return tribenames;
+}
+
+std::vector<TribeBasicInfo> Tribes::get_all_tribeinfos() {
+	std::vector<TribeBasicInfo> tribeinfos;
+	LuaInterface lua;
+	std::unique_ptr<LuaTable> table(lua.run_script("tribes/preload.lua"));
+	for (const int key : table->keys<int>()) {
+		tribeinfos.push_back(TribeBasicInfo(table->get_table(key)));
+	}
+	return tribeinfos;
+}
+
+TribeBasicInfo Tribes::tribeinfo(const std::string& tribename) {
+	if (tribe_exists(tribename)) {
+		for (const TribeBasicInfo& info : get_all_tribeinfos()) {
+			if (info.name == tribename) {
+				return info;
+			}
+		}
+	} else {
+		throw GameDataError("The tribe '%s'' does not exist.", tribename.c_str());
+	}
+	assert(false); // A TribeBasicInfo should have been found
+}
+
+bool Tribes::tribe_exists(const std::string& tribename) {
+	for (const std::string& name : get_all_tribenames()) {
+		if (name == tribename) {
+			return true;
+		}
+	}
+	return false;
+}
+
+void Tribes::add_constructionsite_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	buildings_->add(
+				new ConstructionSiteDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					egbase_));
+}
+
+void Tribes::add_dismantlesite_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	buildings_->add(
+				new DismantleSiteDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					egbase_));
+}
+
+void Tribes::add_militarysite_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	buildings_->add(
+				new MilitarySiteDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					egbase_));
+}
+
+void Tribes::add_productionsite_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	const char* msgctxt = table.get_string("msgctxt").c_str();
+	buildings_->add(
+				new ProductionSiteDescr(
+					pgettext_expr(msgctxt, table.get_string("descname").c_str()),
+					msgctxt,
+					table,
+					egbase_));
+}
+
+void Tribes::add_trainingsite_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	buildings_->add(
+				new TrainingSiteDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					egbase_));
+}
+
+void Tribes::add_warehouse_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	buildings_->add(
+				new WarehouseDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					egbase_));
+}
+
+void Tribes::add_immovable_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	immovables_->add(
+				new ImmovableDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					*this));
+}
+
+void Tribes::add_ship_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	ships_->add(new ShipDescr(_(table.get_string("descname")), table));
+}
+
+void Tribes::add_ware_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	wares_->add(new WareDescr(
+						pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+						table));
+}
+
+void Tribes::add_carrier_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	workers_->add(new CarrierDescr(
+						  pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+						  table,
+						  egbase_));
+}
+
+void Tribes::add_soldier_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	workers_->add(
+				new SoldierDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					egbase_));
+}
+
+void Tribes::add_worker_type(const LuaTable& table) {
+	i18n::Textdomain td("tribes");
+	workers_->add(
+				new WorkerDescr(
+					pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
+					table,
+					egbase_));
+}
+
+void Tribes::add_tribe(const LuaTable& table) {
+	const std::string name = table.get_string("name");
+	if (tribe_exists(name)) {
+		tribes_->add(new TribeDescr(table, Tribes::tribeinfo(name), egbase_.tribes()));
+	} else {
+		throw GameDataError("The tribe '%s'' has no preload file.", name.c_str());
+	}
+}
+
+size_t Tribes::nrbuildings() const {
+	return buildings_->size();
+}
+
+size_t Tribes::nrtribes() const {
+	return tribes_->size();
+}
+
+size_t Tribes::nrwares() const {
+	return wares_->size();
+}
+
+size_t Tribes::nrworkers() const {
+	return workers_->size();
+}
+
+bool Tribes::ware_exists(const WareIndex& index) const {
+	return wares_->get_mutable(index) != nullptr;
+}
+bool Tribes::worker_exists(const WareIndex& index) const {
+	return workers_->get_mutable(index) != nullptr;
+}
+bool Tribes::building_exists(const std::string& buildingname) const {
+	return buildings_->exists(buildingname) != nullptr;
+}
+bool Tribes::building_exists(const BuildingIndex& index) const {
+	return buildings_->get_mutable(index) != nullptr;
+}
+bool Tribes::immovable_exists(WareIndex index) const {
+	return immovables_->get_mutable(index) != nullptr;
+}
+bool Tribes::ship_exists(int index) const {
+	return ships_->get_mutable(index) != nullptr;
+}
+bool Tribes::tribe_exists(int index) const {
+	return tribes_->get_mutable(index) != nullptr;
+}
+
+BuildingIndex Tribes::safe_building_index(const std::string& buildingname) const {
+	const BuildingIndex result = building_index(buildingname);
+	if (!building_exists(result)) {
+		throw GameDataError("Unknown building type \"%s\"", buildingname.c_str());
+	}
+	return result;
+}
+
+WareIndex Tribes::safe_immovable_index(const std::string& immovablename) const {
+	const WareIndex result = immovable_index(immovablename);
+	if (!immovable_exists(result)) {
+		throw GameDataError("Unknown immovable type \"%s\"", immovablename.c_str());
+	}
+	return result;
+}
+
+WareIndex Tribes::safe_ship_index(const std::string& shipname) const {
+	const int result = ship_index(shipname);
+	if (!ship_exists(result)) {
+		throw GameDataError("Unknown ship type \"%s\"", shipname.c_str());
+	}
+	return result;
+}
+
+WareIndex Tribes::safe_tribe_index(const std::string& tribename) const {
+	const int result = tribe_index(tribename);
+	if (!tribe_exists(result)) {
+		throw GameDataError("Unknown tribe \"%s\"", tribename.c_str());
+	}
+	return result;
+}
+
+WareIndex Tribes::safe_ware_index(const std::string& warename) const {
+	const WareIndex result = ware_index(warename);
+	if (!ware_exists(result)) {
+		throw GameDataError("Unknown ware type \"%s\"", warename.c_str());
+	}
+	return result;
+}
+
+WareIndex Tribes::safe_worker_index(const std::string& workername) const {
+	const WareIndex result = worker_index(workername);
+	if (!worker_exists(result)) {
+		throw GameDataError("Unknown worker type \"%s\"", workername.c_str());
+	}
+	return result;
+}
+
+
+BuildingIndex Tribes::building_index(const std::string& buildingname) const {
+	return buildings_->get_index(buildingname);
+}
+
+WareIndex Tribes::immovable_index(const std::string& immovablename) const {
+	return immovables_->get_index(immovablename);
+}
+
+WareIndex Tribes::ship_index(const std::string& shipname) const {
+	return ships_->get_index(shipname);
+}
+
+WareIndex Tribes::tribe_index(const std::string& tribename) const {
+	return tribes_->get_index(tribename);
+}
+
+
+WareIndex Tribes::ware_index(const std::string& warename) const {
+	return wares_->get_index(warename);
+}
+
+WareIndex Tribes::worker_index(const std::string& workername) const {
+	return workers_->get_index(workername);
+}
+
+
+const BuildingDescr* Tribes::get_building_descr(BuildingIndex buildingindex) const {
+	return buildings_->get_mutable(buildingindex);
+}
+
+const ImmovableDescr* Tribes::get_immovable_descr(WareIndex immovableindex) const {
+	return immovables_->get_mutable(immovableindex);
+}
+
+const ShipDescr* Tribes::get_ship_descr(WareIndex shipindex) const {
+	return ships_->get_mutable(shipindex);
+}
+
+
+const WareDescr* Tribes::get_ware_descr(WareIndex wareindex) const {
+	return wares_->get_mutable(wareindex);
+}
+
+const WorkerDescr* Tribes::get_worker_descr(WareIndex workerindex) const {
+	return workers_->get_mutable(workerindex);
+}
+
+const TribeDescr* Tribes::get_tribe_descr(WareIndex tribeindex) const {
+	return tribes_->get_mutable(tribeindex);
+}
+
+void Tribes::set_ware_type_has_demand_check(const WareIndex& wareindex, const std::string& tribename) const {
+	wares_->get_mutable(wareindex)->set_has_demand_check(tribename);
+}
+
+void Tribes::set_worker_type_has_demand_check(const WareIndex& workerindex) const {
+	workers_->get_mutable(workerindex)->set_has_demand_check();
+}
+
+
+void Tribes::load_graphics()
+{
+	for (WareIndex i = 0; i < static_cast<WareIndex>(workers_->size()); ++i) {
+		workers_->get_mutable(i)->load_graphics();
+	}
+
+	for (WareIndex i = 0; i < static_cast<WareIndex>(wares_->size()); ++i) {
+		wares_->get_mutable(i)->load_graphics();
+	}
+
+	for (BuildingIndex i = 0; i < buildings_->size(); ++i) {
+		buildings_->get_mutable(i)->load_graphics();
+	}
+
+	// Construct and hold on to the texture atlas that contains all road images.
+	TextureAtlas ta;
+
+	// These will be deleted at the end of the method.
+	std::vector<std::unique_ptr<Texture>> individual_textures_;
+	for (size_t tribeindex = 0; tribeindex < nrtribes(); ++tribeindex) {
+		TribeDescr* tribe = tribes_->get_mutable(tribeindex);
+		for (const std::string& texture_path : tribe->normal_road_paths()) {
+			individual_textures_.emplace_back(load_image(texture_path, g_fs));
+			ta.add(*individual_textures_.back());
+		}
+		for (const std::string& texture_path : tribe->busy_road_paths()) {
+			individual_textures_.emplace_back(load_image(texture_path, g_fs));
+			ta.add(*individual_textures_.back());
+		}
+	}
+
+	std::vector<std::unique_ptr<Texture>> textures;
+	road_texture_ = ta.pack(&textures);
+
+	size_t next_texture_to_move = 0;
+	for (size_t tribeindex = 0; tribeindex < nrtribes(); ++tribeindex) {
+		TribeDescr* tribe = tribes_->get_mutable(tribeindex);
+		for (size_t i = 0; i < tribe->normal_road_paths().size(); ++i) {
+			tribe->add_normal_road_texture(std::move(textures.at(next_texture_to_move++)));
+		}
+		for (size_t i = 0; i < tribe->busy_road_paths().size(); ++i) {
+			tribe->add_busy_road_texture(std::move(textures.at(next_texture_to_move++)));
+		}
+	}
+}
+
+void Tribes::postload() {
+	for (BuildingIndex i = 0; i < buildings_->size(); ++i) {
+		BuildingDescr& building_descr = *buildings_->get_mutable(i);
+
+		// Add consumers and producers to wares.
+		if (upcast(ProductionSiteDescr, de, &building_descr)) {
+			for (const WareAmount& ware_amount : de->inputs()) {
+				wares_->get_mutable(ware_amount.first)->add_consumer(i);
+			}
+			for (const WareIndex& wareindex : de->output_ware_types()) {
+				wares_->get_mutable(wareindex)->add_producer(i);
+			}
+		}
+
+		// Register which buildings buildings can have been enhanced from
+		const BuildingIndex& enhancement = building_descr.enhancement();
+		if (building_exists(enhancement)) {
+			buildings_->get_mutable(enhancement)->set_enhanced_from(i);
+		}
+	}
+	// 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() - 290) / (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + 12);
+	for (WareIndex i = 0; i < tribes_->size(); ++i) {
+		tribes_->get_mutable(i)->resize_ware_orders(number);
+	}
+}
+
+} // namespace Widelands

=== added file 'src/logic/tribes/tribes.h'
--- src/logic/tribes/tribes.h	1970-01-01 00:00:00 +0000
+++ src/logic/tribes/tribes.h	2015-10-18 20:57:50 +0000
@@ -0,0 +1,164 @@
+/*
+ * 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 WL_LOGIC_TRIBES_TRIBES_H
+#define WL_LOGIC_TRIBES_TRIBES_H
+
+#include <memory>
+
+#include "base/macros.h"
+#include "graphic/texture.h"
+#include "logic/carrier.h"
+#include "logic/constructionsite.h"
+#include "logic/description_maintainer.h"
+#include "logic/dismantlesite.h"
+#include "logic/immovable.h"
+#include "logic/militarysite.h"
+#include "logic/productionsite.h"
+#include "logic/ship.h"
+#include "logic/soldier.h"
+#include "logic/trainingsite.h"
+#include "logic/tribes/tribe_descr.h"
+#include "logic/tribes/tribe_basic_info.h"
+#include "logic/warehouse.h"
+#include "logic/ware_descr.h"
+#include "logic/worker_descr.h"
+#include "scripting/lua_table.h"
+
+namespace Widelands {
+
+class WareDescr;
+class WorkerDescr;
+
+class Tribes {
+public:
+	Tribes(EditorGameBase&);
+	~Tribes() {}
+
+	/// Returns a string vector with the names of all tribes.
+	static std::vector<std::string> get_all_tribenames();
+
+	/// Returns a vector with the basic info for all tribes.
+	static std::vector<TribeBasicInfo> get_all_tribeinfos();
+
+	/// Returns the basic preload info for a tribe.
+	static TribeBasicInfo tribeinfo(const std::string& tribename);
+
+	/// Returns whether this tribe is listed in tribes/preload.lua.
+	static bool tribe_exists(const std::string & tribename);
+
+	/// Adds this building type to the tribe description.
+	void add_constructionsite_type(const LuaTable& table);
+
+	/// Adds this building type to the tribe description.
+	void add_dismantlesite_type(const LuaTable& table);
+
+	/// Adds this building type to the tribe description.
+	void add_militarysite_type(const LuaTable& table);
+
+	/// Adds this building type to the tribe description.
+	void add_productionsite_type(const LuaTable& table);
+
+	/// Adds this building type to the tribe description.
+	void add_trainingsite_type(const LuaTable& table);
+
+	/// Adds this building type to the tribe description.
+	void add_warehouse_type(const LuaTable& table);
+
+	/// Adds this immovable type to the tribe description.
+	void add_immovable_type(const LuaTable& table);
+
+	/// Adds this ship type to the tribe description.
+	void add_ship_type(const LuaTable& table);
+
+	/// Adds this ware type to the tribe description.
+	void add_ware_type(const LuaTable& table);
+
+	/// Adds this worker type to the tribe description.
+	void add_carrier_type(const LuaTable& table);
+
+	/// Adds this worker type to the tribe description.
+	void add_soldier_type(const LuaTable& table);
+
+	/// Adds this worker type to the tribe description.
+	void add_worker_type(const LuaTable& table);
+
+	/// Adds a specific tribe's configuration.
+	void add_tribe(const LuaTable& table);
+
+	size_t nrbuildings() const;
+	size_t nrtribes() const;
+	size_t nrwares() const;
+	size_t nrworkers() const;
+
+	bool ware_exists(const WareIndex& index) const;
+	bool worker_exists(const WareIndex& index) const;
+	bool building_exists(const std::string& buildingname) const;
+	bool building_exists(const BuildingIndex& index) const;
+	bool immovable_exists(WareIndex index) const;
+	bool ship_exists(int index) const;
+	bool tribe_exists(int index) const;
+
+	BuildingIndex safe_building_index(const std::string& buildingname) const;
+	WareIndex safe_immovable_index(const std::string& immovablename) const;
+	WareIndex safe_ship_index(const std::string& shipname) const;
+	WareIndex safe_tribe_index(const std::string& tribename) const;
+	WareIndex safe_ware_index(const std::string& warename) const;
+	WareIndex safe_worker_index(const std::string& workername) const;
+
+	BuildingIndex building_index(const std::string& buildingname) const;
+	WareIndex immovable_index(const std::string& immovablename) const;
+	WareIndex ship_index(const std::string& shipname) const;
+	WareIndex tribe_index(const std::string& tribename) const;
+	WareIndex ware_index(const std::string& warename) const;
+	WareIndex worker_index(const std::string& workername) const;
+
+	const BuildingDescr* get_building_descr(BuildingIndex building_index) const;
+	const ImmovableDescr* get_immovable_descr(WareIndex immovable_index) const;
+	const ShipDescr* get_ship_descr(WareIndex ship_index) const;
+	const WareDescr* get_ware_descr(WareIndex ware_index) const;
+	const WorkerDescr* get_worker_descr(WareIndex worker_index) const;
+	const TribeDescr* get_tribe_descr(WareIndex tribe_index) const;
+
+	void set_ware_type_has_demand_check(const WareIndex& ware_index, const std::string& tribename) const;
+	void set_worker_type_has_demand_check(const WareIndex& worker_index) const;
+
+	/// Load tribes' graphics
+	void load_graphics();
+
+	/// Complete the Description objects' information with data from other Description objects.
+	void postload();
+
+private:
+	EditorGameBase& egbase_;
+	std::unique_ptr<DescriptionMaintainer<BuildingDescr>> buildings_;
+	std::unique_ptr<DescriptionMaintainer<ImmovableDescr>> immovables_;
+	std::unique_ptr<DescriptionMaintainer<ShipDescr>> ships_;
+	std::unique_ptr<DescriptionMaintainer<WareDescr>> wares_;
+	std::unique_ptr<DescriptionMaintainer<WorkerDescr>> workers_;
+	std::unique_ptr<DescriptionMaintainer<TribeDescr>> tribes_;
+
+	std::unique_ptr<Texture> road_texture_; // Used in loading the road texture graphics
+
+	DISALLOW_COPY_AND_ASSIGN(Tribes);
+};
+
+}  // namespace Widelands
+
+#endif  // end of include guard: WL_LOGIC_TRIBES_TRIBES_H

=== modified file 'src/logic/ware_descr.cc'
--- src/logic/ware_descr.cc	2014-11-23 14:34:38 +0000
+++ src/logic/ware_descr.cc	2015-10-18 20:57:50 +0000
@@ -19,40 +19,93 @@
 
 #include "logic/ware_descr.h"
 
+#include <memory>
+
+#include <boost/format.hpp>
+
 #include "base/i18n.h"
 #include "graphic/animation.h"
 #include "graphic/graphic.h"
-#include "logic/tribe.h"
-#include "profile/profile.h"
+#include "logic/tribes/tribe_descr.h"
 
 namespace Widelands {
 
-WareDescr::WareDescr
-	(const TribeDescr & gtribe, char const * const _name,
-	 char const * const _descname,
-	 const std::string & directory, Profile & prof, Section & global_s)
-	:
-	MapObjectDescr(MapObjectType::WARE, _name, _descname),
-	m_tribe         (gtribe),
-	m_helptext      (global_s.get_string("help", "")),
-	m_icon_fname    (directory + "/menu.png"),
-	m_icon(g_gr->images().get("pics/but0.png"))
-{
-	m_default_target_quantity =
-		global_s.get_positive("default_target_quantity", std::numeric_limits<uint32_t>::max());
-
-	add_animation("idle", g_gr->animations().load(directory, prof.get_safe_section("idle")));
-
-	m_preciousness =
-		static_cast<uint8_t>(global_s.get_natural("preciousness", 0));
-}
+WareDescr::WareDescr(const std::string& init_descname, const LuaTable& table) :
+	MapObjectDescr(MapObjectType::WARE, table.get_string("name"), init_descname),
+	icon_fname_(table.get_string("icon")),
+	icon_(g_gr->images().get("pics/but0.png")) {
+
+	i18n::Textdomain td("tribes");
+
+	directory_ = table.get_string("directory");
+
+	std::unique_ptr<LuaTable> items_table = table.get_table("default_target_quantity");
+	for (const std::string& key : items_table->keys<std::string>()) {
+		default_target_quantities_.emplace(key, items_table->get_int(key));
+	}
+
+	items_table = table.get_table("preciousness");
+	for (const std::string& key : items_table->keys<std::string>()) {
+		preciousnesses_.emplace(key, items_table->get_int(key));
+	}
+
+	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)));
+	}
+	assert(is_animation_known("idle"));
+}
+
+int WareDescr::preciousness(const std::string& tribename) const {
+	if (preciousnesses_.count(tribename) > 0) {
+		return preciousnesses_.at(tribename);
+	}
+	return kInvalidWare;
+}
+
+
+WareIndex WareDescr::default_target_quantity(const std::string& tribename) const {
+	if (default_target_quantities_.count(tribename) > 0) {
+		return default_target_quantities_.at(tribename);
+	}
+	return kInvalidWare;
+}
+
 
 /**
  * Load all static graphics
  */
 void WareDescr::load_graphics()
 {
-	m_icon = g_gr->images().get(m_icon_fname);
-}
+	icon_ = g_gr->images().get(icon_fname_);
+}
+
+bool WareDescr::has_demand_check(const std::string& tribename) const {
+	return default_target_quantity(tribename) != kInvalidWare;
+}
+
+void WareDescr::set_has_demand_check(const std::string& tribename) {
+	if (default_target_quantities_.count(tribename) > 0
+		 && default_target_quantities_.at(tribename) == kInvalidWare) {
+		default_target_quantities_.at(tribename) = 1;
+	}
+}
+
+void WareDescr::add_consumer(const BuildingIndex& building_index) {
+	consumers_.emplace(building_index);
+}
+
+void WareDescr::add_producer(const BuildingIndex& building_index) {
+	producers_.emplace(building_index);
+}
+
+const std::set<BuildingIndex>& WareDescr::consumers() const {
+	return consumers_;
+}
+
+const std::set<BuildingIndex>& WareDescr::producers() const {
+	return producers_;
+}
+
 
 }

=== modified file 'src/logic/ware_descr.h'
--- src/logic/ware_descr.h	2015-02-08 18:16:41 +0000
+++ src/logic/ware_descr.h	2015-10-18 20:57:50 +0000
@@ -22,15 +22,18 @@
 
 #include <cstring>
 #include <string>
+#include <unordered_map>
 
 #include <stdint.h>
 
 #include "base/macros.h"
 #include "logic/instances.h"
+#include "scripting/lua_table.h"
 
+class Image;
+class LuaTable;
 class Profile;
 class Section;
-class Image;
 
 #define WARE_MENU_PIC_WIDTH   24  //< Default width for ware's menu icons
 #define WARE_MENU_PIC_HEIGHT  24  //< Default height for ware's menu icons
@@ -45,52 +48,57 @@
  * Wares can be stored in warehouses. They can be transferred across an
  * Economy. They can be traded.
 */
-struct WareDescr : public MapObjectDescr {
-	WareDescr
-		(const TribeDescr & tribe, char const * const name,
-		 char const * const descname, const std::string & directory,
-		 Profile &, Section & global_s);
+class WareDescr : public MapObjectDescr {
+public:
+	WareDescr(const std::string& init_descname, const LuaTable& t);
 	~WareDescr() override {}
 
-	const TribeDescr & tribe() const {return m_tribe;}
+	/// Returns the preciousness of the ware, or kInvalidWare if the tribe doesn't use the ware.
+	/// It is used by the computer player.
+	int preciousness(const std::string& tribename) const;
+
+	/// How much of the ware type an economy should store in warehouses.
+	/// The special value kInvalidWare means that the target quantity of this ware type will never be checked
+  ///  and should not be configurable.
+	WareIndex default_target_quantity(const std::string& tribename) const;
+
+	std::string directory() const {return directory_;}
 
 	/// \return index to ware's icon inside picture stack
-	const Image* icon() const {return m_icon;}
-	std::string icon_name() const {return m_icon_fname;}
-
-	/// \return ware's localized descriptive text
-	const std::string & helptext() const {return m_helptext;}
-
-	/// How much of the ware type that an economy should store in warehouses.
-	/// The special value std::numeric_limits<uint32_t>::max() means that the
-	/// the target quantity of this ware type will never be checked and should
-	/// not be configurable.
-	uint32_t default_target_quantity() const {return m_default_target_quantity;}
-
-	bool has_demand_check() const {
-		return default_target_quantity() != std::numeric_limits<uint32_t>::max();
-	}
+	const Image* icon() const {return icon_;}
+	std::string icon_name() const {return icon_fname_;}
+
+	virtual void load_graphics();
+
+	bool has_demand_check(const std::string& tribename) const;
 
 	/// Called when a demand check for this ware type is encountered during
 	/// parsing. If there was no default target quantity set in the ware type's
-	/// configuration, set the default value 1.
-	void set_has_demand_check() {
-		if (m_default_target_quantity == std::numeric_limits<uint32_t>::max())
-			m_default_target_quantity = 1;
-	}
-
-	virtual void load_graphics();
-
-	/// returns the preciousness of the ware. It is used by the computer player
-	uint8_t preciousness() const {return m_preciousness;}
+	/// configuration for the 'tribename', sets the default value to 1.
+	void set_has_demand_check(const std::string& tribename);
+
+	// Add a building to the list of consumers
+	void add_consumer(const BuildingIndex& building_index);
+	// Add a building to the list of producers
+	void add_producer(const BuildingIndex& building_index);
+
+	// The buildings that consume this ware
+	const std::set<BuildingIndex>& consumers() const;
+	// The buildings that produce this ware
+	const std::set<BuildingIndex>& producers() const;
 
 private:
-	const TribeDescr & m_tribe;
-	std::string m_helptext;   ///< Long descriptive text
-	uint32_t    m_default_target_quantity;
-	std::string m_icon_fname; ///< Filename of ware's main picture
-	const Image* m_icon;       ///< Index of ware's picture in picture stack
-	uint8_t     m_preciousness;
+	// tribename, quantity. No default.
+	std::unordered_map<std::string, int> default_target_quantities_;
+	// tribename, preciousness. No default.
+	std::unordered_map<std::string, int> preciousnesses_;
+
+	std::set<BuildingIndex> consumers_; // Buildings that consume this ware
+	std::set<BuildingIndex> producers_; // Buildings that produce this ware
+
+	std::string  directory_;  /// The directory where the init files are located
+	std::string  icon_fname_; ///< Filename of ware's main picture
+	const Image* icon_;       ///< Index of ware's picture in picture stack
 	DISALLOW_COPY_AND_ASSIGN(WareDescr);
 };
 

=== modified file 'src/logic/warehouse.cc'
--- src/logic/warehouse.cc	2015-10-12 15:43:01 +0000
+++ src/logic/warehouse.cc	2015-10-18 20:57:50 +0000
@@ -45,9 +45,8 @@
 #include "logic/player.h"
 #include "logic/requirements.h"
 #include "logic/soldier.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/worker.h"
-#include "profile/profile.h"
 
 namespace Widelands {
 
@@ -252,18 +251,17 @@
 ==============================
 */
 
-
-/// Warehouse Descr
 WarehouseDescr::WarehouseDescr
-	(char const* const _name, char const* const _descname,
-	 const std::string& directory, Profile& prof, Section& global_s, const TribeDescr& _tribe)
-	: BuildingDescr(MapObjectType::WAREHOUSE, _name, _descname, directory, prof, global_s, _tribe),
+	(const std::string& init_descname, const LuaTable& table, const EditorGameBase& egbase)
+	: BuildingDescr(init_descname, MapObjectType::WAREHOUSE, table, egbase),
 	  m_conquers         (0),
 	  m_heal_per_second  (0)
 {
-	m_heal_per_second = global_s.get_safe_int("heal_per_second");
-	if ((m_conquers = prof.get_safe_section("global").get_positive("conquers", 0)))
+	m_heal_per_second = table.get_int("heal_per_second");
+	if (table.has_key("conquers")) {
+		m_conquers = table.get_int("conquers");
 		m_workarea_info[m_conquers].insert(descname() + " conquer");
+	}
 }
 
 /*
@@ -278,13 +276,6 @@
 	m_next_military_act(0),
 	m_portdock(nullptr)
 {
-	uint8_t nr_worker_types_without_cost =
-		warehouse_descr.tribe().worker_types_without_cost().size();
-	m_next_worker_without_cost_spawn =
-		new uint32_t[nr_worker_types_without_cost];
-	for (int i = 0; i < nr_worker_types_without_cost; ++i) {
-		m_next_worker_without_cost_spawn[i] = never();
-	}
 	m_next_stock_remove_act = 0;
 	m_cleanup_in_progress = false;
 }
@@ -293,7 +284,6 @@
 Warehouse::~Warehouse()
 {
 	delete m_supply;
-	delete[] m_next_worker_without_cost_spawn;
 }
 
 /**
@@ -302,12 +292,21 @@
  */
 bool Warehouse::_load_finish_planned_worker(PlannedWorkers & pw)
 {
-	if (pw.index == INVALID_INDEX || !(pw.index < m_supply->get_workers().get_nrwareids()))
-		return false;
-
-	const WorkerDescr * w_desc = descr().tribe().get_worker_descr(pw.index);
-	if (!w_desc || !w_desc->is_buildable())
-		return false;
+	const TribeDescr& tribe = owner().tribe();
+
+	if (pw.index == INVALID_INDEX || !(pw.index < m_supply->get_workers().get_nrwareids())) {
+		return false;
+	}
+
+	const WorkerDescr * w_desc = tribe.get_worker_descr(pw.index);
+
+	if (!(tribe.has_worker(pw.index) && w_desc->is_buildable())) {
+		return false;
+	}
+
+	if (!(pw.index < m_supply->get_workers().get_nrwareids())) {
+		return false;
+	}
 
 	const WorkerDescr::Buildcost & cost = w_desc->buildcost();
 	uint32_t idx = 0;
@@ -317,25 +316,29 @@
 		 cost_it != cost.end(); ++cost_it, ++idx)
 	{
 		WareWorker type;
-		WareIndex ware;
-		ware = descr().tribe().ware_index(cost_it->first);
-		if (ware != INVALID_INDEX)
+		WareIndex wareindex;
+		wareindex = owner().tribe().ware_index(cost_it->first);
+		if (owner().tribe().has_ware(wareindex)) {
 			type = wwWARE;
-		else if ((ware = descr().tribe().worker_index(cost_it->first)) != INVALID_INDEX)
-			type = wwWORKER;
-		else
-			return false;
+		} else {
+			wareindex = owner().tribe().worker_index(cost_it->first);
+			if (owner().tribe().has_worker(wareindex)) {
+				type = wwWORKER;
+			} else {
+				return false;
+			}
+		}
 
 		if (idx < pw.requests.size()) {
 			if
 				(pw.requests[idx]->get_type() == type &&
-				 pw.requests[idx]->get_index() == ware)
+				 pw.requests[idx]->get_index() == wareindex)
 				continue;
 
 			std::vector<Request *>::iterator req_it =
 				pw.requests.begin() + idx + 1;
 			while (req_it != pw.requests.end()) {
-				if ((*req_it)->get_type() == type && (*req_it)->get_index() == ware)
+				if ((*req_it)->get_type() == type && (*req_it)->get_index() == wareindex)
 					break;
 				++req_it;
 			}
@@ -352,7 +355,7 @@
 			 cost_it->first.c_str());
 		pw.requests.insert
 			(pw.requests.begin() + idx,
-			 new Request(*this, ware, &Warehouse::request_cb, type));
+			 new Request(*this, wareindex, &Warehouse::request_cb, type));
 	}
 
 	while (pw.requests.size() > idx) {
@@ -369,16 +372,16 @@
 void Warehouse::load_finish(EditorGameBase & egbase) {
 	Building::load_finish(egbase);
 
-	uint32_t next_spawn = never();
+	Time next_spawn = never();
 	const std::vector<WareIndex> & worker_types_without_cost =
-		descr().tribe().worker_types_without_cost();
+		owner().tribe().worker_types_without_cost();
 	for (uint8_t i = worker_types_without_cost.size(); i;) {
 		WareIndex const worker_index = worker_types_without_cost.at(--i);
 		if
 			(owner().is_worker_type_allowed(worker_index) &&
-			 m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never()))
+			 m_next_worker_without_cost_spawn[i] == never())
 		{
-			if (next_spawn == static_cast<uint32_t>(never())) {
+			if (next_spawn == never()) {
 				next_spawn = schedule_act(dynamic_cast<Game&>(egbase), WORKER_WITHOUT_COST_SPAWN_INTERVAL);
 			}
 			m_next_worker_without_cost_spawn[i] = next_spawn;
@@ -387,7 +390,7 @@
 				 "%s %u at (%i, %i) does not have a next_spawn time set for that "
 				 "worker type; setting it to %u\n",
 				 owner().player_number(),
-				 descr().tribe().get_worker_descr(worker_index)->descname().c_str(),
+				 owner().tribe().get_worker_descr(worker_index)->descname().c_str(),
 				 descr().descname().c_str(), serial(), get_position().x, get_position().y,
 				 next_spawn);
 		}
@@ -411,18 +414,13 @@
 {
 	Building::init(egbase);
 
-	WareIndex const nr_wares   = descr().tribe().get_nrwares  ();
-	WareIndex const nr_workers = descr().tribe().get_nrworkers();
-	m_supply->set_nrwares  (nr_wares);
-	m_supply->set_nrworkers(nr_workers);
+	Player & player = owner();
 
-	m_ware_policy.resize(nr_wares, SP_Normal);
-	m_worker_policy.resize(nr_workers, SP_Normal);
+	init_containers(player);
 
 	// Even though technically, a warehouse might be completely empty,
 	// we let warehouse see always for simplicity's sake (since there's
 	// almost always going to be a carrier inside, that shouldn't hurt).
-	Player & player = owner();
 	if (upcast(Game, game, &egbase)) {
 		player.see_area
 			(Area<FCoords>
@@ -432,7 +430,7 @@
 			uint32_t const act_time = schedule_act
 					(*game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
 			const std::vector<WareIndex> & worker_types_without_cost =
-				descr().tribe().worker_types_without_cost();
+				owner().tribe().worker_types_without_cost();
 
 			for (size_t i = 0; i < worker_types_without_cost.size(); ++i) {
 				if (owner().is_worker_type_allowed(worker_types_without_cost.at(i))) {
@@ -441,7 +439,7 @@
 			}
 		}
 		// m_next_military_act is not touched in the loading code. Is only needed
-		// if there warehous is created in the game?  I assume it's for the
+		// if the warehouse is created in the game?  I assume it's for the
 		// conquer_radius thing
 		m_next_military_act = schedule_act(*game, 1000);
 
@@ -449,14 +447,14 @@
 
 		log("Message: adding (wh) (%s) %i \n", to_string(descr().type()).c_str(), player.player_number());
 
-		if (descr().name() == "port") {
+		if (descr().get_isport()) {
 			send_message
 				(*game,
 				 Message::Type::kSeafaring,
 				 descr().descname(),
 				 _("A new port was added to your economy."),
 				 true);
-		} else if (descr().name() == "headquarters") {
+		} else if (!descr().is_buildable()) {
 			send_message
 				(*game,
 				 Message::Type::kEconomy,
@@ -496,6 +494,19 @@
 
 }
 
+void Warehouse::init_containers(Player& player) {
+	WareIndex const nr_wares = player.egbase().tribes().nrwares();
+	WareIndex const nr_workers = player.egbase().tribes().nrworkers();
+	m_supply->set_nrwares(nr_wares);
+	m_supply->set_nrworkers(nr_workers);
+
+	m_ware_policy.resize(nr_wares, SP_Normal);
+	m_worker_policy.resize(nr_workers, SP_Normal);
+
+	uint8_t nr_worker_types_without_cost = player.tribe().worker_types_without_cost().size();
+	m_next_worker_without_cost_spawn.resize(nr_worker_types_without_cost, never());
+}
+
 /**
  * Find a contiguous set of water fields close to the port for docking
  * and initialize the @ref PortDock instance.
@@ -631,7 +642,7 @@
 /// at night ;-)
 void Warehouse::act(Game & game, uint32_t const data)
 {
-	uint32_t const gametime = game.get_gametime();
+	const int32_t gametime = game.get_gametime();
 	{
 		const std::vector<WareIndex> & worker_types_without_cost =
 			owner().tribe().worker_types_without_cost();
@@ -661,10 +672,10 @@
 
 	//  Military stuff: Kill the soldiers that are dead.
 	if (m_next_military_act <= gametime) {
-		WareIndex const ware = descr().tribe().safe_worker_index("soldier");
+		WareIndex const soldier_index = owner().tribe().soldier();
 
-		if (m_incorporated_workers.count(ware)) {
-			WorkerList & soldiers = m_incorporated_workers[ware];
+		if (m_incorporated_workers.count(soldier_index)) {
+			WorkerList & soldiers = m_incorporated_workers[soldier_index];
 
 			uint32_t total_heal = descr().get_heal_per_second();
 			// Using an explicit iterator, as we plan to erase some
@@ -681,7 +692,7 @@
 				//  Soldier dead ...
 				if (!soldier || soldier->get_current_hitpoints() == 0) {
 					it = soldiers.erase(it);
-					m_supply->remove_workers(ware, 1);
+					m_supply->remove_workers(soldier_index, 1);
 					continue;
 				}
 
@@ -797,7 +808,7 @@
 /// Launch a carrier to fetch an ware from our flag.
 bool Warehouse::fetch_from_flag(Game & game)
 {
-	WareIndex const carrierid = descr().tribe().safe_worker_index("carrier");
+	WareIndex const carrierid = owner().tribe().carrier();
 
 	if (!m_supply->stock_workers(carrierid))
 	{
@@ -838,8 +849,8 @@
 			}
 		}
 
-		ware = descr().tribe().get_worker_descr(ware)->becomes();
-	} while (ware != INVALID_INDEX);
+		ware = owner().tribe().get_worker_descr(ware)->becomes();
+	} while (owner().tribe().has_ware(ware));
 
 	return sum;
 }
@@ -884,7 +895,7 @@
 				// Create a new one
 				// NOTE: This code lies about the TrainingAttributes of the new worker
 				m_supply->remove_workers(ware, 1);
-				const WorkerDescr & workerdescr = *descr().tribe().get_worker_descr(ware);
+				const WorkerDescr & workerdescr = *game.tribes().get_worker_descr(ware);
 				return workerdescr.create(game, owner(), this, m_position);
 			}
 		}
@@ -893,9 +904,9 @@
 			// don't want to use an upgraded worker, so create new one.
 			create_worker(game, ware);
 		} else {
-			ware = descr().tribe().get_worker_descr(ware)->becomes();
+			ware = game.tribes().get_worker_descr(ware)->becomes();
 		}
-	} while (ware != INVALID_INDEX);
+	} while (owner().tribe().has_ware(ware));
 
 	throw wexception
 		("Warehouse::launch_worker: worker does not actually exist");
@@ -910,7 +921,7 @@
 	if (WareInstance* ware = w->fetch_carried_ware(egbase))
 		incorporate_ware(egbase, ware);
 
-	WareIndex worker_index = descr().tribe().worker_index(w->descr().name().c_str());
+	WareIndex worker_index = owner().tribe().worker_index(w->descr().name().c_str());
 
 	m_supply->add_workers(worker_index, 1);
 
@@ -945,7 +956,7 @@
 /// carried out of the warehouse.
 WareInstance & Warehouse::launch_ware(Game & game, WareIndex const ware_index) {
 	// Create the ware
-	WareInstance & ware = *new WareInstance(ware_index, descr().tribe().get_ware_descr(ware_index));
+	WareInstance & ware = *new WareInstance(ware_index, owner().tribe().get_ware_descr(ware_index));
 	ware.init(game);
 	if (do_launch_ware(game, ware))
 	{
@@ -959,7 +970,7 @@
 bool Warehouse::do_launch_ware(Game & game, WareInstance & ware)
 {
 	// Create a carrier
-	WareIndex const carrierid = descr().tribe().worker_index("carrier");
+	const WareIndex carrierid = owner().tribe().carrier();
 
 	if (!m_supply->stock_workers(carrierid))
 	{
@@ -1032,32 +1043,40 @@
 
 
 bool Warehouse::can_create_worker(Game &, WareIndex const worker) const {
+	assert(owner().tribe().has_worker(worker));
+
 	if (!(worker < m_supply->get_workers().get_nrwareids()))
 		throw wexception
 			("worker type %d does not exists (max is %d)",
 			 worker, m_supply->get_workers().get_nrwareids());
 
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
+	const WorkerDescr& w_desc = *owner().tribe().get_worker_descr(worker);
 	assert(&w_desc);
-	if (!w_desc.is_buildable())
+	if (!w_desc.is_buildable()) {
 		return false;
+	}
 
 	//  see if we have the resources
 	for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
 		const std::string & input_name = buildcost.first;
-		WareIndex id_w = descr().tribe().ware_index(input_name);
-		if (id_w != INVALID_INDEX) {
-			if (m_supply->stock_wares(id_w) < buildcost.second)
-				return false;
-		} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
-			if (m_supply->stock_workers(id_w) < buildcost.second)
-				return false;
-		} else
-			throw wexception
-				("worker type %s needs \"%s\" to be built but that is neither "
-				 "a ware type nor a worker type defined in the tribe %s",
-				 w_desc.descname().c_str(), input_name.c_str(),
-				 descr().tribe().name().c_str());
+		WareIndex id_w = owner().tribe().ware_index(input_name);
+		if (owner().tribe().has_ware(id_w)) {
+			if (m_supply->stock_wares(id_w) < buildcost.second) {
+				return false;
+			}
+		} else {
+			id_w = owner().tribe().worker_index(input_name);
+			if (owner().tribe().has_worker(id_w)) {
+				if (m_supply->stock_workers(id_w) < buildcost.second) {
+					return false;
+				}
+			} else
+				throw wexception
+					("worker type %s needs \"%s\" to be built but that is neither "
+					 "a ware type nor a worker type defined in the tribe %s",
+					 w_desc.descname().c_str(), input_name.c_str(),
+					 owner().tribe().name().c_str());
+		}
 	}
 	return true;
 }
@@ -1066,17 +1085,17 @@
 void Warehouse::create_worker(Game & game, WareIndex const worker) {
 	assert(can_create_worker (game, worker));
 
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
+	const WorkerDescr & w_desc = *owner().tribe().get_worker_descr(worker);
 
 	for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
 		const std::string & input = buildcost.first;
-		WareIndex const id_ware = descr().tribe().ware_index(input);
-		if (id_ware != INVALID_INDEX) {
-			remove_wares  (id_ware,                        buildcost.second);
+		WareIndex const id_ware = owner().tribe().ware_index(input);
+		if (owner().tribe().has_ware(id_ware)) {
+			remove_wares(id_ware, buildcost.second);
 			//update statistic accordingly
 			owner().ware_consumed(id_ware, buildcost.second);
 		} else
-			remove_workers(descr().tribe().safe_worker_index(input), buildcost.second);
+			remove_workers(owner().tribe().safe_worker_index(input), buildcost.second);
 	}
 
 	incorporate_worker(game, &w_desc.create(game, owner(), this, m_position));
@@ -1113,20 +1132,23 @@
 std::vector<uint32_t> Warehouse::calc_available_for_worker
 	(Game & /* game */, WareIndex index) const
 {
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(index);
+	const WorkerDescr & w_desc = *owner().tribe().get_worker_descr(index);
 	std::vector<uint32_t> available;
 
 	for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
 		const std::string & input_name = buildcost.first;
-		WareIndex id_w = descr().tribe().ware_index(input_name);
-		if (id_w != INVALID_INDEX) {
+		WareIndex id_w = owner().tribe().ware_index(input_name);
+		if (owner().tribe().has_ware(id_w)) {
 			available.push_back(get_wares().stock(id_w));
-		} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
-			available.push_back(get_workers().stock(id_w));
-		} else
-			throw wexception
-				("Economy::_create_requested_worker: buildcost inconsistency '%s'",
-				 input_name.c_str());
+		} else {
+			id_w = owner().tribe().worker_index(input_name);
+			if (owner().tribe().has_worker(id_w)) {
+				available.push_back(get_workers().stock(id_w));
+			} else
+				throw wexception
+					("Economy::_create_requested_worker: buildcost inconsistency '%s'",
+					 input_name.c_str());
+		}
 	}
 
 	for (const PlannedWorkers& pw : m_planned_workers) {
@@ -1167,22 +1189,25 @@
 		pw->index = index;
 		pw->amount = 0;
 
-		const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw->index);
+		const WorkerDescr & w_desc = *owner().tribe().get_worker_descr(pw->index);
 		for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
 			const std::string & input_name = buildcost.first;
 
-			WareIndex id_w = descr().tribe().ware_index(input_name);
-			if (id_w != INVALID_INDEX) {
+			WareIndex id_w = owner().tribe().ware_index(input_name);
+			if (owner().tribe().has_ware(id_w)) {
 				pw->requests.push_back
 					(new Request
 					 (*this, id_w, &Warehouse::request_cb, wwWARE));
-			} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
-				pw->requests.push_back
-					(new Request
-					 (*this, id_w, &Warehouse::request_cb, wwWORKER));
-			} else
-				throw wexception
-					("plan_workers: bad buildcost '%s'", input_name.c_str());
+			} else {
+				id_w = owner().tribe().worker_index(input_name);
+				if (owner().tribe().has_worker(id_w)) {
+					pw->requests.push_back
+						(new Request
+						 (*this, id_w, &Warehouse::request_cb, wwWORKER));
+				} else
+					throw wexception
+						("plan_workers: bad buildcost '%s'", input_name.c_str());
+			}
 		}
 	}
 
@@ -1197,7 +1222,7 @@
 void Warehouse::_update_planned_workers
 	(Game & game, Warehouse::PlannedWorkers & pw)
 {
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw.index);
+	const WorkerDescr & w_desc = *owner().tribe().get_worker_descr(pw.index);
 
 	while (pw.amount && can_create_worker(game, pw.index)) {
 		create_worker(game, pw.index);
@@ -1209,15 +1234,17 @@
 		const std::string & input_name = buildcost.first;
 		uint32_t supply;
 
-		WareIndex id_w = descr().tribe().ware_index(input_name);
-		if (id_w != INVALID_INDEX) {
+		WareIndex id_w = owner().tribe().ware_index(input_name);
+		if (owner().tribe().has_ware(id_w)) {
 			supply = m_supply->stock_wares(id_w);
-		} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
+		} else {
+			id_w = owner().tribe().worker_index(input_name);
+			if (owner().tribe().has_worker(id_w)) {
 			supply = m_supply->stock_workers(id_w);
-		} else
-			throw wexception
-				("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
-
+			} else
+				throw wexception
+					("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
+		}
 		if (supply >= pw.amount * buildcost.second)
 			pw.requests[idx]->set_count(0);
 		else
@@ -1256,19 +1283,13 @@
 void Warehouse::enable_spawn
 	(Game & game, uint8_t const worker_types_without_cost_index)
 {
-	assert
-		(m_next_worker_without_cost_spawn[worker_types_without_cost_index]
-		 ==
-		 static_cast<uint32_t>(never()));
+	assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] == never());
 	m_next_worker_without_cost_spawn[worker_types_without_cost_index] =
 		schedule_act(game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
 }
 void Warehouse::disable_spawn(uint8_t const worker_types_without_cost_index)
 {
-	assert
-		(m_next_worker_without_cost_spawn[worker_types_without_cost_index]
-		 !=
-		 static_cast<uint32_t>(never()));
+	assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] != never());
 	m_next_worker_without_cost_spawn[worker_types_without_cost_index] = never();
 }
 
@@ -1300,7 +1321,7 @@
 		 	 FindBobEnemySoldier(&owner())))
 		return;
 
-	WareIndex const soldier_index = descr().tribe().worker_index("soldier");
+	WareIndex const soldier_index = owner().tribe().soldier();
 	Requirements noreq;
 
 	if (!count_workers(game, soldier_index, noreq))
@@ -1313,7 +1334,7 @@
 bool Warehouse::attack(Soldier & enemy)
 {
 	Game & game = dynamic_cast<Game&>(owner().egbase());
-	WareIndex const soldier_index = descr().tribe().worker_index("soldier");
+	WareIndex const soldier_index = owner().tribe().soldier();
 	Requirements noreq;
 
 	if (count_workers(game, soldier_index, noreq)) {
@@ -1338,13 +1359,13 @@
 
 Warehouse::StockPolicy Warehouse::get_ware_policy(WareIndex ware) const
 {
-	assert(ware < m_ware_policy.size());
+	assert(ware < static_cast<WareIndex>(m_ware_policy.size()));
 	return m_ware_policy[ware];
 }
 
 Warehouse::StockPolicy Warehouse::get_worker_policy(WareIndex ware) const
 {
-	assert(ware < m_worker_policy.size());
+	assert(ware < static_cast<WareIndex>(m_worker_policy.size()));
 	return m_worker_policy[ware];
 }
 
@@ -1360,14 +1381,14 @@
 
 void Warehouse::set_ware_policy(WareIndex ware, Warehouse::StockPolicy policy)
 {
-	assert(ware < m_ware_policy.size());
+	assert(ware < static_cast<WareIndex>(m_ware_policy.size()));
 	m_ware_policy[ware] = policy;
 }
 
 void Warehouse::set_worker_policy
 	(WareIndex ware, Warehouse::StockPolicy policy)
 {
-	assert(ware < m_worker_policy.size());
+	assert(ware < static_cast<WareIndex>(m_worker_policy.size()));
 	m_worker_policy[ware] = policy;
 }
 
@@ -1378,7 +1399,7 @@
 void Warehouse::check_remove_stock(Game & game)
 {
 	if (base_flag().current_wares() < base_flag().total_capacity() / 2) {
-		for (WareIndex ware = 0; ware < m_ware_policy.size(); ++ware) {
+		for (WareIndex ware = 0; ware < static_cast<WareIndex>(m_ware_policy.size()); ++ware) {
 			if (get_ware_policy(ware) != SP_Remove || !get_wares().stock(ware))
 				continue;
 
@@ -1387,7 +1408,7 @@
 		}
 	}
 
-	for (WareIndex widx = 0; widx < m_worker_policy.size(); ++widx) {
+	for (WareIndex widx = 0; widx < static_cast<WareIndex>(m_worker_policy.size()); ++widx) {
 		if (get_worker_policy(widx) != SP_Remove || !get_workers().stock(widx))
 			continue;
 
@@ -1411,8 +1432,8 @@
 {
 	std::vector<Soldier *> rv;
 
-	WareIndex const ware = descr().tribe().safe_worker_index("soldier");
-	IncorporatedWorkers::const_iterator sidx = m_incorporated_workers.find(ware);
+	WareIndex const soldier_index = owner().tribe().soldier();
+	IncorporatedWorkers::const_iterator sidx = m_incorporated_workers.find(soldier_index);
 
 	if (sidx != m_incorporated_workers.end()) {
 		const WorkerList & soldiers = sidx->second;
@@ -1431,15 +1452,15 @@
 
 int Warehouse::outcorporate_soldier(EditorGameBase & /* egbase */, Soldier & soldier) {
 
-	WareIndex const ware = descr().tribe().safe_worker_index("soldier");
-	if (m_incorporated_workers.count(ware)) {
-		WorkerList & soldiers = m_incorporated_workers[ware];
+	WareIndex const soldier_index = owner().tribe().soldier();
+	if (m_incorporated_workers.count(soldier_index)) {
+		WorkerList & soldiers = m_incorporated_workers[soldier_index];
 
 		WorkerList::iterator i = std::find
 			(soldiers.begin(), soldiers.end(), &soldier);
 
 		soldiers.erase(i);
-		m_supply->remove_workers(ware, 1);
+		m_supply->remove_workers(soldier_index, 1);
 	}
 #ifndef NDEBUG
 	else

=== modified file 'src/logic/warehouse.h'
--- src/logic/warehouse.h	2015-10-02 17:55:51 +0000
+++ src/logic/warehouse.h	2015-10-18 20:57:50 +0000
@@ -48,11 +48,9 @@
 */
 struct WarehouseSupply;
 
-struct WarehouseDescr : public BuildingDescr {
-	WarehouseDescr
-		(char const * name, char const * descname,
-		 const std::string & directory, Profile &, Section & global_s,
-		 const TribeDescr &);
+class WarehouseDescr : public BuildingDescr {
+public:
+	WarehouseDescr(const std::string& init_descname, const LuaTable& t, const EditorGameBase& egbase);
 	~WarehouseDescr() override {}
 
 	Building & create_object() const override;
@@ -225,6 +223,8 @@
 	void log_general_info(const EditorGameBase &) override;
 
 protected:
+	/// Initializes the container sizes for the owner's tribe.
+	void init_containers(Player& owner);
 	/// Create the warehouse information window.
 	virtual void create_options_window
 		(InteractiveGameBase &, UI::Window * & registry) override;
@@ -267,9 +267,9 @@
 	using WorkerList = std::vector<Worker *>;
 	using IncorporatedWorkers = std::map<WareIndex, WorkerList>;
 	IncorporatedWorkers        m_incorporated_workers;
-	uint32_t                 * m_next_worker_without_cost_spawn;
-	uint32_t                   m_next_military_act;
-	uint32_t m_next_stock_remove_act;
+	std::vector<Time>          m_next_worker_without_cost_spawn;
+	Time                       m_next_military_act;
+	Time                       m_next_stock_remove_act;
 
 	std::vector<PlannedWorkers> m_planned_workers;
 

=== modified file 'src/logic/widelands.h'
--- src/logic/widelands.h	2014-09-19 12:54:54 +0000
+++ src/logic/widelands.h	2015-10-18 20:57:50 +0000
@@ -62,10 +62,11 @@
 
 using Serial = uint32_t; /// Serial number for MapObject.
 
-constexpr uint8_t INVALID_INDEX = std::numeric_limits<uint8_t>::max();
 using WareIndex = uint8_t;
 using BuildingIndex = uint8_t;
 using Direction = uint8_t;
+constexpr uint8_t INVALID_INDEX = std::numeric_limits<uint8_t>::max();
+constexpr WareIndex kInvalidWare = INVALID_INDEX - 1;
 
 struct SoldierStrength {
 	uint8_t hp, attack, defense, evade;

=== modified file 'src/logic/worker.cc'
--- src/logic/worker.cc	2015-05-10 15:25:34 +0000
+++ src/logic/worker.cc	2015-10-18 20:57:50 +0000
@@ -52,7 +52,7 @@
 #include "logic/player.h"
 #include "logic/soldier.h"
 #include "logic/terrain_affinity.h"
-#include "logic/tribe.h"
+#include "logic/tribes/tribe_descr.h"
 #include "logic/warehouse.h"
 #include "logic/worker_program.h"
 #include "logic/world/resource_description.h"
@@ -60,7 +60,7 @@
 #include "logic/world/world.h"
 #include "map_io/map_object_loader.h"
 #include "map_io/map_object_saver.h"
-#include "profile/profile.h"
+#include "map_io/tribes_legacy_lookup_table.h"
 #include "sound/sound_handler.h"
 
 namespace Widelands {
@@ -83,7 +83,7 @@
 	Player & player = *get_owner();
 	WareIndex const wareid(action.iparam1);
 	WareInstance & ware =
-		*new WareInstance(wareid, descr().tribe().get_ware_descr(wareid));
+		*new WareInstance(wareid, player.tribe().get_ware_descr(wareid));
 	ware.init(game);
 
 	set_carried_ware(game, &ware);
@@ -114,7 +114,7 @@
 	//Make sure that the specified resource is available in this world
 	ResourceIndex const res =
 		game.world().get_resource(action.sparam1.c_str());
-	if (static_cast<int8_t>(res) == -1) //  TODO(unknown): ARGH!!
+	if (res == Widelands::INVALID_INDEX)
 		throw GameDataError
 			(_
 				("should mine resource %s, which does not exist in world; tribe "
@@ -219,7 +219,7 @@
 	//Make sure that the specified resource is available in this world
 	ResourceIndex const res =
 		game.world().get_resource(action.sparam1.c_str());
-	if (static_cast<int8_t>(res) == -1) //  TODO(unknown): ARGH!!
+	if (res == Widelands::INVALID_INDEX)
 		throw GameDataError
 			(_
 				("should breed resource type %s, which does not exist in world; "
@@ -353,7 +353,7 @@
 		state.svar1 == "world" ?
 		game.world().get_bob(bob.c_str())
 		:
-		descr ().tribe().get_bob(bob.c_str());
+		game.tribes().ship_index(bob.c_str());
 
 	if (state.ivar2 < 0) {
 		molog("  WARNING: Unknown bob %s\n", action.sparamv[idx].c_str());
@@ -521,7 +521,7 @@
 // as in this case, only before a worker starts walking there to place an
 // object. But that would make it very difficult to find space for things
 // like farm fileds. So our only option seems to be to keep all farm
-// fields, trees, stones and such on triangles and keep the nodes
+// fields, trees, rocks and such on triangles and keep the nodes
 // passable. See code structure issue #1096824.
 struct FindNodeSpace {
 	FindNodeSpace(BaseImmovable * const ignoreimm)
@@ -783,12 +783,12 @@
 	// affinity). We will pick one of them at random later. The container is
 	// picked to be a stable sorting one, so that no deyncs happen in
 	// multiplayer.
-	std::set<std::tuple<double, uint32_t>> best_suited_immovables_index;
+	std::set<std::tuple<double, WareIndex>> best_suited_immovables_index;
 
 	// Checks if the 'immovable_description' has a terrain_affinity, if so use it. Otherwise assume it
 	// to be 1. (perfect fit). Adds it to the best_suited_immovables_index.
 	const auto test_suitability = [&best_suited_immovables_index, &fpos, &map, &game](
-		const uint32_t index, const ImmovableDescr& immovable_description) {
+		const WareIndex index, const ImmovableDescr& immovable_description) {
 		double p = 1.;
 		if (immovable_description.has_terrain_affinity()) {
 			p = probability_to_grow(
@@ -816,8 +816,8 @@
 		const DescriptionMaintainer<ImmovableDescr>& immovables = game.world().immovables();
 
 		const uint32_t attribute_id = ImmovableDescr::get_attribute_id(list[1]);
-		for (uint32_t i = 0; i < immovables.get_nitems(); ++i) {
-			ImmovableDescr& immovable_descr = immovables.get_unmutable(i);
+		for (uint32_t i = 0; i < immovables.size(); ++i) {
+			ImmovableDescr& immovable_descr = immovables.get(i);
 			if (!immovable_descr.has_attribute(attribute_id)) {
 				continue;
 			}
@@ -825,10 +825,10 @@
 		}
 	} else {
 		state.svar1 = "tribe";
-		uint32_t immovable_index = descr().tribe().get_immovable_index(list[1]);
+		WareIndex immovable_index = game.tribes().immovable_index(list[1]);
 
-		if (immovable_index > 0) {
-			const ImmovableDescr* imm = descr().tribe().get_immovable_descr(immovable_index);
+		if (game.tribes().immovable_exists(immovable_index)) {
+			const ImmovableDescr* imm = game.tribes().get_immovable_descr(immovable_index);
 			test_suitability(immovable_index, *imm);
 		}
 	}
@@ -864,7 +864,10 @@
 	}
 
 	Immovable& newimm =
-	   game.create_immovable(pos, state.ivar2, state.svar1 == "tribe" ? &descr().tribe() : nullptr);
+		game.create_immovable(pos, state.ivar2,
+									 state.svar1 == "tribe" ?
+										 MapObjectDescr::OwnerType::kTribe :
+										 MapObjectDescr::OwnerType::kWorld);
 	newimm.set_owner(get_owner());
 
 	if (action.iparam1 == Action::plantUnlessObject)
@@ -882,8 +885,11 @@
  */
 bool Worker::run_create_bob(Game & game, State & state, const Action &)
 {
-	game.create_bob
-		(get_position(), state.ivar2, state.svar1 == "world" ? nullptr : &descr().tribe());
+	if (state.svar1 == "world") {
+		game.create_critter(get_position(), state.ivar2);
+	} else {
+		game.create_ship(get_position(), state.ivar2);
+	}
 	++state.ivar1;
 	schedule_act(game, 10);
 	return true;
@@ -

Follow ups