← Back to team overview

widelands-dev team mailing list archive

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

 

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

Commit message:
Some refactoring for the Soldier code:
- Refactored the battle attributes in SoldierDescr (health, attack, defense, evade) into a nice Lua table and struct.
- Made member variables in SolderDescr private.
- Renamed all instances of "hp" and "hitpoints" to "health" for consistency.
- TrainingAttribute is now an enum class with consistent saveloading datatype.


Requested reviews:
  Widelands Developers (widelands-dev)

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

The Lua code for the soldier descriptions was still a holdover from the old conf file format. I have now created some nicer data structures and done some code refactoring (see commit message).

I'd like this in Build 19, because it will be a pain for modders otherwise.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/soldier_refactoring into lp:widelands.
=== modified file 'data/campaigns/tutorial02_warfare.wmf/scripting/texts.lua'
--- data/campaigns/tutorial02_warfare.wmf/scripting/texts.lua	2016-01-28 05:24:34 +0000
+++ data/campaigns/tutorial02_warfare.wmf/scripting/texts.lua	2016-02-21 19:03:44 +0000
@@ -31,7 +31,7 @@
       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/workers/barbarians/soldier/hp_level0.png", h2(_"Health:"))..
+   rt("image=tribes/workers/barbarians/soldier/health_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/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.]])) ..

=== modified file 'data/tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua'
--- data/tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua	2016-02-17 15:29:52 +0000
+++ data/tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua	2016-02-21 19:03:44 +0000
@@ -69,7 +69,7 @@
          "shield_advanced"
       }
    },
-   ["soldier hp"] = {
+   ["soldier health"] = {
       min_level = 0,
       max_level = 0,
       food = {
@@ -119,15 +119,15 @@
             "train=soldier defense 1 2"
          }
       },
-      upgrade_soldier_hp_0 = {
+      upgrade_soldier_health_0 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 0 to level 1",
          actions = {
-            "check_soldier=soldier hp 0", -- Fails when aren't any soldier of level 0 hp
+            "check_soldier=soldier health 0", -- Fails when aren't any soldier of level 0 health
             "sleep=30000",
-            "check_soldier=soldier hp 0", -- Because the soldier can be expelled by the player
+            "check_soldier=soldier health 0", -- Because the soldier can be expelled by the player
             "consume=smoked_fish,smoked_meat:2 tabard_golden",
-            "train=soldier hp 0 1"
+            "train=soldier health 0 1"
          }
       },
       upgrade_soldier_evade_0 = {

=== modified file 'data/tribes/buildings/trainingsites/barbarians/trainingcamp/init.lua'
--- data/tribes/buildings/trainingsites/barbarians/trainingcamp/init.lua	2016-01-02 21:39:43 +0000
+++ data/tribes/buildings/trainingsites/barbarians/trainingcamp/init.lua	2016-02-21 19:03:44 +0000
@@ -82,7 +82,7 @@
          "ax_warriors"
       }
    },
-   ["soldier hp"] = {
+   ["soldier health"] = {
       min_level = 0,
       max_level = 2,
       food = {
@@ -160,37 +160,37 @@
             "train=soldier attack 4 5"
          }
       },
-      upgrade_soldier_hp_0 = {
+      upgrade_soldier_health_0 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 0 to level 1",
          actions = {
-            "check_soldier=soldier hp 0",
+            "check_soldier=soldier health 0",
             "sleep=30000",
-            "check_soldier=soldier hp 0",
+            "check_soldier=soldier health 0",
             "consume=helmet barbarians_bread,fish,meat",
-            "train=soldier hp 0 1"
+            "train=soldier health 0 1"
          }
       },
-      upgrade_soldier_hp_1 = {
+      upgrade_soldier_health_1 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 1 to level 2",
          actions = {
-            "check_soldier=soldier hp 1",
+            "check_soldier=soldier health 1",
             "sleep=30000",
-            "check_soldier=soldier hp 1",
+            "check_soldier=soldier health 1",
             "consume=helmet_mask fish,meat barbarians_bread",
-            "train=soldier hp 1 2"
+            "train=soldier health 1 2"
          }
       },
-      upgrade_soldier_hp_2 = {
+      upgrade_soldier_health_2 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 2 to level 3",
          actions = {
-            "check_soldier=soldier hp 2",
+            "check_soldier=soldier health 2",
             "sleep=30000",
-            "check_soldier=soldier hp 2",
+            "check_soldier=soldier health 2",
             "consume=helmet_warhelm fish,meat:2 barbarians_bread",
-            "train=soldier hp 2 3"
+            "train=soldier health 2 3"
          }
       },
    },

=== modified file 'data/tribes/buildings/trainingsites/empire/trainingcamp/init.lua'
--- data/tribes/buildings/trainingsites/empire/trainingcamp/init.lua	2016-01-02 21:39:43 +0000
+++ data/tribes/buildings/trainingsites/empire/trainingcamp/init.lua	2016-02-21 19:03:44 +0000
@@ -75,7 +75,7 @@
          "spear_war"
       }
    },
-   ["soldier hp"] = {
+   ["soldier health"] = {
       min_level = 0,
       max_level = 3,
       food = {
@@ -143,48 +143,48 @@
             "train=soldier attack 3 4"
          }
       },
-      upgrade_soldier_hp_0 = {
+      upgrade_soldier_health_0 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 0 to level 1",
          actions = {
-            "check_soldier=soldier hp 0",
+            "check_soldier=soldier health 0",
             "sleep=30000",
-            "check_soldier=soldier hp 0",
+            "check_soldier=soldier health 0",
             "consume=armor_helmet empire_bread,fish,meat",
-            "train=soldier hp 0 1"
+            "train=soldier health 0 1"
          }
       },
-      upgrade_soldier_hp_1 = {
+      upgrade_soldier_health_1 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 1 to level 2",
          actions = {
-            "check_soldier=soldier hp 1",
+            "check_soldier=soldier health 1",
             "sleep=30000",
-            "check_soldier=soldier hp 1",
+            "check_soldier=soldier health 1",
             "consume=armor empire_bread fish,meat",
-            "train=soldier hp 1 2"
+            "train=soldier health 1 2"
          }
       },
-      upgrade_soldier_hp_2 = {
+      upgrade_soldier_health_2 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 2 to level 3",
          actions = {
-            "check_soldier=soldier hp 2",
+            "check_soldier=soldier health 2",
             "sleep=30000",
-            "check_soldier=soldier hp 2",
+            "check_soldier=soldier health 2",
             "consume=armor_chain empire_bread:2 fish,meat:2",
-            "train=soldier hp 2 3"
+            "train=soldier health 2 3"
          }
       },
-      upgrade_soldier_hp_3 = {
+      upgrade_soldier_health_3 = {
          -- TRANSLATORS: Completed/Skipped/Did not start upgrading ... because ...
          descname = _"upgrading soldier health from level 3 to level 4",
          actions = {
-            "check_soldier=soldier hp 3",
+            "check_soldier=soldier health 3",
             "sleep=30000",
-            "check_soldier=soldier hp 3",
+            "check_soldier=soldier health 3",
             "consume=armor_gilded empire_bread:2 fish,meat:2",
-            "train=soldier hp 3 4"
+            "train=soldier health 3 4"
          }
       },
    },

=== modified file 'data/tribes/scripting/help/building_help.lua'
--- data/tribes/scripting/help/building_help.lua	2016-02-14 16:31:07 +0000
+++ data/tribes/scripting/help/building_help.lua	2016-02-21 19:03:44 +0000
@@ -373,18 +373,18 @@
 --
 function building_help_dependencies_training(tribe, building_description)
    local result = ""
-   if (building_description.max_hp and building_description.min_hp) then
+   if (building_description.max_health and building_description.min_health) then
       result = result .. rt(h2(_"Health Training"))
       result = result .. rt(p(_"Trains ‘Health’ from %1% up to %2%":
-            bformat(building_description.min_hp, building_description.max_hp+1)))
+            bformat(building_description.min_health, building_description.max_health+1)))
       result = result .. rt(h3(_"Soldiers:"))
       result = result ..
          dependencies_basic({
-            "tribes/workers/" .. tribe.name .. "/soldier/hp_level" .. building_description.min_hp .. ".png",
+            "tribes/workers/" .. tribe.name .. "/soldier/health_level" .. building_description.min_health .. ".png",
             building_description.icon_name,
-            "tribes/workers/" .. tribe.name .. "/soldier/hp_level" .. (building_description.max_hp + 1) ..".png"})
-      result = result .. dependencies_training_food(building_description.food_hp)
-      result = result .. dependencies_training_weapons(building_description.weapons_hp)
+            "tribes/workers/" .. tribe.name .. "/soldier/health_level" .. (building_description.max_health + 1) ..".png"})
+      result = result .. dependencies_training_food(building_description.food_health)
+      result = result .. dependencies_training_weapons(building_description.weapons_health)
    end
    if (building_description.max_attack and building_description.min_attack) then
       result = result .. rt(h2(_"Attack Training"))

=== renamed file 'data/tribes/workers/atlanteans/soldier/hp_level0.png' => 'data/tribes/workers/atlanteans/soldier/health_level0.png'
=== renamed file 'data/tribes/workers/atlanteans/soldier/hp_level1.png' => 'data/tribes/workers/atlanteans/soldier/health_level1.png'
=== modified file 'data/tribes/workers/atlanteans/soldier/init.lua'
--- data/tribes/workers/atlanteans/soldier/init.lua	2015-12-11 16:54:00 +0000
+++ data/tribes/workers/atlanteans/soldier/init.lua	2016-02-21 19:03:44 +0000
@@ -77,37 +77,32 @@
 
    animations = animations,
 
-   max_hp_level = 1,
-   max_attack_level = 4,
-   max_defense_level = 2,
-   max_evade_level = 2,
-
-   -- Initial values and per level increments.
-   hp = 13500,
-   hp_incr_per_level = 4000,
+   -- Battle attributes - initial values and per level increase
+   health = {
+      max_level = 1,
+      base = 13500,
+      increase_per_level = 4000,
+      pictures = path.list_files(dirname .. "health_level?.png"),
+   },
    attack = {
-      minimum = 1200,
-      maximum = 1600
-   },
-   attack_incr_per_level = 800,
-   defense = 6,
-   defense_incr_per_level = 8,
-   evade = 30,
-   evade_incr_per_level = 17,
-
-   hp_level_0_pic = dirname .. "hp_level0.png",
-   hp_level_1_pic = dirname .. "hp_level1.png",
-   evade_level_0_pic = dirname .. "evade_level0.png",
-   evade_level_1_pic = dirname .. "evade_level1.png",
-   evade_level_2_pic = dirname .. "evade_level2.png",
-   attack_level_0_pic = dirname .. "attack_level0.png",
-   attack_level_1_pic = dirname .. "attack_level1.png",
-   attack_level_2_pic = dirname .. "attack_level2.png",
-   attack_level_3_pic = dirname .. "attack_level3.png",
-   attack_level_4_pic = dirname .. "attack_level4.png",
-   defense_level_0_pic = dirname .. "defense_level0.png",
-   defense_level_1_pic = dirname .. "defense_level1.png",
-   defense_level_2_pic = dirname .. "defense_level2.png",
+      max_level = 4,
+      base = 1200,
+      maximum = 1600,
+      increase_per_level = 800,
+      pictures = path.list_files(dirname .. "attack_level?.png"),
+   },
+   defense = {
+      max_level = 2,
+      base = 6,
+      increase_per_level = 8,
+      pictures = path.list_files(dirname .. "defense_level?.png"),
+   },
+   evade = {
+      max_level = 2,
+      base = 30,
+      increase_per_level = 17,
+      pictures = path.list_files(dirname .. "evade_level?.png"),
+   },
 
    -- Random animations for battle
    -- TODO(GunChleoc): Make more animations to use the random function

=== renamed file 'data/tribes/workers/barbarians/soldier/hp_level0.png' => 'data/tribes/workers/barbarians/soldier/health_level0.png'
=== renamed file 'data/tribes/workers/barbarians/soldier/hp_level1.png' => 'data/tribes/workers/barbarians/soldier/health_level1.png'
=== renamed file 'data/tribes/workers/barbarians/soldier/hp_level2.png' => 'data/tribes/workers/barbarians/soldier/health_level2.png'
=== renamed file 'data/tribes/workers/barbarians/soldier/hp_level3.png' => 'data/tribes/workers/barbarians/soldier/health_level3.png'
=== modified file 'data/tribes/workers/barbarians/soldier/init.lua'
--- data/tribes/workers/barbarians/soldier/init.lua	2016-02-20 08:51:41 +0000
+++ data/tribes/workers/barbarians/soldier/init.lua	2016-02-21 19:03:44 +0000
@@ -76,38 +76,32 @@
 
    animations = animations,
 
-   max_hp_level = 3,
-   max_attack_level = 5,
-   max_defense_level = 0,
-   max_evade_level = 2,
-
-   -- initial values and per level increasements
-   hp = 13000,
-   hp_incr_per_level = 2800,
+   -- Battle attributes - initial values and per level increase
+   health = {
+      max_level = 3,
+      base = 13000,
+      increase_per_level = 2800,
+      pictures = path.list_files(dirname .. "health_level?.png"),
+   },
    attack = {
-      minimum = 1200,
-      maximum = 1600
-   },
-   attack_incr_per_level = 850,
-   defense = 3,
-   defense_incr_per_level = 4,
-   evade = 25,
-   evade_incr_per_level = 15,
-
-   hp_level_0_pic = dirname .. "hp_level0.png",
-   hp_level_1_pic = dirname .. "hp_level1.png",
-   hp_level_2_pic = dirname .. "hp_level2.png",
-   hp_level_3_pic = dirname .. "hp_level3.png",
-   evade_level_0_pic = dirname .. "evade_level0.png",
-   evade_level_1_pic = dirname .. "evade_level1.png",
-   evade_level_2_pic = dirname .. "evade_level2.png",
-   attack_level_0_pic = dirname .. "attack_level0.png",
-   attack_level_1_pic = dirname .. "attack_level1.png",
-   attack_level_2_pic = dirname .. "attack_level2.png",
-   attack_level_3_pic = dirname .. "attack_level3.png",
-   attack_level_4_pic = dirname .. "attack_level4.png",
-   attack_level_5_pic = dirname .. "attack_level5.png",
-   defense_level_0_pic = dirname .. "defense_level0.png",
+      max_level = 5,
+      base = 1200,
+      maximum = 1600,
+      increase_per_level = 850,
+      pictures = path.list_files(dirname .. "attack_level?.png"),
+   },
+   defense = {
+      max_level = 0,
+      base = 3,
+      increase_per_level = 4,
+      pictures = path.list_files(dirname .. "defense_level?.png"),
+   },
+   evade = {
+      max_level = 2,
+      base = 25,
+      increase_per_level = 15,
+      pictures = path.list_files(dirname .. "evade_level?.png"),
+   },
 
    -- Random animations for battle
    attack_success_w = {

=== renamed file 'data/tribes/workers/empire/soldier/hp_level0.png' => 'data/tribes/workers/empire/soldier/health_level0.png'
=== renamed file 'data/tribes/workers/empire/soldier/hp_level1.png' => 'data/tribes/workers/empire/soldier/health_level1.png'
=== renamed file 'data/tribes/workers/empire/soldier/hp_level2.png' => 'data/tribes/workers/empire/soldier/health_level2.png'
=== renamed file 'data/tribes/workers/empire/soldier/hp_level3.png' => 'data/tribes/workers/empire/soldier/health_level3.png'
=== renamed file 'data/tribes/workers/empire/soldier/hp_level4.png' => 'data/tribes/workers/empire/soldier/health_level4.png'
=== modified file 'data/tribes/workers/empire/soldier/init.lua'
--- data/tribes/workers/empire/soldier/init.lua	2015-12-11 16:54:00 +0000
+++ data/tribes/workers/empire/soldier/init.lua	2016-02-21 19:03:44 +0000
@@ -77,38 +77,32 @@
 
    animations = animations,
 
-   max_hp_level = 4,
-   max_attack_level = 4,
-   max_defense_level = 0,
-   max_evade_level = 2,
-
-   -- initial values and per level increasements
-   hp = 13000,
-   hp_incr_per_level = 2100,
+   -- Battle attributes - initial values and per level increase
+   health = {
+      max_level = 4,
+      base = 13000,
+      increase_per_level = 2100,
+      pictures = path.list_files(dirname .. "health_level?.png"),
+   },
    attack = {
-      minimum = 1300,
-      maximum = 1500
-   },
-   attack_incr_per_level = 800,
-   defense = 5,
-   defense_incr_per_level = 5,
-   evade = 30,
-   evade_incr_per_level = 16,
-
-   hp_level_0_pic = dirname .. "hp_level0.png",
-   hp_level_1_pic = dirname .. "hp_level1.png",
-   hp_level_2_pic = dirname .. "hp_level2.png",
-   hp_level_3_pic = dirname .. "hp_level3.png",
-   hp_level_4_pic = dirname .. "hp_level4.png",
-   evade_level_0_pic = dirname .. "evade_level0.png",
-   evade_level_1_pic = dirname .. "evade_level1.png",
-   evade_level_2_pic = dirname .. "evade_level2.png",
-   attack_level_0_pic = dirname .. "attack_level0.png",
-   attack_level_1_pic = dirname .. "attack_level1.png",
-   attack_level_2_pic = dirname .. "attack_level2.png",
-   attack_level_3_pic = dirname .. "attack_level3.png",
-   attack_level_4_pic = dirname .. "attack_level4.png",
-   defense_level_0_pic = dirname .. "defense_level0.png",
+      max_level = 4,
+      base = 1300,
+      maximum = 1500,
+      increase_per_level = 800,
+      pictures = path.list_files(dirname .. "attack_level?.png"),
+   },
+   defense = {
+      max_level = 0,
+      base = 5,
+      increase_per_level = 5,
+      pictures = path.list_files(dirname .. "defense_level?.png"),
+   },
+   evade = {
+      max_level = 2,
+      base = 30,
+      increase_per_level = 16,
+      pictures = path.list_files(dirname .. "evade_level?.png"),
+   },
 
    -- Random animations for battle
    attack_success_w = {

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2016-02-18 08:42:46 +0000
+++ src/ai/defaultai.cc	2016-02-21 19:03:44 +0000
@@ -5259,37 +5259,37 @@
 			soldiers.at(0)->get_owner()->tribe().name().c_str());
 	}
 
-	float hp = 0;
-	float al = 0;
-	float dl = 0;
-	float el = 0;
+	float health = 0;
+	float attack = 0;
+	float defense = 0;
+	float evade = 0;
 	float final = 0;
 
 	for (Soldier * soldier : soldiers) {
 		switch (tribe) {
 			case (Tribes::kAtlanteans):
-				hp = 135 + 40 * soldier->get_hp_level();
-				al =  14 +  8 * soldier->get_attack_level();
-				dl = static_cast<float>(94 -  8 * soldier->get_defense_level()) / 100;
-				el = static_cast<float>(70 - 17 * soldier->get_evade_level()) / 100;
+				health = 135 + 40 * soldier->get_health_level();
+				attack =  14 +  8 * soldier->get_attack_level();
+				defense = static_cast<float>(94 -  8 * soldier->get_defense_level()) / 100;
+				evade = static_cast<float>(70 - 17 * soldier->get_evade_level()) / 100;
 				break;
 			case (Tribes::kBarbarians):
-				hp += 130 + 28 * soldier->get_hp_level();
-				al +=  14 +  7 * soldier->get_attack_level();
-				dl += static_cast<float>(97 -  8 * soldier->get_defense_level()) / 100;
-				el += static_cast<float>(75 - 15 * soldier->get_evade_level()) / 100;
+				health += 130 + 28 * soldier->get_health_level();
+				attack +=  14 +  7 * soldier->get_attack_level();
+				defense += static_cast<float>(97 -  8 * soldier->get_defense_level()) / 100;
+				evade += static_cast<float>(75 - 15 * soldier->get_evade_level()) / 100;
 				break;
 			case (Tribes::kEmpire):
-				hp += 130 + 21 * soldier->get_hp_level();
-				al +=  14 +  8 * soldier->get_attack_level();
-				dl += static_cast<float>(95 -  8 * soldier->get_defense_level()) / 100;
-				el += static_cast<float>(70 - 16 * soldier->get_evade_level()) / 100;
+				health += 130 + 21 * soldier->get_health_level();
+				attack +=  14 +  8 * soldier->get_attack_level();
+				defense += static_cast<float>(95 -  8 * soldier->get_defense_level()) / 100;
+				evade += static_cast<float>(70 - 16 * soldier->get_evade_level()) / 100;
 				break;
 			default:
 				NEVER_HERE();
 		}
 
-		final += (al * hp) / (dl * el);
+		final += (attack * health) / (defense * evade);
 	}
 
 	// 2500 is aproximate strength of one unpromoted soldier

=== modified file 'src/logic/findbob.cc'
--- src/logic/findbob.cc	2016-02-15 23:26:42 +0000
+++ src/logic/findbob.cc	2016-02-21 19:03:44 +0000
@@ -36,7 +36,7 @@
 		if
 			(soldier->is_on_battlefield() &&
 			 (!player || soldier->owner().is_hostile(*player)) &&
-			 soldier->get_current_hitpoints())
+			 soldier->get_current_health())
 			return true;
 
 	return false;

=== modified file 'src/logic/game.cc'
--- src/logic/game.cc	2016-02-21 18:02:23 +0000
+++ src/logic/game.cc	2016-02-21 19:03:44 +0000
@@ -792,11 +792,11 @@
 
 
 void Game::send_player_change_training_options
-	(TrainingSite & ts, int32_t const atr, int32_t const val)
+	(TrainingSite & ts, TrainingAttribute attr, int32_t const val)
 {
 	send_player_command
 		(*new CmdChangeTrainingOptions
-		 	(get_gametime(), ts.owner().player_number(), ts, atr, val));
+			(get_gametime(), ts.owner().player_number(), ts, attr, val));
 }
 
 void Game::send_player_drop_soldier (Building & b, int32_t const ser)
@@ -931,7 +931,7 @@
 		for (Bob const * b = fc.field->get_first_bob(); b; b = b->get_next_bob())
 			if (upcast(Soldier const, s, b))
 				miltary_strength[s->owner().player_number() - 1] +=
-					s->get_level(atrTotal) + 1; //  So that level 0 also counts.
+					s->get_level(TrainingAttribute::kTotal) + 1; //  So that level 0 also counts.
 	}
 
 	//  Number of workers / wares / casualties / kills.

=== modified file 'src/logic/game.h'
--- src/logic/game.h	2016-02-21 18:02:23 +0000
+++ src/logic/game.h	2016-02-21 19:03:44 +0000
@@ -184,7 +184,7 @@
 		(PlayerImmovable &, int32_t type, DescriptionIndex index, int32_t prio);
 	void send_player_set_ware_max_fill
 		(PlayerImmovable &, DescriptionIndex index, uint32_t);
-	void send_player_change_training_options(TrainingSite &, int32_t, int32_t);
+	void send_player_change_training_options(TrainingSite &, TrainingAttribute, int32_t);
 	void send_player_drop_soldier(Building &, int32_t);
 	void send_player_change_soldier_capacity(Building &, int32_t);
 	void send_player_enemyflagaction

=== modified file 'src/logic/map_objects/map_object.cc'
--- src/logic/map_objects/map_object.cc	2016-02-07 09:30:20 +0000
+++ src/logic/map_objects/map_object.cc	2016-02-21 19:03:44 +0000
@@ -487,7 +487,7 @@
 /**
  * Default implementation
  */
-int32_t MapObject::get_training_attribute(uint32_t) const
+int32_t MapObject::get_training_attribute(TrainingAttribute) const
 {
 	return -1;
 }

=== modified file 'src/logic/map_objects/map_object.h'
--- src/logic/map_objects/map_object.h	2016-02-09 16:29:48 +0000
+++ src/logic/map_objects/map_object.h	2016-02-21 19:03:44 +0000
@@ -35,6 +35,7 @@
 #include "graphic/color.h"
 #include "graphic/image.h"
 #include "logic/cmd_queue.h"
+#include "logic/map_objects/tribes/training_attribute.h"
 #include "logic/widelands.h"
 #include "scripting/lua_table.h"
 
@@ -271,7 +272,7 @@
 	 * doesn't have this kind of attribute.
 	 * The default behaviour returns \c -1 for all attributes.
 	 */
-	virtual int32_t get_training_attribute(uint32_t attr) const;
+	virtual int32_t get_training_attribute(TrainingAttribute attr) const;
 
 	void remove(EditorGameBase &);
 	virtual void destroy(EditorGameBase &);

=== modified file 'src/logic/map_objects/tribes/battle.cc'
--- src/logic/map_objects/tribes/battle.cc	2016-02-08 17:25:17 +0000
+++ src/logic/map_objects/tribes/battle.cc	2016-02-21 19:03:44 +0000
@@ -71,7 +71,7 @@
 	}
 
 	// Ensures only live soldiers eganges in a battle
-	assert(First.get_current_hitpoints() && Second.get_current_hitpoints());
+	assert(First.get_current_health() && Second.get_current_health());
 
 	init(game);
 }
@@ -184,7 +184,7 @@
 		damage_ = 0;
 	}
 
-	if (soldier.get_current_hitpoints() < 1) {
+	if (soldier.get_current_health() < 1) {
 		molog("[battle] soldier %u lost the battle\n", soldier.serial());
 		soldier          . owner().count_casualty();
 		opponent(soldier)->owner().count_kill    ();

=== modified file 'src/logic/map_objects/tribes/militarysite.cc'
--- src/logic/map_objects/tribes/militarysite.cc	2016-02-13 12:15:29 +0000
+++ src/logic/map_objects/tribes/militarysite.cc	2016-02-21 19:03:44 +0000
@@ -289,7 +289,7 @@
 	int worst_soldier_level = INT_MIN;
 	Soldier * worst_soldier = nullptr;
 	for (Soldier* sld : present) {
-		int this_soldier_level = multiplier * static_cast<int> (sld->get_level(atrTotal));
+		int this_soldier_level = multiplier * static_cast<int> (sld->get_level(TrainingAttribute::kTotal));
 		if (this_soldier_level > worst_soldier_level)
 		{
 			worst_soldier_level = this_soldier_level;
@@ -327,8 +327,8 @@
 		// If the arriving guy is worse than worst present, I wont't release.
 		if (nullptr != newguy && nullptr != kickoutCandidate)
 		{
-			int32_t old_level = kickoutCandidate->get_level(atrTotal);
-			int32_t new_level = newguy->get_level(atrTotal);
+			int32_t old_level = kickoutCandidate->get_level(TrainingAttribute::kTotal);
+			int32_t new_level = newguy->get_level(TrainingAttribute::kTotal);
 			if (kPrefersHeroes == soldier_preference_ && old_level >= new_level)
 			{
 				return false;
@@ -599,12 +599,12 @@
 			// The healing algorithm is:
 			// * heal soldier with highest total level
 			// * heal healthiest if multiple of same total level exist
-			if (s->get_current_hitpoints() < s->get_max_hitpoints()) {
+			if (s->get_current_health() < s->get_max_health()) {
 				if (0 == soldier_to_heal || s->get_total_level() > max_total_level ||
 						(s->get_total_level() == max_total_level &&
-								s->get_current_hitpoints() / s->get_max_hitpoints() > max_health)) {
+								s->get_current_health() / s->get_max_health() > max_health)) {
 					max_total_level = s->get_total_level();
-					max_health = s->get_current_hitpoints() / s->get_max_hitpoints();
+					max_health = s->get_current_health() / s->get_max_health();
 					soldier_to_heal = s;
 				}
 			}
@@ -824,12 +824,12 @@
 	Soldier * defender = nullptr;
 
 	if (!present.empty()) {
-		// Find soldier with greatest hitpoints
+		// Find soldier with greatest health
 		uint32_t current_max = 0;
 		for (Soldier * temp_soldier : present) {
-			if (temp_soldier->get_current_hitpoints() > current_max) {
+			if (temp_soldier->get_current_health() > current_max) {
 				defender = temp_soldier;
-				current_max = defender->get_current_hitpoints();
+				current_max = defender->get_current_health();
 			}
 		}
 	} else {
@@ -1074,7 +1074,7 @@
 		// There could be no soldier in the militarysite right now. No reason to freak out.
 		return false;
 	}
-	int32_t wg_level = worst_guy->get_level(atrTotal);
+	int32_t wg_level = worst_guy->get_level(TrainingAttribute::kTotal);
 
 	// Micro-optimization: I assume that the majority of military sites have only level-zero
 	// soldiers and prefer rookies. Handle them separately.
@@ -1100,7 +1100,7 @@
 		{
 			upgrade_soldier_request_.reset();
 		}
-		soldier_upgrade_requirements_ = RequireAttribute(atrTotal, reqmin, reqmax);
+		soldier_upgrade_requirements_ = RequireAttribute(TrainingAttribute::kTotal, reqmin, reqmax);
 
 		return true;
 	}

=== modified file 'src/logic/map_objects/tribes/production_program.cc'
--- src/logic/map_objects/tribes/production_program.cc	2016-02-18 08:42:46 +0000
+++ src/logic/map_objects/tribes/production_program.cc	2016-02-21 19:03:44 +0000
@@ -1354,18 +1354,18 @@
 		throw GameDataError
 			("expected %s but found \"%s\"", "soldier type", parameters);
 	try {
-		if      (match_force_skip(parameters, "hp"))
-			attribute = atrHP;
+		if      (match_force_skip(parameters, "health"))
+			attribute = TrainingAttribute::kHealth;
 		else if (match_force_skip(parameters, "attack"))
-			attribute = atrAttack;
+			attribute = TrainingAttribute::kAttack;
 		else if (match_force_skip(parameters, "defense"))
-			attribute = atrDefense;
+			attribute = TrainingAttribute::kDefense;
 		else if (match_force_skip(parameters, "evade"))
-			attribute = atrEvade;
+			attribute = TrainingAttribute::kEvade;
 		else
 			throw GameDataError
 				("expected %s but found \"%s\"",
-					"{\"hp\"|\"attack\"|\"defense\"|\"evade\"}", parameters);
+					"{\"health\"|\"attack\"|\"defense\"|\"evade\"}", parameters);
 
 		char * endp;
 		unsigned long long int const value = strtoull(parameters, &endp, 0);
@@ -1395,16 +1395,16 @@
 			ps.set_production_result(_("No soldier found for this training level!"));
 			return ps.program_end(game, Skipped);
 		}
-		if        (attribute == atrHP)      {
-			if ((*it)->get_hp_level()      == level)
+		if        (attribute == TrainingAttribute::kHealth)  {
+			if ((*it)->get_health_level()  == level)
 				break;
-		} else if (attribute == atrAttack)  {
+		} else if (attribute == TrainingAttribute::kAttack) {
 			if ((*it)->get_attack_level()  == level)
 				break;
-		} else if (attribute == atrDefense) {
+		} else if (attribute == TrainingAttribute::kDefense) {
 			if ((*it)->get_defense_level() == level)
 				break;
-		} else if (attribute == atrEvade)   {
+		} else if (attribute == TrainingAttribute::kEvade) {
 			if ((*it)->get_evade_level()   == level)
 				break;
 		}
@@ -1426,18 +1426,18 @@
 		throw GameDataError
 			("expected %s but found \"%s\"", "soldier type", parameters);
 	try {
-		if      (match_force_skip(parameters, "hp"))
-			attribute = atrHP;
+		if      (match_force_skip(parameters, "health"))
+			attribute = TrainingAttribute::kHealth;
 		else if (match_force_skip(parameters, "attack"))
-			attribute = atrAttack;
+			attribute = TrainingAttribute::kAttack;
 		else if (match_force_skip(parameters, "defense"))
-			attribute = atrDefense;
+			attribute = TrainingAttribute::kDefense;
 		else if (match_force_skip(parameters, "evade"))
-			attribute = atrEvade;
+			attribute = TrainingAttribute::kEvade;
 		else
 			throw GameDataError
 				("expected %s but found \"%s\"",
-				 "{\"hp\"|\"attack\"|\"defense\"|\"evade\"}", parameters);
+				 "{\"health\"|\"attack\"|\"defense\"|\"evade\"}", parameters);
 
 		{
 			char * endp;
@@ -1480,31 +1480,32 @@
 			ps.set_production_result(_("No soldier found for this training level!"));
 			return ps.program_end(game, Skipped);
 		}
-		if        (attribute == atrHP)      {
-			if ((*it)->get_hp_level     () == level)
+		if        (attribute == TrainingAttribute::kHealth) {
+			if ((*it)->get_health_level () == level)
 				break;
-		} else if (attribute == atrAttack)  {
+		} else if (attribute == TrainingAttribute::kAttack) {
 			if ((*it)->get_attack_level () == level)
 				break;
-		} else if (attribute == atrDefense) {
+		} else if (attribute == TrainingAttribute::kDefense) {
 			if ((*it)->get_defense_level() == level)
 				break;
-		} else if (attribute == atrEvade)
+		} else if (attribute == TrainingAttribute::kEvade) {
 			if ((*it)->get_evade_level  () == level)
 				break;
+		}
 	}
 	ps.molog("    okay\n"); // okay, do nothing
 
 		try {
-			if      (attribute == atrHP)
-				(*it)->set_hp_level      (target_level);
-			else if (attribute == atrAttack)
+			if      (attribute == TrainingAttribute::kHealth)
+				(*it)->set_health_level  (target_level);
+			else if (attribute == TrainingAttribute::kAttack)
 				(*it)->set_attack_level  (target_level);
 
-			else if (attribute == atrDefense)
+			else if (attribute == TrainingAttribute::kDefense)
 				(*it)->set_defense_level (target_level);
 
-			else if (attribute == atrEvade)
+			else if (attribute == TrainingAttribute::kEvade)
 				(*it)->set_evade_level   (target_level);
 
 		} catch (...) {

=== modified file 'src/logic/map_objects/tribes/requirements.cc'
--- src/logic/map_objects/tribes/requirements.cc	2016-02-14 14:09:29 +0000
+++ src/logic/map_objects/tribes/requirements.cc	2016-02-21 19:03:44 +0000
@@ -32,7 +32,7 @@
 	return !m || m->check(obj);
 }
 
-constexpr uint16_t kCurrentPacketVersion = 3;
+constexpr uint16_t kCurrentPacketVersion = 4;
 
 /**
  * Read this requirement from a file
@@ -201,7 +201,7 @@
 
 bool RequireAttribute::check(const MapObject & obj) const
 {
-	if (atrTotal != at)
+	if (TrainingAttribute::kTotal != at)
 	{
 		int32_t const value = obj.get_training_attribute(at);
 
@@ -210,10 +210,10 @@
 	else
 	{
 		int32_t value = 0;
-		value += obj.get_training_attribute(atrHP);
-		value += obj.get_training_attribute(atrAttack);
-		value += obj.get_training_attribute(atrDefense);
-		value += obj.get_training_attribute(atrEvade);
+		value += obj.get_training_attribute(TrainingAttribute::kHealth);
+		value += obj.get_training_attribute(TrainingAttribute::kAttack);
+		value += obj.get_training_attribute(TrainingAttribute::kDefense);
+		value += obj.get_training_attribute(TrainingAttribute::kEvade);
 		return value >= min && value <= max;
 	}
 }
@@ -221,7 +221,7 @@
 void RequireAttribute::write
 	(FileWrite & fw, EditorGameBase &, MapObjectSaver &) const
 {
-	fw.unsigned_32(at);
+	fw.unsigned_8(static_cast<uint8_t>(at));
 	fw.signed_32(min);
 	fw.signed_32(max);
 }
@@ -229,16 +229,23 @@
 static Requirements read_attribute
 	(FileRead & fr, EditorGameBase &, MapObjectLoader &)
 {
-	TrainingAttribute const at  = static_cast<TrainingAttribute>(fr.unsigned_32());
+	TrainingAttribute const at  = static_cast<TrainingAttribute>(fr.unsigned_8());
 	if
-		(at != atrHP && at != atrAttack && at != atrDefense && at != atrEvade
-		 &&
-		 at != atrTotal)
+		(at != TrainingAttribute::kHealth
+		 && at != TrainingAttribute::kAttack
+		 && at != TrainingAttribute::kDefense
+		 && at != TrainingAttribute::kEvade
+		 && at != TrainingAttribute::kTotal)
 		throw GameDataError
 			(
-			 "expected atrHP (%u), atrAttack (%u), atrDefense (%u), atrEvade "
-			 "(%u) or atrTotal (%u) but found unknown attribute value (%u)",
-			 atrHP, atrAttack, atrDefense, atrEvade, atrTotal, at);
+			 "expected kHealth (%u), kAttack (%u), kDefense (%u), kEvade "
+			 "(%u) or kTotal (%u) but found unknown attribute value (%u)",
+				TrainingAttribute::kHealth,
+				TrainingAttribute::kAttack,
+				TrainingAttribute::kDefense,
+				TrainingAttribute::kEvade,
+				TrainingAttribute::kTotal,
+				at);
 	int32_t const min = fr.signed_32();
 	int32_t const max = fr.signed_32();
 

=== modified file 'src/logic/map_objects/tribes/requirements.h'
--- src/logic/map_objects/tribes/requirements.h	2016-02-14 14:09:29 +0000
+++ src/logic/map_objects/tribes/requirements.h	2016-02-21 19:03:44 +0000
@@ -176,7 +176,7 @@
 		(TrainingAttribute const init_at, int32_t const init_min, int32_t const init_max)
 		: at(init_at), min(init_min), max(init_max) {}
 
-	RequireAttribute() : at(atrTotal), min(SHRT_MIN), max(SHRT_MAX) {}
+	RequireAttribute() : at(TrainingAttribute::kTotal), min(SHRT_MIN), max(SHRT_MAX) {}
 	bool check(const MapObject &) const;
 	void write
 		(FileWrite &, EditorGameBase & egbase, MapObjectSaver &) const;

=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc	2016-02-16 13:15:29 +0000
+++ src/logic/map_objects/tribes/soldier.cc	2016-02-21 19:03:44 +0000
@@ -64,58 +64,15 @@
 SoldierDescr::SoldierDescr(const std::string& init_descname,
 									const LuaTable& table,
 									const EditorGameBase& egbase) :
-	WorkerDescr(init_descname, MapObjectType::SOLDIER, table, egbase)
+	WorkerDescr(init_descname, MapObjectType::SOLDIER, table, egbase),
+	health_(table.get_table("health")),
+	attack_(table.get_table("attack")),
+	defense_(table.get_table("defense")),
+	evade_(table.get_table("evade"))
 {
 	add_attribute(MapObject::Attribute::SOLDIER);
 
-	base_hp_ = table.get_int("hp");
-
-	// Parse attack
-	std::unique_ptr<LuaTable> items_table = table.get_table("attack");
-	min_attack_ = items_table->get_int("minimum");
-	max_attack_ = items_table->get_int("maximum");
-	if (min_attack_ > max_attack_) {
-		throw GameDataError("Minimum attack %d is greater than maximum attack %d.", min_attack_, max_attack_);
-	}
-
-	// Parse defend
-	defense_           = table.get_int("defense");
-
-	// Parse evade
-	evade_             = table.get_int("evade");
-
-	// Parse increases per level
-	hp_incr_           = table.get_int("hp_incr_per_level");
-	attack_incr_       = table.get_int("attack_incr_per_level");
-	defense_incr_      = table.get_int("defense_incr_per_level");
-	evade_incr_        = table.get_int("evade_incr_per_level");
-
-	// Parse max levels
-	max_hp_level_      = table.get_int("max_hp_level");
-	max_attack_level_  = table.get_int("max_attack_level");
-	max_defense_level_ = table.get_int("max_defense_level");
-	max_evade_level_   = table.get_int("max_evade_level");
-
-	// Load the filenames
-	hp_pics_fn_     .resize(max_hp_level_      + 1);
-	attack_pics_fn_ .resize(max_attack_level_  + 1);
-	defense_pics_fn_.resize(max_defense_level_ + 1);
-	evade_pics_fn_  .resize(max_evade_level_   + 1);
-
-	for (uint32_t i = 0; i <= max_hp_level_;      ++i) {
-		hp_pics_fn_[i] = table.get_string((boost::format("hp_level_%u_pic") % i).str());
-	}
-	for (uint32_t i = 0; i <= max_attack_level_;  ++i) {
-		attack_pics_fn_[i] = table.get_string((boost::format("attack_level_%u_pic") % i).str());
-	}
-	for (uint32_t i = 0; i <= max_defense_level_; ++i) {
-		defense_pics_fn_[i] = table.get_string((boost::format("defense_level_%u_pic") % i).str());
-	}
-	for (uint32_t i = 0; i <= max_evade_level_;   ++i) {
-		evade_pics_fn_[i] = table.get_string((boost::format("evade_level_%u_pic") % i).str());
-	}
-
-	//  Battle animations
+	// Battle animations
 	// attack_success_*-> soldier is attacking and hit his opponent
 	add_battle_animation(table.get_table("attack_success_w"), &attack_success_w_name_);
 	add_battle_animation(table.get_table("attack_success_e"), &attack_success_e_name_);
@@ -135,23 +92,32 @@
 	// die_*           -> soldier is dying
 	add_battle_animation(table.get_table("die_w"), &die_w_name_);
 	add_battle_animation(table.get_table("die_e"), &die_e_name_);
+}
+
+SoldierDescr::BattleAttribute::BattleAttribute(std::unique_ptr<LuaTable> table) {
+	base = table->get_int("base");
+
+	if (table->has_key("maximum")) {
+		 maximum = table->get_int("maximum");
+		 if (base > maximum) {
+			 throw GameDataError("Minimum %d is greater than maximum %d for a soldier's battle attribute.",
+										base, maximum);
+		 }
+	} else {
+		maximum = base;
+	}
+	increase = table->get_int("increase_per_level");
+	max_level = table->get_int("max_level");
 
 	// Load Graphics
-	hp_pics_     .resize(max_hp_level_      + 1);
-	attack_pics_ .resize(max_attack_level_  + 1);
-	defense_pics_.resize(max_defense_level_ + 1);
-	evade_pics_  .resize(max_evade_level_   + 1);
-	for (uint32_t i = 0; i <= max_hp_level_;      ++i)
-		hp_pics_[i] = g_gr->images().get(hp_pics_fn_[i]);
-	for (uint32_t i = 0; i <= max_attack_level_;  ++i)
-		attack_pics_[i] =
-			g_gr->images().get(attack_pics_fn_[i]);
-	for (uint32_t i = 0; i <= max_defense_level_; ++i)
-		defense_pics_[i] =
-			g_gr->images().get(defense_pics_fn_[i]);
-	for (uint32_t i = 0; i <= max_evade_level_;   ++i)
-		evade_pics_[i] =
-			g_gr->images().get(evade_pics_fn_[i]);
+	std::vector<std::string> image_filenames = table->get_table("pictures")->array_entries<std::string>();
+	if (image_filenames.size() != max_level + 1) {
+		throw GameDataError("Soldier needs to have %d pictures for battle attribute, but found %lu",
+									max_level + 1, image_filenames.size());
+	}
+	for (const std::string& image_filename : image_filenames) {
+		images.push_back(g_gr->images().get(image_filename));
+	}
 }
 
 /**
@@ -253,12 +219,12 @@
 Soldier::Soldier(const SoldierDescr & soldier_descr) : Worker(soldier_descr)
 {
 	battle_ = nullptr;
-	hp_level_      = 0;
+	health_level_  = 0;
 	attack_level_  = 0;
 	defense_level_ = 0;
 	evade_level_   = 0;
 
-	hp_current_    = get_max_hitpoints();
+	current_health_    = get_max_health();
 
 	combat_walking_   = CD_NONE;
 	combat_walkstart_ = 0;
@@ -268,12 +234,12 @@
 
 void Soldier::init(EditorGameBase & egbase)
 {
-	hp_level_      = 0;
+	health_level_  = 0;
 	attack_level_  = 0;
 	defense_level_ = 0;
 	evade_level_   = 0;
 
-	hp_current_    = get_max_hitpoints();
+	current_health_ = get_max_health();
 
 	combat_walking_   = CD_NONE;
 	combat_walkstart_ = 0;
@@ -296,26 +262,26 @@
  * Set this soldiers level. Automatically sets the new values
  */
 void Soldier::set_level
-	(uint32_t const hp,
+	(uint32_t const health,
 	 uint32_t const attack,
 	 uint32_t const defense,
 	 uint32_t const evade)
 {
-	set_hp_level(hp);
+	set_health_level(health);
 	set_attack_level(attack);
 	set_defense_level(defense);
 	set_evade_level(evade);
 }
-void Soldier::set_hp_level(const uint32_t hp) {
-	assert(hp_level_ <= hp);
-	assert              (hp <= descr().get_max_hp_level());
-
-	uint32_t oldmax = get_max_hitpoints();
-
-	hp_level_ = hp;
-
-	uint32_t newmax = get_max_hitpoints();
-	hp_current_ = hp_current_ * newmax / oldmax;
+void Soldier::set_health_level(const uint32_t health) {
+	assert(health_level_ <= health);
+	assert(health <= descr().get_max_health_level());
+
+	uint32_t oldmax = get_max_health();
+
+	health_level_ = health;
+
+	uint32_t newmax = get_max_health();
+	current_health_ = current_health_ * newmax / oldmax;
 }
 void Soldier::set_attack_level(const uint32_t attack) {
 	assert(attack_level_ <= attack);
@@ -338,34 +304,34 @@
 
 uint32_t Soldier::get_level(TrainingAttribute const at) const {
 	switch (at) {
-	case atrHP:      return hp_level_;
-	case atrAttack:  return attack_level_;
-	case atrDefense: return defense_level_;
-	case atrEvade:   return evade_level_;
-	case atrTotal:
-		return hp_level_ + attack_level_ + defense_level_ + evade_level_;
+	case TrainingAttribute::kHealth:  return health_level_;
+	case TrainingAttribute::kAttack:  return attack_level_;
+	case TrainingAttribute::kDefense: return defense_level_;
+	case TrainingAttribute::kEvade:   return evade_level_;
+	case TrainingAttribute::kTotal:
+		return health_level_ + attack_level_ + defense_level_ + evade_level_;
 	}
 	NEVER_HERE();
 }
 
 
-int32_t Soldier::get_training_attribute(uint32_t const attr) const
+int32_t Soldier::get_training_attribute(TrainingAttribute const attr) const
 {
 	switch (attr) {
-	case atrHP: return hp_level_;
-	case atrAttack: return attack_level_;
-	case atrDefense: return defense_level_;
-	case atrEvade: return evade_level_;
-	case atrTotal:
-		return hp_level_ + attack_level_ + defense_level_ + evade_level_;
+	case TrainingAttribute::kHealth: return health_level_;
+	case TrainingAttribute::kAttack: return attack_level_;
+	case TrainingAttribute::kDefense: return defense_level_;
+	case TrainingAttribute::kEvade: return evade_level_;
+	case TrainingAttribute::kTotal:
+		return health_level_ + attack_level_ + defense_level_ + evade_level_;
 	default:
 		return Worker::get_training_attribute(attr);
 	}
 }
 
-uint32_t Soldier::get_max_hitpoints() const
+uint32_t Soldier::get_max_health() const
 {
-	return descr().get_base_hp() + hp_level_ * descr().get_hp_incr_per_level();
+	return descr().get_base_health() + health_level_ * descr().get_health_incr_per_level();
 }
 
 uint32_t Soldier::get_min_attack() const
@@ -397,29 +363,29 @@
 }
 
 //  Unsignedness ensures that we can only heal, not hurt through this method.
-void Soldier::heal (const uint32_t hp) {
+void Soldier::heal (const uint32_t health) {
 	molog
-		("[soldier] healing (%d+)%d/%d\n", hp, hp_current_, get_max_hitpoints());
-	assert(hp);
-	assert(hp_current_ <  get_max_hitpoints());
-	hp_current_ += std::min(hp, get_max_hitpoints() - hp_current_);
-	assert(hp_current_ <= get_max_hitpoints());
+		("[soldier] healing (%d+)%d/%d\n", health, current_health_, get_max_health());
+	assert(health);
+	assert(current_health_ <  get_max_health());
+	current_health_ += std::min(health, get_max_health() - current_health_);
+	assert(current_health_ <= get_max_health());
 }
 
 /**
- * This only subs the specified number of hitpoints, don't do anything more.
+ * This only subs the specified number of health points, don't do anything more.
  */
 void Soldier::damage (const uint32_t value)
 {
-	assert (hp_current_ > 0);
+	assert (current_health_ > 0);
 
 	molog
 		("[soldier] damage %d(-%d)/%d\n",
-		 hp_current_, value, get_max_hitpoints());
-	if (hp_current_ < value)
-		hp_current_ = 0;
+		 current_health_, value, get_max_health());
+	if (current_health_ < value)
+		current_health_ = 0;
 	else
-		hp_current_ -= value;
+		current_health_ -= value;
 }
 
 /// Calculates the actual position to draw on from the base node position.
@@ -486,7 +452,7 @@
 }
 
 /*
- * Draw this soldier. This basically draws him as a worker, but add hitpoints
+ * Draw this soldier. This basically draws him as a worker, but add health points
  */
 void Soldier::draw
 	(const EditorGameBase & game, RenderTarget & dst, const Point& pos) const
@@ -501,7 +467,7 @@
 }
 
 /**
- * Draw the info icon (level indicators + HP bar) for this soldier.
+ * Draw the info icon (level indicators + health bar) for this soldier.
  *
  * \param anchor_below if \c true, the icon is drawn horizontally centered above
  * \p pt. Otherwise, the icon is drawn below and right of \p pt.
@@ -511,15 +477,15 @@
 {
 	// Gather information to determine coordinates
 	uint32_t w;
-	w = kSoldierHpBarWidth;
+	w = kSoldierHealthBarWidth;
 
-	const Image* hppic = get_hp_level_pic();
+	const Image* healthpic = get_health_level_pic();
 	const Image* attackpic = get_attack_level_pic();
 	const Image* defensepic = get_defense_level_pic();
 	const Image* evadepic = get_evade_level_pic();
 
-	uint16_t hpw = hppic->width();
-	uint16_t hph = hppic->height();
+	uint16_t hpw = healthpic->width();
+	uint16_t hph = healthpic->height();
 	uint16_t atw = attackpic->width();
 	uint16_t ath = attackpic->height();
 	uint16_t dew = defensepic->width();
@@ -539,10 +505,10 @@
 
 	// Draw energy bar
 	Rect energy_outer(Point(pt.x - w, pt.y), w * 2, 5);
-	dst.draw_rect(energy_outer, HP_FRAMECOLOR);
+	dst.draw_rect(energy_outer, RGBColor(255, 255, 255));
 
-	assert(get_max_hitpoints());
-	uint32_t health_width = 2 * (w - 1) * hp_current_ / get_max_hitpoints();
+	assert(get_max_health());
+	uint32_t health_width = 2 * (w - 1) * current_health_ / get_max_health();
 	Rect energy_inner(Point(pt.x - w + 1, pt.y + 1), health_width, 3);
 	Rect energy_complement
 		(energy_inner.origin() + Point(health_width, 0), 2 * (w - 1) - health_width, 3);
@@ -561,13 +527,13 @@
 	{
 		dst.blit(pt + Point(-atw, -(hph + ath)), attackpic);
 		dst.blit(pt + Point(0, -(evh + deh)), defensepic);
-		dst.blit(pt + Point(-hpw, -hph), hppic);
+		dst.blit(pt + Point(-hpw, -hph), healthpic);
 		dst.blit(pt + Point(0, -evh), evadepic);
 	}
 }
 
 /**
- * Compute the size of the info icon (level indicators + HP bar) for soldiers of
+ * Compute the size of the info icon (level indicators + health bar) for soldiers of
  * the given tribe.
  */
 void Soldier::calc_info_icon_size
@@ -575,12 +541,12 @@
 {
 	const SoldierDescr * soldierdesc = static_cast<const SoldierDescr *>
 		(tribe.get_worker_descr(tribe.soldier()));
-	const Image* hppic = soldierdesc->get_hp_level_pic(0);
+	const Image* healthpic = soldierdesc->get_health_level_pic(0);
 	const Image* attackpic = soldierdesc->get_attack_level_pic(0);
 	const Image* defensepic = soldierdesc->get_defense_level_pic(0);
 	const Image* evadepic = soldierdesc->get_evade_level_pic(0);
-	uint16_t hpw = hppic->width();
-	uint16_t hph = hppic->height();
+	uint16_t hpw = healthpic->width();
+	uint16_t hph = healthpic->height();
 	uint16_t atw = attackpic->width();
 	uint16_t ath = attackpic->height();
 	uint16_t dew = defensepic->width();
@@ -589,7 +555,7 @@
 	uint16_t evh = evadepic->height();
 
 	uint16_t animw;
-	animw = kSoldierHpBarWidth;
+	animw = kSoldierHealthBarWidth;
 
 	w = std::max(std::max(atw + dew, hpw + evw), 2 * animw);
 	h = 5 + std::max(hph + ath, evh + deh);
@@ -657,7 +623,7 @@
  */
 bool Soldier::can_be_challenged()
 {
-	if (hp_current_ < 1) {  //< Soldier is dead!
+	if (current_health_ < 1) {  //< Soldier is dead!
 		return false;
 	}
 	if (!is_on_battlefield()) {
@@ -686,7 +652,7 @@
  * Set a fallback task.
  */
 void Soldier::init_auto_task(Game & game) {
-	if (get_current_hitpoints() < 1) {
+	if (get_current_health() < 1) {
 		molog("[soldier] init_auto_task: die\n");
 		return start_task_die(game);
 	}
@@ -730,11 +696,11 @@
 	state.ivar3    = 0; // Counts how often the soldier is blocked in a row
 
 	state.ivar1    |= CF_RETREAT_WHEN_INJURED;
-	state.ui32var3 = kRetreatWhenHealthDropsBelowThisPercentage * get_max_hitpoints() / 100;
+	state.ui32var3 = kRetreatWhenHealthDropsBelowThisPercentage * get_max_health() / 100;
 
 	// Injured soldiers are not allowed to attack
-	if (state.ui32var3 > get_current_hitpoints()) {
-		state.ui32var3 = get_current_hitpoints();
+	if (state.ui32var3 > get_current_health()) {
+		state.ui32var3 = get_current_health();
 	}
 }
 
@@ -918,11 +884,11 @@
 	if
 		(!enemy ||
 		 ((state.ivar1 & CF_RETREAT_WHEN_INJURED) &&
-		  state.ui32var3 > get_current_hitpoints() &&
+		  state.ui32var3 > get_current_health() &&
 		  defenders > 0))
 	{
 		// Injured soldiers will try to return to safe site at home.
-		if (state.ui32var3 > get_current_hitpoints() && defenders) {
+		if (state.ui32var3 > get_current_health() && defenders) {
 			state.coords = Coords::null();
 			state.objvar1 = nullptr;
 		}
@@ -1006,7 +972,7 @@
 	{
 		if (upcast(Soldier, soldier, bob)) {
 			return
-				soldier->get_current_hitpoints() &&
+				soldier->get_current_health() &&
 				soldier->is_attacking_player(game, player) &&
 				soldier->owner().is_hostile(player);
 		}
@@ -1027,7 +993,7 @@
  * Variables used:
  * \li ivar1 used to store \c CombatFlags
  * \li ivar2 when CF_DEFEND_STAYHOME, 1 if it has reached the flag
-//           when CF_RETREAT_WHEN_INJURED, the lesser HP before fleeing
+//           when CF_RETREAT_WHEN_INJURED, the lesser health before fleeing
  */
 Bob::Task const Soldier::taskDefense = {
 	"defense",
@@ -1053,11 +1019,11 @@
 	} else {
 		/* Flag defenders are not allowed to flee, to avoid abuses */
 		state.ivar1 |= CF_RETREAT_WHEN_INJURED;
-		state.ui32var3 = get_max_hitpoints() * kRetreatWhenHealthDropsBelowThisPercentage / 100;
+		state.ui32var3 = get_max_health() * kRetreatWhenHealthDropsBelowThisPercentage / 100;
 
 		// Soldier must defend even if he starts injured
-		if (state.ui32var3 < get_current_hitpoints())
-			state.ui32var3 = get_current_hitpoints();
+		if (state.ui32var3 < get_current_health())
+			state.ui32var3 = get_current_health();
 	}
 }
 
@@ -1163,10 +1129,10 @@
 	if
 		(soldiers.empty() ||
 		 ((state.ivar1 & CF_RETREAT_WHEN_INJURED) &&
-		  get_current_hitpoints() < state.ui32var3))
+		  get_current_health() < state.ui32var3))
 	{
 
-		if (get_current_hitpoints() < state.ui32var3)
+		if (get_current_health() < state.ui32var3)
 			molog("[defense] I am heavily injured!\n");
 		else
 			molog("[defense] no enemy soldiers found, ending task\n");
@@ -1615,7 +1581,7 @@
 		if (upcast(Soldier, soldier, bob))
 			return
 				soldier->is_on_battlefield() &&
-				soldier->get_current_hitpoints();
+				soldier->get_current_health();
 		return false;
 	}
 };
@@ -1636,7 +1602,7 @@
 	if
 		(!attackdefense ||
 		 ((attackdefense->ivar1 & CF_RETREAT_WHEN_INJURED) &&
-		  attackdefense->ui32var3 > get_current_hitpoints()))
+		  attackdefense->ui32var3 > get_current_health()))
 	{
 		// Retreating or non-combatant soldiers act like normal bobs
 		return Bob::check_node_blocked(game, field, commit);
@@ -1661,7 +1627,7 @@
 		 bob; bob = bob->get_next_on_field())
 	{
 		if (upcast(Soldier, soldier, bob)) {
-			if (!soldier->is_on_battlefield() || !soldier->get_current_hitpoints())
+			if (!soldier->is_on_battlefield() || !soldier->get_current_health())
 				continue;
 
 			if (!foundsoldier) {
@@ -1750,10 +1716,10 @@
 	molog("[Soldier]\n");
 	molog
 		("Levels: %d/%d/%d/%d\n",
-		 hp_level_, attack_level_, defense_level_, evade_level_);
-	molog ("HitPoints: %d/%d\n", hp_current_, get_max_hitpoints());
-	molog ("Attack :  %d-%d\n", get_min_attack(), get_max_attack());
-	molog ("Defense : %d%%\n", get_defense());
+		 health_level_, attack_level_, defense_level_, evade_level_);
+	molog ("Health:   %d/%d\n", current_health_, get_max_health());
+	molog ("Attack:   %d-%d\n", get_min_attack(), get_max_attack());
+	molog ("Defense:  %d%%\n", get_defense());
 	molog ("Evade:    %d%%\n", get_evade());
 	molog ("CombatWalkingDir:   %i\n", combat_walking_);
 	molog ("CombatWalkingStart: %i\n", combat_walkstart_);
@@ -1789,10 +1755,10 @@
 		if (packet_version == kCurrentPacketVersion) {
 
 			Soldier & soldier = get<Soldier>();
-			soldier.hp_current_ = fr.unsigned_32();
+			soldier.current_health_ = fr.unsigned_32();
 
-			soldier.hp_level_ =
-				std::min(fr.unsigned_32(), soldier.descr().get_max_hp_level());
+			soldier.health_level_ =
+				std::min(fr.unsigned_32(), soldier.descr().get_max_health_level());
 			soldier.attack_level_ =
 				std::min(fr.unsigned_32(), soldier.descr().get_max_attack_level());
 			soldier.defense_level_ =
@@ -1800,8 +1766,8 @@
 			soldier.evade_level_ =
 				std::min(fr.unsigned_32(), soldier.descr().get_max_evade_level());
 
-			if (soldier.hp_current_ > soldier.get_max_hitpoints())
-				soldier.hp_current_ = soldier.get_max_hitpoints();
+			if (soldier.current_health_ > soldier.get_max_health())
+				soldier.current_health_ = soldier.get_max_health();
 
 			soldier.combat_walking_ = static_cast<CombatWalkingDir>(fr.unsigned_8());
 			if (soldier.combat_walking_ != CD_NONE) {
@@ -1849,8 +1815,8 @@
 	Worker::do_save(egbase, mos, fw);
 
 	fw.unsigned_8(kCurrentPacketVersion);
-	fw.unsigned_32(hp_current_);
-	fw.unsigned_32(hp_level_);
+	fw.unsigned_32(current_health_);
+	fw.unsigned_32(health_level_);
 	fw.unsigned_32(attack_level_);
 	fw.unsigned_32(defense_level_);
 	fw.unsigned_32(evade_level_);

=== modified file 'src/logic/map_objects/tribes/soldier.h'
--- src/logic/map_objects/tribes/soldier.h	2016-02-15 23:26:42 +0000
+++ src/logic/map_objects/tribes/soldier.h	2016-02-21 19:03:44 +0000
@@ -37,8 +37,6 @@
 class EditorGameBase;
 class Battle;
 
-#define HP_FRAMECOLOR RGBColor(255, 255, 255)
-
 class SoldierDescr : public WorkerDescr {
 public:
 	friend class Economy;
@@ -47,33 +45,37 @@
 					 const LuaTable& t, const EditorGameBase& egbase);
 	~SoldierDescr() override {}
 
-	uint32_t get_max_hp_level          () const {return max_hp_level_;}
-	uint32_t get_max_attack_level      () const {return max_attack_level_;}
-	uint32_t get_max_defense_level     () const {return max_defense_level_;}
-	uint32_t get_max_evade_level       () const {return max_evade_level_;}
-
-	uint32_t get_base_hp        () const {return base_hp_;}
-	uint32_t get_base_min_attack() const {return min_attack_;}
-	uint32_t get_base_max_attack() const {return max_attack_;}
-	uint32_t get_base_defense   () const {return defense_;}
-	uint32_t get_base_evade     () const {return evade_;}
-
-	uint32_t get_hp_incr_per_level     () const {return hp_incr_;}
-	uint32_t get_attack_incr_per_level () const {return attack_incr_;}
-	uint32_t get_defense_incr_per_level() const {return defense_incr_;}
-	uint32_t get_evade_incr_per_level  () const {return evade_incr_;}
-
-	const Image* get_hp_level_pic     (uint32_t const level) const {
-		assert(level <= max_hp_level_);      return hp_pics_     [level];
+	uint32_t get_max_health_level      () const {return health_.max_level;}
+	uint32_t get_max_attack_level      () const {return attack_.max_level;}
+	uint32_t get_max_defense_level     () const {return defense_.max_level;}
+	uint32_t get_max_evade_level       () const {return evade_.max_level;}
+
+	uint32_t get_base_health    () const {return health_.base;}
+	uint32_t get_base_min_attack() const {return attack_.base;}
+	uint32_t get_base_max_attack() const {return attack_.maximum;}
+	uint32_t get_base_defense   () const {return defense_.base;}
+	uint32_t get_base_evade     () const {return evade_.base;}
+
+	uint32_t get_health_incr_per_level () const {return health_.increase;}
+	uint32_t get_attack_incr_per_level () const {return attack_.increase;}
+	uint32_t get_defense_incr_per_level() const {return defense_.increase;}
+	uint32_t get_evade_incr_per_level  () const {return evade_.increase;}
+
+	const Image* get_health_level_pic(uint32_t const level) const {
+		assert(level <= get_max_health_level());
+		return health_.images[level];
 	}
-	const Image* get_attack_level_pic (uint32_t const level) const {
-		assert(level <= max_attack_level_);  return attack_pics_ [level];
+	const Image* get_attack_level_pic(uint32_t const level) const {
+		assert(level <= get_max_attack_level());
+		return attack_.images[level];
 	}
 	const Image* get_defense_level_pic(uint32_t const level) const {
-		assert(level <= max_defense_level_); return defense_pics_[level];
+		assert(level <= get_max_defense_level());
+		return defense_.images[level];
 	}
-	const Image* get_evade_level_pic  (uint32_t const level) const {
-		assert(level <= max_evade_level_);   return evade_pics_  [level];
+	const Image* get_evade_level_pic(uint32_t const level) const {
+		assert(level <= get_max_evade_level());
+		return evade_.images[level];
 	}
 
 	uint32_t get_rand_anim(Game & game, const char * const name) const;
@@ -81,36 +83,24 @@
 protected:
 	Bob & create_object() const override;
 
-	//  start values
-	uint32_t base_hp_;
-	uint32_t min_attack_;
-	uint32_t max_attack_;
-	uint32_t defense_;
-	uint32_t evade_;
-
-	//  per level increases
-	uint32_t hp_incr_;
-	uint32_t attack_incr_;
-	uint32_t defense_incr_;
-	uint32_t evade_incr_;
-
-	//  max levels
-	uint32_t max_hp_level_;
-	uint32_t max_attack_level_;
-	uint32_t max_defense_level_;
-	uint32_t max_evade_level_;
-
-	//  level pictures
-	std::vector<const Image* >   hp_pics_;
-	std::vector<const Image* >   attack_pics_;
-	std::vector<const Image* >   evade_pics_;
-	std::vector<const Image* >   defense_pics_;
-	std::vector<std::string> hp_pics_fn_;
-	std::vector<std::string> attack_pics_fn_;
-	std::vector<std::string> evade_pics_fn_;
-	std::vector<std::string> defense_pics_fn_;
-
-	// animation names
+private:
+	// Health, Attack, Defense and Evade values.
+	struct BattleAttribute {
+		BattleAttribute(std::unique_ptr<LuaTable> table);
+
+		uint32_t base; // Base value
+		uint32_t maximum; // Maximum value for randomizing attack values
+		uint32_t increase; // Per level increase
+		uint32_t max_level; // Maximum level
+		std::vector<const Image* > images; // Level images
+	};
+
+	BattleAttribute health_;
+	BattleAttribute attack_;
+	BattleAttribute defense_;
+	BattleAttribute evade_;
+
+	// Battle animation names
 	std::vector<std::string> attack_success_w_name_;
 	std::vector<std::string> attack_failure_w_name_;
 	std::vector<std::string> evade_success_w_name_;
@@ -123,7 +113,6 @@
 	std::vector<std::string> evade_failure_e_name_;
 	std::vector<std::string> die_e_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);
 
@@ -145,7 +134,7 @@
 enum CombatFlags {
 	/// Soldier will wait enemies at his building flag. Only for defenders.
 	CF_DEFEND_STAYHOME = 1,
-	/// When current hitpoints goes under a fixed percentage, soldier will flee
+	/// When current health points drop below a fixed percentage, soldier will flee
 	/// and heal inside military building
 	CF_RETREAT_WHEN_INJURED = 2,
 	/// Attackers would try avoid entering combat with others soldiers but 'flag
@@ -165,17 +154,17 @@
 	void cleanup(EditorGameBase &) override;
 
 	void set_level
-		(uint32_t hp, uint32_t attack, uint32_t defense, uint32_t evade);
-	void set_hp_level     (uint32_t);
+		(uint32_t health, uint32_t attack, uint32_t defense, uint32_t evade);
+	void set_health_level (uint32_t);
 	void set_attack_level (uint32_t);
 	void set_defense_level(uint32_t);
 	void set_evade_level  (uint32_t);
 	uint32_t get_level (TrainingAttribute) const;
-	uint32_t get_hp_level     () const {return hp_level_;}
+	uint32_t get_health_level     () const {return health_level_;}
 	uint32_t get_attack_level () const {return attack_level_;}
 	uint32_t get_defense_level() const {return defense_level_;}
 	uint32_t get_evade_level  () const {return evade_level_;}
-	uint32_t get_total_level () const {return hp_level_ + attack_level_ + defense_level_ + evade_level_;}
+	uint32_t get_total_level() const   {return health_level_ + attack_level_ + defense_level_ + evade_level_;}
 
 	/// Automatically select a task.
 	void init_auto_task(Game &) override;
@@ -188,15 +177,15 @@
 		(const TribeDescr &, uint32_t & w, uint32_t & h);
 	void draw_info_icon(RenderTarget &, Point, bool anchor_below) const;
 
-	uint32_t get_current_hitpoints() const {return hp_current_;}
-	uint32_t get_max_hitpoints() const;
+	uint32_t get_current_health() const {return current_health_;}
+	uint32_t get_max_health() const;
 	uint32_t get_min_attack() const;
 	uint32_t get_max_attack() const;
 	uint32_t get_defense() const;
 	uint32_t get_evade() const;
 
-	const Image* get_hp_level_pic     () const {
-		return descr().get_hp_level_pic     (hp_level_);
+	const Image* get_health_level_pic () const {
+		return descr().get_health_level_pic(health_level_);
 	}
 	const Image* get_attack_level_pic () const {
 		return descr().get_attack_level_pic (attack_level_);
@@ -208,15 +197,15 @@
 		return descr().get_evade_level_pic  (evade_level_);
 	}
 
-	int32_t get_training_attribute(uint32_t attr) const override;
+	int32_t get_training_attribute(TrainingAttribute attr) const override;
 
 	/// Sets a random animation of desired type and start playing it.
 	void start_animation
 		(EditorGameBase &, char const * animname, uint32_t time);
 
-	/// Heal quantity of hit points instantly
+	/// Heal quantity of health points instantly
 	void heal (uint32_t);
-	void damage (uint32_t); /// Damage quantity of hit points
+	void damage (uint32_t); /// Damage quantity of health points
 
 	void log_general_info(const EditorGameBase &) override;
 
@@ -262,8 +251,8 @@
 	bool is_evict_allowed() override;
 
 private:
-	uint32_t hp_current_;
-	uint32_t hp_level_;
+	uint32_t current_health_;
+	uint32_t health_level_;
 	uint32_t attack_level_;
 	uint32_t defense_level_;
 	uint32_t evade_level_;
@@ -284,7 +273,7 @@
 	 */
 	Battle * battle_;
 
-	static constexpr uint8_t kSoldierHpBarWidth = 13;
+	static constexpr uint8_t kSoldierHealthBarWidth = 13;
 
 	/// Number of consecutive blocked signals until the soldiers are considered permanently stuck
 	static constexpr uint8_t kBockCountIsStuck = 10;

=== modified file 'src/logic/map_objects/tribes/training_attribute.h'
--- src/logic/map_objects/tribes/training_attribute.h	2015-11-28 22:29:26 +0000
+++ src/logic/map_objects/tribes/training_attribute.h	2016-02-21 19:03:44 +0000
@@ -26,12 +26,12 @@
  * Indices for specific, individual attributes that \ref MapObject instances
  * may have. Used in conjunction with \ref Requirements.
  */
-enum TrainingAttribute {
-	atrHP = 0,
-	atrAttack,
-	atrDefense,
-	atrEvade,
-	atrTotal = 100
+enum class TrainingAttribute : uint8_t {
+	kHealth = 0,
+	kAttack,
+	kDefense,
+	kEvade,
+	kTotal = 100
 };
 
 }

=== modified file 'src/logic/map_objects/tribes/trainingsite.cc'
--- src/logic/map_objects/tribes/trainingsite.cc	2016-02-09 07:42:38 +0000
+++ src/logic/map_objects/tribes/trainingsite.cc	2016-02-21 19:03:44 +0000
@@ -49,15 +49,15 @@
 	num_soldiers_      (table.get_int("soldier_capacity")),
 	max_stall_         (table.get_int("trainer_patience")),
 
-	train_hp_          (false),
+	train_health_      (false),
 	train_attack_      (false),
 	train_defense_     (false),
 	train_evade_       (false),
-	min_hp_            (0),
+	min_health_        (0),
 	min_attack_        (0),
 	min_defense_       (0),
 	min_evade_         (0),
-	max_hp_            (0),
+	max_health_        (0),
 	max_attack_        (0),
 	max_defense_       (0),
 	max_evade_         (0)
@@ -68,12 +68,12 @@
 	//  These sections also seem redundant. Eliminate them (having the
 	//  programs should be enough).
 	std::unique_ptr<LuaTable> items_table;
-	if (table.has_key("soldier hp")) {
-		items_table = table.get_table("soldier hp");
-		train_hp_      = true;
-		min_hp_ = items_table->get_int("min_level");
-		max_hp_ = items_table->get_int("max_level");
-		add_training_inputs(*items_table.get(), &food_hp_, &weapons_hp_);
+	if (table.has_key("soldier health")) {
+		items_table = table.get_table("soldier health");
+		train_health_ = true;
+		min_health_ = items_table->get_int("min_level");
+		max_health_ = items_table->get_int("max_level");
+		add_training_inputs(*items_table.get(), &food_health_, &weapons_health_);
 	}
 
 	if (table.has_key("soldier attack")) {
@@ -114,15 +114,15 @@
  */
 int32_t TrainingSiteDescr::get_min_level(const TrainingAttribute at) const {
 	switch (at) {
-	case atrHP:
-		return min_hp_;
-	case atrAttack:
+	case TrainingAttribute::kHealth:
+		return min_health_;
+	case TrainingAttribute::kAttack:
 		return min_attack_;
-	case atrDefense:
+	case TrainingAttribute::kDefense:
 		return min_defense_;
-	case atrEvade:
+	case TrainingAttribute::kEvade:
 		return min_evade_;
-	case atrTotal:
+	case TrainingAttribute::kTotal:
 		throw wexception("Unknown attribute value!");
 	}
 	NEVER_HERE();
@@ -136,15 +136,15 @@
  */
 int32_t TrainingSiteDescr::get_max_level(const TrainingAttribute at) const {
 	switch (at) {
-	case atrHP:
-		return max_hp_;
-	case atrAttack:
+	case TrainingAttribute::kHealth:
+		return max_health_;
+	case TrainingAttribute::kAttack:
 		return max_attack_;
-	case atrDefense:
+	case TrainingAttribute::kDefense:
 		return max_defense_;
-	case atrEvade:
+	case TrainingAttribute::kEvade:
 		return max_evade_;
-	case atrTotal:
+	case TrainingAttribute::kTotal:
 		throw wexception("Unknown attribute value!");
 	}
 	NEVER_HERE();
@@ -201,14 +201,14 @@
 	training_failure_count_.clear();
 	max_stall_val_ = training_state_multiplier_ * d.get_max_stall();
 
-	if (d.get_train_hp())
-		init_kick_state(atrHP, d);
+	if (d.get_train_health())
+		init_kick_state(TrainingAttribute::kHealth, d);
 	if (d.get_train_attack())
-		init_kick_state(atrAttack, d);
+		init_kick_state(TrainingAttribute::kAttack, d);
 	if (d.get_train_defense())
-		init_kick_state(atrDefense, d);
+		init_kick_state(TrainingAttribute::kDefense, d);
 	if (d.get_train_evade())
-		init_kick_state(atrEvade, d);
+		init_kick_state(TrainingAttribute::kEvade, d);
 }
 void
 TrainingSite::init_kick_state(const TrainingAttribute & art, const TrainingSiteDescr & d)
@@ -322,27 +322,27 @@
 			if (descr().get_train_attack())
 				r.add
 					(RequireAttribute
-					 	(atrAttack,
-					 	 descr().get_min_level(atrAttack),
-					 	 descr().get_max_level(atrAttack)));
+						(TrainingAttribute::kAttack,
+						 descr().get_min_level(TrainingAttribute::kAttack),
+						 descr().get_max_level(TrainingAttribute::kAttack)));
 			if (descr().get_train_defense())
 				r.add
 					(RequireAttribute
-					 	(atrDefense,
-					 	 descr().get_min_level(atrDefense),
-					 	 descr().get_max_level(atrDefense)));
+						(TrainingAttribute::kDefense,
+						 descr().get_min_level(TrainingAttribute::kDefense),
+						 descr().get_max_level(TrainingAttribute::kDefense)));
 			if (descr().get_train_evade())
 				r.add
 					(RequireAttribute
-					 	(atrEvade,
-					 	 descr().get_min_level(atrEvade),
-					 	 descr().get_max_level(atrEvade)));
-			if (descr().get_train_hp())
+						(TrainingAttribute::kEvade,
+						 descr().get_min_level(TrainingAttribute::kEvade),
+						 descr().get_max_level(TrainingAttribute::kEvade)));
+			if (descr().get_train_health())
 				r.add
 					(RequireAttribute
-					 	(atrHP,
-					 	 descr().get_min_level(atrHP),
-					 	 descr().get_max_level(atrHP)));
+						(TrainingAttribute::kHealth,
+						 descr().get_min_level(TrainingAttribute::kHealth),
+						 descr().get_max_level(TrainingAttribute::kHealth)));
 
 			soldier_request_->set_requirements(r);
 		}
@@ -506,7 +506,7 @@
 
 	for (uint32_t i = 0; i < soldiers_.size(); ++i)
 	{
-		uint32_t this_soldier_level = soldiers_[i]->get_level(atrTotal);
+		uint32_t this_soldier_level = soldiers_[i]->get_level(TrainingAttribute::kTotal);
 
 		bool this_soldier_is_safe = false;
 		if (this_soldier_level <= highest_soldier_level_seen)
@@ -775,19 +775,19 @@
 
 	//  TODO(unknown): This is currently hardcoded for "soldier" but it should allow any
 	//  soldier type name.
-	if (descr().get_train_hp())
-		add_upgrade(atrHP, "upgrade_soldier_hp_");
+	if (descr().get_train_health())
+		add_upgrade(TrainingAttribute::kHealth, "upgrade_soldier_health_");
 	if (descr().get_train_attack())
-		add_upgrade(atrAttack, "upgrade_soldier_attack_");
+		add_upgrade(TrainingAttribute::kAttack, "upgrade_soldier_attack_");
 	if (descr().get_train_defense())
-		add_upgrade(atrDefense, "upgrade_soldier_defense_");
+		add_upgrade(TrainingAttribute::kDefense, "upgrade_soldier_defense_");
 	if (descr().get_train_evade())
-		add_upgrade(atrEvade, "upgrade_soldier_evade_");
+		add_upgrade(TrainingAttribute::kEvade, "upgrade_soldier_evade_");
 }
 
 
 void
-TrainingSite::training_attempted(uint32_t type, uint32_t level)
+TrainingSite::training_attempted(TrainingAttribute type, uint32_t level)
 	{
 	        TypeAndLevel key(type, level);
 		if (training_failure_count_.find(key) == training_failure_count_.end())
@@ -801,7 +801,7 @@
  */
 
 void
-TrainingSite::training_successful(uint32_t type, uint32_t level)
+TrainingSite::training_successful(TrainingAttribute type, uint32_t level)
 {
 	TypeAndLevel key(type, level);
 	// Here I assume that key exists: training has been attempted before it can succeed.

=== modified file 'src/logic/map_objects/tribes/trainingsite.h'
--- src/logic/map_objects/tribes/trainingsite.h	2016-02-09 07:42:38 +0000
+++ src/logic/map_objects/tribes/trainingsite.h	2016-02-21 19:03:44 +0000
@@ -41,7 +41,7 @@
 	uint32_t get_max_number_of_soldiers() const {
 		return num_soldiers_;
 	}
-	bool get_train_hp     () const {return train_hp_;}
+	bool get_train_health () const {return train_health_;}
 	bool get_train_attack () const {return train_attack_;}
 	bool get_train_defense() const {return train_defense_;}
 	bool get_train_evade  () const {return train_evade_;}
@@ -50,8 +50,8 @@
 	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_health() const {
+		return food_health_;
 	}
 	const std::vector<std::vector<std::string>>& get_food_attack() const {
 		return food_attack_;
@@ -62,8 +62,8 @@
 	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_health() const {
+		return weapons_health_;
 	}
 	const std::vector<std::string>& get_weapons_attack() const {
 		return weapons_attack_;
@@ -77,7 +77,7 @@
 
 private:
 	// Read the table to add needed food and weapons for training a property.
-	// Properties are hp, attack, defense, and evade.
+	// Properties are health, attack, defense, and evade.
 	void add_training_inputs(const LuaTable& table,
 			std::vector<std::vector<std::string>>* food, std::vector<std::string>* weapons);
 
@@ -88,8 +88,8 @@
 	uint32_t num_soldiers_;
 	/** Number of rounds w/o successful training, after which a soldier is kicked out.**/
 	uint32_t max_stall_;
-	/** Whether this site can train hitpoints*/
-	bool train_hp_;
+	/** Whether this site can train health*/
+	bool train_health_;
 	/** Whether this site can train attack*/
 	bool train_attack_;
 	/** Whether this site can train defense*/
@@ -97,8 +97,8 @@
 	/** Whether this site can train evasion*/
 	bool train_evade_;
 
-	/** Minimum hitpoints to which a soldier can drop at this site*/
-	int32_t min_hp_;
+	/** Minimum health to which a soldier can drop at this site*/
+	int32_t min_health_;
 	/** Minimum attacks to which a soldier can drop at this site*/
 	int32_t min_attack_;
 	/** Minimum defense to which a soldier can drop at this site*/
@@ -106,8 +106,8 @@
 	/** Minimum evasion to which a soldier can drop at this site*/
 	int32_t min_evade_;
 
-	/** Maximum hitpoints a soldier can acquire at this site*/
-	int32_t max_hp_;
+	/** Maximum health a soldier can acquire at this site*/
+	int32_t max_health_;
 	/** Maximum attack a soldier can acquire at this site*/
 	int32_t max_attack_;
 	/** Maximum defense a soldier can acquire at this site*/
@@ -116,11 +116,11 @@
 	int32_t max_evade_;
 
 	// For building help
-	std::vector<std::vector<std::string>> food_hp_;
+	std::vector<std::vector<std::string>> food_health_;
 	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_health_;
 	std::vector<std::string> weapons_attack_;
 	std::vector<std::string> weapons_defense_;
 	std::vector<std::string> weapons_evade_;
@@ -130,7 +130,7 @@
 
 /**
  * A building to change soldiers' abilities.
- * Soldiers can gain hitpoints, or experience in attack, defense and evasion.
+ * Soldiers can gain health, or experience in attack, defense and evasion.
  *
  * \note  A training site does not change influence areas. If you lose the
  *        surrounding strongholds, the training site will burn even if it
@@ -192,8 +192,8 @@
 	void set_pri(enum TrainingAttribute atr, int32_t prio);
 
 	// These are for premature soldier kick-out
-	void training_attempted(uint32_t type, uint32_t level);
-	void training_successful(uint32_t type, uint32_t level);
+	void training_attempted(TrainingAttribute type, uint32_t level);
+	void training_successful(TrainingAttribute type, uint32_t level);
 	void training_done();
 
 
@@ -240,7 +240,7 @@
 	// These are used for kicking out soldiers prematurely
 	static const uint32_t training_state_multiplier_;
 	// Unuque key to address each training level of each war art
-	using TypeAndLevel = std::pair<uint16_t, uint16_t>;
+	using TypeAndLevel = std::pair<TrainingAttribute, uint16_t>;
 	// First entry is the "stallness", second is a bool
 	using FailAndPresence = std::pair<uint16_t, uint8_t>; // first might wrap in a long play..
 	using TrainFailCount = std::map<TypeAndLevel, FailAndPresence>;

=== modified file 'src/logic/map_objects/tribes/warehouse.cc'
--- src/logic/map_objects/tribes/warehouse.cc	2016-02-18 08:42:46 +0000
+++ src/logic/map_objects/tribes/warehouse.cc	2016-02-21 19:03:44 +0000
@@ -693,13 +693,13 @@
 				Soldier * soldier = static_cast<Soldier *>(*it);
 
 				//  Soldier dead ...
-				if (!soldier || soldier->get_current_hitpoints() == 0) {
+				if (!soldier || soldier->get_current_health() == 0) {
 					it = soldiers.erase(it);
 					supply_->remove_workers(soldier_index, 1);
 					continue;
 				}
 
-				if (soldier->get_current_hitpoints() < soldier->get_max_hitpoints()) {
+				if (soldier->get_current_health() < soldier->get_max_health()) {
 					soldier->heal(total_heal);
 					continue;
 				}

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc	2016-02-18 08:42:46 +0000
+++ src/logic/player.cc	2016-02-21 19:03:44 +0000
@@ -872,10 +872,9 @@
 ==========
 */
 void Player::change_training_options
-	(TrainingSite & trainingsite, int32_t const atr, int32_t const val)
+	(TrainingSite & trainingsite, TrainingAttribute attr, int32_t const val)
 {
 	if (trainingsite.get_owner() == this) {
-		TrainingAttribute const attr = static_cast<TrainingAttribute>(atr);
 		trainingsite.set_pri(attr, trainingsite.get_pri(attr) + val);
 	}
 }

=== modified file 'src/logic/player.h'
--- src/logic/player.h	2016-02-18 08:42:46 +0000
+++ src/logic/player.h	2016-02-21 19:03:44 +0000
@@ -489,7 +489,7 @@
 
 	// Military stuff
 	void drop_soldier(PlayerImmovable &, Soldier &);
-	void change_training_options(TrainingSite &, int32_t atr, int32_t val);
+	void change_training_options(TrainingSite &, TrainingAttribute attr, int32_t val);
 
 	uint32_t find_attack_soldiers
 		(Flag                   &,

=== modified file 'src/logic/playercommand.cc'
--- src/logic/playercommand.cc	2016-02-09 16:29:48 +0000
+++ src/logic/playercommand.cc	2016-02-21 19:03:44 +0000
@@ -1560,26 +1560,25 @@
 PlayerCommand (0, des.unsigned_8())
 {
 	serial    = des.unsigned_32();  //  Serial of the building
-	attribute = des.unsigned_16();  //  Attribute to modify
+	attribute = static_cast<TrainingAttribute>(des.unsigned_8());  //  Attribute to modify
 	value     = des.unsigned_16();  //  New vale
 }
 
 void CmdChangeTrainingOptions::execute (Game & game)
 {
 	if (upcast(TrainingSite, trainingsite, game.objects().get_object(serial)))
-		game.player(sender()).change_training_options
-			(*trainingsite, attribute, value);
+		game.player(sender()).change_training_options(*trainingsite, attribute, value);
 }
 
 void CmdChangeTrainingOptions::serialize (StreamWrite & ser) {
 	ser.unsigned_8 (PLCMD_CHANGETRAININGOPTIONS);
 	ser.unsigned_8 (sender());
 	ser.unsigned_32(serial);
-	ser.unsigned_16(attribute);
+	ser.unsigned_8(static_cast<uint8_t>(attribute));
 	ser.unsigned_16(value);
 }
 
-constexpr uint16_t kCurrentPacketVersionChangeTrainingOptions = 1;
+constexpr uint16_t kCurrentPacketVersionChangeTrainingOptions = 2;
 
 void CmdChangeTrainingOptions::read
 	(FileRead & fr, EditorGameBase & egbase, MapObjectLoader & mol)
@@ -1589,7 +1588,7 @@
 		if (packet_version == kCurrentPacketVersionChangeTrainingOptions) {
 			PlayerCommand::read(fr, egbase, mol);
 			serial = get_object_serial_or_zero<TrainingSite>(fr.unsigned_32(), mol);
-			attribute = fr.unsigned_16();
+			attribute = static_cast<TrainingAttribute>(fr.unsigned_8());
 			value     = fr.unsigned_16();
 		} else {
 			throw UnhandledVersionError("CmdChangeTrainingOptions",
@@ -1611,7 +1610,7 @@
 	// Now serial
 	fw.unsigned_32(mos.get_object_file_index_or_zero(egbase.objects().get_object(serial)));
 
-	fw.unsigned_16(attribute);
+	fw.unsigned_8(static_cast<uint8_t>(attribute));
 	fw.unsigned_16(value);
 }
 

=== modified file 'src/logic/playercommand.h'
--- src/logic/playercommand.h	2016-02-09 16:29:48 +0000
+++ src/logic/playercommand.h	2016-02-21 19:03:44 +0000
@@ -579,12 +579,13 @@
 };
 
 struct CmdChangeTrainingOptions : public PlayerCommand {
-	CmdChangeTrainingOptions() : PlayerCommand(), serial(0), attribute(0), value(0) {} // For savegame loading
+	CmdChangeTrainingOptions() : PlayerCommand(),
+		serial(0), attribute(TrainingAttribute::kHealth), value(0) {} // For savegame loading
 	CmdChangeTrainingOptions
 		(const uint32_t    t,
 		 const PlayerNumber p,
 		 TrainingSite &   ts,
-		 const int32_t    at,
+		 const TrainingAttribute at,
 		 const int32_t    val)
 		: PlayerCommand(t, p), serial(ts.serial()), attribute(at), value(val)
 	{}
@@ -602,7 +603,7 @@
 
 private:
 	Serial serial;
-	int32_t attribute;
+	TrainingAttribute attribute;
 	int32_t value;
 };
 

=== modified file 'src/logic/widelands.h'
--- src/logic/widelands.h	2016-01-01 17:35:01 +0000
+++ src/logic/widelands.h	2016-02-21 19:03:44 +0000
@@ -65,18 +65,18 @@
 constexpr DescriptionIndex kNoResource = INVALID_INDEX - 1;
 
 struct SoldierStrength {
-	uint8_t hp, attack, defense, evade;
+	uint8_t health, attack, defense, evade;
 	bool operator== (const SoldierStrength & other) const {
 		return
-			hp      == other.hp      &&
+			health  == other.health  &&
 			attack  == other.attack  &&
 			defense == other.defense &&
 			evade   == other.evade;
 	}
 	bool operator<  (const SoldierStrength & other) const {
 		return
-			hp      <  other.hp ||
-			(hp      == other.hp &&
+			health  <  other.health ||
+			(health  == other.health &&
 			 (attack  <  other.attack ||
 			  (attack  == other.attack &&
 			   (defense <  other.defense ||

=== modified file 'src/map_io/map_buildingdata_packet.cc'
--- src/map_io/map_buildingdata_packet.cc	2016-02-13 12:15:29 +0000
+++ src/map_io/map_buildingdata_packet.cc	2016-02-21 19:03:44 +0000
@@ -62,7 +62,7 @@
 constexpr uint16_t kCurrentPacketVersionWarehouse = 6;
 constexpr uint16_t kCurrentPacketVersionMilitarysite = 5;
 constexpr uint16_t kCurrentPacketVersionProductionsite = 5;
-constexpr uint16_t kCurrentPacketVersionTrainingsite = 4;
+constexpr uint16_t kCurrentPacketVersionTrainingsite = 5;
 
 void MapBuildingdataPacket::read
 	(FileSystem            &       fs,
@@ -562,7 +562,8 @@
 
 			uint16_t reqmin = fr.unsigned_16();
 			uint16_t reqmax = fr.unsigned_16();
-			militarysite.soldier_upgrade_requirements_ = RequireAttribute(atrTotal, reqmin, reqmax);
+			militarysite.soldier_upgrade_requirements_ =
+					RequireAttribute(TrainingAttribute::kTotal, reqmin, reqmax);
 			militarysite.soldier_preference_ = static_cast<MilitarySite::SoldierPreference>(fr.unsigned_8());
 			militarysite.next_swap_soldiers_time_ = fr.signed_32();
 			militarysite.soldier_upgrade_try_ = 0 != fr.unsigned_8() ? true : false;
@@ -829,13 +830,13 @@
 			uint16_t mapsize = fr.unsigned_16(); // map of training levels (not _the_ map)
 			while (mapsize)
 			{
-				uint16_t traintype  = fr.unsigned_16();
+				TrainingAttribute traintype  = static_cast<TrainingAttribute>(fr.unsigned_8());
 				uint16_t trainlevel = fr.unsigned_16();
 				uint16_t trainstall = fr.unsigned_16();
 				uint16_t spresence  = fr.unsigned_8();
 				mapsize--;
-				std::pair<uint16_t, uint8_t> t = std::make_pair(trainstall, spresence);
-				trainingsite.training_failure_count_[std::make_pair(traintype, trainlevel)] = t;
+				trainingsite.training_failure_count_[std::make_pair(traintype, trainlevel)] =
+						std::make_pair(trainstall, spresence);
 			}
 		} else {
 			throw UnhandledVersionError("MapBuildingdataPacket - Trainingsite",
@@ -1275,7 +1276,7 @@
 	fw.unsigned_8(trainingsite.upgrades_.size());
 	for (uint8_t i = 0; i < trainingsite.upgrades_.size(); ++i) {
 		const TrainingSite::Upgrade & upgrade = trainingsite.upgrades_[i];
-		fw.unsigned_8(upgrade.attribute);
+		fw.unsigned_8(static_cast<uint8_t>(upgrade.attribute));
 		fw.unsigned_8(upgrade.prio);
 		fw.unsigned_8(upgrade.credit);
 		fw.signed_32(upgrade.lastattempt);
@@ -1290,7 +1291,7 @@
 		(TrainingSite::TrainFailCount::const_iterator i = trainingsite.training_failure_count_.begin();
 		 i != trainingsite.training_failure_count_.end(); i++)
 	{
-		fw.unsigned_16(i->first.first);
+		fw.unsigned_8(static_cast<uint8_t>(i->first.first));
 		fw.unsigned_16(i->first.second);
 		fw.unsigned_16(i->second.first);
 		fw.unsigned_8(i->second.second);

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2016-02-18 08:42:46 +0000
+++ src/scripting/lua_map.cc	2016-02-21 19:03:44 +0000
@@ -112,31 +112,31 @@
 }
 
 struct SoldierMapDescr {
-	SoldierMapDescr(uint8_t ghp, uint8_t gat, uint8_t gde, uint8_t gev)
-	   : hp(ghp), at(gat), de(gde), ev(gev) {
+	SoldierMapDescr(uint8_t init_health, uint8_t init_attack, uint8_t init_defense, uint8_t init_evade)
+		: health(init_health), attack(init_attack), defense(init_defense), evade(init_evade) {
 	}
-	SoldierMapDescr() : hp(0), at(0), de(0), ev(0) {
+	SoldierMapDescr() : health(0), attack(0), defense(0), evade(0) {
 	}
 
-	uint8_t hp;
-	uint8_t at;
-	uint8_t de;
-	uint8_t ev;
+	uint8_t health;
+	uint8_t attack;
+	uint8_t defense;
+	uint8_t evade;
 
 	bool operator<(const SoldierMapDescr& ot) const {
-		bool hp_eq = hp == ot.hp;
-		bool at_eq = at == ot.at;
-		bool de_eq = de == ot.de;
-		if (hp_eq && at_eq && de_eq)
-			return ev < ot.ev;
-		if (hp_eq && at_eq)
-			return de < ot.de;
-		if (hp_eq)
-			return at < ot.at;
-		return hp < ot.hp;
+		bool equal_health = health == ot.health;
+		bool equal_attack = attack == ot.attack;
+		bool equal_defense = defense == ot.defense;
+		if (equal_health && equal_attack && equal_defense)
+			return evade < ot.evade;
+		if (equal_health && equal_attack)
+			return defense < ot.defense;
+		if (equal_health)
+			return attack < ot.attack;
+		return health < ot.health;
 	}
 	bool operator == (const SoldierMapDescr& ot) const {
-		if (hp == ot.hp && at == ot.at && de == ot.de && ev == ot.ev)
+		if (health == ot.health && attack == ot.attack && defense == ot.defense && evade == ot.evade)
 			return true;
 		return false;
 	}
@@ -375,43 +375,43 @@
 	return 0;
 }
 
-// Unpacks the Lua table of the form {hp, at, de, ev} at the stack index
+// Unpacks the Lua table of the form {health, attack, defense, evade} at the stack index
 // 'table_index' into a SoldierMapDescr struct.
 SoldierMapDescr unbox_lua_soldier_description(lua_State* L, int table_index, const SoldierDescr& sd) {
 	SoldierMapDescr soldier_descr;
 
 	lua_pushuint32(L, 1);
 	lua_rawget(L, table_index);
-	soldier_descr.hp = luaL_checkuint32(L, -1);
+	soldier_descr.health = luaL_checkuint32(L, -1);
 	lua_pop(L, 1);
-	if (soldier_descr.hp > sd.get_max_hp_level())
+	if (soldier_descr.health > sd.get_max_health_level())
 		report_error
-			(L, "hp level (%i) > max hp level (%i)", soldier_descr.hp, sd.get_max_hp_level());
+			(L, "health level (%i) > max health level (%i)", soldier_descr.health, sd.get_max_health_level());
 
 	lua_pushuint32(L, 2);
 	lua_rawget(L, table_index);
-	soldier_descr.at = luaL_checkuint32(L, -1);
+	soldier_descr.attack = luaL_checkuint32(L, -1);
 	lua_pop(L, 1);
-	if (soldier_descr.at > sd.get_max_attack_level())
+	if (soldier_descr.attack > sd.get_max_attack_level())
 		report_error
-			(L, "attack level (%i) > max attack level (%i)", soldier_descr.at, sd.get_max_attack_level());
+			(L, "attack level (%i) > max attack level (%i)", soldier_descr.attack, sd.get_max_attack_level());
 
 	lua_pushuint32(L, 3);
 	lua_rawget(L, table_index);
-	soldier_descr.de = luaL_checkuint32(L, -1);
+	soldier_descr.defense = luaL_checkuint32(L, -1);
 	lua_pop(L, 1);
-	if (soldier_descr.de > sd.get_max_defense_level())
+	if (soldier_descr.defense > sd.get_max_defense_level())
 		report_error
-			(L, "defense level (%i) > max defense level (%i)", soldier_descr.de,
+			(L, "defense level (%i) > max defense level (%i)", soldier_descr.defense,
 			 sd.get_max_defense_level());
 
 	lua_pushuint32(L, 4);
 	lua_rawget(L, table_index);
-	soldier_descr.ev = luaL_checkuint32(L, -1);
+	soldier_descr.evade = luaL_checkuint32(L, -1);
 	lua_pop(L, 1);
-	if (soldier_descr.ev > sd.get_max_evade_level())
+	if (soldier_descr.evade > sd.get_max_evade_level())
 		report_error
-			(L, "evade level (%i) > max evade level (%i)", soldier_descr.ev, sd.get_max_evade_level());
+			(L, "evade level (%i) > max evade level (%i)", soldier_descr.evade, sd.get_max_evade_level());
 
 	return soldier_descr;
 }
@@ -451,7 +451,7 @@
 		SoldiersMap hist;
 		for (const Soldier* s : soldiers) {
 			SoldierMapDescr sd
-				(s->get_hp_level(), s->get_attack_level(),
+				(s->get_health_level(), s->get_attack_level(),
 				 s->get_defense_level(), s->get_evade_level());
 
 			SoldiersMap::iterator i = hist.find(sd);
@@ -469,10 +469,10 @@
 	lua_pushuint32(L, idx);                                                                         \
 	lua_pushuint32(L, i.first.name);                                                                \
 	lua_rawset(L, -3);
-			PUSHLEVEL(1, hp);
-			PUSHLEVEL(2, at);
-			PUSHLEVEL(3, de);
-			PUSHLEVEL(4, ev);
+			PUSHLEVEL(1, health);
+			PUSHLEVEL(2, attack);
+			PUSHLEVEL(3, defense);
+			PUSHLEVEL(4, evade);
 #undef PUSHLEVEL
 
 			lua_pushuint32(L, i.second);
@@ -487,7 +487,7 @@
 		uint32_t rv = 0;
 		for (const Soldier* s : soldiers) {
 			SoldierMapDescr sd
-				(s->get_hp_level(), s->get_attack_level(), s->get_defense_level(), s->get_evade_level());
+				(s->get_health_level(), s->get_attack_level(), s->get_defense_level(), s->get_evade_level());
 			if (sd == wanted)
 				++rv;
 		}
@@ -514,7 +514,7 @@
 	SoldiersMap hist;
 	for (const Soldier* s : curs) {
 		SoldierMapDescr sd
-			(s->get_hp_level(), s->get_attack_level(),
+			(s->get_health_level(), s->get_attack_level(),
 			 s->get_defense_level(), s->get_evade_level());
 
 		SoldiersMap::iterator i = hist.find(sd);
@@ -539,7 +539,7 @@
 			while (d) {
 				for (Soldier* s : sc->stationed_soldiers()) {
 					SoldierMapDescr is
-						(s->get_hp_level(), s->get_attack_level(),
+						(s->get_health_level(), s->get_attack_level(),
 						 s->get_defense_level(), s->get_evade_level());
 
 					if (is == sp.first) {
@@ -555,7 +555,7 @@
 				Soldier& soldier = dynamic_cast<Soldier&>
 					(soldier_descr.create(egbase, *owner, nullptr, building_position));
 				soldier.set_level
-					(sp.first.hp, sp.first.at, sp.first.de, sp.first.ev);
+					(sp.first.health, sp.first.attack, sp.first.defense, sp.first.evade);
 				if (sc->incorporate_soldier(egbase, soldier)) {
 					soldier.remove(egbase);
 					report_error(L, "No space left for soldier!");
@@ -807,7 +807,7 @@
 			kind in this building.
 
 			A soldier description is a :class:`array` that contains the level for
-			hitpoints, attack, defense and evade (in this order). An usage example:
+			health, attack, defense and evade (in this order). A usage example:
 
 			.. code-block:: lua
 
@@ -2180,20 +2180,20 @@
 	PROP_RO(LuaTrainingSiteDescription, food_attack),
 	PROP_RO(LuaTrainingSiteDescription, food_defense),
 	PROP_RO(LuaTrainingSiteDescription, food_evade),
-	PROP_RO(LuaTrainingSiteDescription, food_hp),
+	PROP_RO(LuaTrainingSiteDescription, food_health),
 	PROP_RO(LuaTrainingSiteDescription, max_attack),
 	PROP_RO(LuaTrainingSiteDescription, max_defense),
 	PROP_RO(LuaTrainingSiteDescription, max_evade),
-	PROP_RO(LuaTrainingSiteDescription, max_hp),
+	PROP_RO(LuaTrainingSiteDescription, max_health),
 	PROP_RO(LuaTrainingSiteDescription, max_number_of_soldiers),
 	PROP_RO(LuaTrainingSiteDescription, min_attack),
 	PROP_RO(LuaTrainingSiteDescription, min_defense),
 	PROP_RO(LuaTrainingSiteDescription, min_evade),
-	PROP_RO(LuaTrainingSiteDescription, min_hp),
+	PROP_RO(LuaTrainingSiteDescription, min_health),
 	PROP_RO(LuaTrainingSiteDescription, weapons_attack),
 	PROP_RO(LuaTrainingSiteDescription, weapons_defense),
 	PROP_RO(LuaTrainingSiteDescription, weapons_evade),
-	PROP_RO(LuaTrainingSiteDescription, weapons_hp),
+	PROP_RO(LuaTrainingSiteDescription, weapons_health),
 	{nullptr, nullptr, nullptr},
 };
 
@@ -2235,13 +2235,13 @@
 
 
 /* RST
-	.. attribute:: food_hp
+	.. attribute:: food_health
 
 		(RO) A table of tables with food ware names used for Health training,
 			  e.g. {{"barbarians_bread"}, {"fish", "meat"}}
 */
-int LuaTrainingSiteDescription::get_food_hp(lua_State * L) {
-	return food_list_to_lua(L, get()->get_food_hp());
+int LuaTrainingSiteDescription::get_food_health(lua_State * L) {
+	return food_list_to_lua(L, get()->get_food_health());
 }
 
 
@@ -2253,7 +2253,7 @@
 int LuaTrainingSiteDescription::get_max_attack(lua_State * L) {
 	const TrainingSiteDescr* descr = get();
 	if (descr->get_train_attack())
-		lua_pushinteger(L, descr->get_max_level(atrAttack));
+		lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kAttack));
 	else
 		lua_pushnil(L);
 	return 1;
@@ -2267,7 +2267,7 @@
 int LuaTrainingSiteDescription::get_max_defense(lua_State * L) {
 	const TrainingSiteDescr* descr = get();
 	if (descr->get_train_defense())
-		lua_pushinteger(L, descr->get_max_level(atrDefense));
+		lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kDefense));
 	else
 		lua_pushnil(L);
 	return 1;
@@ -2282,21 +2282,21 @@
 int LuaTrainingSiteDescription::get_max_evade(lua_State * L) {
 	const TrainingSiteDescr * descr = get();
 	if (descr->get_train_evade())
-		lua_pushinteger(L, descr->get_max_level(atrEvade));
+		lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kEvade));
 	else lua_pushnil(L);
 	return 1;
 }
 
 
 /* RST
-	.. attribute:: max_hp
+	.. attribute:: max_health
 
 		(RO) The number of health points that a soldier can train
 */
-int LuaTrainingSiteDescription::get_max_hp(lua_State * L) {
+int LuaTrainingSiteDescription::get_max_health(lua_State * L) {
 	const TrainingSiteDescr * descr = get();
-	if (descr->get_train_hp())
-		lua_pushinteger(L, descr->get_max_level(atrHP));
+	if (descr->get_train_health())
+		lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kHealth));
 	else lua_pushnil(L);
 	return 1;
 }
@@ -2322,7 +2322,7 @@
 int LuaTrainingSiteDescription::get_min_attack(lua_State * L) {
 	const TrainingSiteDescr * descr = get();
 	if (descr->get_train_attack())
-		lua_pushinteger(L, descr->get_min_level(atrAttack));
+		lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kAttack));
 	else lua_pushnil(L);
 	return 1;
 }
@@ -2335,7 +2335,7 @@
 int LuaTrainingSiteDescription::get_min_defense(lua_State * L) {
 	const TrainingSiteDescr * descr = get();
 	if (descr->get_train_defense())
-		lua_pushinteger(L, descr->get_min_level(atrDefense));
+		lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kDefense));
 	else lua_pushnil(L);
 	return 1;
 }
@@ -2349,21 +2349,21 @@
 int LuaTrainingSiteDescription::get_min_evade(lua_State * L) {
 	const TrainingSiteDescr * descr = get();
 	if (descr->get_train_evade())
-		lua_pushinteger(L, descr->get_min_level(atrEvade));
+		lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kEvade));
 	else lua_pushnil(L);
 	return 1;
 }
 
 
 /* RST
-	.. attribute:: min_hp
+	.. attribute:: min_health
 
 		(RO) The number of health points that a soldier starts training with
 */
-int LuaTrainingSiteDescription::get_min_hp(lua_State * L) {
+int LuaTrainingSiteDescription::get_min_health(lua_State * L) {
 	const TrainingSiteDescr * descr = get();
-	if (descr->get_train_hp())
-		lua_pushinteger(L, descr->get_min_level(atrHP));
+	if (descr->get_train_health())
+		lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kHealth));
 	else lua_pushnil(L);
 	return 1;
 }
@@ -2417,14 +2417,14 @@
 }
 
 /* RST
-	.. attribute:: weapons_hp
+	.. attribute:: weapons_health
 
 		(RO) A table with weapon ware names used for Health training
 */
-int LuaTrainingSiteDescription::get_weapons_hp(lua_State * L) {
+int LuaTrainingSiteDescription::get_weapons_health(lua_State * L) {
 	lua_newtable(L);
 	int counter = 0;
-	for (const std::string& weaponname : get()->get_weapons_hp()) {
+	for (const std::string& weaponname : get()->get_weapons_health()) {
 		lua_pushnumber(L, ++counter);
 		lua_pushstring(L, weaponname);
 		lua_settable(L, -3);
@@ -4747,7 +4747,7 @@
 const PropertyType<LuaSoldier> LuaSoldier::Properties[] = {
 	PROP_RO(LuaSoldier, attack_level),
 	PROP_RO(LuaSoldier, defense_level),
-	PROP_RO(LuaSoldier, hp_level),
+	PROP_RO(LuaSoldier, health_level),
 	PROP_RO(LuaSoldier, evade_level),
 	{nullptr, nullptr, nullptr},
 };
@@ -4781,13 +4781,13 @@
 }
 
 /* RST
-	.. attribute:: hp_level
+	.. attribute:: health_level
 
-		(RO) The current hp level of this soldier
+		(RO) The current health level of this soldier
 */
 // UNTESTED
-int LuaSoldier::get_hp_level(lua_State * L) {
-	lua_pushuint32(L, get(L, get_egbase(L))->get_hp_level());
+int LuaSoldier::get_health_level(lua_State * L) {
+	lua_pushuint32(L, get(L, get_egbase(L))->get_health_level());
 	return 1;
 }
 

=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h	2016-02-14 16:31:07 +0000
+++ src/scripting/lua_map.h	2016-02-21 19:03:44 +0000
@@ -423,20 +423,20 @@
 	int get_food_attack(lua_State *);
 	int get_food_defense(lua_State *);
 	int get_food_evade(lua_State *);
-	int get_food_hp(lua_State *);
+	int get_food_health(lua_State *);
 	int get_max_attack(lua_State *);
 	int get_max_defense(lua_State *);
 	int get_max_evade(lua_State *);
-	int get_max_hp(lua_State *);
+	int get_max_health(lua_State *);
 	int get_max_number_of_soldiers(lua_State *);
 	int get_min_attack(lua_State *);
 	int get_min_defense(lua_State *);
 	int get_min_evade(lua_State *);
-	int get_min_hp(lua_State *);
+	int get_min_health(lua_State *);
 	int get_weapons_attack(lua_State *);
 	int get_weapons_defense(lua_State *);
 	int get_weapons_evade(lua_State *);
-	int get_weapons_hp(lua_State *);
+	int get_weapons_health(lua_State *);
 
 	/*
 	 * Lua methods
@@ -1091,7 +1091,7 @@
 	 */
 	int get_attack_level(lua_State *);
 	int get_defense_level(lua_State *);
-	int get_hp_level(lua_State *);
+	int get_health_level(lua_State *);
 	int get_evade_level(lua_State *);
 
 	/*

=== modified file 'src/wui/soldierlist.cc'
--- src/wui/soldierlist.cc	2016-02-09 08:07:48 +0000
+++ src/wui/soldierlist.cc	2016-02-21 19:03:44 +0000
@@ -41,7 +41,7 @@
 using Widelands::SoldierControl;
 
 /**
- * Iconic representation of soldiers, including their levels and current HP.
+ * Iconic representation of soldiers, including their levels and current health.
  */
 struct SoldierPanel : UI::Panel {
 	using SoldierFn = boost::function<void (const Soldier *)>;
@@ -257,9 +257,9 @@
 		uint32_t level = soldier->get_attack_level();
 		level = level * (soldier->descr().get_max_defense_level() + 1) + soldier->get_defense_level();
 		level = level * (soldier->descr().get_max_evade_level() + 1) + soldier->get_evade_level();
-		level = level * (soldier->descr().get_max_hp_level() + 1) + soldier->get_hp_level();
+		level = level * (soldier->descr().get_max_health_level() + 1) + soldier->get_health_level();
 
-		uint32_t health = soldier->get_current_hitpoints();
+		uint32_t health = soldier->get_current_health();
 
 		if (health != icon.cache_health || level != icon.cache_level) {
 			icon.cache_level = level;
@@ -484,7 +484,7 @@
 
 	m_infotext.set_text(
 		(boost::format(_("HP: %1$u/%2$u  AT: %3$u/%4$u  DE: %5$u/%6$u  EV: %7$u/%8$u"))
-			% soldier->get_hp_level() % soldier->descr().get_max_hp_level()
+			% soldier->get_health_level() % soldier->descr().get_max_health_level()
 			% soldier->get_attack_level() % soldier->descr().get_max_attack_level()
 			% soldier->get_defense_level() % soldier->descr().get_max_defense_level()
 			% soldier->get_evade_level() % soldier->descr().get_max_evade_level()

=== modified file 'src/wui/trainingsitewindow.cc'
--- src/wui/trainingsitewindow.cc	2016-01-28 05:24:34 +0000
+++ src/wui/trainingsitewindow.cc	2016-02-21 19:03:44 +0000
@@ -25,7 +25,6 @@
 #include "wui/soldierlist.h"
 
 using Widelands::TrainingSite;
-using Widelands::atrAttack;
 
 static char const * pic_tab_military = "images/wui/buildings/menu_tab_military.png";
 

=== modified file 'test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua'
--- test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua	2016-02-15 19:02:29 +0000
+++ test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua	2016-02-21 19:03:44 +0000
@@ -386,9 +386,9 @@
    assert_equal(nil, egbase:get_building_description("barbarians_trainingcamp").max_evade)
 end
 
-function test_descr:test_max_hp()
-   assert_equal(nil, egbase:get_building_description("barbarians_battlearena").max_hp)
-   assert_equal(2, egbase:get_building_description("barbarians_trainingcamp").max_hp)
+function test_descr:test_max_health()
+   assert_equal(nil, egbase:get_building_description("barbarians_battlearena").max_health)
+   assert_equal(2, egbase:get_building_description("barbarians_trainingcamp").max_health)
 end
 
 function test_descr:test_min_attack()
@@ -407,9 +407,9 @@
    assert_equal(nil, egbase:get_building_description("barbarians_trainingcamp").min_evade)
 end
 
-function test_descr:test_min_hp()
-   assert_equal(nil, egbase:get_building_description("barbarians_battlearena").min_hp)
-   assert_equal(0, egbase:get_building_description("barbarians_trainingcamp").min_hp)
+function test_descr:test_min_health()
+   assert_equal(nil, egbase:get_building_description("barbarians_battlearena").min_health)
+   assert_equal(0, egbase:get_building_description("barbarians_trainingcamp").min_health)
 end
 
 function test_descr:test_type()

=== modified file 'test/maps/lua_testsuite.wmf/scripting/warehouse.lua'
--- test/maps/lua_testsuite.wmf/scripting/warehouse.lua	2015-10-31 12:11:44 +0000
+++ test/maps/lua_testsuite.wmf/scripting/warehouse.lua	2016-02-21 19:03:44 +0000
@@ -168,8 +168,8 @@
    assert_equal(2, self.w:get_soldiers({1,1,0,1}))
    assert_equal(0, self.w:get_soldiers({2,1,0,1}))
 end
-function warehouse_tests:test_set_soldiers_hp_too_high()
-   assert_error("hp too high", function()
+function warehouse_tests:test_set_soldiers_health_too_high()
+   assert_error("health too high", function()
       self.w:set_soldiers({10,0,0,0}, 1)
    end)
 end


Follow ups