From 0d6c49e43a0e877068168006e5aa54b5248862ed Mon Sep 17 00:00:00 2001
From: jsalmon3 <>
Date: Sun, 27 Apr 2003 03:33:35 +0000
Subject: [PATCH] AI doesn't wait for attack forces to finish before sending
 another force with the same number

---
 doc/ChangeLog.html   |  1 +
 src/ai/ai.cpp        | 23 +++++++++++++++-------
 src/ai/ai_force.cpp  | 46 +++++++++++++++++++++++++++++++++++++++++---
 src/ai/script_ai.cpp |  2 +-
 4 files changed, 61 insertions(+), 11 deletions(-)

diff --git a/doc/ChangeLog.html b/doc/ChangeLog.html
index 61ab7376c..e434e2a15 100644
--- a/doc/ChangeLog.html
+++ b/doc/ChangeLog.html
@@ -30,6 +30,7 @@
 <li>Future 1.19 Release<p>
     <ul>
     <li>+++
+    <li>AI doesn't wait for attack forces to finish before sending another force with the same number (from Jimmy Salmon).
     <li>Fixed Bug #724884: Draw levels (from Russell Smith).
     <li>Rewrote middle click scrolling, added ctrl-middle click (from Jimmy Salmon).
     <li>Changed damage calculation to be more random (from Jimmy Salmon).
diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp
index 8d2b4d057..59fc235a8 100644
--- a/src/ai/ai.cpp
+++ b/src/ai/ai.cpp
@@ -193,6 +193,7 @@ local void AiExecuteScript(void)
 local void AiCheckUnits(void)
 {
     int counter[UnitTypeMax];
+    int attacking[UnitTypeMax];
     const AiBuildQueue* queue;
     const int* unit_types_count;
     int i;
@@ -203,6 +204,7 @@ local void AiCheckUnits(void)
     int e;
 
     memset(counter,0,sizeof(counter));
+    memset(attacking,0,sizeof(attacking));
     //
     //	Count the already made build requests.
     //
@@ -258,6 +260,13 @@ local void AiCheckUnits(void)
     //
     //	Look through the forces what is missing.
     //
+    for( i=AI_MAX_FORCES; i<AI_MAX_ATTACKING_FORCES; ++i ) {
+	const AiUnit* unit;
+
+	for( unit=AiPlayer->Force[i].Units; unit; unit=unit->Next ) {
+	    attacking[unit->Unit->Type->Type]++;
+	}
+    }
     for( i=0; i<AI_MAX_FORCES; ++i ) {
 	const AiUnitType* aiut;
 
@@ -270,12 +279,12 @@ local void AiCheckUnits(void)
 	for( aiut=AiPlayer->Force[i].UnitTypes; aiut; aiut=aiut->Next ) {
 	    t=aiut->Type->Type;
 	    x=aiut->Want;
-	    if( x>unit_types_count[t]+counter[t] ) {	// Request it.
+	    if( x>unit_types_count[t]+counter[t]-attacking[t] ) {	// Request it.
 		DebugLevel2Fn("Force %d need %s * %d\n" _C_ i _C_
 			aiut->Type->Ident _C_ x);
 		AiAddUnitTypeRequest(aiut->Type,
-			x-unit_types_count[t]-counter[t]);
-		counter[t]+=x-unit_types_count[t]-counter[t];
+			x-(unit_types_count[t]+counter[t]-attacking[t]));
+		counter[t]+=x-(unit_types_count[t]+counter[t]-attacking[t]);
 		AiPlayer->Force[i].Completed=0;
 	    }
 	    counter[t]-=x;
@@ -662,7 +671,7 @@ local void SaveAiPlayer(FILE* file,unsigned plynr,const PlayerAi* ai)
     //
     //	All forces
     //
-    for( i=0; i<AI_MAX_FORCES; ++i ) {
+    for( i=0; i<AI_MAX_ATTACKING_FORCES; ++i ) {
 	const AiUnitType* aut;
 	const AiUnit* aiunit;
 
@@ -896,7 +905,7 @@ global void CleanAi(void)
 	    //
 	    //	Free forces
 	    //
-	    for( i=0; i<AI_MAX_FORCES; ++i ) {
+	    for( i=0; i<AI_MAX_ATTACKING_FORCES; ++i ) {
 		AiUnitType* aut;
 		AiUnit* aiunit;
 
@@ -1161,12 +1170,12 @@ global void AiHelpMe(const Unit* attacker,Unit* defender)
     //
     //	If unit belongs to an attacking force, don't defend it.
     //
-    for( force=0; force<AI_MAX_FORCES; ++force ) {
-	aiunit=pai->Force[force].Units;
+    for( force=0; force<AI_MAX_ATTACKING_FORCES; ++force ) {
 	if( !pai->Force[force].Attacking ) {	// none attacking
 	    // FIXME, send the force for help
 	    continue;
 	}
+	aiunit=pai->Force[force].Units;
 	while( aiunit ) {
 	    if( defender==aiunit->Unit ) {
 		return;
diff --git a/src/ai/ai_force.cpp b/src/ai/ai_force.cpp
index 4106d8e63..7b7042862 100644
--- a/src/ai/ai_force.cpp
+++ b/src/ai/ai_force.cpp
@@ -148,7 +148,7 @@ global void AiCleanForces(void)
     //
     //	Release all killed units.
     //
-    for( force=0; force<AI_MAX_FORCES; ++force ) {
+    for( force=0; force<AI_MAX_ATTACKING_FORCES; ++force ) {
 	AiCleanForce(force);
     }
 }
@@ -253,7 +253,7 @@ global void AiAssignFreeUnitsToForce(void)
     //
     //	Remove all units already in forces.
     //
-    for( f=0; f<AI_MAX_FORCES; ++f ) {
+    for( f=0; f<AI_MAX_ATTACKING_FORCES; ++f ) {
 	aiunit=AiPlayer->Force[f].Units;
 	while( aiunit ) {
 	    unit=aiunit->Unit;
@@ -317,6 +317,46 @@ global void AiAttackWithForce(int force)
     const Unit* enemy;
     int x;
     int y;
+    int f;
+
+    // Move the force to a free position so it can be used for a new
+    // attacking party
+    if( force<AI_MAX_FORCES ) {
+	AiUnitType *aiut;
+	AiUnitType *temp;
+	AiUnitType **aiut2;
+
+	f=AI_MAX_FORCES;
+	while( AiPlayer->Force[f].Attacking ) {
+	    ++f;
+	    if( f==AI_MAX_ATTACKING_FORCES ) {
+		DebugLevel0Fn("No free attacking forces\n");
+		f=force;
+		break;
+	    }
+	}
+	if( f!=AI_MAX_ATTACKING_FORCES ) {
+	    for( aiut=AiPlayer->Force[f].UnitTypes; aiut; aiut=temp ) {
+		temp=aiut->Next;
+		free(aiut);
+	    }
+
+	    AiPlayer->Force[f]=AiPlayer->Force[force];
+	    memset(&AiPlayer->Force[force],0,sizeof(AiForce));
+	    aiut=AiPlayer->Force[force].UnitTypes;
+	    aiut2=&AiPlayer->Force[force].UnitTypes;
+	    while( aiut ) {
+		*aiut2=malloc(sizeof(**aiut2));
+		(*aiut2)->Next=NULL;
+		(*aiut2)->Want=aiut->Want;
+		(*aiut2)->Type=aiut->Type;
+		aiut=aiut->Next;
+		aiut2=&(*aiut2)->Next;
+	    }
+	}
+
+	force=f;
+    }
 
     AiCleanForce(force);
 
@@ -590,7 +630,7 @@ global void AiForceManager(void)
     //
     //	Look if our defenders still have enemies in range.
     //
-    for( force=0; force<AI_MAX_FORCES; ++force ) {
+    for( force=0; force<AI_MAX_ATTACKING_FORCES; ++force ) {
 	if( AiPlayer->Force[force].Defending ) {
 	    const AiUnit* aiunit;
 
diff --git a/src/ai/script_ai.cpp b/src/ai/script_ai.cpp
index b5bc45597..af339d794 100644
--- a/src/ai/script_ai.cpp
+++ b/src/ai/script_ai.cpp
@@ -953,7 +953,7 @@ local SCM CclAiDump(void)
     //
     //	PrintForce
     //
-    for( i=0; i<AI_MAX_FORCES; ++i) {
+    for( i=0; i<AI_MAX_ATTACKING_FORCES; ++i) {
 	printf("Force(%d%s%s%s):\n",i,
 		AiPlayer->Force[i].Completed ? ",complete" : ",recruit",
 		AiPlayer->Force[i].Attacking ? ",attack" : "",