From ba017c443d6fb3847696a892203f4a68388cffd7 Mon Sep 17 00:00:00 2001
From: AlexVinS <alexvins@users.noreply.github.com>
Date: Sat, 7 Nov 2015 11:42:06 +0300
Subject: [PATCH 1/2] Start from diff of pull request #124 from vcmi/issue/1372

---
 client/battle/CBattleInterface.cpp |  15 +++-
 lib/GameConstants.cpp              |   1 +
 lib/GameConstants.h                |   1 +
 lib/NetPacksLib.cpp                |   2 +-
 server/CGameHandler.cpp            | 112 ++++++++++++++++++++++-------
 server/CGameHandler.h              |   9 ++-
 6 files changed, 107 insertions(+), 33 deletions(-)

diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp
index 83bf8fde7..d43467c3f 100644
--- a/client/battle/CBattleInterface.cpp
+++ b/client/battle/CBattleInterface.cpp
@@ -2163,7 +2163,15 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 				break;
 			case RISE_DEMONS:
 				if (shere && ourStack && !shere->alive())
-					legalAction = true;
+				{
+					if(!(shere->hasBonusOfType(Bonus::UNDEAD) 
+						|| shere->hasBonusOfType(Bonus::NON_LIVING) 
+						|| vstd::contains(shere->state, EBattleStackState::SUMMONED)
+						|| vstd::contains(shere->state, EBattleStackState::CLONED)
+						|| shere->hasBonusOfType(Bonus::SIEGE_WEAPON)
+						))
+						legalAction = true;
+				}					
 				break;
 		}
 		if (legalAction)
@@ -2320,7 +2328,10 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 				break;
 			case RISE_DEMONS:
 				cursorType = ECursor::SPELLBOOK;
-				realizeAction = [=]{ giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); };
+				realizeAction = [=]
+				{ 
+					giveCommand(Battle::DAEMON_SUMMONING, myNumber, activeStack->ID); 
+				};
 				break;
 			case CATAPULT:
 				cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT;
diff --git a/lib/GameConstants.cpp b/lib/GameConstants.cpp
index 864b1aba2..712cdd722 100644
--- a/lib/GameConstants.cpp
+++ b/lib/GameConstants.cpp
@@ -19,6 +19,7 @@
 #include "spells/CSpellHandler.h"
 
 const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2);
+const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(255);
 const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253);
 const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254);
 const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255);
diff --git a/lib/GameConstants.h b/lib/GameConstants.h
index 623eb29f5..1ece2170a 100644
--- a/lib/GameConstants.h
+++ b/lib/GameConstants.h
@@ -236,6 +236,7 @@ class SlotID : public BaseForID<SlotID, si32>
 	friend class CNonConstInfoCallback;
 
 	DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER;
+	DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///<for all summoned creatures, only during battle
 
 	bool validSlot() const
 	{
diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp
index 46d515a78..a5b5cd314 100644
--- a/lib/NetPacksLib.cpp
+++ b/lib/NetPacksLib.cpp
@@ -1616,7 +1616,7 @@ DLL_LINKAGE void BattleStackAdded::applyGs(CGameState *gs)
 	}
 
 	CStackBasicDescriptor csbd(creID, amount);
-	CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID(255), pos); //TODO: netpacks?
+	CStack * addedStack = gs->curB->generateNewStack(csbd, attacker, SlotID::SUMMONED_SLOT_PLACEHOLDER, pos); //TODO: netpacks?
 	if (summoned)
 		addedStack->state.insert(EBattleStackState::SUMMONED);
 
diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp
index 368201a81..30cdeab52 100644
--- a/server/CGameHandler.cpp
+++ b/server/CGameHandler.cpp
@@ -662,8 +662,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 		sendAndApply(&cs);
 	}
 
-	cab1.takeFromArmy(this);
-	cab2.takeFromArmy(this); //take casualties after battle is deleted
+	cab1.updateArmy(this);
+	cab2.updateArmy(this); //take casualties after battle is deleted
 
 	//if one hero has lost we will erase him
 	if(battleResult.data->winner!=0 && hero1)
@@ -3907,18 +3907,16 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 			//TODO: From Strategija:
 			//Summon Demon is a level 2 spell.
 		{
-			StartAction start_action(ba);
-			sendAndApply(&start_action);
-
 			const CStack *summoner = gs->curB->battleGetStackByID(ba.stackNumber),
 				*destStack = gs->curB->battleGetStackByPos(ba.destinationTile, false);
 
+			CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
 			BattleStackAdded bsa;
 			bsa.attacker = summoner->attackerOwned;
 
-			bsa.creID = CreatureID(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype); //in case summoner can summon more than one type of monsters... scream!
+			bsa.creID = summonedType; 
 			ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum());
-			ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;
+			ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect
 
 			ui64 canRiseHp = std::min(targetHealth, risedHp);
 			ui32 canRiseAmount = canRiseHp / VLC->creh->creatures.at(bsa.creID)->MaxHealth();
@@ -3930,6 +3928,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 
 			if (bsa.amount) //there's rare possibility single creature cannot rise desired type
 			{
+				StartAction start_action(ba);
+				sendAndApply(&start_action);
+
 				BattleStacksRemoved bsr; //remove body
 				bsr.stackIDs.insert(destStack->ID);
 				sendAndApply(&bsr);
@@ -3941,9 +3942,9 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 				ssp.val = -1;
 				ssp.absolute = false;
 				sendAndApply(&ssp);
-			}
 
-			sendAndApply(&end_action);
+				sendAndApply(&end_action);
+			}
 			break;
 		}
 		case Battle::MONSTER_SPELL:
@@ -5878,13 +5879,52 @@ void CGameHandler::duelFinished()
 	return;
 }
 
-CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat)
+CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat):
+	army(_army)
 {
 	heroWithDeadCommander = ObjectInstanceID();
 
 	PlayerColor color = army->tempOwner;
 	if(color == PlayerColor::UNFLAGGABLE)
 		color = PlayerColor::NEUTRAL;
+		
+	auto killStack = [&, this](const SlotID slot, const CStackInstance * instance)
+	{
+		StackLocation sl(army, slot);
+		newStackCounts.push_back(TStackAndItsNewCount(sl, 0));
+		if(nullptr == instance)
+			return;
+		auto c = dynamic_cast <const CCommanderInstance *>(instance);
+		if (c) //switch commander status to dead
+		{
+			auto h = dynamic_cast <const CGHeroInstance *>(army);
+			if (h && h->commander == c)
+				heroWithDeadCommander = army->id; //TODO: unify commander handling
+		}
+	};
+
+	//1. Find removed stacks.
+	for(const auto & slotInfo : army->stacks)
+	{
+		const SlotID slot = slotInfo.first;
+		const CStackInstance * instance = slotInfo.second;
+
+		if(nullptr != instance)//just in case
+		{
+			bool found = false;
+			for(const CStack * sta : bat->stacks)
+			{
+				if(sta->base == instance)
+				{
+					found = true;
+					break;
+				}
+			}
+			//stack in this slot was removed == it is dead
+			if(!found)
+				killStack(slot, instance);
+		}
+	}
 
 	for(CStack *st : bat->stacks)
 	{
@@ -5896,7 +5936,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
 		//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor
 		st->count = std::max (0, st->count - st->resurrected);
 
-		if (!st->count && !st->base) //we can imagine stacks of war mahcines that are not spawned by artifacts?
+		if (!st->count && !st->base) //we can imagine stacks of war machines that are not spawned by artifacts?
 		{
 			auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber);
 			//catapult artifact remain even if "creature" killed in siege
@@ -5907,29 +5947,32 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
 					removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
 			}
 		}
-
-		if(!army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))
+		
+		if(army->slotEmpty(st->slot))
 		{
-			StackLocation sl(army, st->slot);
-			if(st->alive())
-				newStackCounts.push_back(std::pair<StackLocation, int>(sl, st->count));
-			else
-				newStackCounts.push_back(std::pair<StackLocation, int>(sl, 0));
-		}
-		if (st->base && !st->count)
-		{
-			auto c = dynamic_cast <const CCommanderInstance *>(st->base);
-			if (c) //switch commander status to dead
+			if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive() && st->count > 0)
 			{
-				auto h = dynamic_cast <const CGHeroInstance *>(army);
-				if (h && h->commander == c)
-					heroWithDeadCommander = army->id; //TODO: unify commander handling
+				//this stack was permanently summoned
+				const CreatureID summonedType = st->type->idNumber;
+				summoned[summonedType] += st->count;
+			}			
+		}
+		else
+		{
+			if(st->count == 0 || !st->alive())
+			{
+				killStack(st->slot, st->base);
+			}
+			else if(st->count < army->getStackCount(st->slot))
+			{			
+				StackLocation sl(army, st->slot);
+				newStackCounts.push_back(TStackAndItsNewCount(sl, st->count));
 			}
 		}
 	}
 }
 
-void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh)
+void CasualtiesAfterBattle::updateArmy(CGameHandler *gh)
 {
 	for(TStackAndItsNewCount &ncount : newStackCounts)
 	{
@@ -5938,6 +5981,21 @@ void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh)
 		else
 			gh->eraseStack(ncount.first, true);
 	}
+	for(auto summoned_iter : summoned)
+	{
+		SlotID slot = army->getSlotFor(summoned_iter.first);
+		if(slot.validSlot())
+		{
+			StackLocation location(army, slot);
+			gh->addToSlot(location, summoned_iter.first.toCreature(), summoned_iter.second);
+		}
+		else
+		{
+			//even if it will be possible to summon anything permanently it should be checked for free slot
+			//necromancy is handled separately
+			gh->complain("No free slot to put summoned creature");
+		}
+	}
 	for (auto al : removedWarMachines)
 	{
 		gh->removeArtifact(al);
diff --git a/server/CGameHandler.h b/server/CGameHandler.h
index 104979140..e8ae1153b 100644
--- a/server/CGameHandler.h
+++ b/server/CGameHandler.h
@@ -69,13 +69,16 @@ public:
 struct CasualtiesAfterBattle
 {
 	typedef std::pair<StackLocation, int> TStackAndItsNewCount;
+	typedef std::map<CreatureID, TQuantity> TSummoned;
 	enum {ERASE = -1};
+	const CArmedInstance * army;
 	std::vector<TStackAndItsNewCount> newStackCounts;
 	std::vector<ArtifactLocation> removedWarMachines;
-	ObjectInstanceID heroWithDeadCommander; //TODO: unify stack loactions
+	TSummoned summoned;
+	ObjectInstanceID heroWithDeadCommander; //TODO: unify stack locations
 
-	CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat);
-	void takeFromArmy(CGameHandler *gh);
+	CasualtiesAfterBattle(const CArmedInstance * _army, BattleInfo *bat);
+	void updateArmy(CGameHandler *gh);
 };
 
 class CGameHandler : public IGameCallback, CBattleInfoCallback

From 16e0d188807926c53dc5c84e41ac2f762d5ad39d Mon Sep 17 00:00:00 2001
From: AlexVinS <alexvins@users.noreply.github.com>
Date: Sat, 30 Jan 2016 00:53:53 +0300
Subject: [PATCH 2/2] Added  special slots for war machines and arrow towers

---
 lib/BattleState.cpp     | 16 +++++++--------
 lib/GameConstants.cpp   |  5 ++++-
 lib/GameConstants.h     |  6 ++++--
 server/CGameHandler.cpp | 44 ++++++++++++++++++++++++++++++-----------
 4 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp
index 178f9b961..5c6fdefb4 100644
--- a/lib/BattleState.cpp
+++ b/lib/BattleState.cpp
@@ -469,7 +469,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
 		auto handleWarMachine= [&](int side, ArtifactPosition artslot, CreatureID cretype, BattleHex hex)
 		{
 			if(heroes[side] && heroes[side]->getArt(artslot))
-				stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID(255), hex));
+				stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID::WAR_MACHINES_SLOT, hex));
 		};
 
 		handleWarMachine(0, ArtifactPosition::MACH1, CreatureID::BALLISTA, 52);
@@ -526,15 +526,15 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
 	if (curB->town && curB->town->fortLevel() >= CGTownInstance::CITADEL)
 	{
 		// keep tower
-		CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -2);
+		CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -2);
 		stacks.push_back(stack);
 
 		if (curB->town->fortLevel() >= CGTownInstance::CASTLE)
 		{
 			// lower tower + upper tower
-			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -4);
+			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -4);
 			stacks.push_back(stack);
-			stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -3);
+			stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -3);
 			stacks.push_back(stack);
 		}
 
@@ -712,7 +712,7 @@ std::shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile)
 
 BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType)
 {
-	static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap = 
+	static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap =
 	{
 		{BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD},
 		{BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND},
@@ -1141,7 +1141,7 @@ bool CStack::ableToRetaliate() const //FIXME: crash after clone is killed
 
 ui8 CStack::counterAttacksTotal() const
 {
-	//after dispell bonus should remain during current round 
+	//after dispell bonus should remain during current round
 	ui8 val = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
 	vstd::amax(counterAttacksTotalCache, val);
 	return counterAttacksTotalCache;
@@ -1183,9 +1183,9 @@ ui32 CStack::calculateHealedHealthPoints(ui32 toHeal, const bool resurrect) cons
 ui8 CStack::getSpellSchoolLevel(const CSpell * spell, int * outSelectedSchool) const
 {
 	int skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id));
-	
+
 	vstd::abetween(skill, 0, 3);
-	
+
 	return skill;
 }
 
diff --git a/lib/GameConstants.cpp b/lib/GameConstants.cpp
index 712cdd722..a5a4ca7f1 100644
--- a/lib/GameConstants.cpp
+++ b/lib/GameConstants.cpp
@@ -19,7 +19,10 @@
 #include "spells/CSpellHandler.h"
 
 const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2);
-const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(255);
+const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(-3);
+const SlotID SlotID::WAR_MACHINES_SLOT = SlotID(-4);
+const SlotID SlotID::ARROW_TOWERS_SLOT = SlotID(-5);
+
 const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253);
 const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254);
 const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255);
diff --git a/lib/GameConstants.h b/lib/GameConstants.h
index 1ece2170a..d75ffade5 100644
--- a/lib/GameConstants.h
+++ b/lib/GameConstants.h
@@ -237,6 +237,8 @@ class SlotID : public BaseForID<SlotID, si32>
 
 	DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER;
 	DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///<for all summoned creatures, only during battle
+	DLL_LINKAGE static const SlotID WAR_MACHINES_SLOT; ///<for all war machines during battle
+	DLL_LINKAGE static const SlotID ARROW_TOWERS_SLOT; ///<for all arrow towers during battle
 
 	bool validSlot() const
 	{
@@ -444,11 +446,11 @@ namespace ESpellCastProblem
 
 namespace ECastingMode
 {
-	enum ECastingMode 
+	enum ECastingMode
 	{
 		HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack
 		MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING,
-		SPELL_LIKE_ATTACK, 
+		SPELL_LIKE_ATTACK,
 		PASSIVE_CASTING//f.e. opening battle spells
 	};
 }
diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp
index 30cdeab52..3740fcb7f 100644
--- a/server/CGameHandler.cpp
+++ b/server/CGameHandler.cpp
@@ -3914,7 +3914,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 			BattleStackAdded bsa;
 			bsa.attacker = summoner->attackerOwned;
 
-			bsa.creID = summonedType; 
+			bsa.creID = summonedType;
 			ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum());
 			ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect
 
@@ -5887,7 +5887,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl
 	PlayerColor color = army->tempOwner;
 	if(color == PlayerColor::UNFLAGGABLE)
 		color = PlayerColor::NEUTRAL;
-		
+
 	auto killStack = [&, this](const SlotID slot, const CStackInstance * instance)
 	{
 		StackLocation sl(army, slot);
@@ -5928,47 +5928,67 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl
 
 	for(CStack *st : bat->stacks)
 	{
-		if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks
+		if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account temporary summoned stacks
 			continue;
 		if (st->owner != color) //remove only our stacks
 			continue;
 
+		logGlobal->debugStream() << "Calculating casualties for " << st->nodeName();
+
 		//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor
 		st->count = std::max (0, st->count - st->resurrected);
 
-		if (!st->count && !st->base) //we can imagine stacks of war machines that are not spawned by artifacts?
+		if(st->slot == SlotID::ARROW_TOWERS_SLOT)
+		{
+			//do nothing
+			logGlobal->debugStream() << "Ignored arrow towers stack";
+		}
+		else if(st->slot == SlotID::WAR_MACHINES_SLOT)
 		{
 			auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber);
-			//catapult artifact remain even if "creature" killed in siege
-			if(warMachine != ArtifactID::NONE && warMachine != ArtifactID::CATAPULT)
+
+			if(warMachine == ArtifactID::NONE)
 			{
+				logGlobal->errorStream() << "Invalid creature in war machine virtual slot: " << st->nodeName();
+			}
+			//catapult artifact remain even if "creature" killed in siege
+			else if(warMachine != ArtifactID::CATAPULT && !st->count)
+			{
+				logGlobal->debugStream() << "War machine has been destroyed";
 				auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
 				if (hero)
 					removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
+				else
+					logGlobal->errorStream() << "War machine in army without hero";
 			}
 		}
-		
-		if(army->slotEmpty(st->slot))
+		else if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER)
 		{
-			if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive() && st->count > 0)
+			if(st->alive() && st->count > 0)
 			{
+				logGlobal->debugStream() << "Stack has been permanently summoned";
 				//this stack was permanently summoned
 				const CreatureID summonedType = st->type->idNumber;
 				summoned[summonedType] += st->count;
-			}			
+			}
 		}
-		else
+		else if(st->base && !army->slotEmpty(st->slot))
 		{
 			if(st->count == 0 || !st->alive())
 			{
 				killStack(st->slot, st->base);
+				logGlobal->debugStream() << "Stack has been destroyed";
 			}
 			else if(st->count < army->getStackCount(st->slot))
-			{			
+			{
 				StackLocation sl(army, st->slot);
 				newStackCounts.push_back(TStackAndItsNewCount(sl, st->count));
 			}
 		}
+		else
+		{
+			logGlobal->warnStream() << "Unhandled stack " << st->nodeName();
+		}
 	}
 }