← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1554552 into lp:widelands

 

TiborB has proposed merging lp:~widelands-dev/widelands/bug-1554552 into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1554552 in widelands: "wounded attacking soldiers failing to retreat"
  https://bugs.launchpad.net/widelands/+bug/1554552

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1554552/+merge/289830

I got rid of ui32var3 task's variable, that misbehaved and replaced it with retreat_health_ variable (soldier's atribute)

When you will test it, you can keep soldier's DBG window opened and watch what is going on (also with retreat_health_)
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1554552 into lp:widelands.
=== modified file 'src/logic/map_objects/bob.h'
--- src/logic/map_objects/bob.h	2016-02-07 09:30:20 +0000
+++ src/logic/map_objects/bob.h	2016-03-22 19:48:28 +0000
@@ -213,7 +213,7 @@
 		const Task           * task;
 		int32_t                ivar1;
 		int32_t                ivar2;
-		union                  {int32_t ivar3; uint32_t ui32var3;};
+		int32_t                ivar3;
 		ObjectPointer             objvar1;
 		std::string            svar1;
 

=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc	2016-03-08 08:22:28 +0000
+++ src/logic/map_objects/tribes/soldier.cc	2016-03-22 19:48:28 +0000
@@ -223,6 +223,7 @@
 	attack_level_  = 0;
 	defense_level_ = 0;
 	evade_level_   = 0;
+	retreat_health_    = 0;
 
 	current_health_    = get_max_health();
 
@@ -238,6 +239,7 @@
 	attack_level_  = 0;
 	defense_level_ = 0;
 	evade_level_   = 0;
+	retreat_health_ = 0;
 
 	current_health_ = get_max_health();
 
@@ -301,6 +303,11 @@
 
 	evade_level_ = evade;
 }
+void Soldier::set_retreat_health(const uint32_t retreat) {
+	assert(retreat <= get_max_health());
+
+	retreat_health_ = retreat;
+}
 
 uint32_t Soldier::get_level(TrainingAttribute const at) const {
 	switch (at) {
@@ -696,12 +703,13 @@
 	state.ivar3    = 0; // Counts how often the soldier is blocked in a row
 
 	state.ivar1    |= CF_RETREAT_WHEN_INJURED;
-	state.ui32var3 = kRetreatWhenHealthDropsBelowThisPercentage * get_max_health() / 100;
+	set_retreat_health(kRetreatWhenHealthDropsBelowThisPercentage * get_max_health() / 100);
 
 	// Injured soldiers are not allowed to attack
-	if (state.ui32var3 > get_current_health()) {
-		state.ui32var3 = get_current_health();
+	if (get_retreat_health() > get_current_health()) {
+		set_retreat_health(get_current_health());
 	}
+	molog("[attack] starting, retreat health: %d\n", get_retreat_health());
 }
 
 void Soldier::attack_update(Game & game, State & state)
@@ -883,12 +891,16 @@
 
 	if
 		(!enemy ||
-		 ((state.ivar1 & CF_RETREAT_WHEN_INJURED) &&
-		  state.ui32var3 > get_current_health() &&
+		 (get_retreat_health() > get_current_health() &&
 		  defenders > 0))
 	{
+		if (get_retreat_health() > get_current_health()) {
+			assert(state.ivar1 & CF_RETREAT_WHEN_INJURED);
+		}
+
 		// Injured soldiers will try to return to safe site at home.
-		if (state.ui32var3 > get_current_health() && defenders) {
+		if (get_retreat_health() > get_current_health() && defenders) {
+			molog(" [attack] badly injured (%d), retreating...\n", get_current_health());
 			state.coords = Coords::null();
 			state.objvar1 = nullptr;
 		}
@@ -1016,15 +1028,19 @@
 	// Here goes 'configuration'
 	if (stayhome) {
 		state.ivar1 |= CF_DEFEND_STAYHOME;
+		set_retreat_health(0);
 	} else {
 		/* Flag defenders are not allowed to flee, to avoid abuses */
 		state.ivar1 |= CF_RETREAT_WHEN_INJURED;
-		state.ui32var3 = get_max_health() * kRetreatWhenHealthDropsBelowThisPercentage / 100;
+		set_retreat_health(get_max_health() * kRetreatWhenHealthDropsBelowThisPercentage / 100);
 
 		// Soldier must defend even if he starts injured
-		if (state.ui32var3 < get_current_health())
-			state.ui32var3 = get_current_health();
+		// (current health is below retreat treshold)
+		if (get_retreat_health() > get_current_health()) {
+			set_retreat_health(get_current_health());
+		}
 	}
+	molog("[defense] retreat health set: %d\n", get_retreat_health());
 }
 
 struct SoldierDistance {
@@ -1128,13 +1144,15 @@
 
 	if
 		(soldiers.empty() ||
-		 ((state.ivar1 & CF_RETREAT_WHEN_INJURED) &&
-		  get_current_health() < state.ui32var3))
+		 (get_current_health() < get_retreat_health()))
 	{
+		if (get_retreat_health() > get_current_health()) {
+			assert(state.ivar1 & CF_RETREAT_WHEN_INJURED);
+		}
 
-		if (get_current_health() < state.ui32var3)
-			molog("[defense] I am heavily injured!\n");
-		else
+		if (get_current_health() < get_retreat_health()) {
+			molog("[defense] I am heavily injured (%d)!\n", get_current_health());
+		} else
 			molog("[defense] no enemy soldiers found, ending task\n");
 
 		// If no enemy was found, return home
@@ -1158,7 +1176,6 @@
 					 descr().get_right_walk_anims(does_carry_ware()),
 					 true);
 		}
-
 		molog("[defense] return home\n");
 		if
 			(start_task_movepath
@@ -1602,7 +1619,7 @@
 	if
 		(!attackdefense ||
 		 ((attackdefense->ivar1 & CF_RETREAT_WHEN_INJURED) &&
-		  attackdefense->ui32var3 > get_current_health()))
+		  get_retreat_health() > get_current_health()))
 	{
 		// Retreating or non-combatant soldiers act like normal bobs
 		return Bob::check_node_blocked(game, field, commit);
@@ -1718,6 +1735,7 @@
 		("Levels: %d/%d/%d/%d\n",
 		 health_level_, attack_level_, defense_level_, evade_level_);
 	molog ("Health:   %d/%d\n", current_health_, get_max_health());
+	molog ("Retreat:  %d\n", retreat_health_);
 	molog ("Attack:   %d-%d\n", get_min_attack(), get_max_attack());
 	molog ("Defense:  %d%%\n", get_defense());
 	molog ("Evade:    %d%%\n", get_evade());

=== modified file 'src/logic/map_objects/tribes/soldier.h'
--- src/logic/map_objects/tribes/soldier.h	2016-02-21 19:43:07 +0000
+++ src/logic/map_objects/tribes/soldier.h	2016-03-22 19:48:28 +0000
@@ -159,6 +159,7 @@
 	void set_attack_level (uint32_t);
 	void set_defense_level(uint32_t);
 	void set_evade_level  (uint32_t);
+	void set_retreat_health (uint32_t);
 	uint32_t get_level (TrainingAttribute) const;
 	uint32_t get_health_level () const {return health_level_;}
 	uint32_t get_attack_level () const {return attack_level_;}
@@ -178,6 +179,7 @@
 	void draw_info_icon(RenderTarget &, Point, bool anchor_below) const;
 
 	uint32_t get_current_health() const {return current_health_;}
+	uint32_t get_retreat_health() const {return retreat_health_;}
 	uint32_t get_max_health() const;
 	uint32_t get_min_attack() const;
 	uint32_t get_max_attack() const;
@@ -256,6 +258,7 @@
 	uint32_t attack_level_;
 	uint32_t defense_level_;
 	uint32_t evade_level_;
+	uint32_t retreat_health_;
 
 	/// This is used to replicate walk for soldiers but only just before and
 	/// just after figthing in a battle, to draw soldier at proper position.


Follow ups