From de0530e856a3ffb0480d2df2e84c8777afc93d40 Mon Sep 17 00:00:00 2001
From: Joris Dauphin <joris.dauphin@gmail.com>
Date: Thu, 7 Jul 2011 12:40:27 +0200
Subject: [PATCH] Some Clean up in Ai Module Fix missing RefDecrease in AiForce
 Remove unused flag MustTransport remove Big unused Array
 units_with_resource[MaxCost][UnitMax] in AiCollectResources

---
 src/ai/ai.cpp          |   4 +-
 src/ai/ai_force.cpp    | 338 ++++++++++++++++++-----------------------
 src/ai/ai_local.h      | 101 ++++++------
 src/ai/ai_magic.cpp    |  12 +-
 src/ai/ai_plan.cpp     |  19 +--
 src/ai/ai_resource.cpp | 107 +++++--------
 src/ai/script_ai.cpp   |   6 +-
 7 files changed, 243 insertions(+), 344 deletions(-)

diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp
index 8151668a1..c3012c115 100644
--- a/src/ai/ai.cpp
+++ b/src/ai/ai.cpp
@@ -316,8 +316,8 @@ static void SaveAiPlayer(CFile *file, int plynr, PlayerAi *ai)
 			file->printf(" %d, \"%s\",", UnitNumber(aiunit),
 				aiunit.Type->Ident.c_str());
 		}
-		file->printf("},\n    \"state\", %d, \"goalx\", %d, \"goaly\", %d, \"must-transport\", %d,",
-			ai->Force[i].State, ai->Force[i].GoalPos.x, ai->Force[i].GoalPos.y, ai->Force[i].MustTransport);
+		file->printf("},\n    \"state\", %d, \"goalx\", %d, \"goaly\", %d,",
+			ai->Force[i].State, ai->Force[i].GoalPos.x, ai->Force[i].GoalPos.y);
 		file->printf("},\n");
 	}
 
diff --git a/src/ai/ai_force.cpp b/src/ai/ai_force.cpp
index 147bd4594..4b7f61c9f 100644
--- a/src/ai/ai_force.cpp
+++ b/src/ai/ai_force.cpp
@@ -44,8 +44,6 @@
 #include "actions.h"
 #include "map.h"
 #include "depend.h"
-#include "pathfinder.h"
-#include "player.h"
 
 /*----------------------------------------------------------------------------
 --  Types
@@ -78,10 +76,27 @@ struct AiForceEnemyFinder {
 	AiForceEnemyFinder(AiForce *force):	enemy(NULL) {
 		force->Units.for_each_if(*this);
 	}
-
 };
 
-struct AiForceAttackSender {
+class AiForceAttackSender {
+public:
+	//  Send all units in the force to enemy at pos.
+	AiForceAttackSender(int force, const Vec2i &pos) : goalPos(pos), delta(0) {
+		DebugPrint("%d: Attacking with force #%d\n" _C_ AiPlayer->Player->Index _C_ force);
+		AiForce *fptr = &AiPlayer->Force[force];
+		fptr->Attacking = true;
+		fptr->State = AiForceAttackingState_Attacking;
+		fptr->Units.for_each(*this);
+	}
+
+	AiForceAttackSender(AiForce *force, const Vec2i &pos) :
+		 goalPos(pos), delta(0) {
+		DebugPrint("%d: Attacking with force #%lu\n" _C_ AiPlayer->Player->Index
+			 _C_ (long unsigned int)(force  - &(AiPlayer->Force[0])));
+		force->Attacking = true;
+		force->State = AiForceAttackingState_Attacking;
+		force->Units.for_each(*this);
+	}
 
 	inline void operator() (CUnit *const unit) {
 	// this may be problem if units are in bunker and we want sent
@@ -94,32 +109,13 @@ struct AiForceAttackSender {
 				CommandUnload(*unit, goalPos, NULL, FlushCommands);
 			} else if (unit->Type->CanAttack) {
 				CommandAttack(*unit, goalPos,  NULL, FlushCommands);
-			} else /*if (force->State == 2) */{
+			} else {
 				CommandMove(*unit, goalPos, FlushCommands);
 			}
 		}
 	}
 
-	//
-	//  Send all units in the force to enemy at x,y.
-	//
-	AiForceAttackSender(int force, const Vec2i &pos) : goalPos(pos), delta(0) {
-		DebugPrint("%d: Attacking with force #%d\n" _C_ AiPlayer->Player->Index _C_ force);
-		AiForce *fptr = &AiPlayer->Force[force];
-		fptr->Attacking = true;
-		fptr->State = AI_FORCE_STATE_ATTACKING;
-		fptr->Units.for_each(*this);
-	}
-
-	AiForceAttackSender(AiForce *force, const Vec2i &pos) :
-		 goalPos(pos), delta(0) {
-		DebugPrint("%d: Attacking with force #%lu\n" _C_ AiPlayer->Player->Index
-			 _C_ (long unsigned int)(force  - &(AiPlayer->Force[0])));
-		force->Attacking = true;
-		force->State = AI_FORCE_STATE_ATTACKING;
-		force->Units.for_each(*this);
-	}
-
+private:
 	Vec2i goalPos;
 	int delta;
 };
@@ -154,22 +150,16 @@ void AiResetUnitTypeEquiv()
 */
 void AiNewUnitTypeEquiv(CUnitType *a, CUnitType *b)
 {
-	int find;
-	int replace;
-	int i;
-
-	find = UnitTypeEquivs[a->Slot];
-	replace = UnitTypeEquivs[b->Slot];
+	int find = UnitTypeEquivs[a->Slot];
+	int replace = UnitTypeEquivs[b->Slot];
 
 	// Always record equivalences with the lowest unittype.
 	if (find < replace) {
-		i = find;
-		find = replace;
-		replace = i;
+		std::swap(find, replace);
 	}
 
 	// Then just find & replace in UnitTypeEquivs...
-	for (i = 0; i <= UnitTypeMax; ++i) {
+	for (unsigned int i = 0; i <= UnitTypeMax; ++i) {
 		if (UnitTypeEquivs[i] == find) {
 			UnitTypeEquivs[i] = replace;
 		}
@@ -194,12 +184,21 @@ int AiFindUnitTypeEquiv(const CUnitType &unittype, int *result)
 		if (UnitTypeEquivs[i] == search) {
 			// Found one
 			result[count] = i;
-			count++;
+			++count;
 		}
 	}
 	return count;
 }
 
+class UnitTypePrioritySorter_Decreasing
+{
+public:
+	bool operator () (int lhs, int rhs) const
+	{
+		return UnitTypes[lhs]->Priority > UnitTypes[rhs]->Priority;
+	}
+};
+
 /**
 **  Find All unittypes equivalent to a given one, and which are available
 **  UnitType are returned in the prefered order ( ie palladin >> knight... )
@@ -226,35 +225,26 @@ int AiFindAvailableUnitTypeEquiv(const CUnitType &unittype, int *usableTypes)
 	}
 
 	// 3 - Sort by level
-	// We won't have usableTypesCount>4, so simple sort should do it
-	for (int i = 0; i < usableTypesCount - 1; ++i) {
-		int bestlevel = UnitTypes[usableTypes[i]]->Priority;
-		for (int j = i + 1; j < usableTypesCount; ++j) {
-			const int curlevel = UnitTypes[usableTypes[j]]->Priority;
+	std::sort(usableTypes, usableTypes + usableTypesCount, UnitTypePrioritySorter_Decreasing());
 
-			if (curlevel > bestlevel) {
-				std::swap(usableTypes[j], usableTypes[i]);
-				bestlevel = curlevel;
-			}
-		}
-	}
 	return usableTypesCount;
 }
 
 /* =========================== FORCES ========================== */
 
-struct AiForceCounter {
-	unsigned int *data;//[UnitTypeMax + 1];
-
-	inline void operator() (CUnit *const unit) {
-		data[UnitTypeEquivs[unit->Type->Slot]]++;
-	}
-
-	AiForceCounter(CUnitCache &units, unsigned int *d, const size_t len): data(d)
+class AiForceCounter
+{
+public:
+	AiForceCounter(CUnitCache &units, unsigned int *d, const size_t len) : data(d)
 	{
 		memset(data, 0, len);
 		units.for_each(*this);
 	}
+	inline void operator() (CUnit *const unit) {
+		data[UnitTypeEquivs[unit->Type->Slot]]++;
+	}
+private:
+	unsigned int *data;//[UnitTypeMax + 1];
 };
 
 void AiForce::CountTypes(unsigned int *counter, const size_t len) {
@@ -270,9 +260,7 @@ void AiForce::CountTypes(unsigned int *counter, const size_t len) {
 */
 bool AiForce::IsBelongsTo(const CUnitType *type)
 {
-	AiUnitType *aitype;
 	bool flag = false;
-	int slot;
 	unsigned int counter[UnitTypeMax + 1];
 
 	//
@@ -285,11 +273,12 @@ bool AiForce::IsBelongsTo(const CUnitType *type)
 	//
 	Completed = true;
 	for (unsigned int i = 0; i < UnitTypes.size(); ++i) {
-		aitype = &UnitTypes[i];
-		slot = aitype->Type->Slot;
-		if (aitype->Want > counter[slot]) {
+		const AiUnitType &aitype = UnitTypes[i];
+		const int slot = aitype.Type->Slot;
+
+		if (counter[slot] < aitype.Want) {
 			if (UnitTypeEquivs[type->Slot] == slot) {
-				if (aitype->Want - 1 > counter[slot]) {
+				if (counter[slot] < aitype.Want - 1) {
 					Completed = false;
 				}
 				flag = true;
@@ -303,20 +292,17 @@ bool AiForce::IsBelongsTo(const CUnitType *type)
 
 /**
 **  Ai clean units in a force.
-**
 */
-void AiForce::Clean() {
-
-	CUnit *aiunit;
+void AiForce::Clean()
+{
 	unsigned int i = 0;
-	//
+
 	// Release all killed units.
-	//
 	while (i != Units.size()) {
-		aiunit = Units[i];
+		CUnit *aiunit = Units[i];
+
 		if (!aiunit->IsAlive()) {
-			aiunit->GroupId = 0;
-			aiunit->RefsDecrease();
+			InternalRemoveUnit(aiunit);
 			Units.Remove(i);
 			continue;
 		}
@@ -331,34 +317,34 @@ void AiForce::Attack(const Vec2i &pos)
 	Clean();
 
 	Attacking = false;
-	if (Units.size() > 0) {
-		Attacking = true;
+	if (Units.size() == 0) {
+		return;
+	}
+	Attacking = true;
 
-		if (goalPos.x == -1 || goalPos.y == -1) {
-			/* Search in entire map */
-			const CUnit *enemy = AiForceEnemyFinder<false>(this).enemy;
-			if (enemy) {
-				goalPos = enemy->tilePos;
-			}
+	if (goalPos.x == -1 || goalPos.y == -1) {
+		/* Search in entire map */
+		const CUnit *enemy = AiForceEnemyFinder<false>(this).enemy;
+		if (enemy) {
+			goalPos = enemy->tilePos;
 		}
-
-		this->GoalPos = goalPos;
-
-		if (goalPos.x == -1 || goalPos.y == -1) {
-			DebugPrint("%d: Need to plan an attack with transporter\n" _C_ AiPlayer->Player->Index);
-			if (State == AI_FORCE_STATE_WAITING && !PlanAttack()) {
-				DebugPrint("%d: Can't transport\n" _C_ AiPlayer->Player->Index);
-				Attacking = false;
-			}
-			return;
-		}
-
-		//
-		//  Send all units in the force to enemy.
-		//
-		AiForceAttackSender(this, goalPos);
 	}
 
+	this->GoalPos = goalPos;
+
+	if (goalPos.x == -1 || goalPos.y == -1) {
+		DebugPrint("%d: Need to plan an attack with transporter\n" _C_ AiPlayer->Player->Index);
+		if (State == AiForceAttackingState_Waiting && !PlanAttack()) {
+			DebugPrint("%d: Can't transport\n" _C_ AiPlayer->Player->Index);
+			Attacking = false;
+		}
+		return;
+	}
+
+	//
+	//  Send all units in the force to enemy.
+	//
+	AiForceAttackSender(this, goalPos);
 }
 
 AiForceManager::AiForceManager() {
@@ -370,13 +356,13 @@ unsigned int AiForceManager::FindFreeForce(int role)
 {
 	/* find free force */
 	unsigned int f = 0;
-	while (f < forces.size() && (forces[f].State > AI_FORCE_STATE_FREE)) {
+	while (f < forces.size() && (forces[f].State > AiForceAttackingState_Free)) {
 		++f;
 	};
 	if (f == forces.size()) {
 		forces.resize(f + 1);
 	}
-	forces[f].State = AI_FORCE_STATE_WAITING;
+	forces[f].State = AiForceAttackingState_Waiting;
 	forces[f].Role = role;
 	return f;
 }
@@ -399,18 +385,20 @@ void AiForceManager::Clean()
 */
 bool AiForceManager::Assign(CUnit &unit)
 {
-	//
+	if (unit.GroupId != 0) {
+		return false;
+	}
+
 	// Check to which force it belongs
-	//
-	for(unsigned int i = 0; i < forces.size(); ++i)
+	for (unsigned int i = 0; i < forces.size(); ++i)
 	{
-		AiForce *force = &forces[i];
+		AiForce &force = forces[i];
 		// No troops for attacking force
-		if (force->IsAttacking()) {
+		if (force.IsAttacking()) {
 			continue;
 		}
-		if (unit.GroupId == 0 && force->IsBelongsTo(unit.Type)) {
-			force->Insert(unit);
+		if (force.IsBelongsTo(unit.Type)) {
+			force.Insert(unit);
 			unit.GroupId = i + 1;
 			return true;
 		}
@@ -428,11 +416,11 @@ void AiForceManager::CheckUnits(int *counter)
 	// Look through the forces what is missing.
 	for (unsigned int i = 0; i < forces.size(); ++i)
 	{
-		AiForce *force = &forces[i];
+		const AiForce &force = forces[i];
 
-		if (force->State > AI_FORCE_STATE_FREE && force->IsAttacking()) {
-			for (unsigned int j = 0; j < forces[i].Size(); ++j) {
-				const CUnit *unit = forces[i].Units[j];
+		if (force.State > AiForceAttackingState_Free && force.IsAttacking()) {
+			for (unsigned int j = 0; j < force.Size(); ++j) {
+				const CUnit *unit = force.Units[j];
 				attacking[unit->Type->Slot]++;
 			}
 		}
@@ -441,24 +429,24 @@ void AiForceManager::CheckUnits(int *counter)
 	// create missing units
 	for (unsigned int i = 0; i < forces.size(); ++i)
 	{
-		AiForce *force = &forces[i];
+		AiForce &force = forces[i];
 
 		// No troops for attacking force
-		if (force->State == AI_FORCE_STATE_FREE || force->IsAttacking()) {
+		if (force.State == AiForceAttackingState_Free || force.IsAttacking()) {
 			continue;
 		}
-		for (unsigned int j = 0; j < force->UnitTypes.size(); ++j) {
-			const AiUnitType *aiut = &force->UnitTypes[j];
-			const int t = aiut->Type->Slot;
-			const int x = aiut->Want;
-			const int requested = x - (unit_types_count[t] + counter[t] - attacking[t]);
+		for (unsigned int j = 0; j < force.UnitTypes.size(); ++j) {
+			const AiUnitType &aiut = force.UnitTypes[j];
+			const int t = aiut.Type->Slot;
+			const int wantedCount = aiut.Want;
+			const int requested = wantedCount - (unit_types_count[t] + counter[t] - attacking[t]);
 
 			if (requested > 0) {  // Request it.
-				AiAddUnitTypeRequest(*aiut->Type, requested);
+				AiAddUnitTypeRequest(*aiut.Type, requested);
 				counter[t] += requested;
-				force->Completed = false;
+				force.Completed = false;
 			}
-			counter[t] -= x;
+			counter[t] -= wantedCount;
 		}
 	}
 }
@@ -560,7 +548,7 @@ void AiAttackWithForce(unsigned int force)
 
 /**
 **  Attack opponent with forces.
-**	Merge forces in array into one attack force and attack with it
+**  Merge forces in array into one attack force and attack with it
 **  Merge is make because units in one force help each other during attack
 **
 **  @param forces  Array with Force numbers to attack with (array should be finished with -1).
@@ -611,41 +599,41 @@ void AiAttackWithForces(int *forces)
 **
 **  @param aiForce force to group.
 */
-static void AiGroupAttackerForTransport(AiForce *aiForce)
+static void AiGroupAttackerForTransport(AiForce &aiForce)
 {
-	Assert(aiForce->State == AI_FORCE_STATE_BOARDING);
+	Assert(aiForce.State == AiForceAttackingState_Boarding);
 
 	unsigned int nbToTransport = 0;
 	unsigned int transporterIndex = 0;
 	bool goNext = true;
 
-	for (; transporterIndex < aiForce->Size(); ++transporterIndex) {
-		const CUnit *unit = aiForce->Units[transporterIndex];
+	for (; transporterIndex < aiForce.Size(); ++transporterIndex) {
+		const CUnit *unit = aiForce.Units[transporterIndex];
 
 		if (unit->Type->CanTransport() && unit->Type->MaxOnBoard - unit->BoardCount > 0) {
 			nbToTransport = unit->Type->MaxOnBoard - unit->BoardCount;
 			break;
 		}
 	}
-	if (transporterIndex == aiForce->Size()) {
-		aiForce->State++;
+	if (transporterIndex == aiForce.Size()) {
+		aiForce.State = AiForceAttackingState_Attacking;
 		return ;
 	}
-	for (unsigned int i = 0; i < aiForce->Size(); ++i) {
-		const CUnit &unit = *aiForce->Units[i];
-		const CUnit &transporter = *aiForce->Units[transporterIndex];
+	for (unsigned int i = 0; i < aiForce.Size(); ++i) {
+		const CUnit &unit = *aiForce.Units[i];
+		const CUnit &transporter = *aiForce.Units[transporterIndex];
 
 		if (CanTransport(transporter, unit) && unit.Container == NULL) {
 			goNext = false;
 		}
 	}
 	if (goNext == true) {
-		aiForce->State++;
+		aiForce.State = AiForceAttackingState_Attacking;
 		return ;
 	}
-	for (unsigned int i = 0; i < aiForce->Size(); ++i) {
-		CUnit &unit = *aiForce->Units[i];
-		CUnit &transporter = *aiForce->Units[transporterIndex];
+	for (unsigned int i = 0; i < aiForce.Size(); ++i) {
+		CUnit &unit = *aiForce.Units[i];
+		CUnit &transporter = *aiForce.Units[transporterIndex];
 
 		if (transporter.IsIdle() && unit.CurrentOrder()->GetGoal() == &transporter) {
 			CommandFollow(transporter, unit, 0);
@@ -653,16 +641,16 @@ static void AiGroupAttackerForTransport(AiForce *aiForce)
 		if (CanTransport(transporter, unit) && unit.IsIdle() && unit.Container == NULL) {
 			CommandBoard(unit, transporter, FlushCommands);
 			CommandFollow(transporter, unit, 0);
-			if (--nbToTransport == 0) { // full : nxt transporter.
-				for (++transporterIndex; transporterIndex < aiForce->Size(); ++transporterIndex) {
-					const CUnit &nextTransporter = *aiForce->Units[transporterIndex];
+			if (--nbToTransport == 0) { // full : next transporter.
+				for (++transporterIndex; transporterIndex < aiForce.Size(); ++transporterIndex) {
+					const CUnit &nextTransporter = *aiForce.Units[transporterIndex];
 
 					if (nextTransporter.Type->CanTransport()) {
 						nbToTransport = nextTransporter.Type->MaxOnBoard - nextTransporter.BoardCount;
 						break ;
 					}
 				}
-				if (transporterIndex == aiForce->Size()) { // No more transporter.
+				if (transporterIndex == aiForce.Size()) { // No more transporter.
 					break ;
 				}
 			}
@@ -681,7 +669,7 @@ void AiForce::Update()
 
 	if (Size() == 0) {
 		Attacking = false;
-		if (!Defending && State > 0) {
+		if (!Defending && State > AiForceAttackingState_Waiting) {
 			DebugPrint("%d: Attack force #%lu was destroyed, giving up\n"
 				_C_ AiPlayer->Player->Index _C_ (long unsigned int)(this  - &(AiPlayer->Force[0])));
 			Reset(true);
@@ -698,7 +686,7 @@ void AiForce::Update()
 		}
 	}
 	if (Attacking == false) {
-		if (!Defending && State > 0) {
+		if (!Defending && State > AiForceAttackingState_Waiting) {
 			DebugPrint("%d: Attack force #%lu has lost all agresive units, giving up\n"
 				_C_ AiPlayer->Player->Index _C_ (long unsigned int)(this  - &(AiPlayer->Force[0])));
 			Reset(true);
@@ -707,31 +695,30 @@ void AiForce::Update()
 	}
 
 #if 0
-	if (State == AI_FORCE_STATE_WAITING) {
-		if (!AiPlanAttack(force)) {
+	if (State == AiForceAttackingState_Waiting) {
+		if (!this->PlanAttack()) {
 			DebugPrint("Can't transport, look for walls\n");
-			if (!AiFindWall(force)) {
+			if (!AiFindWall(this)) {
 				Attacking = false;
 				return ;
 			}
 		}
-		State = AI_FORCE_STATE_BOARDING;
+		State = AiForceAttackingState_Boarding;
 	}
 #endif
 
-	if (State == AI_FORCE_STATE_BOARDING) {
-		AiGroupAttackerForTransport(this);
+	if (State == AiForceAttackingState_Boarding) {
+		AiGroupAttackerForTransport(*this);
 		return ;
 	}
 
-
 	// Find a unit that isn't idle
 	unit = NoUnitP;
-	if (State == AI_FORCE_STATE_ATTACKING) {
+	if (State == AiForceAttackingState_Attacking) {
 		for (unsigned int i = 0; i < Size(); ++i) {
 			CUnit *aiunit = Units[i];
 			if (!aiunit->IsIdle()) {
-				// Found an idle unit, use it if we find nothing better
+				// Found an no-idle unit, use it if we find nothing better
 				if (unit == NoUnitP) {
 					unit = aiunit;
 				}
@@ -772,44 +759,8 @@ void AiForce::Update()
 		}
 	} else { // Everyone is idle, find a new target
 		Vec2i pos;
-//FIXME: rb - I don't know if AI can use transport now
-#if 0
-		if (State == AI_FORCE_STATE_ATTACKING) {
-			unit = NULL;
-
-			for (unsigned int i = 0; i < Units.size(); ++i) {
-				CUnit *aiunit = Units[i];
-				if (aiunit->Type->CanAttack) {
-					unit = AttackUnitsInDistance(aiunit, MaxMapWidth);
-					break;
-				}
-			}
-			if (!unit) {
-				// No enemy found, give up
-				// FIXME: should the force go home or keep trying to attack?
-				DebugPrint("Attack force can't find a target, giving up\n");
-				Attacking = false;
-				return;
-			}
-			pos = unit->tilePos;
-		} else {
-			pos = this->GoalPos;
-		}
-		for (unsigned int i = 0; i < Units.size(); ++i) {
-			CUnit *aiunit = Units[i];
-
-			if (aiunit->Type->CanTransport() && aiunit->BoardCount > 0) {
-				CommandUnload(aiunit, pos, NULL, FlushCommands);
-			} else if (aiunit->Type->CanAttack) {
-				CommandAttack(aiunit, pos, NULL, FlushCommands);
-			} else if (force->State == 2) {
-				CommandMove(aiunit, pos, FlushCommands);
-			}
-		}
-		force->State = 3;
-#else
-		if (State == AI_FORCE_STATE_ATTACKING) {
 
+		if (State == AiForceAttackingState_Attacking) {
 			unit = AiForceEnemyFinder<false>(this).enemy;
 
 			if (!unit) {
@@ -825,7 +776,6 @@ void AiForce::Update()
 			pos = this->GoalPos;
 		}
 		AiForceAttackSender(this, pos);
-#endif
 	}
 }
 
@@ -833,30 +783,30 @@ void AiForceManager::Update()
 {
 	for(unsigned int f = 0; f < forces.size(); ++f)
 	{
-		AiForce *force = &forces[f];
+		AiForce &force = forces[f];
 		//
 		//  Look if our defenders still have enemies in range.
 		//
-		if (force->Defending) {
-			force->Clean();
+		if (force.Defending) {
+			force.Clean();
 			//
 			//  Look if still enemies in attack range.
 			//
-			if(!AiForceEnemyFinder<true>(force).found()) {
+			if(!AiForceEnemyFinder<true>(&force).found()) {
 				DebugPrint("%d:FIXME: not written, should send force #%d home\n"
 					_C_ AiPlayer->Player->Index _C_ f);
-				force->Defending = false;
-				force->Attacking = false;
+				force.Defending = false;
+				force.Attacking = false;
 			}
-		} else if (force->Attacking) {
-			force->Clean();
-			force->Update();
+		} else if (force.Attacking) {
+			force.Clean();
+			force.Update();
 		}
 	}
 }
 
 /**
-**  Entry point of force manager, perodic called.
+**  Entry point of force manager, periodic called.
 **
 ** @todo FIXME: is this really needed anymore
 */
diff --git a/src/ai/ai_local.h b/src/ai/ai_local.h
index 208506b2d..f3fdd4172 100644
--- a/src/ai/ai_local.h
+++ b/src/ai/ai_local.h
@@ -60,14 +60,7 @@ public:
 	std::string Name;     /// Name of this ai
 	std::string Race;     /// for this race
 	std::string Class;    /// class of this ai
-
-#if 0
-	// nice flags
-	unsigned char AllExplored : 1; /// Ai sees unexplored area
-	unsigned char AllVisbile : 1;  /// Ai sees invisibile area
-#endif
-
-	std::string Script;       /// Main script
+	std::string Script;   /// Main script
 };
 
 /**
@@ -89,7 +82,7 @@ public:
 	AiUnitType() : Want(0), Type(NULL) {}
 
 	unsigned int Want; /// number of this unit-type wanted
-	CUnitType *Type; /// unit-type self
+	CUnitType *Type;   /// unit-type self
 };
 
 /**
@@ -100,11 +93,13 @@ enum AiForceRole {
 	AiForceRoleDefend      /// Force should defend
 };
 
-#define AI_FORCE_STATE_FREE			-1
-#define AI_FORCE_STATE_WAITING		0
-#define AI_FORCE_STATE_BOARDING 	1
-//#define AI_FORCE_STATE_OERATIONAL 	2
-#define AI_FORCE_STATE_ATTACKING	3
+enum AiForceAttackingState
+{
+	AiForceAttackingState_Free = -1,
+	AiForceAttackingState_Waiting = 0,
+	AiForceAttackingState_Boarding,
+	AiForceAttackingState_Attacking,
+};
 
 /**
 **  Define an AI force.
@@ -113,19 +108,10 @@ enum AiForceRole {
 */
 class AiForce {
 	friend class AiForceManager;
-
-	bool IsBelongsTo(const CUnitType *type);
-	void Insert(CUnit &unit)
-	{
-		Units.Insert(&unit);
-		unit.RefsIncrease();
-	}
-
-	void Update();
 public:
-	AiForce() : Completed(false), Defending(false), Attacking(false),
-		Role(0), State(AI_FORCE_STATE_FREE),
-		MustTransport(false)
+	AiForce() :
+		Completed(false), Defending(false), Attacking(false),
+		Role(0), State(AiForceAttackingState_Free)
 	{
 		GoalPos.x = GoalPos.y = 0;
 	}
@@ -133,8 +119,7 @@ public:
 	void Remove(CUnit &unit)
 	{
 		if (Units.Remove(&unit)) {
-			unit.GroupId = 0;
-			unit.RefsDecrease();
+			InternalRemoveUnit(&unit);
 		}
 	}
 
@@ -147,13 +132,13 @@ public:
 		Attacking = false;
 		if (types) {
 			UnitTypes.clear();
-			State = AI_FORCE_STATE_FREE;
+			State = AiForceAttackingState_Free;
 		} else {
-			State = AI_FORCE_STATE_WAITING;
+			State = AiForceAttackingState_Waiting;
 		}
+		Units.for_each(InternalRemoveUnit);
 		Units.clear();
 		GoalPos.x = GoalPos.y = 0;
-		MustTransport = false;
 	}
 	inline size_t Size() const
 	{
@@ -165,39 +150,51 @@ public:
 		return (!Defending && Attacking);
 	}
 
-	void CountTypes(unsigned int *counter, const size_t len);
+	void Attack(const Vec2i &pos);
+	void Clean();
+	int PlanAttack();
 
+private:
+	void CountTypes(unsigned int *counter, const size_t len);
+	bool IsBelongsTo(const CUnitType *type);
+	void Insert(CUnit &unit)
+	{
+		Units.Insert(&unit);
+		unit.RefsIncrease();
+	}
+
+	void Update();
+
+	static void InternalRemoveUnit(CUnit *unit) {
+		unit->GroupId = 0;
+		unit->RefsDecrease();
+	}
+
+public:
 	bool Completed;     /// Flag saying force is complete build
 	bool Defending;     /// Flag saying force is defending
 	bool Attacking;     /// Flag saying force is attacking
 	char Role;          /// Role of the force
 
 	std::vector<AiUnitType> UnitTypes; /// Count and types of unit-type
-	CUnitCache Units;						/// Units in the force
+	CUnitCache Units;   /// Units in the force
 
 	//
 	// If attacking
 	//
-	int State;/// Attack state
+	AiForceAttackingState State; /// Attack state
 	Vec2i GoalPos; /// Attack point tile map position
-	bool MustTransport;/// Flag must use transporter
-
-	void Attack(const Vec2i &pos);
-	void Clean();
-	int PlanAttack();
 };
 
 	// forces
 #define AI_MAX_FORCES 10                    /// How many forces are supported
-//#define AI_MAX_ATTACKING_FORCES 30          /// Attacking forces (max supported 32)
+
 /**
 **  AI force manager.
 **
 **  A Forces container for the force manager to handle
 */
 class AiForceManager {
-	std::vector<AiForce> forces;
-	char script[AI_MAX_FORCES];
 public:
 	AiForceManager();
 
@@ -217,7 +214,6 @@ public:
 		return -1;
 	}
 
-
 	inline unsigned int getScriptForce(unsigned int index) {
 		if (script[index] == -1) {
 			script[index] = FindFreeForce();
@@ -230,6 +226,9 @@ public:
 	void Update();
 	unsigned int FindFreeForce(int role = AiForceRoleAttack);
 	void CheckUnits(int *counter);
+private:
+	std::vector<AiForce> forces;
+	char script[AI_MAX_FORCES];
 };
 
 /**
@@ -241,12 +240,13 @@ class AiBuildQueue {
 public:
 	AiBuildQueue() : Want(0), Made(0), Type(NULL), Wait(0), X(-1), Y(-1)  {}
 
+public:
 	unsigned int Want;  /// requested number
 	unsigned int Made;  /// built number
 	CUnitType *Type;    /// unit-type
 	unsigned long Wait; /// wait until this cycle
-	short int X;              /// build near x pos on map
-	short int Y;              /// build near y pos on map
+	short int X;        /// build near x pos on map
+	short int Y;        /// build near y pos on map
 };
 
 /**
@@ -256,6 +256,7 @@ class AiExplorationRequest {
 public:
 	AiExplorationRequest(const Vec2i& pos, int mask) : pos(pos), Mask(mask) { }
 
+public:
 	Vec2i pos;          /// pos on map
 	int Mask;           /// mask ( ex: MapFieldLandUnit )
 };
@@ -267,6 +268,7 @@ class AiTransportRequest {
 public:
 	AiTransportRequest() : Unit(NULL) {}
 
+public:
 	CUnit *Unit;
 	CUnit::COrder Order;
 };
@@ -279,7 +281,7 @@ public:
 	PlayerAi() : Player(NULL), AiType(NULL),
 		SleepCycles(0), NeededMask(0), NeedSupply(false),
 		ScriptDebug(false), LastExplorationGameCycle(0),
-		LastCanNotMoveGameCycle(0),	LastRepairBuilding(0)
+		LastCanNotMoveGameCycle(0), LastRepairBuilding(0)
 	{
 		memset(Reserve, 0, sizeof(Reserve));
 		memset(Used, 0, sizeof(Used));
@@ -288,13 +290,14 @@ public:
 		memset(TriedRepairWorkers, 0, sizeof(TriedRepairWorkers));
 	}
 
+public:
 	CPlayer *Player;               /// Engine player structure
 	CAiType *AiType;               /// AI type of this player AI
 	// controller
 	std::string Script;            /// Script executed
 	unsigned long SleepCycles;     /// Cycles to sleep
 
-	AiForceManager	Force;		/// Forces controlled by AI
+	AiForceManager Force;  /// Forces controlled by AI
 
 	// resource manager
 	int Reserve[MaxCosts]; /// Resources to keep in reserve
@@ -314,7 +317,7 @@ public:
 	std::vector<CUpgrade *> ResearchRequests;       /// Upgrades requested and priority list
 	std::vector<AiBuildQueue> UnitTypeBuilt;        /// What the resource manager should build
 	int LastRepairBuilding;                         /// Last building checked for repair in this turn
-	unsigned int TriedRepairWorkers[UnitMax];           /// No. workers that failed trying to repair a building
+	unsigned int TriedRepairWorkers[UnitMax];       /// No. workers that failed trying to repair a building
 };
 
 /**
@@ -373,8 +376,6 @@ public:
 	** units/buildings/mines which can store this resource.
 	*/
 	std::vector<std::vector<CUnitType *> > Depots;
-
-
 };
 
 /*----------------------------------------------------------------------------
diff --git a/src/ai/ai_magic.cpp b/src/ai/ai_magic.cpp
index 7c460ea28..4e17eba21 100644
--- a/src/ai/ai_magic.cpp
+++ b/src/ai/ai_magic.cpp
@@ -33,17 +33,11 @@
 --  Includes
 ----------------------------------------------------------------------------*/
 
-#include <stdio.h>
-#include <stdlib.h>
-
 #include "stratagus.h"
 #include "unittype.h"
 #include "unit.h"
 #include "spells.h"
-#include "actions.h"
-#include "map.h"
 #include "ai_local.h"
-#include "player.h"
 
 /*----------------------------------------------------------------------------
 --  Functions
@@ -55,9 +49,9 @@
 */
 void AiCheckMagic()
 {
-	const int n = AiPlayer->Player->TotalNumUnits;
-	CUnit **units = AiPlayer->Player->Units;
-	const CPlayer &player = *AiPlayer->Player; /*units[0]->Player */
+	CPlayer &player = *AiPlayer->Player;
+	const int n = player.TotalNumUnits;
+	CUnit **units = player.Units;
 
 	for (int i = 0; i < n; ++i) {
 		CUnit &unit = *units[i];
diff --git a/src/ai/ai_plan.cpp b/src/ai/ai_plan.cpp
index e9adb9e89..1db06be39 100644
--- a/src/ai/ai_plan.cpp
+++ b/src/ai/ai_plan.cpp
@@ -43,7 +43,6 @@
 #include "pathfinder.h"
 #include "actions.h"
 #include "ai_local.h"
-#include "player.h"
 
 /*----------------------------------------------------------------------------
 --  Variables
@@ -433,7 +432,7 @@ int AiFindWall(AiForce *force)
 	delete[] points;
 
 	if (dest.x != -1) {
-		force->State = AI_FORCE_STATE_WAITING;
+		force->State = AiForceAttackingState_Waiting;
 		for (unsigned int i = 0; i < force->Units.size(); ++i) {
 			CUnit &aiunit = *force->Units[i];
 			if (aiunit.Type->CanAttack) {
@@ -460,20 +459,16 @@ int AiFindWall(AiForce *force)
 */
 int AiForce::PlanAttack()
 {
-	unsigned char *watermatrix;
-	int state;
-	CUnit *transporter;
-
 	DebugPrint("%d: Planning for force #%lu of player #%d\n"_C_ AiPlayer->Player->Index
 	 _C_ (long unsigned int)(this - &(AiPlayer->Force[0])) _C_ AiPlayer->Player->Index);
 
-	watermatrix = CreateMatrix();
+	unsigned char *watermatrix = CreateMatrix();
 
 	//
 	// Transporter must be already assigned to the force.
-	// NOTE: finding free transportes was too much work for me.
+	// NOTE: finding free transporters was too much work for me.
 	//
-	state = 1;
+	int state = 1;
 	for (unsigned int i = 0; i < Size(); ++i) {
 		const CUnit &aiunit = *Units[i];
 
@@ -487,7 +482,7 @@ int AiForce::PlanAttack()
 	//
 	// No transport that belongs to the force.
 	//
-	transporter = NULL;
+	CUnit *transporter = NULL;
 	if (state) {
 		for (int i = 0; i < AiPlayer->Player->TotalNumUnits; ++i) {
 			CUnit &unit = *AiPlayer->Player->Units[i];
@@ -572,9 +567,7 @@ int AiForce::PlanAttack()
 		}
 		DebugPrint("%d: Can attack\n" _C_ AiPlayer->Player->Index);
 		GoalPos = pos;
-		MustTransport = state == 2;
-
-		State = AI_FORCE_STATE_BOARDING;
+		State = AiForceAttackingState_Boarding;
 		return 1;
 	}
 	return 0;
diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp
index 31e2979c9..b4d117e84 100644
--- a/src/ai/ai_resource.cpp
+++ b/src/ai/ai_resource.cpp
@@ -977,21 +977,13 @@ static int CmpWorkers(const void *w0,const void *w1) {
 */
 static void AiCollectResources()
 {
-	CUnit *units_with_resource[MaxCosts][UnitMax]; // Worker with resource
 	CUnit *units_assigned[MaxCosts][UnitMax]; // Worker assigned to resource
 	CUnit *units_unassigned[MaxCosts][UnitMax]; // Unassigned workers
 	int num_units_with_resource[MaxCosts];
 	int num_units_assigned[MaxCosts];
 	int num_units_unassigned[MaxCosts];
-	int c;
-	int src_c;
-	int i;
-	int j;
-	int k;
-	int n;
 	CUnit **units;
 	int percent[MaxCosts];
-	int percent_total;
 
 	int priority_resource[MaxCosts];
 	int priority_needed[MaxCosts];
@@ -1007,19 +999,17 @@ static void AiCollectResources()
 	//
 	total_harvester = 0;
 
-	n = AiPlayer->Player->TotalNumUnits;
+	const int n = AiPlayer->Player->TotalNumUnits;
 	units = AiPlayer->Player->Units;
-	for (i = 0; i < n; ++i) {
+	for (int i = 0; i < n; ++i) {
 		CUnit &unit = *units[i];
 		if (!unit.Type->Harvester) {
 			continue;
 		}
 
-		c = unit.CurrentResource;
+		const int c = unit.CurrentResource;
 
-		//
 		// See if it's assigned already
-		//
 		if (c && unit.OrderCount == 1 &&
 			unit.CurrentAction() == UnitActionResource) {
 			units_assigned[c][num_units_assigned[c]++] = &unit;
@@ -1027,27 +1017,21 @@ static void AiCollectResources()
 			continue;
 		}
 
-		//
 		// Ignore busy units. ( building, fighting, ... )
-		//
 		if (!unit.IsIdle()) {
 			continue;
 		}
 
-		//
 		// Send workers with resources back home.
-		//
 		if (unit.ResourcesHeld && c) {
-			units_with_resource[c][num_units_with_resource[c]++] = &unit;
+			num_units_with_resource[c]++;
 			CommandReturnGoods(unit, 0, FlushCommands);
 			total_harvester++;
 			continue;
 		}
 
-		//
 		// Look what the unit can do
-		//
-		for (c = 1; c < MaxCosts; ++c) {
+		for (int c = 1; c < MaxCosts; ++c) {
 			if (unit.Type->ResInfo[c]) {
 				units_unassigned[c][num_units_unassigned[c]++] = &unit;
 			}
@@ -1055,14 +1039,14 @@ static void AiCollectResources()
 		++total_harvester;
 	}
 
-	if(!total_harvester) {
+	if (!total_harvester) {
 		return;
 	}
 
 	memset(wanted, 0, sizeof(wanted));
 
-	percent_total = 100;
-	for (c = 1; c < MaxCosts; ++c) {
+	int percent_total = 100;
+	for (int c = 1; c < MaxCosts; ++c) {
 		percent[c] = AiPlayer->Collect[c];
 		if ((AiPlayer->NeededMask & (1 << c))) { // Double percent if needed
 			percent_total += percent[c];
@@ -1070,11 +1054,9 @@ static void AiCollectResources()
 		}
 	}
 
-	//
 	// Turn percent values into harvester numbers.
-	//
-	for (c = 1; c < MaxCosts; ++c ) {
-		if(percent[c]) {
+	for (int c = 1; c < MaxCosts; ++c ) {
+		if (percent[c]) {
 			// Wanted needs to be representative.
 			if (total_harvester < 5) {
 				wanted[c] = 1 + (percent[c] * 5) / percent_total;
@@ -1084,67 +1066,55 @@ static void AiCollectResources()
 		}
 	}
 
-	//
 	// Initialise priority & mapping
-	//
-	for (c = 0; c < MaxCosts; ++c) {
+	for (int c = 0; c < MaxCosts; ++c) {
 		priority_resource[c] = c;
 		priority_needed[c] = wanted[c] - num_units_assigned[c] - num_units_with_resource[c];
 
 		if (c && num_units_assigned[c] > 1) {
 			//first should go workers with lower ResourcesHeld value
-			qsort(units_assigned[c], num_units_assigned[c],
-							 sizeof(CUnit*), CmpWorkers);
+			qsort(units_assigned[c], num_units_assigned[c], sizeof(CUnit*), CmpWorkers);
 		}
 
 	}
 	CUnit* unit;
 	do {
-		//
 		// sort resources by priority
-		//
-		for (i = 0; i < MaxCosts; ++i) {
-			for (j = i + 1; j < MaxCosts; ++j) {
+		for (int i = 0; i < MaxCosts; ++i) {
+			for (int j = i + 1; j < MaxCosts; ++j) {
 				if (priority_needed[j] > priority_needed[i]) {
-					c = priority_needed[j];
-					priority_needed[j] = priority_needed[i];
-					priority_needed[i] = c;
-					c = priority_resource[j];
-					priority_resource[j] = priority_resource[i];
-					priority_resource[i] = c;
+					std::swap(priority_needed[i], priority_needed[j]);
+					std::swap(priority_resource[i], priority_resource[j]);
 				}
 			}
 		}
 		unit = NoUnitP;
-		//
-		// Try to complete each ressource in the priority order
-		//
 
-		for (i = 0; i < MaxCosts; ++i) {
-			c = priority_resource[i];
+		// Try to complete each ressource in the priority order
+		for (int i = 0; i < MaxCosts; ++i) {
+			int c = priority_resource[i];
 
 			//
 			// If there is a free worker for c, take it.
 			//
 			if (num_units_unassigned[c]) {
 				// Take the unit.
-				j = 0;
-				while (j < num_units_unassigned[c] && !AiAssignHarvester(*units_unassigned[c][j], c)) {
+				while (0 < num_units_unassigned[c] && !AiAssignHarvester(*units_unassigned[c][0], c)) {
 					// can't assign to c => remove from units_unassigned !
-					units_unassigned[c][j] = units_unassigned[c][--num_units_unassigned[c]];
+					units_unassigned[c][0] = units_unassigned[c][--num_units_unassigned[c]];
 				}
 
 				// unit is assigned
-				if (j < num_units_unassigned[c]) {
-					unit = units_unassigned[c][j];
-					units_unassigned[c][j] = units_unassigned[c][--num_units_unassigned[c]];
+				if (0 < num_units_unassigned[c]) {
+					unit = units_unassigned[c][0];
+					units_unassigned[c][0] = units_unassigned[c][--num_units_unassigned[c]];
 
 					// remove it from other ressources
-					for (j = 0; j < MaxCosts; ++j) {
+					for (int j = 0; j < MaxCosts; ++j) {
 						if (j == c || !unit->Type->ResInfo[j]) {
 							continue;
 						}
-						for (k = 0; k < num_units_unassigned[j]; ++k) {
+						for (int k = 0; k < num_units_unassigned[j]; ++k) {
 							if (units_unassigned[j][k] == unit) {
 								units_unassigned[j][k] = units_unassigned[j][--num_units_unassigned[j]];
 								break;
@@ -1159,9 +1129,9 @@ static void AiCollectResources()
 			//
 			if (!unit) {
 				// Take from lower priority only (i+1).
-				for (j = i + 1; j < MaxCosts && !unit; ++j) {
+				for (int j = i + 1; j < MaxCosts && !unit; ++j) {
 					// Try to move worker from src_c to c
-					src_c = priority_resource[j];
+					const int src_c = priority_resource[j];
 
 					// Don't complete with lower priority ones...
 					if (wanted[src_c] > wanted[c] ||
@@ -1170,7 +1140,7 @@ static void AiCollectResources()
 						continue;
 					}
 
-					for (k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) {
+					for (int k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) {
 						unit = units_assigned[src_c][k];
 
 						if (unit->SubAction >= 65 /* SUB_STOP_GATHERING */ ) {
@@ -1334,7 +1304,6 @@ static int AiRepairUnit(CUnit &unit)
 			}
 		}
 	}
-
 	return 0;
 }
 
@@ -1343,25 +1312,20 @@ static int AiRepairUnit(CUnit &unit)
 */
 static void AiCheckRepair()
 {
-	int i;
-	int j;
-	int k;
-	int n;
-	bool repair_flag;
+	const int n = AiPlayer->Player->TotalNumUnits;
+	int k = 0;
 
-	n = AiPlayer->Player->TotalNumUnits;
-	k = 0;
 	// Selector for next unit
-	for (i = n - 1; i >= 0; --i) {
+	for (int i = n - 1; i >= 0; --i) {
 		CUnit *unit = AiPlayer->Player->Units[i];
 		if (unit && UnitNumber(*unit) == AiPlayer->LastRepairBuilding) {
 			k = i + 1;
 		}
 	}
 
-	for (i = k; i < n; ++i) {
+	for (int i = k; i < n; ++i) {
 		CUnit &unit = *AiPlayer->Player->Units[i];
-		repair_flag = true;
+		bool repair_flag = true;
 
 		if (!unit.IsAliveOnMap()) {
 			continue;
@@ -1374,7 +1338,6 @@ static void AiCheckRepair()
 				unit.CurrentAction() != UnitActionUpgradeTo &&
 				unit.Variable[HP_INDEX].Value < unit.Variable[HP_INDEX].Max &&
 				unit.Attacked + 5 * CYCLES_PER_SECOND < GameCycle) {
-
 			//
 			// FIXME: Repair only units under control
 			//
@@ -1384,7 +1347,7 @@ static void AiCheckRepair()
 			//
 			// Must check, if there are enough resources
 			//
-			for (j = 1; j < MaxCosts; ++j) {
+			for (int j = 1; j < MaxCosts; ++j) {
 				if (unit.Stats->Costs[j] &&
 						AiPlayer->Player->Resources[j] < 99) {
 					repair_flag = false;
diff --git a/src/ai/script_ai.cpp b/src/ai/script_ai.cpp
index 4560ef27b..6b3b77607 100644
--- a/src/ai/script_ai.cpp
+++ b/src/ai/script_ai.cpp
@@ -1420,7 +1420,7 @@ static int CclDefineAiPlayer(lua_State *l)
 					lua_pop(l, 1);
 				} else if (!strcmp(value, "state")) {
 					lua_rawgeti(l, j + 1, k + 1);
-					ai->Force[i].State = LuaToNumber(l, -1);
+					ai->Force[i].State = AiForceAttackingState(LuaToNumber(l, -1));
 					lua_pop(l, 1);
 				} else if (!strcmp(value, "goalx")) {
 					lua_rawgeti(l, j + 1, k + 1);
@@ -1431,9 +1431,7 @@ static int CclDefineAiPlayer(lua_State *l)
 					ai->Force[i].GoalPos.y = LuaToNumber(l, -1);
 					lua_pop(l, 1);
 				} else if (!strcmp(value, "must-transport")) {
-					lua_rawgeti(l, j + 1, k + 1);
-					ai->Force[i].MustTransport = LuaToNumber(l, -1) ? true : false;
-					lua_pop(l, 1);
+					// Keep for backward compatibility
 				} else {
 					LuaError(l, "Unsupported tag: %s" _C_ value);
 				}